Leaked source code of windows server 2003
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.

522 lines
16 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999-2000 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Object which maps one palette to another.
  8. *
  9. * It only maps colors which match exactly - its purpose is to deal
  10. * with, e.g., the halftone palette which has identical colors on different
  11. * platforms, but colors may be in different positions.
  12. *
  13. * Revision History:
  14. *
  15. * 12/09/1999 ericvan
  16. * Created it.
  17. * 01/20/2000 agodfrey
  18. * Moved it from Imaging\Api. Renamed it to EpPaletteMap.
  19. * Replaced the halftoning function pointer with 'isVGAOnly'.
  20. *
  21. \**************************************************************************/
  22. #include "precomp.hpp"
  23. //#define GDIPLUS_WIN9X_HALFTONE_MAP
  24. #if defined(GDIPLUS_WIN9X_HALFTONE_MAP)
  25. // The first array maps from our halftone color palette to the Windows 9x
  26. // halftone color palette, while the second array does the reverse. Negative
  27. // values indicate an unmatched color:
  28. //
  29. // -1 no exact match (Win9x is missing 4 of our halftone colors)
  30. // -2 magic color
  31. INT HTToWin9xPaletteMap[256] = {
  32. 0, 1, 2, 3, 4, 5, 6, 7,
  33. -2, -2, -2, -2, 248, 249, 250, 251,
  34. 252, 253, 254, 255, 0, 0, 0, 0,
  35. 0, 0, 0, 0, 0, 0, 0, 0,
  36. 0, 0, 0, 0, 0, 0, 0, 0,
  37. 0, 60, 95, 133, 161, 252, 33, 66,
  38. 101, 166, 199, -1, 39, 72, 107, 138,
  39. 172, 205, 45, 78, 112, 129, 178, 211,
  40. 51, 84, 118, 149, 184, 217, 250, -1,
  41. 123, 155, 190, 254, 29, 61, 96, 162,
  42. 196, -1, 34, 67, 102, 134, 167, 200,
  43. 40, 73, 108, 139, 173, 206, 46, 79,
  44. 113, 144, 179, 212, 52, 85, 119, 150,
  45. 185, 218, -1, 90, 124, 156, 191, 223,
  46. 30, 62, 97, 135, 163, 197, 35, 68,
  47. 103, 140, 168, 201, 41, 74, 109, 174,
  48. 207, 230, 47, 80, 114, 145, 180, 213,
  49. 53, 86, 151, 157, 186, 219, 57, 91,
  50. 228, 192, 224, 232, 31, 63, 98, 131,
  51. 164, 198, 36, 69, 104, 130, 169, 202,
  52. 42, 75, 110, 141, 175, 208, 48, 81,
  53. 115, 146, 181, 214, 54, 87, 120, 152,
  54. 187, 220, 58, 92, 125, 158, 193, 225,
  55. 32, 64, 99, 132, 165, 128, 37, 70,
  56. 105, 136, 170, 203, 43, 76, 111, 142,
  57. 176, 209, 49, 82, 116, 147, 182, 215,
  58. 55, 88, 121, 153, 188, 221, 59, 93,
  59. 126, 159, 194, 226, 249, 65, 100, 137,
  60. 127, 253, 38, 71, 106, 143, 171, 204,
  61. 44, 77, 227, 177, 210, 231, 50, 83,
  62. 117, 148, 183, 216, 56, 89, 122, 154,
  63. 189, 222, 251, 94, 229, 160, 195, 255
  64. };
  65. INT HTFromWin9xPaletteMap[256] = {
  66. 0, 1, 2, 3, 4, 5, 6, 7,
  67. -2, -2, -1, -1, -1, -1, -1, -1,
  68. -1, -1, -1, -1, -1, -1, -1, -1,
  69. -1, -1, -1, -1, -1, 76, 112, 148,
  70. 184, 46, 82, 118, 154, 190, 226, 52,
  71. 88, 124, 160, 196, 232, 58, 94, 130,
  72. 166, 202, 238, 64, 100, 136, 172, 208,
  73. 244, 142, 178, 214, 41, 77, 113, 149,
  74. 185, 221, 47, 83, 119, 155, 191, 227,
  75. 53, 89, 125, 161, 197, 233, 59, 95,
  76. 131, 167, 203, 239, 65, 101, 137, 173,
  77. 209, 245, 107, 143, 179, 215, 251, 42,
  78. 78, 114, 150, 186, 222, 48, 84, 120,
  79. 156, 192, 228, 54, 90, 126, 162, 198,
  80. 60, 96, 132, 168, 204, 240, 66, 102,
  81. 174, 210, 246, 72, 108, 180, 216, 224,
  82. 189, 61, 157, 151, 187, 43, 85, 115,
  83. 193, 223, 55, 91, 121, 163, 199, 229,
  84. 97, 133, 169, 205, 241, 67, 103, 138,
  85. 175, 211, 247, 73, 109, 139, 181, 217,
  86. 253, 44, 79, 116, 152, 188, 49, 86,
  87. 122, 158, 194, 230, 56, 92, 127, 164,
  88. 200, 235, 62, 98, 134, 170, 206, 242,
  89. 68, 104, 140, 176, 212, 248, 74, 110,
  90. 145, 182, 218, 254, 80, 117, 153, 50,
  91. 87, 123, 159, 195, 231, 57, 93, 128,
  92. 165, 201, 236, 63, 99, 135, 171, 207,
  93. 243, 69, 105, 141, 177, 213, 249, 111,
  94. 146, 183, 219, 234, 144, 252, 129, 237,
  95. 147, -1, -1, -1, -1, -1, -1, -1,
  96. -1, -1, -1, -1, -1, -1, -2, -2,
  97. 12, 13, 14, 15, 16, 17, 18, 19
  98. };
  99. #endif
  100. BYTE
  101. GetNearestColorIndex(
  102. GpColor color,
  103. ColorPalette *palette
  104. )
  105. {
  106. INT i;
  107. BYTE nearestIndex = 0;
  108. INT nearestDistance = INT_MAX;
  109. // Note: This does not optimize for the exact match case because it's
  110. // assumed we already did this check first.
  111. for (i = 0; i < (INT) palette->Count; i++)
  112. {
  113. // Compute the distance (squared) between colors:
  114. GpColor palColor = GpColor(palette->Entries[i]);
  115. INT r = (INT) color.GetRed() - (INT) palColor.GetRed();
  116. INT g = (INT) color.GetGreen() - (INT) palColor.GetGreen();
  117. INT b = (INT) color.GetBlue() - (INT) palColor.GetBlue();
  118. INT distance = (r * r) + (g * g) + (b * b);
  119. if (distance < nearestDistance)
  120. {
  121. nearestDistance = distance;
  122. nearestIndex = static_cast<BYTE>(i);
  123. if (nearestDistance == 0)
  124. {
  125. break;
  126. }
  127. }
  128. }
  129. return nearestIndex;
  130. }
  131. VOID
  132. EpPaletteMap::CreateFromColorPalette(
  133. ColorPalette *palette
  134. )
  135. {
  136. INT i;
  137. INT matchCount = 0;
  138. #if defined(GDIPLUS_WIN9X_HALFTONE_MAP)
  139. // Check for the Win9x halftone palette:
  140. PALETTEENTRY *palEntry = Win9xHalftonePalette.palPalEntry;
  141. for (i = 0; i < 256; i++, palEntry++)
  142. {
  143. // Ignore magic or unmatched colors:
  144. if (HTFromWin9xPaletteMap[i] >= 0)
  145. {
  146. GpColor palColor(palette->Entries[i]);
  147. if ((palColor.GetRed() != palEntry->peRed) ||
  148. (palColor.GetGreen() != palEntry->peGreen) ||
  149. (palColor.GetBlue() != palEntry->peBlue))
  150. {
  151. break;
  152. }
  153. }
  154. }
  155. if (i == 256) // --- Win9x halftone palette ---
  156. {
  157. matchCount = 212;
  158. for (i = 0; i < 256; i++)
  159. {
  160. INT win9xIndex = HTToWin9xPaletteMap[i];
  161. if (win9xIndex >= 0)
  162. {
  163. translate[i] = static_cast<BYTE>(win9xIndex);
  164. }
  165. else
  166. {
  167. GpColor halftoneColor;
  168. if (win9xIndex == -1)
  169. {
  170. halftoneColor =
  171. GpColor(HTColorPalette.palPalEntry[i].peRed,
  172. HTColorPalette.palPalEntry[i].peGreen,
  173. HTColorPalette.palPalEntry[i].peBlue);
  174. }
  175. else
  176. {
  177. ASSERT(win9xIndex == -2);
  178. ASSERT((i >= 8) && (i <= 11));
  179. COLORREF systemColor = Globals::SystemColors[i + 8];
  180. halftoneColor = GpColor(GetRValue(systemColor),
  181. GetGValue(systemColor),
  182. GetBValue(systemColor));
  183. }
  184. translate[i] = GetNearestColorIndex(halftoneColor,
  185. palette);
  186. }
  187. }
  188. }
  189. else // --- Any other palette ---
  190. #endif
  191. {
  192. for (i = 0; i < 256; i++)
  193. {
  194. GpColor color;
  195. if ((i > 11) || (i < 8))
  196. {
  197. color = GpColor(HTColorPalette.palPalEntry[i].peRed,
  198. HTColorPalette.palPalEntry[i].peGreen,
  199. HTColorPalette.palPalEntry[i].peBlue);
  200. }
  201. else
  202. {
  203. COLORREF systemColor = Globals::SystemColors[i + 8];
  204. color = GpColor(GetRValue(systemColor),
  205. GetGValue(systemColor),
  206. GetBValue(systemColor));
  207. }
  208. // First look for exact matches:
  209. INT j;
  210. for (j = 0; j < (INT) palette->Count; j++)
  211. {
  212. if (GpColor(palette->Entries[j]).IsEqual(color))
  213. {
  214. // We found an exact match:
  215. translate[i] = static_cast<BYTE>(j);
  216. if (i >= 40)
  217. {
  218. matchCount++;
  219. }
  220. break;
  221. }
  222. }
  223. // If we didn't find an exact match, look for the nearest:
  224. if (j == (INT) palette->Count)
  225. {
  226. translate[i] = GetNearestColorIndex(color,
  227. palette);
  228. }
  229. }
  230. }
  231. uniqueness = 0;
  232. // See comments in UpdateTranslate to see why we look for 212 colors.
  233. isVGAOnly = (matchCount >= 212) ? FALSE : TRUE;
  234. }
  235. EpPaletteMap::EpPaletteMap(HDC hdc, ColorPalette **palette, BOOL isDib8)
  236. {
  237. // isDib8 is TRUE when the caller has already determined that the HDC
  238. // bitmap is an 8 bpp DIB section. If the caller hasn't determined, we
  239. // check here:
  240. if (!isDib8 && (GetDCType(hdc) == OBJ_MEMDC))
  241. {
  242. HBITMAP hbm = (HBITMAP) GetCurrentObject(hdc, OBJ_BITMAP);
  243. if (hbm)
  244. {
  245. DIBSECTION dibInfo;
  246. INT infoSize = GetObjectA(hbm, sizeof(dibInfo), &dibInfo);
  247. // Comment below copied from GpGraphics::GetFromGdiBitmap:
  248. //
  249. // WinNT/Win95 differences in GetObject:
  250. //
  251. // WinNT always returns the number of bytes filled, either
  252. // sizeof(BITMAP) or sizeof(DIBSECTION).
  253. //
  254. // Win95 always returns the original requested size (filling the
  255. // remainder with NULLs). So if it is a DIBSECTION, we expect
  256. // dibInfo.dsBmih.biSize != 0; otherwise it is a BITMAP.
  257. if ((infoSize == sizeof(DIBSECTION)) &&
  258. (Globals::IsNt || dibInfo.dsBmih.biSize))
  259. {
  260. if (dibInfo.dsBmih.biBitCount == 8)
  261. {
  262. isDib8 = TRUE;
  263. }
  264. }
  265. }
  266. }
  267. // If we've got an 8 bpp DIB section, extract its color table and create
  268. // the palette map from this. Otherwise, call UpdateTranslate which will
  269. // handle screen and compatible bitmaps.
  270. if (isDib8)
  271. {
  272. // Get the color table from the DIBSection
  273. RGBQUAD colorTable[256];
  274. GetDIBColorTable(hdc, 0, 256, colorTable);
  275. // Create a GDI+ ColorPalette object from it
  276. // Note: the reason we use "255" here is because
  277. // ColorPalette object already has 1 allocation for ARGB
  278. ColorPalette *newPalette =
  279. static_cast<ColorPalette *>(
  280. GpMalloc(sizeof(ColorPalette) + 255 * sizeof(ARGB)));
  281. if (newPalette)
  282. {
  283. newPalette->Flags = 0;
  284. newPalette->Count = 256;
  285. for (int i = 0; i < 256; i++)
  286. {
  287. newPalette->Entries[i] =
  288. MAKEARGB(255,
  289. colorTable[i].rgbRed,
  290. colorTable[i].rgbGreen,
  291. colorTable[i].rgbBlue);
  292. }
  293. CreateFromColorPalette(newPalette);
  294. if (palette)
  295. {
  296. *palette = newPalette;
  297. }
  298. else
  299. {
  300. GpFree(newPalette);
  301. }
  302. SetValid(TRUE);
  303. return;
  304. }
  305. SetValid(FALSE);
  306. }
  307. else
  308. {
  309. UpdateTranslate(hdc, palette);
  310. }
  311. }
  312. EpPaletteMap::~EpPaletteMap()
  313. {
  314. SetValid(FALSE); // so we don't use a deleted object
  315. }
  316. VOID EpPaletteMap::UpdateTranslate(HDC hdc, ColorPalette **palette)
  317. {
  318. SetValid(FALSE);
  319. HPALETTE hSysPal = NULL;
  320. struct
  321. {
  322. LOGPALETTE logpalette;
  323. PALETTEENTRY palEntries[256];
  324. } pal;
  325. pal.logpalette.palVersion = 0x0300;
  326. // <SystemPalette>
  327. // !!! [agodfrey] On Win9x, GetSystemPaletteEntries(hdc, 0, 256, NULL)
  328. // doesn't do what MSDN says it does. It seems to return the number
  329. // of entries in the logical palette of the DC instead. So we have
  330. // to make it up ourselves.
  331. pal.logpalette.palNumEntries = (1 << (GetDeviceCaps(hdc, BITSPIXEL) *
  332. GetDeviceCaps(hdc, PLANES)));
  333. GetSystemPaletteEntries(hdc, 0, 256, &pal.logpalette.palPalEntry[0]);
  334. hSysPal = CreatePalette(&pal.logpalette);
  335. if (hSysPal == NULL)
  336. {
  337. return;
  338. }
  339. if (palette)
  340. {
  341. // system palette is required for ScanDci case.
  342. if (*palette == NULL)
  343. {
  344. *palette = (ColorPalette*)GpMalloc(sizeof(ColorPalette)+sizeof(ARGB)*256);
  345. if (*palette == NULL)
  346. {
  347. goto exit;
  348. }
  349. }
  350. (*palette)->Count = pal.logpalette.palNumEntries;
  351. for (INT j=0; j<pal.logpalette.palNumEntries; j++)
  352. {
  353. (*palette)->Entries[j] = GpColor::MakeARGB(0xFF,
  354. pal.logpalette.palPalEntry[j].peRed,
  355. pal.logpalette.palPalEntry[j].peGreen,
  356. pal.logpalette.palPalEntry[j].peBlue);
  357. }
  358. }
  359. {
  360. GpMemset(translate, 0, 256);
  361. INT matchCount;
  362. INT i;
  363. PALETTEENTRY * halftonePalEntry = HTColorPalette.palPalEntry;
  364. COLORREF halftoneColor;
  365. COLORREF sysColor;
  366. COLORREF matchedColor;
  367. UINT matchingIndex;
  368. // Create a translation table for the 216 halftone colors, and count
  369. // how many exact matches we get.
  370. for (i = 0, matchCount = 0; i < 256; i++, halftonePalEntry++)
  371. {
  372. if ((i > 11) || (i < 8))
  373. {
  374. halftoneColor = PALETTERGB(halftonePalEntry->peRed,
  375. halftonePalEntry->peGreen,
  376. halftonePalEntry->peBlue);
  377. }
  378. else // it is one of the magic 4 changeable system colors
  379. {
  380. halftoneColor = Globals::SystemColors[i + 8] | 0x02000000;
  381. }
  382. // See if the color is actually available in the system palette.
  383. matchedColor = ::GetNearestColor(hdc, halftoneColor) | 0x02000000;
  384. // Find the index of the matching color in the system palette
  385. matchingIndex = ::GetNearestPaletteIndex(hSysPal, matchedColor);
  386. if (matchingIndex == CLR_INVALID)
  387. {
  388. goto exit;
  389. }
  390. // We should never match to an entry outside of the device palette.
  391. ASSERT(matchingIndex < pal.logpalette.palNumEntries);
  392. translate[i] = static_cast<BYTE>(matchingIndex);
  393. sysColor = PALETTERGB(pal.logpalette.palPalEntry[matchingIndex].peRed,
  394. pal.logpalette.palPalEntry[matchingIndex].peGreen,
  395. pal.logpalette.palPalEntry[matchingIndex].peBlue);
  396. // see if we got an exact match
  397. if ((i >= 40) && (sysColor == halftoneColor))
  398. {
  399. matchCount++;
  400. }
  401. }
  402. // If we matched enough colors, we'll do 216-color halftoning.
  403. // Otherwise, we'll have to halftone with the VGA colors.
  404. // The palette returned from CreateHalftonePalette() on Win9x has
  405. // only 212 of the required 216 halftone colors. (On NT it has all 216).
  406. // The 4 colors missing from the Win9x halftone palette are:
  407. // 0x00, 0x33, 0xFF
  408. // 0x00, 0xFF, 0x33
  409. // 0x33, 0x00, 0xFF
  410. // 0x33, 0xFF, 0x00
  411. // We require that all 212 colors be available because our GetNearestColor
  412. // API assumes that all 216 colors are there if we're doing 216-color
  413. // halftoning.
  414. SetValid(TRUE);
  415. if (matchCount >= 212)
  416. {
  417. isVGAOnly = FALSE;
  418. }
  419. else
  420. {
  421. isVGAOnly = TRUE;
  422. }
  423. }
  424. exit:
  425. DeleteObject(hSysPal);
  426. return;
  427. }