Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
11 KiB

  1. /*************************************************
  2. * dibpal.cpp *
  3. * *
  4. * Copyright (C) 1995-1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. // dibpal.cpp : implementation file
  8. //
  9. #include "stdafx.h"
  10. #include "dibpal.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char BASED_CODE THIS_FILE[] = __FILE__;
  14. #endif
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CDIBPal
  17. CDIBPal::CDIBPal()
  18. {
  19. }
  20. CDIBPal::~CDIBPal()
  21. {
  22. }
  23. // Create a palette from the color table in a DIB
  24. BOOL CDIBPal::Create(CDIB *pDIB)
  25. {
  26. DWORD dwColors = pDIB->GetNumClrEntries();
  27. // Check the DIB has a color table
  28. if (! dwColors) {
  29. TRACE("No color table");
  30. return FALSE;
  31. }
  32. // get a pointer to the RGB quads in the color table
  33. RGBQUAD * pRGB = pDIB->GetClrTabAddress();
  34. // allocate a log pal and fill it with the color table info
  35. LOGPALETTE *pPal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE)
  36. + dwColors * sizeof(PALETTEENTRY));
  37. if (!pPal) {
  38. TRACE("Out of memory for logpal");
  39. return FALSE;
  40. }
  41. pPal->palVersion = 0x300; // Windows 3.0
  42. pPal->palNumEntries = (WORD) dwColors; // table size
  43. for (DWORD dw=0; dw<dwColors; dw++) {
  44. pPal->palPalEntry[dw].peRed = pRGB[dw].rgbRed;
  45. pPal->palPalEntry[dw].peGreen = pRGB[dw].rgbGreen;
  46. pPal->palPalEntry[dw].peBlue = pRGB[dw].rgbBlue;
  47. pPal->palPalEntry[dw].peFlags = 0;
  48. }
  49. BOOL bResult = CreatePalette(pPal);
  50. free (pPal);
  51. return bResult;
  52. }
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CDIBPal commands
  55. int CDIBPal::GetNumColors()
  56. {
  57. int iColors = 0;
  58. if (!GetObject(sizeof(iColors), &iColors)) {
  59. TRACE("Failed to get num pal colors");
  60. return 0;
  61. }
  62. return iColors;
  63. }
  64. void CDIBPal::Draw(CDC *pDC, CRect *pRect, BOOL bBkgnd)
  65. {
  66. int iColors = GetNumColors();
  67. CPalette *pOldPal = pDC->SelectPalette(this, bBkgnd);
  68. pDC->RealizePalette();
  69. int i, j, top, left, bottom, right;
  70. for (j=0, top=0; j<16 && iColors; j++, top=bottom) {
  71. bottom = (j+1) * pRect->bottom / 16 + 1;
  72. for(i=0, left=0; i<16 && iColors; i++, left=right) {
  73. right = (i+1) * pRect->right / 16 + 1;
  74. CBrush br (PALETTEINDEX(j * 16 + i));
  75. CBrush *brold = pDC->SelectObject(&br);
  76. pDC->Rectangle(left-1, top-1, right, bottom);
  77. pDC->SelectObject(brold);
  78. iColors--;
  79. }
  80. }
  81. pDC->SelectPalette(pOldPal, FALSE);
  82. }
  83. BYTE Color16[16][3] = {{0,0,0},{128,0,0},{0,128,0},{128,128,0},
  84. {0,0,128},{128,0,128},{0,128,128},{192,192,192},
  85. {128,128,128},{255,0,0},{0,255,0},{255,255,0},
  86. {0,0,255},{255,0,255},{0,255,255},{255,255,255}};
  87. BOOL CDIBPal::SetSysPalColors()
  88. {
  89. BOOL bResult = FALSE;
  90. int i, iSysColors, iPalEntries;
  91. HPALETTE hpalOld;
  92. int nColorMode;
  93. // Get a screen DC to work with
  94. HWND hwndActive = ::GetActiveWindow();
  95. HDC hdcScreen = ::GetDC(hwndActive);
  96. ASSERT(hdcScreen);
  97. // Make sure we are on a palettized device
  98. if (!(GetDeviceCaps(hdcScreen, RASTERCAPS) & RC_PALETTE)) {
  99. TRACE("Not a palettized device");
  100. goto abort;
  101. }
  102. // Get the number of system colors and the number of palette entries
  103. // Note that on a palletized device the number of colors is the
  104. // number of guaranteed colors. I.e. the number of reserved system colors
  105. iSysColors = GetDeviceCaps(hdcScreen, NUMCOLORS);
  106. iPalEntries = GetDeviceCaps(hdcScreen, SIZEPALETTE);
  107. if (iSysColors > 256) goto abort;
  108. if (iSysColors == -1)
  109. nColorMode = 16;
  110. else if (iPalEntries == 0)
  111. nColorMode = 4;
  112. else
  113. nColorMode = 8;
  114. SetSystemPaletteUse(hdcScreen, SYSPAL_NOSTATIC);
  115. SetSystemPaletteUse(hdcScreen, SYSPAL_STATIC);
  116. hpalOld = ::SelectPalette(hdcScreen,
  117. (HPALETTE)m_hObject, // our hpal
  118. FALSE);
  119. ::RealizePalette(hdcScreen);
  120. ::SelectPalette(hdcScreen, hpalOld, FALSE);
  121. PALETTEENTRY pe[256];
  122. switch (nColorMode)
  123. {
  124. case 4:
  125. {
  126. iPalEntries = 16;
  127. for (i = 0; i <iPalEntries ; i++)
  128. {
  129. pe[i].peFlags = PC_NOCOLLAPSE;
  130. pe[i].peRed = Color16[i][0];
  131. pe[i].peGreen = Color16[i][1];
  132. pe[i].peBlue = Color16[i][2];
  133. }
  134. }
  135. break;
  136. case 16:
  137. iPalEntries = 256;
  138. iSysColors = 20;
  139. break;
  140. case 8:
  141. {
  142. int nCount = GetSystemPaletteEntries(hdcScreen,
  143. 0,
  144. iPalEntries,
  145. pe);
  146. for (i = 0; i < iSysColors/2; i++)
  147. pe[i].peFlags = 0;
  148. for (; i < iPalEntries-iSysColors/2; i++)
  149. pe[i].peFlags = PC_NOCOLLAPSE;
  150. for (; i < iPalEntries; i++)
  151. pe[i].peFlags = 0;
  152. }
  153. break;
  154. }
  155. ResizePalette(iPalEntries);
  156. SetPaletteEntries(0, iPalEntries, pe);
  157. // for (i=0; i<iPalEntries; i++)
  158. // {
  159. // TRACE("%d>>%d:%d:%d\n",i,pe[i].peRed,pe[i].peGreen,pe[i].peBlue);
  160. // }
  161. bResult = TRUE;
  162. abort:
  163. ::ReleaseDC(hwndActive, hdcScreen);
  164. return bResult;
  165. }
  166. // Load a palette from a named file
  167. BOOL CDIBPal::Load(char *pszFileName)
  168. {
  169. CString strFile;
  170. if ((pszFileName == NULL)
  171. || (strlen(pszFileName) == 0)) {
  172. // Show an open file dialog to get the name
  173. CFileDialog dlg (TRUE, // open
  174. NULL, // no default extension
  175. NULL, // no initial file name
  176. OFN_FILEMUSTEXIST
  177. | OFN_HIDEREADONLY,
  178. "Palette files (*.PAL)|*.PAL|All files (*.*)|*.*||");
  179. if (dlg.DoModal() == IDOK) {
  180. strFile = dlg.GetPathName();
  181. } else {
  182. return FALSE;
  183. }
  184. } else {
  185. // copy the supplied file path
  186. strFile = pszFileName;
  187. }
  188. // Try to open the file for read access
  189. CFile file;
  190. if (! file.Open(strFile,
  191. CFile::modeRead | CFile::shareDenyWrite)) {
  192. AfxMessageBox("Failed to open file");
  193. return FALSE;
  194. }
  195. BOOL bResult = Load(&file);
  196. file.Close();
  197. if (!bResult) AfxMessageBox("Failed to load file");
  198. return bResult;
  199. }
  200. // Load a palette from an open CFile object
  201. BOOL CDIBPal::Load(CFile *fp)
  202. {
  203. return Load(fp->m_hFile);
  204. }
  205. // Load a palette from an open file handle
  206. BOOL CDIBPal::Load(UINT_PTR hFile)
  207. {
  208. HMMIO hmmio;
  209. MMIOINFO info;
  210. memset(&info, 0, sizeof(info));
  211. info.adwInfo[0] = (DWORD)hFile;
  212. hmmio = mmioOpen(NULL,
  213. &info,
  214. MMIO_READ | MMIO_ALLOCBUF);
  215. if (!hmmio) {
  216. TRACE("mmioOpen failed");
  217. return FALSE;
  218. }
  219. BOOL bResult = Load(hmmio);
  220. mmioClose(hmmio, MMIO_FHOPEN);
  221. return bResult;
  222. }
  223. // Load a palette from an open MMIO handle
  224. BOOL CDIBPal::Load(HMMIO hmmio)
  225. {
  226. // Check it's a RIFF PAL file
  227. MMCKINFO ckFile;
  228. ckFile.fccType = mmioFOURCC('P','A','L',' ');
  229. if (mmioDescend(hmmio,
  230. &ckFile,
  231. NULL,
  232. MMIO_FINDRIFF) != 0) {
  233. TRACE("Not a RIFF or PAL file");
  234. return FALSE;
  235. }
  236. // Find the 'data' chunk
  237. MMCKINFO ckChunk;
  238. ckChunk.ckid = mmioFOURCC('d','a','t','a');
  239. if (mmioDescend(hmmio,
  240. &ckChunk,
  241. &ckFile,
  242. MMIO_FINDCHUNK) != 0) {
  243. TRACE("No data chunk in file");
  244. return FALSE;
  245. }
  246. // allocate some memory for the data chunk
  247. int iSize = ckChunk.cksize;
  248. void *pdata = malloc(iSize);
  249. if (!pdata) {
  250. TRACE("No mem for data");
  251. return FALSE;
  252. }
  253. // read the data chunk
  254. if (mmioRead(hmmio,
  255. (char *)pdata,
  256. iSize) != iSize) {
  257. TRACE("Failed to read data chunk");
  258. free(pdata);
  259. return FALSE;
  260. }
  261. // The data chunk should be a LOGPALETTE structure
  262. // which we can create a palette from
  263. LOGPALETTE* pLogPal = (LOGPALETTE*)pdata;
  264. if (pLogPal->palVersion != 0x300) {
  265. TRACE("Invalid version number");
  266. free(pdata);
  267. return FALSE;
  268. }
  269. // Get the number of entries
  270. int iColors = pLogPal->palNumEntries;
  271. if (iColors <= 0) {
  272. TRACE("No colors in palette");
  273. free(pdata);
  274. return FALSE;
  275. }
  276. return CreatePalette(pLogPal);
  277. }
  278. // Save a palette to an open CFile object
  279. BOOL CDIBPal::Save(CFile *fp)
  280. {
  281. return Save(fp->m_hFile);
  282. }
  283. // Save a palette to an open file handle
  284. BOOL CDIBPal::Save(UINT_PTR hFile)
  285. {
  286. HMMIO hmmio;
  287. MMIOINFO info;
  288. memset(&info, 0, sizeof(info));
  289. info.adwInfo[0] = (DWORD)hFile;
  290. hmmio = mmioOpen(NULL,
  291. &info,
  292. MMIO_WRITE | MMIO_CREATE | MMIO_ALLOCBUF);
  293. if (!hmmio) {
  294. TRACE("mmioOpen failed");
  295. return FALSE;
  296. }
  297. BOOL bResult = Save(hmmio);
  298. mmioClose(hmmio, MMIO_FHOPEN);
  299. return bResult;
  300. }
  301. // Save a palette to an open MMIO handle
  302. BOOL CDIBPal::Save(HMMIO hmmio)
  303. {
  304. // Create a RIFF chunk for a PAL file
  305. MMCKINFO ckFile;
  306. ckFile.cksize = 0; // corrected later
  307. ckFile.fccType = mmioFOURCC('P','A','L',' ');
  308. if (mmioCreateChunk(hmmio,
  309. &ckFile,
  310. MMIO_CREATERIFF) != 0) {
  311. TRACE("Failed to create RIFF-PAL chunk");
  312. return FALSE;
  313. }
  314. // create the LOGPALETTE data which will become
  315. // the data chunk
  316. int iColors = GetNumColors();
  317. ASSERT(iColors > 0);
  318. int iSize = sizeof(LOGPALETTE)
  319. + (iColors-1) * sizeof(PALETTEENTRY);
  320. LOGPALETTE* plp = (LOGPALETTE*) malloc(iSize);
  321. ASSERT(plp);
  322. plp->palVersion = 0x300;
  323. plp->palNumEntries = (unsigned short) iColors;
  324. GetPaletteEntries(0, iColors, plp->palPalEntry);
  325. // create the data chunk
  326. MMCKINFO ckData;
  327. ckData.cksize = iSize;
  328. ckData.ckid = mmioFOURCC('d','a','t','a');
  329. if (mmioCreateChunk(hmmio,
  330. &ckData,
  331. 0) != 0) {
  332. TRACE("Failed to create data chunk");
  333. return FALSE;
  334. }
  335. // write the data chunk
  336. if (mmioWrite(hmmio,
  337. (char*)plp,
  338. iSize) != iSize) {
  339. TRACE("Failed to write data chunk");
  340. free(plp);
  341. return FALSE;
  342. }
  343. free(plp);
  344. // Ascend from the data chunk which will correct the length
  345. mmioAscend(hmmio, &ckData, 0);
  346. // Ascend from the RIFF/PAL chunk
  347. mmioAscend(hmmio, &ckFile, 0);
  348. return TRUE;
  349. }