Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / subsys / win32k / eng / xlate.c
1 /*
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
7 * REVISION HISTORY:
8 * 8/20/1999: Created
9 */
10
11 // TODO: Cache XLATEOBJs that are created by EngCreateXlate by checking if the given palettes match a cached list
12
13 #include <ddk/ntddk.h>
14 #include <ddk/winddi.h>
15 #include <ddk/ntddvdeo.h>
16
17 #include <include/object.h>
18 #include "handle.h"
19
20 //#define NDEBUG
21 #include <win32k/debug1.h>
22
23 ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0;
24
25 ULONG RGBtoULONG(BYTE Red, BYTE Green, BYTE Blue)
26 {
27 return ((Red & 0xff) << 16) | ((Green & 0xff) << 8) | (Blue & 0xff);
28 }
29
30 ULONG BGRtoULONG(BYTE Blue, BYTE Green, BYTE Red)
31 {
32 return ((Blue & 0xff) << 16) | ((Green & 0xff) << 8) | (Red & 0xff);
33 }
34
35 INT abs(INT nm)
36 {
37 if(nm<0)
38 {
39 return nm * -1;
40 } else
41 {
42 return nm;
43 }
44 }
45
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.
48
49 // Takes indexed palette and a
50 ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors,
51 ULONG NumColors)
52 {
53 PVIDEO_CLUTDATA cSourceColor;
54 PVIDEO_CLUTDATA cDestColors;
55 LONG idx = 0, i, rt;
56 ULONG cxRed, cxGreen, cxBlue, BestMatch = 65535;
57
58 // Simple cache -- only one value because we don't want to waste time
59 // if the colors aren't very sequential
60
61 if(SourceColor == CCMLastSourceColor)
62 {
63 return CCMLastColorMatch;
64 }
65
66 cSourceColor = (PVIDEO_CLUTDATA)&SourceColor;
67 for (i=0; i<NumColors; i++)
68 {
69 cDestColors = (PVIDEO_CLUTDATA)&DestColors[i];
70
71 cxRed = abs(cSourceColor->Red - cDestColors->Red) ^ 2;
72 cxGreen = abs(cSourceColor->Green - cDestColors->Green) ^ 2;
73 cxBlue = abs(cSourceColor->Blue - cDestColors->Blue) ^ 2;
74
75 rt = /* sqrt */ (cxRed + cxGreen + cxBlue);
76
77 if(rt<=BestMatch)
78 {
79 idx = i;
80 BestMatch = rt;
81 }
82 }
83
84 CCMLastSourceColor = SourceColor;
85 CCMLastColorMatch = idx;
86
87 return idx;
88 }
89
90 VOID IndexedToIndexedTranslationTable(ULONG *TranslationTable,
91 PALGDI *PalDest, PALGDI *PalSource)
92 {
93 ULONG i;
94
95 for(i=0; i<PalSource->NumColors; i++)
96 {
97 TranslationTable[i] = ClosestColorMatch(PalSource->IndexedColors[i], PalDest->IndexedColors, PalDest->NumColors);
98 }
99 }
100
101 XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
102 HPALETTE PaletteDest, HPALETTE PaletteSource)
103 {
104 // FIXME: Add support for BGR conversions
105
106 HPALETTE NewXlate;
107 XLATEOBJ *XlateObj;
108 XLATEGDI *XlateGDI;
109 PALGDI *SourcePalGDI, *DestPalGDI;
110 ULONG IndexedColors;
111
112 NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ ));
113 if( !ValidEngHandle( NewXlate ) )
114 return NULL;
115
116 XlateObj = (XLATEOBJ*) AccessUserObject( NewXlate );
117 XlateGDI = (XLATEGDI*) AccessInternalObject( NewXlate );
118 ASSERT( XlateObj );
119 ASSERT( XlateGDI );
120
121 if(SourcePalType == PAL_INDEXED)
122 SourcePalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteSource);
123 if(DestPalType == PAL_INDEXED)
124 DestPalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteDest);
125
126 XlateObj->iSrcType = SourcePalType;
127 XlateObj->iDstType = DestPalType;
128
129 // Store handles of palettes in internal Xlate GDI object (or NULLs)
130 XlateGDI->DestPal = PaletteDest;
131 XlateGDI->SourcePal = PaletteSource;
132
133 XlateObj->flXlate = 0;
134
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)) )
139 {
140 XlateObj->flXlate |= XO_TRIVIAL;
141 return XlateObj;
142 }
143
144 // Prepare the translation table
145 if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) )
146 {
147 XlateObj->flXlate |= XO_TABLE;
148 if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED))
149 {
150 if(SourcePalGDI->NumColors > DestPalGDI->NumColors)
151 {
152 IndexedColors = SourcePalGDI->NumColors;
153 } else
154 IndexedColors = DestPalGDI->NumColors;
155 }
156 else if (SourcePalType == PAL_INDEXED) { IndexedColors = SourcePalGDI->NumColors; }
157 else if (DestPalType == PAL_INDEXED) { IndexedColors = DestPalGDI->NumColors; }
158
159 XlateGDI->translationTable = EngAllocMem(FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, 0);
160 }
161
162 // Source palette is indexed
163 if(XlateObj->iSrcType == PAL_INDEXED)
164 {
165 if(XlateObj->iDstType == PAL_INDEXED)
166 {
167 // Converting from indexed to indexed
168 IndexedToIndexedTranslationTable(XlateGDI->translationTable, DestPalGDI, SourcePalGDI);
169 } else
170 if(XlateObj->iDstType == PAL_RGB)
171 {
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
174
175 // Converting from indexed to RGB
176
177 XLATEOBJ_cGetPalette(XlateObj, XO_SRCPALETTE,
178 SourcePalGDI->NumColors,
179 XlateGDI->translationTable);
180 }
181
182 XlateObj->pulXlate = XlateGDI->translationTable;
183 }
184
185 // Source palette is RGB
186 if(XlateObj->iSrcType == PAL_RGB)
187 {
188 if(XlateObj->iDstType == PAL_INDEXED)
189 {
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
192
193 // Converting from RGB to indexed
194 XLATEOBJ_cGetPalette(XlateObj, XO_DESTPALETTE, DestPalGDI->NumColors, XlateGDI->translationTable);
195 }
196 }
197
198 // FIXME: Add support for XO_TO_MONO
199 return XlateObj;
200 }
201
202 VOID STDCALL
203 EngDeleteXlate(XLATEOBJ *XlateObj)
204 {
205 HPALETTE HXlate = (HPALETTE)AccessHandleFromUserObject(XlateObj);
206 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObject((ULONG)HXlate);
207
208 if(XlateGDI->translationTable!=NULL)
209 {
210 EngFreeMem(XlateGDI->translationTable);
211 }
212
213 FreeGDIHandle((ULONG)HXlate);
214 }
215
216 ULONG * STDCALL
217 XLATEOBJ_piVector(XLATEOBJ *XlateObj)
218 {
219 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
220
221 if(XlateObj->iSrcType == PAL_INDEXED)
222 {
223 return XlateGDI->translationTable;
224 }
225
226 return NULL;
227 }
228
229 ULONG STDCALL
230 XLATEOBJ_iXlate(XLATEOBJ *XlateObj,
231 ULONG Color)
232 {
233 PALGDI *PalGDI;
234 XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
235
236 if(XlateObj->flXlate & XO_TRIVIAL)
237 {
238 return Color;
239 } else
240 if(XlateObj->iSrcType == PAL_RGB)
241 {
242 // FIXME: should we cache colors used often?
243 // FIXME: won't work if destination isn't indexed
244
245 // Extract the destination palette
246 PalGDI = (PALGDI*)AccessInternalObject((ULONG)XlateGDI->DestPal);
247
248 // Return closest match for the given RGB color
249 return ClosestColorMatch(Color, PalGDI->IndexedColors, PalGDI->NumColors);
250 } else
251 if(XlateObj->iSrcType == PAL_INDEXED)
252 {
253 return XlateGDI->translationTable[Color];
254 }
255
256 return 0;
257 }
258
259 ULONG STDCALL
260 XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj,
261 ULONG PalOutType,
262 ULONG cPal,
263 ULONG *OutPal)
264 {
265 ULONG i;
266 HPALETTE HPal;
267 XLATEGDI *XlateGDI;
268 PALGDI *PalGDI;
269
270 XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj);
271
272 if(PalOutType == XO_SRCPALETTE)
273 {
274 HPal = XlateGDI->SourcePal;
275 } else
276 if(PalOutType == XO_DESTPALETTE)
277 {
278 HPal = XlateGDI->DestPal;
279 }
280
281 PalGDI = (PALGDI*)AccessInternalObject((ULONG)HPal);
282 RtlCopyMemory(OutPal, PalGDI->IndexedColors, sizeof(ULONG)*cPal);
283
284 return i;
285 }