[WIN32K]
[reactos.git] / reactos / win32ss / gdi / eng / engbrush.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Brush Functions
5 * FILE: subsystem/win32/win32k/eng/engbrush.c
6 * PROGRAMER: Jason Filby
7 * Timo Kreuzer
8 */
9
10 #include <win32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 static const ULONG gaulHatchBrushes[HS_DDI_MAX][8] =
16 {
17 {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, /* HS_HORIZONTAL */
18 {0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7}, /* HS_VERTICAL */
19 {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}, /* HS_FDIAGONAL */
20 {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE}, /* HS_BDIAGONAL */
21 {0xF7, 0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7}, /* HS_CROSS */
22 {0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E} /* HS_DIAGCROSS */
23 };
24
25 HSURF gahsurfHatch[HS_DDI_MAX];
26
27 /** Internal functions ********************************************************/
28
29 INIT_FUNCTION
30 NTSTATUS
31 NTAPI
32 InitBrushImpl(VOID)
33 {
34 ULONG i;
35 SIZEL sizl = {8, 8};
36
37 /* Loop all hatch styles */
38 for (i = 0; i < HS_DDI_MAX; i++)
39 {
40 /* Create a default hatch bitmap */
41 gahsurfHatch[i] = (HSURF)EngCreateBitmap(sizl,
42 0,
43 BMF_1BPP,
44 0,
45 (PVOID)gaulHatchBrushes[i]);
46 }
47
48 return STATUS_SUCCESS;
49 }
50
51 VOID
52 NTAPI
53 EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
54 {
55 ASSERT(pebo);
56 ASSERT(pbrush);
57 ASSERT(pdc);
58
59 pebo->BrushObject.flColorType = 0;
60 pebo->BrushObject.pvRbrush = NULL;
61 pebo->pbrush = pbrush;
62 pebo->pengbrush = NULL;
63 pebo->flattrs = pbrush->flAttrs;
64
65 /* Initialize 1 bpp fore and back colors */
66 pebo->crCurrentBack = pdc->pdcattr->crBackgroundClr;
67 pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
68
69 pebo->psurfTrg = pdc->dclevel.pSurface;
70 ASSERT(pebo->psurfTrg);
71 ASSERT(pebo->psurfTrg->ppal);
72
73 pebo->ppalSurf = pebo->psurfTrg->ppal;
74 GDIOBJ_vReferenceObjectByPointer(&pebo->ppalSurf->BaseObject);
75 pebo->ppalDC = pdc->dclevel.ppal;
76 GDIOBJ_vReferenceObjectByPointer(&pebo->ppalDC->BaseObject);
77
78 if (pbrush->flAttrs & BR_IS_NULL)
79 {
80 /* NULL brushes don't need a color */
81 pebo->BrushObject.iSolidColor = 0;
82 }
83 else if (pbrush->flAttrs & BR_IS_SOLID)
84 {
85 /* Set the RGB color */
86 EBRUSHOBJ_vSetSolidRGBColor(pebo, pbrush->BrushAttr.lbColor);
87 }
88 else
89 {
90 /* This is a pattern brush that needs realization */
91 pebo->BrushObject.iSolidColor = 0xFFFFFFFF;
92
93 /* Use foreground color of hatch brushes */
94 if (pbrush->flAttrs & BR_IS_HATCH)
95 pebo->crCurrentText = pbrush->BrushAttr.lbColor;
96 }
97 }
98
99 VOID
100 FASTCALL
101 EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor)
102 {
103 ULONG iSolidColor;
104 EXLATEOBJ exlo;
105
106 /* Never use with non-solid brushes */
107 ASSERT(pebo->flattrs & BR_IS_SOLID);
108
109 /* Set the RGB color */
110 pebo->crRealize = crColor;
111 pebo->ulRGBColor = crColor;
112
113 /* Initialize an XLATEOBJ RGB -> surface */
114 EXLATEOBJ_vInitialize(&exlo,
115 &gpalRGB,
116 pebo->ppalSurf,
117 pebo->crCurrentBack,
118 0,
119 0);
120
121 /* Translate the brush color to the target format */
122 iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
123 pebo->BrushObject.iSolidColor = iSolidColor;
124
125 /* Clean up the XLATEOBJ */
126 EXLATEOBJ_vCleanup(&exlo);
127 }
128
129 VOID
130 NTAPI
131 EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
132 {
133 /* Check if there's a GDI realisation */
134 if (pebo->pengbrush)
135 {
136 /* Unlock the bitmap again */
137 SURFACE_ShareUnlockSurface(pebo->pengbrush);
138 pebo->pengbrush = NULL;
139 }
140
141 /* Check if there's a driver's realisation */
142 if (pebo->BrushObject.pvRbrush)
143 {
144 /* Free allocated driver memory */
145 EngFreeMem(pebo->BrushObject.pvRbrush);
146 pebo->BrushObject.pvRbrush = NULL;
147 }
148
149 /* Dereference the palettes */
150 PALETTE_ShareUnlockPalette(pebo->ppalSurf);
151 PALETTE_ShareUnlockPalette(pebo->ppalDC);
152 if (pebo->ppalDIB) PALETTE_ShareUnlockPalette(pebo->ppalDIB);
153 }
154
155 VOID
156 NTAPI
157 EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
158 {
159 /* Cleanup the brush */
160 EBRUSHOBJ_vCleanup(pebo);
161
162 /* Reinitialize */
163 EBRUSHOBJ_vInit(pebo, pbrush, pdc);
164 }
165
166 /**
167 * This function is not exported, because it makes no sense for
168 * The driver to punt back to this function */
169 BOOL
170 APIENTRY
171 EngRealizeBrush(
172 BRUSHOBJ *pbo,
173 SURFOBJ *psoDst,
174 SURFOBJ *psoPattern,
175 SURFOBJ *psoMask,
176 XLATEOBJ *pxlo,
177 ULONG iHatch)
178 {
179 EBRUSHOBJ *pebo;
180 HBITMAP hbmpRealize;
181 SURFOBJ *psoRealize;
182 PSURFACE psurfRealize;
183 POINTL ptlSrc = {0, 0};
184 RECTL rclDest;
185 ULONG lWidth;
186
187 /* Calculate width in bytes of the realized brush */
188 lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx,
189 BitsPerFormat(psoDst->iBitmapFormat));
190
191 /* Allocate a bitmap */
192 hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap,
193 lWidth,
194 psoDst->iBitmapFormat,
195 BMF_NOZEROINIT,
196 NULL);
197 if (!hbmpRealize)
198 {
199 return FALSE;
200 }
201
202 /* Lock the bitmap */
203 psurfRealize = SURFACE_ShareLockSurface(hbmpRealize);
204
205 /* Already delete the pattern bitmap (will be kept until dereferenced) */
206 EngDeleteSurface((HSURF)hbmpRealize);
207
208 if (!psurfRealize)
209 {
210 return FALSE;
211 }
212
213 /* Copy the bits to the new format bitmap */
214 rclDest.left = rclDest.top = 0;
215 rclDest.right = psoPattern->sizlBitmap.cx;
216 rclDest.bottom = psoPattern->sizlBitmap.cy;
217 psoRealize = &psurfRealize->SurfObj;
218 EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc);
219
220
221 pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
222 pebo->pengbrush = (PVOID)psurfRealize;
223
224 return TRUE;
225 }
226
227 static
228 PPALETTE
229 FixupDIBBrushPalette(
230 _In_ PPALETTE ppalDIB,
231 _In_ PPALETTE ppalDC)
232 {
233 PPALETTE ppalNew;
234 ULONG i, iPalIndex, crColor;
235
236 /* Allocate a new palette */
237 ppalNew = PALETTE_AllocPalette(PAL_INDEXED,
238 ppalDIB->NumColors,
239 NULL,
240 0,
241 0,
242 0);
243
244 /* Loop all colors */
245 for (i = 0; i < ppalDIB->NumColors; i++)
246 {
247 /* Get the RGB color, which is the index into the DC palette */
248 iPalIndex = PALETTE_ulGetRGBColorFromIndex(ppalDIB, i);
249
250 /* Roll over when index is too big */
251 iPalIndex %= ppalDC->NumColors;
252
253 /* Set the indexed DC color as the new color */
254 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, iPalIndex);
255 PALETTE_vSetRGBColorForIndex(ppalNew, i, crColor);
256 }
257
258 /* Return the new palette */
259 return ppalNew;
260 }
261
262 BOOL
263 NTAPI
264 EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver)
265 {
266 BOOL bResult;
267 PFN_DrvRealizeBrush pfnRealzizeBrush = NULL;
268 PSURFACE psurfPattern, psurfMask;
269 PPDEVOBJ ppdev;
270 EXLATEOBJ exlo;
271 PPALETTE ppalPattern;
272 PBRUSH pbr = pebo->pbrush;
273 HBITMAP hbmPattern;
274 ULONG iHatch;
275
276 /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */
277 ASSERT(pebo->psurfTrg);
278
279 ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
280 if (!ppdev) ppdev = gppdevPrimary;
281
282 if (bCallDriver)
283 pfnRealzizeBrush = ppdev->DriverFunctions.RealizeBrush;
284
285 if (!pfnRealzizeBrush)
286 pfnRealzizeBrush = EngRealizeBrush;
287
288 /* Check if this is a hatch brush */
289 if (pbr->flAttrs & BR_IS_HATCH)
290 {
291 /* Get the hatch brush pattern from the PDEV */
292 hbmPattern = (HBITMAP)ppdev->ahsurf[pbr->ulStyle];
293 iHatch = pbr->ulStyle;
294 }
295 else
296 {
297 /* Use the brushes pattern */
298 hbmPattern = pbr->hbmPattern;
299 iHatch = -1;
300 }
301
302 psurfPattern = SURFACE_ShareLockSurface(hbmPattern);
303 ASSERT(psurfPattern);
304 ASSERT(psurfPattern->ppal);
305
306 /* FIXME: implement mask */
307 psurfMask = NULL;
308
309 /* DIB brushes with DIB_PAL_COLORS usage need a new palette */
310 if (pbr->flAttrs & BR_IS_DIBPALCOLORS)
311 {
312 ASSERT(FALSE);
313 ppalPattern = FixupDIBBrushPalette(psurfPattern->ppal, pebo->ppalDC);
314 pebo->ppalDIB = ppalPattern;
315 }
316 else
317 {
318 /* The palette is already as it should be */
319 ppalPattern = psurfPattern->ppal;
320 }
321
322 /* Initialize XLATEOBJ for the brush */
323 EXLATEOBJ_vInitialize(&exlo,
324 ppalPattern,
325 pebo->psurfTrg->ppal,
326 0,
327 pebo->crCurrentBack,
328 pebo->crCurrentText);
329
330 /* Create the realization */
331 bResult = pfnRealzizeBrush(&pebo->BrushObject,
332 &pebo->psurfTrg->SurfObj,
333 &psurfPattern->SurfObj,
334 psurfMask ? &psurfMask->SurfObj : NULL,
335 &exlo.xlo,
336 iHatch);
337
338 /* Cleanup the XLATEOBJ */
339 EXLATEOBJ_vCleanup(&exlo);
340
341 /* Unlock surfaces */
342 if (psurfPattern)
343 SURFACE_ShareUnlockSurface(psurfPattern);
344 if (psurfMask)
345 SURFACE_ShareUnlockSurface(psurfMask);
346
347 return bResult;
348 }
349
350 PVOID
351 NTAPI
352 EBRUSHOBJ_pvGetEngBrush(EBRUSHOBJ *pebo)
353 {
354 BOOL bResult;
355
356 if (!pebo->pengbrush)
357 {
358 bResult = EBRUSHOBJ_bRealizeBrush(pebo, FALSE);
359 if (!bResult)
360 {
361 if (pebo->pengbrush)
362 EngDeleteSurface(pebo->pengbrush);
363 pebo->pengbrush = NULL;
364 }
365 }
366
367 return pebo->pengbrush;
368 }
369
370 SURFOBJ*
371 NTAPI
372 EBRUSHOBJ_psoPattern(EBRUSHOBJ *pebo)
373 {
374 PSURFACE psurfPattern;
375
376 psurfPattern = EBRUSHOBJ_pvGetEngBrush(pebo);
377
378 return psurfPattern ? &psurfPattern->SurfObj : NULL;
379 }
380
381
382 /** Exported DDI functions ****************************************************/
383
384 /*
385 * @implemented
386 */
387 PVOID APIENTRY
388 BRUSHOBJ_pvAllocRbrush(
389 IN BRUSHOBJ *pbo,
390 IN ULONG cj)
391 {
392 pbo->pvRbrush = EngAllocMem(0, cj, GDITAG_RBRUSH);
393 return pbo->pvRbrush;
394 }
395
396 /*
397 * @implemented
398 */
399 PVOID APIENTRY
400 BRUSHOBJ_pvGetRbrush(
401 IN BRUSHOBJ *pbo)
402 {
403 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
404 BOOL bResult;
405
406 if (!pbo->pvRbrush)
407 {
408 bResult = EBRUSHOBJ_bRealizeBrush(pebo, TRUE);
409 if (!bResult)
410 {
411 if (pbo->pvRbrush)
412 {
413 EngFreeMem(pbo->pvRbrush);
414 pbo->pvRbrush = NULL;
415 }
416 }
417 }
418
419 return pbo->pvRbrush;
420 }
421
422 /*
423 * @implemented
424 */
425 ULONG APIENTRY
426 BRUSHOBJ_ulGetBrushColor(
427 IN BRUSHOBJ *pbo)
428 {
429 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
430 return pebo->ulRGBColor;
431 }
432
433 /* EOF */