2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Color Translation Functions
5 * FILE: subsys/win32k/eng/xlate.c
6 * PROGRAMER: Jason Filby
11 // TODO: Cache XLATEOBJs that are created by EngCreateXlate by checking if the given palettes match a cached list
13 #include <ddk/ntddk.h>
14 #include <ddk/winddi.h>
15 #include <ddk/ntddvid.h>
17 #include <include/object.h>
21 #include <win32k/debug1.h>
23 ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0;
25 ULONG RGBtoULONG(BYTE Red, BYTE Green, BYTE Blue)
27 return ((Red & 0xff) << 16) | ((Green & 0xff) << 8) | (Blue & 0xff);
30 ULONG BGRtoULONG(BYTE Blue, BYTE Green, BYTE Red)
32 return ((Blue & 0xff) << 16) | ((Green & 0xff) << 8) | (Red & 0xff);
36 // FIXME: If the caller knows that the destinations are indexed and not RGB
37 // then we should cache more than one value. Same with the source.
39 // Takes indexed palette and a
40 ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors,
43 PVIDEO_CLUTDATA cSourceColor;
44 PVIDEO_CLUTDATA cDestColors;
46 ULONG cxRed, cxGreen, cxBlue, BestMatch = 16777215;
48 // Simple cache -- only one value because we don't want to waste time
49 // if the colors aren't very sequential
51 if(SourceColor == CCMLastSourceColor)
53 return CCMLastColorMatch;
56 cSourceColor = (PVIDEO_CLUTDATA)&SourceColor;
57 for (i=0; i<NumColors; i++)
59 cDestColors = (PVIDEO_CLUTDATA)&DestColors[i];
61 cxRed = (cSourceColor->Red - cDestColors->Red);
62 cxRed *= cxRed; //compute cxRed squared
63 cxGreen = (cSourceColor->Green - cDestColors->Green);
65 cxBlue = (cSourceColor->Blue - cDestColors->Blue);
68 rt = /* sqrt */ (cxRed + cxGreen + cxBlue);
77 CCMLastSourceColor = SourceColor;
78 CCMLastColorMatch = idx;
83 VOID IndexedToIndexedTranslationTable(ULONG *TranslationTable,
84 PALGDI *PalDest, PALGDI *PalSource)
88 for(i=0; i<PalSource->NumColors; i++)
90 TranslationTable[i] = ClosestColorMatch(PalSource->IndexedColors[i], PalDest->IndexedColors, PalDest->NumColors);
94 XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
95 HPALETTE PaletteDest, HPALETTE PaletteSource)
97 // FIXME: Add support for BGR conversions
102 PALGDI *SourcePalGDI, *DestPalGDI;
105 NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ ));
106 if( !ValidEngHandle( NewXlate ) )
109 XlateObj = (XLATEOBJ*) AccessUserObject( NewXlate );
110 XlateGDI = (XLATEGDI*) AccessInternalObject( NewXlate );
114 if(SourcePalType == PAL_INDEXED)
115 SourcePalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteSource);
116 if(DestPalType == PAL_INDEXED)
117 DestPalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteDest);
119 XlateObj->iSrcType = SourcePalType;
120 XlateObj->iDstType = DestPalType;
122 // Store handles of palettes in internal Xlate GDI object (or NULLs)
123 XlateGDI->DestPal = PaletteDest;
124 XlateGDI->SourcePal = PaletteSource;
126 XlateObj->flXlate = 0;
128 // If source and destination palettes are the same or if they're RGB/BGR
129 if( (PaletteDest == PaletteSource) ||
130 ((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) ||
131 ((DestPalType == PAL_BGR) && (SourcePalType == PAL_BGR)) )
133 XlateObj->flXlate |= XO_TRIVIAL;
137 // Prepare the translation table
138 if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) )
140 XlateObj->flXlate |= XO_TABLE;
141 if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED))
143 if(SourcePalGDI->NumColors > DestPalGDI->NumColors)
145 IndexedColors = SourcePalGDI->NumColors;
147 IndexedColors = DestPalGDI->NumColors;
149 else if (SourcePalType == PAL_INDEXED) { IndexedColors = SourcePalGDI->NumColors; }
150 else if (DestPalType == PAL_INDEXED) { IndexedColors = DestPalGDI->NumColors; }
152 XlateGDI->translationTable = EngAllocMem(FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, 0);
155 // Source palette is indexed
156 if(XlateObj->iSrcType == PAL_INDEXED)
158 if(XlateObj->iDstType == PAL_INDEXED)
160 // Converting from indexed to indexed
161 IndexedToIndexedTranslationTable(XlateGDI->translationTable, DestPalGDI, SourcePalGDI);
163 if(XlateObj->iDstType == PAL_RGB)
165 // FIXME: Is this necessary? I think the driver has to call this
166 // function anyways if pulXlate is NULL and Source is PAL_INDEXED
168 // Converting from indexed to RGB
170 XLATEOBJ_cGetPalette(XlateObj, XO_SRCPALETTE,
171 SourcePalGDI->NumColors,
172 XlateGDI->translationTable);
175 XlateObj->pulXlate = XlateGDI->translationTable;
178 // Source palette is RGB
179 if(XlateObj->iSrcType == PAL_RGB)
181 if(XlateObj->iDstType == PAL_INDEXED)
183 // FIXME: Is this necessary? I think the driver has to call this
184 // function anyways if pulXlate is NULL and Dest is PAL_INDEXED
186 // Converting from RGB to indexed
187 XLATEOBJ_cGetPalette(XlateObj, XO_DESTPALETTE, DestPalGDI->NumColors, XlateGDI->translationTable);
191 // FIXME: Add support for XO_TO_MONO
195 VOID EngDeleteXlate(XLATEOBJ *XlateObj)
197 HPALETTE HXlate = (HPALETTE)AccessHandleFromUserObject(XlateObj);
198 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObject((ULONG)HXlate);
200 if(XlateGDI->translationTable!=NULL)
202 EngFreeMem(XlateGDI->translationTable);
205 FreeGDIHandle((ULONG)HXlate);
209 XLATEOBJ_piVector(XLATEOBJ *XlateObj)
211 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
213 if(XlateObj->iSrcType == PAL_INDEXED)
215 return XlateGDI->translationTable;
222 XLATEOBJ_iXlate(XLATEOBJ *XlateObj,
226 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
228 // Return the original color if there's no color translation object
229 if(!XlateObj) return Color;
231 if(XlateObj->flXlate & XO_TRIVIAL)
235 if(XlateObj->iSrcType == PAL_RGB)
237 // FIXME: should we cache colors used often?
238 // FIXME: won't work if destination isn't indexed
240 // Extract the destination palette
241 PalGDI = (PALGDI*)AccessInternalObject((ULONG)XlateGDI->DestPal);
243 // Return closest match for the given RGB color
244 return ClosestColorMatch(Color, PalGDI->IndexedColors, PalGDI->NumColors);
246 if(XlateObj->iSrcType == PAL_INDEXED)
248 return XlateGDI->translationTable[Color];
255 XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj,
265 XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
267 if(PalOutType == XO_SRCPALETTE)
269 HPal = XlateGDI->SourcePal;
271 if(PalOutType == XO_DESTPALETTE)
273 HPal = XlateGDI->DestPal;
276 PalGDI = (PALGDI*)AccessInternalObject((ULONG)HPal);
277 RtlCopyMemory(OutPal, PalGDI->IndexedColors, sizeof(ULONG)*cPal);