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/ntddvdeo.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);
46 // FIXME: If the caller knows that the destinations are indexed and not RGB
47 // then we should cache more than one value. Same with the source.
49 // Takes indexed palette and a
50 ULONG
ClosestColorMatch(ULONG SourceColor
, ULONG
*DestColors
,
53 PVIDEO_CLUTDATA cSourceColor
;
54 PVIDEO_CLUTDATA cDestColors
;
56 ULONG cxRed
, cxGreen
, cxBlue
, BestMatch
= 65535;
58 // Simple cache -- only one value because we don't want to waste time
59 // if the colors aren't very sequential
61 if(SourceColor
== CCMLastSourceColor
)
63 return CCMLastColorMatch
;
66 cSourceColor
= (PVIDEO_CLUTDATA
)&SourceColor
;
67 for (i
=0; i
<NumColors
; i
++)
69 cDestColors
= (PVIDEO_CLUTDATA
)&DestColors
[i
];
71 cxRed
= abs(cSourceColor
->Red
- cDestColors
->Red
) ^ 2;
72 cxGreen
= abs(cSourceColor
->Green
- cDestColors
->Green
) ^ 2;
73 cxBlue
= abs(cSourceColor
->Blue
- cDestColors
->Blue
) ^ 2;
75 rt
= /* sqrt */ (cxRed
+ cxGreen
+ cxBlue
);
84 CCMLastSourceColor
= SourceColor
;
85 CCMLastColorMatch
= idx
;
90 VOID
IndexedToIndexedTranslationTable(ULONG
*TranslationTable
,
91 PALGDI
*PalDest
, PALGDI
*PalSource
)
95 for(i
=0; i
<PalSource
->NumColors
; i
++)
97 TranslationTable
[i
] = ClosestColorMatch(PalSource
->IndexedColors
[i
], PalDest
->IndexedColors
, PalDest
->NumColors
);
101 XLATEOBJ
*EngCreateXlate(USHORT DestPalType
, USHORT SourcePalType
,
102 HPALETTE PaletteDest
, HPALETTE PaletteSource
)
104 // FIXME: Add support for BGR conversions
109 PALGDI
*SourcePalGDI
, *DestPalGDI
;
112 NewXlate
= (HPALETTE
)CreateGDIHandle(sizeof( XLATEGDI
), sizeof( XLATEOBJ
));
113 if( !ValidEngHandle( NewXlate
) )
116 XlateObj
= (XLATEOBJ
*) AccessUserObject( NewXlate
);
117 XlateGDI
= (XLATEGDI
*) AccessInternalObject( NewXlate
);
121 if(SourcePalType
== PAL_INDEXED
)
122 SourcePalGDI
= (PALGDI
*)AccessInternalObject((ULONG
)PaletteSource
);
123 if(DestPalType
== PAL_INDEXED
)
124 DestPalGDI
= (PALGDI
*)AccessInternalObject((ULONG
)PaletteDest
);
126 XlateObj
->iSrcType
= SourcePalType
;
127 XlateObj
->iDstType
= DestPalType
;
129 // Store handles of palettes in internal Xlate GDI object (or NULLs)
130 XlateGDI
->DestPal
= PaletteDest
;
131 XlateGDI
->SourcePal
= PaletteSource
;
133 XlateObj
->flXlate
= 0;
135 // If source and destination palettes are the same or if they're RGB/BGR
136 if( (PaletteDest
== PaletteSource
) ||
137 ((DestPalType
== PAL_RGB
) && (SourcePalType
== PAL_RGB
)) ||
138 ((DestPalType
== PAL_BGR
) && (SourcePalType
== PAL_BGR
)) )
140 XlateObj
->flXlate
|= XO_TRIVIAL
;
144 // Prepare the translation table
145 if( (SourcePalType
== PAL_INDEXED
) || (SourcePalType
== PAL_RGB
) )
147 XlateObj
->flXlate
|= XO_TABLE
;
148 if ((SourcePalType
== PAL_INDEXED
) && (DestPalType
== PAL_INDEXED
))
150 if(SourcePalGDI
->NumColors
> DestPalGDI
->NumColors
)
152 IndexedColors
= SourcePalGDI
->NumColors
;
154 IndexedColors
= DestPalGDI
->NumColors
;
156 else if (SourcePalType
== PAL_INDEXED
) { IndexedColors
= SourcePalGDI
->NumColors
; }
157 else if (DestPalType
== PAL_INDEXED
) { IndexedColors
= DestPalGDI
->NumColors
; }
159 XlateGDI
->translationTable
= EngAllocMem(FL_ZERO_MEMORY
, sizeof(ULONG
)*IndexedColors
, 0);
162 // Source palette is indexed
163 if(XlateObj
->iSrcType
== PAL_INDEXED
)
165 if(XlateObj
->iDstType
== PAL_INDEXED
)
167 // Converting from indexed to indexed
168 IndexedToIndexedTranslationTable(XlateGDI
->translationTable
, DestPalGDI
, SourcePalGDI
);
170 if(XlateObj
->iDstType
== PAL_RGB
)
172 // FIXME: Is this necessary? I think the driver has to call this
173 // function anyways if pulXlate is NULL and Source is PAL_INDEXED
175 // Converting from indexed to RGB
177 XLATEOBJ_cGetPalette(XlateObj
, XO_SRCPALETTE
,
178 SourcePalGDI
->NumColors
,
179 XlateGDI
->translationTable
);
182 XlateObj
->pulXlate
= XlateGDI
->translationTable
;
185 // Source palette is RGB
186 if(XlateObj
->iSrcType
== PAL_RGB
)
188 if(XlateObj
->iDstType
== PAL_INDEXED
)
190 // FIXME: Is this necessary? I think the driver has to call this
191 // function anyways if pulXlate is NULL and Dest is PAL_INDEXED
193 // Converting from RGB to indexed
194 XLATEOBJ_cGetPalette(XlateObj
, XO_DESTPALETTE
, DestPalGDI
->NumColors
, XlateGDI
->translationTable
);
198 // FIXME: Add support for XO_TO_MONO
203 EngDeleteXlate(XLATEOBJ
*XlateObj
)
205 HPALETTE HXlate
= (HPALETTE
)AccessHandleFromUserObject(XlateObj
);
206 XLATEGDI
*XlateGDI
= (XLATEGDI
*)AccessInternalObject((ULONG
)HXlate
);
208 if(XlateGDI
->translationTable
!=NULL
)
210 EngFreeMem(XlateGDI
->translationTable
);
213 FreeGDIHandle((ULONG
)HXlate
);
217 XLATEOBJ_piVector(XLATEOBJ
*XlateObj
)
219 XLATEGDI
*XlateGDI
= (XLATEGDI
*)AccessInternalObjectFromUserObject(XlateObj
);
221 if(XlateObj
->iSrcType
== PAL_INDEXED
)
223 return XlateGDI
->translationTable
;
230 XLATEOBJ_iXlate(XLATEOBJ
*XlateObj
,
234 XLATEGDI
*XlateGDI
= (XLATEGDI
*)AccessInternalObjectFromUserObject(XlateObj
);
236 if(XlateObj
->flXlate
& XO_TRIVIAL
)
240 if(XlateObj
->iSrcType
== PAL_RGB
)
242 // FIXME: should we cache colors used often?
243 // FIXME: won't work if destination isn't indexed
245 // Extract the destination palette
246 PalGDI
= (PALGDI
*)AccessInternalObject((ULONG
)XlateGDI
->DestPal
);
248 // Return closest match for the given RGB color
249 return ClosestColorMatch(Color
, PalGDI
->IndexedColors
, PalGDI
->NumColors
);
251 if(XlateObj
->iSrcType
== PAL_INDEXED
)
253 return XlateGDI
->translationTable
[Color
];
260 XLATEOBJ_cGetPalette(XLATEOBJ
*XlateObj
,
270 XlateGDI
= (XLATEGDI
*)AccessInternalObjectFromUserObject(XlateObj
);
272 if(PalOutType
== XO_SRCPALETTE
)
274 HPal
= XlateGDI
->SourcePal
;
276 if(PalOutType
== XO_DESTPALETTE
)
278 HPal
= XlateGDI
->DestPal
;
281 PalGDI
= (PALGDI
*)AccessInternalObject((ULONG
)HPal
);
282 RtlCopyMemory(OutPal
, PalGDI
->IndexedColors
, sizeof(ULONG
)*cPal
);