1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS Win32k subsystem
4c2c66affSColin Finck * PURPOSE: GDI Color Translation Functions
5c2c66affSColin Finck * FILE: win32ss/gdi/eng/xlateobj.c
6c2c66affSColin Finck * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include <win32k.h>
10c2c66affSColin Finck
11c2c66affSColin Finck #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck
14c2c66affSColin Finck _Post_satisfies_(return==iColor)
15c2c66affSColin Finck _Function_class_(FN_XLATE)
16c2c66affSColin Finck ULONG
17c2c66affSColin Finck FASTCALL
18c2c66affSColin Finck EXLATEOBJ_iXlateTrivial(
19c2c66affSColin Finck _In_ PEXLATEOBJ pexlo,
20c2c66affSColin Finck _In_ ULONG iColor);
21c2c66affSColin Finck
22c2c66affSColin Finck /** Globals *******************************************************************/
23c2c66affSColin Finck
24c2c66affSColin Finck EXLATEOBJ gexloTrivial = {{0, XO_TRIVIAL, 0, 0, 0, 0}, EXLATEOBJ_iXlateTrivial};
25c2c66affSColin Finck
26c2c66affSColin Finck static ULONG giUniqueXlate = 0;
27c2c66affSColin Finck
28c2c66affSColin Finck static const BYTE gajXlate5to8[32] =
29c2c66affSColin Finck { 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99,107,115,123,
30c2c66affSColin Finck 132,140,148,156,165,173,181,189,197,206,214,222,231,239,247,255};
31c2c66affSColin Finck
32c2c66affSColin Finck static const BYTE gajXlate6to8[64] =
33c2c66affSColin Finck { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 52, 57, 61,
34c2c66affSColin Finck 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125,
35c2c66affSColin Finck 130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,
36c2c66affSColin Finck 194,198,202,207,210,215,219,223,227,231,235,239,243,247,251,255};
37c2c66affSColin Finck
38c2c66affSColin Finck
39c2c66affSColin Finck /** iXlate functions **********************************************************/
40c2c66affSColin Finck
41c2c66affSColin Finck _Post_satisfies_(return==iColor)
_Function_class_(FN_XLATE)42c2c66affSColin Finck _Function_class_(FN_XLATE)
43c2c66affSColin Finck ULONG
44c2c66affSColin Finck FASTCALL
45c2c66affSColin Finck EXLATEOBJ_iXlateTrivial(
46c2c66affSColin Finck _In_ PEXLATEOBJ pexlo,
47c2c66affSColin Finck _In_ ULONG iColor)
48c2c66affSColin Finck {
49c2c66affSColin Finck return iColor;
50c2c66affSColin Finck }
51c2c66affSColin Finck
_Function_class_(FN_XLATE)52c2c66affSColin Finck _Function_class_(FN_XLATE)
53c2c66affSColin Finck ULONG
54c2c66affSColin Finck FASTCALL
55c2c66affSColin Finck EXLATEOBJ_iXlateToMono(_In_ PEXLATEOBJ pexlo, ULONG iColor)
56c2c66affSColin Finck {
57c2c66affSColin Finck return (iColor == pexlo->xlo.pulXlate[0]);
58c2c66affSColin Finck }
59c2c66affSColin Finck
_Function_class_(FN_XLATE)60c2c66affSColin Finck _Function_class_(FN_XLATE)
61c2c66affSColin Finck ULONG
62c2c66affSColin Finck FASTCALL
63c2c66affSColin Finck EXLATEOBJ_iXlateTable(PEXLATEOBJ pexlo, ULONG iColor)
64c2c66affSColin Finck {
65c2c66affSColin Finck if (iColor >= pexlo->xlo.cEntries) return 0;
66c2c66affSColin Finck return pexlo->xlo.pulXlate[iColor];
67c2c66affSColin Finck }
68c2c66affSColin Finck
_Function_class_(FN_XLATE)69c2c66affSColin Finck _Function_class_(FN_XLATE)
70c2c66affSColin Finck ULONG
71c2c66affSColin Finck FASTCALL
72c2c66affSColin Finck EXLATEOBJ_iXlateRGBtoBGR(PEXLATEOBJ pxlo, ULONG iColor)
73c2c66affSColin Finck {
74c2c66affSColin Finck ULONG iNewColor;
75c2c66affSColin Finck
76c2c66affSColin Finck /* Copy green */
77c2c66affSColin Finck iNewColor = iColor & 0xff00ff00;
78c2c66affSColin Finck
79c2c66affSColin Finck /* Mask red and blue */
80c2c66affSColin Finck iColor &= 0x00ff00ff;
81c2c66affSColin Finck
82c2c66affSColin Finck /* Shift and copy red and blue */
83c2c66affSColin Finck iNewColor |= iColor >> 16;
84c2c66affSColin Finck iNewColor |= iColor << 16;
85c2c66affSColin Finck
86c2c66affSColin Finck return iNewColor;
87c2c66affSColin Finck }
88c2c66affSColin Finck
_Function_class_(FN_XLATE)89c2c66affSColin Finck _Function_class_(FN_XLATE)
90c2c66affSColin Finck ULONG
91c2c66affSColin Finck FASTCALL
92c2c66affSColin Finck EXLATEOBJ_iXlateRGBto555(PEXLATEOBJ pxlo, ULONG iColor)
93c2c66affSColin Finck {
94c2c66affSColin Finck ULONG iNewColor;
95c2c66affSColin Finck
96c2c66affSColin Finck /* Copy red */
97c2c66affSColin Finck iColor <<= 7;
98c2c66affSColin Finck iNewColor = iColor & 0x7C00;
99c2c66affSColin Finck
100c2c66affSColin Finck /* Copy green */
101c2c66affSColin Finck iColor >>= 13;
102c2c66affSColin Finck iNewColor |= iColor & 0x3E0;
103c2c66affSColin Finck
104c2c66affSColin Finck /* Copy blue */
105c2c66affSColin Finck iColor >>= 13;
106c2c66affSColin Finck iNewColor |= iColor & 0x1F;
107c2c66affSColin Finck
108c2c66affSColin Finck return iNewColor;
109c2c66affSColin Finck }
110c2c66affSColin Finck
_Function_class_(FN_XLATE)111c2c66affSColin Finck _Function_class_(FN_XLATE)
112c2c66affSColin Finck ULONG
113c2c66affSColin Finck FASTCALL
114c2c66affSColin Finck EXLATEOBJ_iXlateBGRto555(PEXLATEOBJ pxlo, ULONG iColor)
115c2c66affSColin Finck {
116c2c66affSColin Finck ULONG iNewColor;
117c2c66affSColin Finck
118c2c66affSColin Finck /* Copy blue */
119c2c66affSColin Finck iColor >>= 3;
120c2c66affSColin Finck iNewColor = iColor & 0x1f;
121c2c66affSColin Finck
122c2c66affSColin Finck /* Copy green */
123c2c66affSColin Finck iColor >>= 3;
124c2c66affSColin Finck iNewColor |= (iColor & 0x3E0);
125c2c66affSColin Finck
126c2c66affSColin Finck /* Copy red */
127c2c66affSColin Finck iColor >>= 3;
128c2c66affSColin Finck iNewColor |= (iColor & 0x7C00);
129c2c66affSColin Finck
130c2c66affSColin Finck return iNewColor;
131c2c66affSColin Finck }
132c2c66affSColin Finck
_Function_class_(FN_XLATE)133c2c66affSColin Finck _Function_class_(FN_XLATE)
134c2c66affSColin Finck ULONG
135c2c66affSColin Finck FASTCALL
136c2c66affSColin Finck EXLATEOBJ_iXlateRGBto565(PEXLATEOBJ pxlo, ULONG iColor)
137c2c66affSColin Finck {
138c2c66affSColin Finck ULONG iNewColor;
139c2c66affSColin Finck
140c2c66affSColin Finck /* Copy red */
141c2c66affSColin Finck iColor <<= 8;
142c2c66affSColin Finck iNewColor = iColor & 0xF800;
143c2c66affSColin Finck
144c2c66affSColin Finck /* Copy green */
145c2c66affSColin Finck iColor >>= 13;
146c2c66affSColin Finck iNewColor |= iColor & 0x7E0;
147c2c66affSColin Finck
148c2c66affSColin Finck /* Copy green */
149c2c66affSColin Finck iColor >>= 14;
150c2c66affSColin Finck iNewColor |= iColor & 0x1F;
151c2c66affSColin Finck
152c2c66affSColin Finck return iNewColor;
153c2c66affSColin Finck }
154c2c66affSColin Finck
_Function_class_(FN_XLATE)155c2c66affSColin Finck _Function_class_(FN_XLATE)
156c2c66affSColin Finck ULONG
157c2c66affSColin Finck FASTCALL
158c2c66affSColin Finck EXLATEOBJ_iXlateBGRto565(PEXLATEOBJ pxlo, ULONG iColor)
159c2c66affSColin Finck {
160c2c66affSColin Finck ULONG iNewColor;
161c2c66affSColin Finck
162c2c66affSColin Finck /* Copy blue */
163c2c66affSColin Finck iColor >>= 3;
164c2c66affSColin Finck iNewColor = iColor & 0x1f;
165c2c66affSColin Finck
166c2c66affSColin Finck /* Copy green */
167c2c66affSColin Finck iColor >>= 2;
168c2c66affSColin Finck iNewColor |= (iColor & 0x7E0);
169c2c66affSColin Finck
170c2c66affSColin Finck /* Copy red */
171c2c66affSColin Finck iColor >>= 3;
172c2c66affSColin Finck iNewColor |= (iColor & 0xF800);
173c2c66affSColin Finck
174c2c66affSColin Finck return iNewColor;
175c2c66affSColin Finck }
176c2c66affSColin Finck
_Function_class_(FN_XLATE)177c2c66affSColin Finck _Function_class_(FN_XLATE)
178c2c66affSColin Finck ULONG
179c2c66affSColin Finck FASTCALL
180c2c66affSColin Finck EXLATEOBJ_iXlateRGBtoPal(PEXLATEOBJ pexlo, ULONG iColor)
181c2c66affSColin Finck {
182c2c66affSColin Finck return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
183c2c66affSColin Finck }
184c2c66affSColin Finck
_Function_class_(FN_XLATE)185c2c66affSColin Finck _Function_class_(FN_XLATE)
186c2c66affSColin Finck ULONG
187c2c66affSColin Finck FASTCALL
188c2c66affSColin Finck EXLATEOBJ_iXlate555toRGB(PEXLATEOBJ pxlo, ULONG iColor)
189c2c66affSColin Finck {
190c2c66affSColin Finck ULONG iNewColor;
191c2c66affSColin Finck
192c2c66affSColin Finck /* Copy blue */
193c2c66affSColin Finck iNewColor = gajXlate5to8[iColor & 0x1F] << 16;
194c2c66affSColin Finck
195c2c66affSColin Finck /* Copy green */
196c2c66affSColin Finck iColor >>= 5;
197c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F] << 8;
198c2c66affSColin Finck
199c2c66affSColin Finck /* Copy red */
200c2c66affSColin Finck iColor >>= 5;
201c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F];
202c2c66affSColin Finck
203c2c66affSColin Finck return iNewColor;
204c2c66affSColin Finck }
205c2c66affSColin Finck
_Function_class_(FN_XLATE)206c2c66affSColin Finck _Function_class_(FN_XLATE)
207c2c66affSColin Finck ULONG
208c2c66affSColin Finck FASTCALL
209c2c66affSColin Finck EXLATEOBJ_iXlate555toBGR(PEXLATEOBJ pxlo, ULONG iColor)
210c2c66affSColin Finck {
211c2c66affSColin Finck ULONG iNewColor;
212c2c66affSColin Finck
213c2c66affSColin Finck /* Copy blue */
214c2c66affSColin Finck iNewColor = gajXlate5to8[iColor & 0x1F];
215c2c66affSColin Finck
216c2c66affSColin Finck /* Copy green */
217c2c66affSColin Finck iColor >>= 5;
218c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F] << 8;
219c2c66affSColin Finck
220c2c66affSColin Finck /* Copy red */
221c2c66affSColin Finck iColor >>= 5;
222c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F] << 16;
223c2c66affSColin Finck
224c2c66affSColin Finck return iNewColor;
225c2c66affSColin Finck }
226c2c66affSColin Finck
_Function_class_(FN_XLATE)227c2c66affSColin Finck _Function_class_(FN_XLATE)
228c2c66affSColin Finck ULONG
229c2c66affSColin Finck FASTCALL
230c2c66affSColin Finck EXLATEOBJ_iXlate555to565(PEXLATEOBJ pxlo, ULONG iColor)
231c2c66affSColin Finck {
232c2c66affSColin Finck ULONG iNewColor;
233c2c66affSColin Finck
234c2c66affSColin Finck /* Copy blue */
235c2c66affSColin Finck iNewColor = iColor & 0x1f;
236c2c66affSColin Finck
237c2c66affSColin Finck /* Copy red and green */
238c2c66affSColin Finck iColor <<= 1;
239c2c66affSColin Finck iNewColor |= iColor & 0xFFC0;
240c2c66affSColin Finck
241c2c66affSColin Finck /* Duplicate highest green bit */
242c2c66affSColin Finck iColor >>= 5;
243c2c66affSColin Finck iNewColor |= (iColor & 0x20);
244c2c66affSColin Finck
245c2c66affSColin Finck return iNewColor;
246c2c66affSColin Finck }
247c2c66affSColin Finck
_Function_class_(FN_XLATE)248c2c66affSColin Finck _Function_class_(FN_XLATE)
249c2c66affSColin Finck ULONG
250c2c66affSColin Finck FASTCALL
251c2c66affSColin Finck EXLATEOBJ_iXlate555toPal(PEXLATEOBJ pexlo, ULONG iColor)
252c2c66affSColin Finck {
253c2c66affSColin Finck iColor = EXLATEOBJ_iXlate555toRGB(pexlo, iColor);
254c2c66affSColin Finck
255c2c66affSColin Finck return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
256c2c66affSColin Finck }
257c2c66affSColin Finck
_Function_class_(FN_XLATE)258c2c66affSColin Finck _Function_class_(FN_XLATE)
259c2c66affSColin Finck ULONG
260c2c66affSColin Finck FASTCALL
261c2c66affSColin Finck EXLATEOBJ_iXlate565to555(PEXLATEOBJ pxlo, ULONG iColor)
262c2c66affSColin Finck {
263c2c66affSColin Finck ULONG iNewColor;
264c2c66affSColin Finck
265c2c66affSColin Finck /* Copy blue */
266c2c66affSColin Finck iNewColor = iColor & 0x1f;
267c2c66affSColin Finck
268c2c66affSColin Finck /* Copy red and green */
269c2c66affSColin Finck iColor >>= 1;
270c2c66affSColin Finck iNewColor |= iColor & 0x7FE0;
271c2c66affSColin Finck
272c2c66affSColin Finck return iNewColor;
273c2c66affSColin Finck }
274c2c66affSColin Finck
_Function_class_(FN_XLATE)275c2c66affSColin Finck _Function_class_(FN_XLATE)
276c2c66affSColin Finck ULONG
277c2c66affSColin Finck FASTCALL
278c2c66affSColin Finck EXLATEOBJ_iXlate565toRGB(PEXLATEOBJ pexlo, ULONG iColor)
279c2c66affSColin Finck {
280c2c66affSColin Finck ULONG iNewColor;
281c2c66affSColin Finck
282c2c66affSColin Finck /* Copy blue */
283c2c66affSColin Finck iNewColor = gajXlate5to8[iColor & 0x1F] << 16;
284c2c66affSColin Finck
285c2c66affSColin Finck /* Copy green */
286c2c66affSColin Finck iColor >>= 5;
287c2c66affSColin Finck iNewColor |= gajXlate6to8[iColor & 0x3F] << 8;
288c2c66affSColin Finck
289c2c66affSColin Finck /* Copy red */
290c2c66affSColin Finck iColor >>= 6;
291c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F];
292c2c66affSColin Finck
293c2c66affSColin Finck return iNewColor;
294c2c66affSColin Finck }
295c2c66affSColin Finck
_Function_class_(FN_XLATE)296c2c66affSColin Finck _Function_class_(FN_XLATE)
297c2c66affSColin Finck ULONG
298c2c66affSColin Finck FASTCALL
299c2c66affSColin Finck EXLATEOBJ_iXlate565toBGR(PEXLATEOBJ pexlo, ULONG iColor)
300c2c66affSColin Finck {
301c2c66affSColin Finck ULONG iNewColor;
302c2c66affSColin Finck
303c2c66affSColin Finck /* Copy blue */
304c2c66affSColin Finck iNewColor = gajXlate5to8[iColor & 0x1F];
305c2c66affSColin Finck
306c2c66affSColin Finck /* Copy green */
307c2c66affSColin Finck iColor >>= 5;
308c2c66affSColin Finck iNewColor |= gajXlate6to8[iColor & 0x3F] << 8;
309c2c66affSColin Finck
310c2c66affSColin Finck /* Copy blue */
311c2c66affSColin Finck iColor >>= 6;
312c2c66affSColin Finck iNewColor |= gajXlate5to8[iColor & 0x1F] << 16;
313c2c66affSColin Finck
314c2c66affSColin Finck return iNewColor;
315c2c66affSColin Finck }
316c2c66affSColin Finck
_Function_class_(FN_XLATE)317c2c66affSColin Finck _Function_class_(FN_XLATE)
318c2c66affSColin Finck ULONG
319c2c66affSColin Finck FASTCALL
320c2c66affSColin Finck EXLATEOBJ_iXlate565toPal(EXLATEOBJ *pexlo, ULONG iColor)
321c2c66affSColin Finck {
322c2c66affSColin Finck iColor = EXLATEOBJ_iXlate565toRGB(pexlo, iColor);
323c2c66affSColin Finck
324c2c66affSColin Finck return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
325c2c66affSColin Finck }
326c2c66affSColin Finck
_Function_class_(FN_XLATE)327c2c66affSColin Finck _Function_class_(FN_XLATE)
328c2c66affSColin Finck ULONG
329c2c66affSColin Finck FASTCALL
330c2c66affSColin Finck EXLATEOBJ_iXlateShiftAndMask(PEXLATEOBJ pexlo, ULONG iColor)
331c2c66affSColin Finck {
332c2c66affSColin Finck ULONG iNewColor;
333c2c66affSColin Finck
334c2c66affSColin Finck iNewColor = _rotl(iColor, pexlo->ulRedShift) & pexlo->ulRedMask;
335c2c66affSColin Finck iNewColor |= _rotl(iColor, pexlo->ulGreenShift) & pexlo->ulGreenMask;
336c2c66affSColin Finck iNewColor |= _rotl(iColor, pexlo->ulBlueShift) & pexlo->ulBlueMask;
337c2c66affSColin Finck
338c2c66affSColin Finck return iNewColor;
339c2c66affSColin Finck }
340c2c66affSColin Finck
_Function_class_(FN_XLATE)341c2c66affSColin Finck _Function_class_(FN_XLATE)
342c2c66affSColin Finck ULONG
343c2c66affSColin Finck FASTCALL
344c2c66affSColin Finck EXLATEOBJ_iXlateBitfieldsToPal(PEXLATEOBJ pexlo, ULONG iColor)
345c2c66affSColin Finck {
346c2c66affSColin Finck /* Convert bitfields to RGB */
347c2c66affSColin Finck iColor = EXLATEOBJ_iXlateShiftAndMask(pexlo, iColor);
348c2c66affSColin Finck
349c2c66affSColin Finck /* Return nearest index */
350c2c66affSColin Finck return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
351c2c66affSColin Finck }
352c2c66affSColin Finck
353c2c66affSColin Finck
354c2c66affSColin Finck /** Private Functions *********************************************************/
355c2c66affSColin Finck
356c2c66affSColin Finck VOID
357c2c66affSColin Finck NTAPI
EXLATEOBJ_vInitialize(_Out_ PEXLATEOBJ pexlo,_In_opt_ PALETTE * ppalSrc,_In_opt_ PALETTE * ppalDst,_In_ COLORREF crSrcBackColor,_In_ COLORREF crDstBackColor,_In_ COLORREF crDstForeColor)358c2c66affSColin Finck EXLATEOBJ_vInitialize(
359c2c66affSColin Finck _Out_ PEXLATEOBJ pexlo,
360c2c66affSColin Finck _In_opt_ PALETTE *ppalSrc,
361c2c66affSColin Finck _In_opt_ PALETTE *ppalDst,
362c2c66affSColin Finck _In_ COLORREF crSrcBackColor,
363c2c66affSColin Finck _In_ COLORREF crDstBackColor,
364c2c66affSColin Finck _In_ COLORREF crDstForeColor)
365c2c66affSColin Finck {
366c2c66affSColin Finck ULONG cEntries;
367c2c66affSColin Finck ULONG i, ulColor;
368c2c66affSColin Finck
369c2c66affSColin Finck if (!ppalSrc) ppalSrc = &gpalRGB;
370c2c66affSColin Finck if (!ppalDst) ppalDst = &gpalRGB;
371c2c66affSColin Finck
372c2c66affSColin Finck pexlo->xlo.iUniq = InterlockedIncrement((LONG*)&giUniqueXlate);
373c2c66affSColin Finck pexlo->xlo.cEntries = 0;
374c2c66affSColin Finck pexlo->xlo.flXlate = 0;
375c2c66affSColin Finck pexlo->xlo.pulXlate = pexlo->aulXlate;
376c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
377c2c66affSColin Finck pexlo->hColorTransform = NULL;
378c2c66affSColin Finck pexlo->ppalSrc = ppalSrc;
379c2c66affSColin Finck pexlo->ppalDst = ppalDst;
380c2c66affSColin Finck pexlo->xlo.iSrcType = (USHORT)ppalSrc->flFlags;
381c2c66affSColin Finck pexlo->xlo.iDstType = (USHORT)ppalDst->flFlags;
382c2c66affSColin Finck pexlo->ppalDstDc = &gpalRGB;
383c2c66affSColin Finck
384c2c66affSColin Finck if (ppalDst == ppalSrc)
385c2c66affSColin Finck {
386c2c66affSColin Finck pexlo->xlo.flXlate |= XO_TRIVIAL;
387c2c66affSColin Finck return;
388c2c66affSColin Finck }
389c2c66affSColin Finck
390*78d20a9bSHermès Bélusca-Maïto /* Check if both of the palettes are indexed */
391c2c66affSColin Finck if (!(ppalSrc->flFlags & PAL_INDEXED) || !(ppalDst->flFlags & PAL_INDEXED))
392c2c66affSColin Finck {
393c2c66affSColin Finck /* At least one palette is not indexed, calculate shifts/masks */
394c2c66affSColin Finck ULONG aulMasksSrc[3], aulMasksDst[3];
395c2c66affSColin Finck
396c2c66affSColin Finck PALETTE_vGetBitMasks(ppalSrc, aulMasksSrc);
397c2c66affSColin Finck PALETTE_vGetBitMasks(ppalDst, aulMasksDst);
398c2c66affSColin Finck
399c2c66affSColin Finck pexlo->ulRedMask = aulMasksDst[0];
400c2c66affSColin Finck pexlo->ulGreenMask = aulMasksDst[1];
401c2c66affSColin Finck pexlo->ulBlueMask = aulMasksDst[2];
402c2c66affSColin Finck
403c2c66affSColin Finck pexlo->ulRedShift = CalculateShift(aulMasksSrc[0], aulMasksDst[0]);
404c2c66affSColin Finck pexlo->ulGreenShift = CalculateShift(aulMasksSrc[1], aulMasksDst[1]);
405c2c66affSColin Finck pexlo->ulBlueShift = CalculateShift(aulMasksSrc[2], aulMasksDst[2]);
406c2c66affSColin Finck }
407c2c66affSColin Finck
408c2c66affSColin Finck if (ppalSrc->flFlags & PAL_MONOCHROME)
409c2c66affSColin Finck {
410c2c66affSColin Finck /* This is a monochrome palette */
411c2c66affSColin Finck if (!(ppalDst->flFlags & PAL_MONOCHROME))
412c2c66affSColin Finck {
413c2c66affSColin Finck /* Mono to color, use the dest DC's fore and back color */
414c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
415c2c66affSColin Finck pexlo->xlo.flXlate |= XO_TABLE;
416c2c66affSColin Finck pexlo->xlo.cEntries = 2;
417c2c66affSColin Finck pexlo->xlo.pulXlate[0] =
418c2c66affSColin Finck PALETTE_ulGetNearestIndex(ppalDst, crDstForeColor);
419c2c66affSColin Finck pexlo->xlo.pulXlate[1] =
420c2c66affSColin Finck PALETTE_ulGetNearestIndex(ppalDst, crDstBackColor);
421c2c66affSColin Finck }
422c2c66affSColin Finck }
423c2c66affSColin Finck else if (ppalDst->flFlags & PAL_MONOCHROME)
424c2c66affSColin Finck {
425c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateToMono;
426c2c66affSColin Finck pexlo->xlo.flXlate |= XO_TO_MONO;
427c2c66affSColin Finck pexlo->xlo.cEntries = 1;
428c2c66affSColin Finck
429c2c66affSColin Finck if (ppalSrc->flFlags & PAL_INDEXED)
430c2c66affSColin Finck {
431c2c66affSColin Finck pexlo->aulXlate[0] =
432c2c66affSColin Finck PALETTE_ulGetNearestPaletteIndex(ppalSrc, crSrcBackColor);
433c2c66affSColin Finck }
434c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_RGB)
435c2c66affSColin Finck {
436c2c66affSColin Finck pexlo->aulXlate[0] = crSrcBackColor;
437c2c66affSColin Finck }
438c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_BGR)
439c2c66affSColin Finck {
440c2c66affSColin Finck pexlo->aulXlate[0] = RGB(GetBValue(crSrcBackColor),
441c2c66affSColin Finck GetGValue(crSrcBackColor),
442c2c66affSColin Finck GetRValue(crSrcBackColor));
443c2c66affSColin Finck }
444c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_BITFIELDS)
445c2c66affSColin Finck {
446c2c66affSColin Finck PALETTE_vGetBitMasks(ppalSrc, &pexlo->ulRedMask);
447c2c66affSColin Finck pexlo->ulRedShift = CalculateShift(RGB(0xFF,0,0), pexlo->ulRedMask);
448c2c66affSColin Finck pexlo->ulGreenShift = CalculateShift(RGB(0,0xFF,0), pexlo->ulGreenMask);
449c2c66affSColin Finck pexlo->ulBlueShift = CalculateShift(RGB(0,0,0xFF), pexlo->ulBlueMask);
450c2c66affSColin Finck
451c2c66affSColin Finck pexlo->aulXlate[0] = EXLATEOBJ_iXlateShiftAndMask(pexlo, crSrcBackColor);
452c2c66affSColin Finck }
453c2c66affSColin Finck }
454c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_INDEXED)
455c2c66affSColin Finck {
456c2c66affSColin Finck cEntries = ppalSrc->NumColors;
457c2c66affSColin Finck
458c2c66affSColin Finck /* Allocate buffer if needed */
459c2c66affSColin Finck if (cEntries > 6)
460c2c66affSColin Finck {
461c2c66affSColin Finck pexlo->xlo.pulXlate = EngAllocMem(0,
462c2c66affSColin Finck cEntries * sizeof(ULONG),
463c2c66affSColin Finck GDITAG_PXLATE);
464c2c66affSColin Finck if (!pexlo->xlo.pulXlate)
465c2c66affSColin Finck {
466c2c66affSColin Finck DPRINT1("Could not allocate pulXlate buffer.\n");
467c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
468c2c66affSColin Finck pexlo->xlo.flXlate = XO_TRIVIAL;
469c2c66affSColin Finck return;
470c2c66affSColin Finck }
471c2c66affSColin Finck }
472c2c66affSColin Finck
473c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
474c2c66affSColin Finck pexlo->xlo.cEntries = cEntries;
475c2c66affSColin Finck pexlo->xlo.flXlate |= XO_TABLE;
476c2c66affSColin Finck
477c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
478c2c66affSColin Finck {
479c2c66affSColin Finck ULONG cDiff = 0;
480c2c66affSColin Finck
481c2c66affSColin Finck for (i = 0; i < cEntries; i++)
482c2c66affSColin Finck {
483c2c66affSColin Finck ulColor = RGB(ppalSrc->IndexedColors[i].peRed,
484c2c66affSColin Finck ppalSrc->IndexedColors[i].peGreen,
485c2c66affSColin Finck ppalSrc->IndexedColors[i].peBlue);
486c2c66affSColin Finck
487c2c66affSColin Finck pexlo->xlo.pulXlate[i] =
488c2c66affSColin Finck PALETTE_ulGetNearestPaletteIndex(ppalDst, ulColor);
489c2c66affSColin Finck
490c2c66affSColin Finck if (pexlo->xlo.pulXlate[i] != i) cDiff++;
491c2c66affSColin Finck }
492c2c66affSColin Finck
493c2c66affSColin Finck /* Check if we have only trivial mappings */
494c2c66affSColin Finck if (cDiff == 0)
495c2c66affSColin Finck {
496c2c66affSColin Finck if (pexlo->xlo.pulXlate != pexlo->aulXlate)
497c2c66affSColin Finck {
498c2c66affSColin Finck EngFreeMem(pexlo->xlo.pulXlate);
499c2c66affSColin Finck pexlo->xlo.pulXlate = pexlo->aulXlate;
500c2c66affSColin Finck }
501c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
502c2c66affSColin Finck pexlo->xlo.flXlate = XO_TRIVIAL;
503c2c66affSColin Finck pexlo->xlo.cEntries = 0;
504c2c66affSColin Finck return;
505c2c66affSColin Finck }
506c2c66affSColin Finck }
507c2c66affSColin Finck else
508c2c66affSColin Finck {
509c2c66affSColin Finck for (i = 0; i < pexlo->xlo.cEntries; i++)
510c2c66affSColin Finck {
511c2c66affSColin Finck ulColor = RGB(ppalSrc->IndexedColors[i].peRed,
512c2c66affSColin Finck ppalSrc->IndexedColors[i].peGreen,
513c2c66affSColin Finck ppalSrc->IndexedColors[i].peBlue);
514c2c66affSColin Finck pexlo->xlo.pulXlate[i] = PALETTE_ulGetNearestBitFieldsIndex(ppalDst, ulColor);
515c2c66affSColin Finck }
516c2c66affSColin Finck }
517c2c66affSColin Finck }
518c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_RGB)
519c2c66affSColin Finck {
520c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
521c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoPal;
522c2c66affSColin Finck
523c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BGR)
524c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
525c2c66affSColin Finck
526c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_555)
527c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto555;
528c2c66affSColin Finck
529c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_565)
530c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto565;
531c2c66affSColin Finck
532c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BITFIELDS)
533c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
534c2c66affSColin Finck }
535c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_BGR)
536c2c66affSColin Finck {
537c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
538c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
539c2c66affSColin Finck
540c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB)
541c2c66affSColin Finck /* The inverse function works the same */
542c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
543c2c66affSColin Finck
544c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_555)
545c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto555;
546c2c66affSColin Finck
547c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_565)
548c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto565;
549c2c66affSColin Finck
550c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BITFIELDS)
551c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
552c2c66affSColin Finck }
553c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_RGB16_555)
554c2c66affSColin Finck {
555c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
556c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate555toPal;
557c2c66affSColin Finck
558c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB)
559c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate555toRGB;
560c2c66affSColin Finck
561c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BGR)
562c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate555toBGR;
563c2c66affSColin Finck
564c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_565)
565c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate555to565;
566c2c66affSColin Finck
567c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BITFIELDS)
568c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
569c2c66affSColin Finck }
570c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_RGB16_565)
571c2c66affSColin Finck {
572c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
573c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate565toPal;
574c2c66affSColin Finck
575c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB)
576c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate565toRGB;
577c2c66affSColin Finck
578c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BGR)
579c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate565toBGR;
580c2c66affSColin Finck
581c2c66affSColin Finck else if (ppalDst->flFlags & PAL_RGB16_555)
582c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlate565to555;
583c2c66affSColin Finck
584c2c66affSColin Finck else if (ppalDst->flFlags & PAL_BITFIELDS)
585c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
586c2c66affSColin Finck }
587c2c66affSColin Finck else if (ppalSrc->flFlags & PAL_BITFIELDS)
588c2c66affSColin Finck {
589c2c66affSColin Finck if (ppalDst->flFlags & PAL_INDEXED)
590c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
591c2c66affSColin Finck else
592c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
593c2c66affSColin Finck }
594c2c66affSColin Finck
595c2c66affSColin Finck /* Check for a trivial shift and mask operation */
596c2c66affSColin Finck if (pexlo->pfnXlate == EXLATEOBJ_iXlateShiftAndMask &&
597c2c66affSColin Finck !pexlo->ulRedShift && !pexlo->ulGreenShift && !pexlo->ulBlueShift)
598c2c66affSColin Finck {
599c2c66affSColin Finck pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
600c2c66affSColin Finck }
601c2c66affSColin Finck
602c2c66affSColin Finck /* Check for trivial xlate */
603c2c66affSColin Finck if (pexlo->pfnXlate == EXLATEOBJ_iXlateTrivial)
604c2c66affSColin Finck pexlo->xlo.flXlate = XO_TRIVIAL;
605c2c66affSColin Finck else
606c2c66affSColin Finck pexlo->xlo.flXlate &= ~XO_TRIVIAL;
607c2c66affSColin Finck }
608c2c66affSColin Finck
609c2c66affSColin Finck VOID
610c2c66affSColin Finck NTAPI
EXLATEOBJ_vInitXlateFromDCs(_Out_ EXLATEOBJ * pexlo,_In_ PDC pdcSrc,_In_ PDC pdcDst)611c2c66affSColin Finck EXLATEOBJ_vInitXlateFromDCs(
612c2c66affSColin Finck _Out_ EXLATEOBJ* pexlo,
613c2c66affSColin Finck _In_ PDC pdcSrc,
614c2c66affSColin Finck _In_ PDC pdcDst)
615c2c66affSColin Finck {
616c2c66affSColin Finck PSURFACE psurfDst, psurfSrc;
617c2c66affSColin Finck
618c2c66affSColin Finck psurfDst = pdcDst->dclevel.pSurface;
619c2c66affSColin Finck psurfSrc = pdcSrc->dclevel.pSurface;
620c2c66affSColin Finck
621c2c66affSColin Finck /* Normal initialisation. No surface means DEFAULT_BITMAP */
622c2c66affSColin Finck EXLATEOBJ_vInitialize(pexlo,
623c2c66affSColin Finck psurfSrc ? psurfSrc->ppal : gppalMono,
624c2c66affSColin Finck psurfDst ? psurfDst->ppal : gppalMono,
625c2c66affSColin Finck pdcSrc->pdcattr->crBackgroundClr,
626c2c66affSColin Finck pdcDst->pdcattr->crBackgroundClr,
627c2c66affSColin Finck pdcDst->pdcattr->crForegroundClr);
628c2c66affSColin Finck
629c2c66affSColin Finck pexlo->ppalDstDc = pdcDst->dclevel.ppal;
630c2c66affSColin Finck }
631c2c66affSColin Finck
EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo,PPALETTE ppalDst,COLORREF crBackgroundClr,COLORREF crForegroundClr)632c2c66affSColin Finck VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(
633c2c66affSColin Finck PEXLATEOBJ pexlo,
634c2c66affSColin Finck PPALETTE ppalDst,
635c2c66affSColin Finck COLORREF crBackgroundClr,
636c2c66affSColin Finck COLORREF crForegroundClr)
637c2c66affSColin Finck {
638c2c66affSColin Finck /* Normal initialisation, with mono palette as source */
639c2c66affSColin Finck EXLATEOBJ_vInitialize(pexlo,
640c2c66affSColin Finck gppalMono,
641c2c66affSColin Finck ppalDst,
642c2c66affSColin Finck 0,
643c2c66affSColin Finck crBackgroundClr,
644c2c66affSColin Finck crForegroundClr);
645c2c66affSColin Finck }
646c2c66affSColin Finck
647c2c66affSColin Finck VOID
648c2c66affSColin Finck NTAPI
EXLATEOBJ_vCleanup(_Inout_ PEXLATEOBJ pexlo)649c2c66affSColin Finck EXLATEOBJ_vCleanup(
650c2c66affSColin Finck _Inout_ PEXLATEOBJ pexlo)
651c2c66affSColin Finck {
652c2c66affSColin Finck if (pexlo->xlo.pulXlate != pexlo->aulXlate)
653c2c66affSColin Finck {
654c2c66affSColin Finck EngFreeMem(pexlo->xlo.pulXlate);
655c2c66affSColin Finck }
656c2c66affSColin Finck pexlo->xlo.pulXlate = pexlo->aulXlate;
657c2c66affSColin Finck }
658c2c66affSColin Finck
659c2c66affSColin Finck /** Public DDI Functions ******************************************************/
660c2c66affSColin Finck
661c2c66affSColin Finck #undef XLATEOBJ_iXlate
662c2c66affSColin Finck ULONG
663c2c66affSColin Finck NTAPI
XLATEOBJ_iXlate(_In_ XLATEOBJ * pxlo,_In_ ULONG iColor)664c2c66affSColin Finck XLATEOBJ_iXlate(
665c2c66affSColin Finck _In_ XLATEOBJ *pxlo,
666c2c66affSColin Finck _In_ ULONG iColor)
667c2c66affSColin Finck {
668c2c66affSColin Finck PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
669c2c66affSColin Finck
670c2c66affSColin Finck if (!pxlo)
671c2c66affSColin Finck return iColor;
672c2c66affSColin Finck
673c2c66affSColin Finck /* Call the iXlate function */
674c2c66affSColin Finck return pexlo->pfnXlate(pexlo, iColor);
675c2c66affSColin Finck }
676c2c66affSColin Finck
677c2c66affSColin Finck ULONG
678c2c66affSColin Finck NTAPI
XLATEOBJ_cGetPalette(_In_ XLATEOBJ * pxlo,_In_ ULONG iPal,_In_ ULONG cPal,_Out_cap_ (cPal)ULONG * pPalOut)679c2c66affSColin Finck XLATEOBJ_cGetPalette(
680c2c66affSColin Finck _In_ XLATEOBJ *pxlo,
681c2c66affSColin Finck _In_ ULONG iPal,
682c2c66affSColin Finck _In_ ULONG cPal,
683c2c66affSColin Finck _Out_cap_(cPal) ULONG *pPalOut)
684c2c66affSColin Finck {
685c2c66affSColin Finck PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
686c2c66affSColin Finck PPALETTE ppal;
687c2c66affSColin Finck ULONG i;
688c2c66affSColin Finck
689c2c66affSColin Finck if (!pxlo)
690c2c66affSColin Finck {
691c2c66affSColin Finck return 0;
692c2c66affSColin Finck }
693c2c66affSColin Finck
694c2c66affSColin Finck if (iPal > 5)
695c2c66affSColin Finck {
696c2c66affSColin Finck DPRINT1("XLATEOBJ_cGetPalette called with wrong iPal: %lu\n", iPal);
697c2c66affSColin Finck return 0;
698c2c66affSColin Finck }
699c2c66affSColin Finck
700c2c66affSColin Finck /* Get the requested palette */
701c2c66affSColin Finck if (iPal == XO_DESTDCPALETTE)
702c2c66affSColin Finck {
703c2c66affSColin Finck ppal = pexlo->ppalDstDc;
704c2c66affSColin Finck }
705c2c66affSColin Finck else if (iPal == XO_SRCPALETTE || iPal == XO_SRCBITFIELDS)
706c2c66affSColin Finck {
707c2c66affSColin Finck ppal = pexlo->ppalSrc;
708c2c66affSColin Finck }
709c2c66affSColin Finck else
710c2c66affSColin Finck {
711c2c66affSColin Finck ppal = pexlo->ppalDst;
712c2c66affSColin Finck }
713c2c66affSColin Finck
714c2c66affSColin Finck /* Verify palette type match */
715c2c66affSColin Finck if (!ppal ||
716c2c66affSColin Finck ((iPal == XO_SRCPALETTE || iPal == XO_DESTPALETTE)
717c2c66affSColin Finck && !(ppal->flFlags & PAL_INDEXED)) ||
718c2c66affSColin Finck ((iPal == XO_SRCBITFIELDS || iPal == XO_DESTBITFIELDS)
719c2c66affSColin Finck && !(ppal->flFlags & PAL_BITFIELDS)))
720c2c66affSColin Finck {
721c2c66affSColin Finck return 0;
722c2c66affSColin Finck }
723c2c66affSColin Finck
724c2c66affSColin Finck if(!pPalOut)
725c2c66affSColin Finck {
726c2c66affSColin Finck return ppal->NumColors;
727c2c66affSColin Finck }
728c2c66affSColin Finck
729c2c66affSColin Finck /* Copy the values into the buffer */
730c2c66affSColin Finck if (ppal->flFlags & PAL_INDEXED)
731c2c66affSColin Finck {
732c2c66affSColin Finck cPal = min(cPal, ppal->NumColors);
733c2c66affSColin Finck for (i = 0; i < cPal; i++)
734c2c66affSColin Finck {
735c2c66affSColin Finck pPalOut[i] = RGB(ppal->IndexedColors[i].peRed,
736c2c66affSColin Finck ppal->IndexedColors[i].peGreen,
737c2c66affSColin Finck ppal->IndexedColors[i].peBlue);
738c2c66affSColin Finck }
739c2c66affSColin Finck }
740c2c66affSColin Finck else
741c2c66affSColin Finck {
742c2c66affSColin Finck // FIXME: should use the above code
743c2c66affSColin Finck pPalOut[0] = ppal->RedMask;
744c2c66affSColin Finck pPalOut[1] = ppal->GreenMask;
745c2c66affSColin Finck pPalOut[2] = ppal->BlueMask;
746c2c66affSColin Finck }
747c2c66affSColin Finck
748c2c66affSColin Finck return cPal;
749c2c66affSColin Finck }
750c2c66affSColin Finck
751c2c66affSColin Finck HANDLE
752c2c66affSColin Finck NTAPI
XLATEOBJ_hGetColorTransform(_In_ XLATEOBJ * pxlo)753c2c66affSColin Finck XLATEOBJ_hGetColorTransform(
754c2c66affSColin Finck _In_ XLATEOBJ *pxlo)
755c2c66affSColin Finck {
756c2c66affSColin Finck PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
757c2c66affSColin Finck return pexlo->hColorTransform;
758c2c66affSColin Finck }
759c2c66affSColin Finck
760c2c66affSColin Finck PULONG
761c2c66affSColin Finck NTAPI
XLATEOBJ_piVector(_In_ XLATEOBJ * pxlo)762c2c66affSColin Finck XLATEOBJ_piVector(
763c2c66affSColin Finck _In_ XLATEOBJ *pxlo)
764c2c66affSColin Finck {
765c2c66affSColin Finck if (pxlo->iSrcType == PAL_INDEXED)
766c2c66affSColin Finck {
767c2c66affSColin Finck return pxlo->pulXlate;
768c2c66affSColin Finck }
769c2c66affSColin Finck
770c2c66affSColin Finck return NULL;
771c2c66affSColin Finck }
772c2c66affSColin Finck
773c2c66affSColin Finck /* EOF */
774