[WIN32K]
[reactos.git] / subsystems / win32 / win32k / 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 /** Internal functions ********************************************************/
16
17 VOID
18 NTAPI
19 EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
20 {
21 ASSERT(pebo);
22 ASSERT(pbrush);
23 ASSERT(pdc);
24
25 pebo->BrushObject.flColorType = 0;
26 pebo->BrushObject.pvRbrush = NULL;
27 pebo->pbrush = pbrush;
28 pebo->pengbrush = NULL;
29 pebo->flattrs = pbrush->flAttrs;
30
31 /* Initialize 1 bpp fore and back colors */
32 pebo->crCurrentBack = pdc->pdcattr->crBackgroundClr;
33 pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
34
35 pebo->psurfTrg = pdc->dclevel.pSurface;
36 ASSERT(pebo->psurfTrg);
37
38 if (pebo->psurfTrg->hDIBPalette)
39 {
40 pebo->ppalSurf = PALETTE_ShareLockPalette(pebo->psurfTrg->hDIBPalette);
41 }
42 else if (pebo->psurfTrg->ppal)
43 {
44 pebo->ppalSurf = pebo->psurfTrg->ppal;
45 GDIOBJ_IncrementShareCount(&pebo->ppalSurf->BaseObject);
46 }
47 else
48 pebo->ppalSurf = PALETTE_ShareLockPalette(pdc->ppdev->devinfo.hpalDefault);
49
50 if (!pebo->ppalSurf)
51 pebo->ppalSurf = &gpalRGB;
52
53 if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
54 {
55 /* NULL brushes don't need a color */
56 pebo->BrushObject.iSolidColor = 0;
57 }
58 else if (pbrush->flAttrs & GDIBRUSH_IS_SOLID)
59 {
60 /* Set the RGB color */
61 EBRUSHOBJ_vSetSolidBrushColor(pebo, pbrush->BrushAttr.lbColor);
62 }
63 else
64 {
65 /* This is a pattern brush that needs realization */
66 pebo->BrushObject.iSolidColor = 0xFFFFFFFF;
67
68 /* Use foreground color of hatch brushes */
69 if (pbrush->flAttrs & GDIBRUSH_IS_HATCH)
70 pebo->crCurrentText = pbrush->BrushAttr.lbColor;
71 }
72 }
73
74 VOID
75 FASTCALL
76 EBRUSHOBJ_vSetSolidBrushColor(EBRUSHOBJ *pebo, COLORREF crColor)
77 {
78 ULONG iSolidColor;
79 EXLATEOBJ exlo;
80
81 /* Never use with non-solid brushes */
82 ASSERT(pebo->flattrs & GDIBRUSH_IS_SOLID);
83
84 /* Set the RGB color */
85 pebo->crRealize = crColor;
86 pebo->ulRGBColor = crColor;
87
88 /* Initialize an XLATEOBJ RGB -> surface */
89 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, pebo->ppalSurf, 0, 0, 0);
90
91 /* Translate the brush color to the target format */
92 iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
93 pebo->BrushObject.iSolidColor = iSolidColor;
94
95 /* Clean up the XLATEOBJ */
96 EXLATEOBJ_vCleanup(&exlo);
97 }
98
99 VOID
100 NTAPI
101 EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
102 {
103 /* Check if there's a GDI realisation */
104 if (pebo->pengbrush)
105 {
106 EngDeleteSurface(pebo->pengbrush);
107 pebo->pengbrush = NULL;
108 }
109
110 /* Check if there's a driver's realisation */
111 if (pebo->BrushObject.pvRbrush)
112 {
113 /* Free allocated driver memory */
114 EngFreeMem(pebo->BrushObject.pvRbrush);
115 pebo->BrushObject.pvRbrush = NULL;
116 }
117
118 if (pebo->ppalSurf != &gpalRGB)
119 PALETTE_ShareUnlockPalette(pebo->ppalSurf);
120 }
121
122 VOID
123 NTAPI
124 EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
125 {
126 /* Cleanup the brush */
127 EBRUSHOBJ_vCleanup(pebo);
128
129 /* Reinitialize */
130 EBRUSHOBJ_vInit(pebo, pbrush, pdc);
131 }
132
133 /**
134 * This function is not exported, because it makes no sense for
135 * The driver to punt back to this function */
136 BOOL
137 APIENTRY
138 EngRealizeBrush(
139 BRUSHOBJ *pbo,
140 SURFOBJ *psoDst,
141 SURFOBJ *psoPattern,
142 SURFOBJ *psoMask,
143 XLATEOBJ *pxlo,
144 ULONG iHatch)
145 {
146 EBRUSHOBJ *pebo;
147 HBITMAP hbmpRealize;
148 SURFOBJ *psoRealize;
149 POINTL ptlSrc = {0, 0};
150 RECTL rclDest;
151 ULONG lWidth;
152
153 /* Calculate width in bytes of the realized brush */
154 lWidth = DIB_GetDIBWidthBytes(psoPattern->sizlBitmap.cx,
155 BitsPerFormat(psoDst->iBitmapFormat));
156
157 /* Allocate a bitmap */
158 hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap,
159 lWidth,
160 psoDst->iBitmapFormat,
161 BMF_NOZEROINIT,
162 NULL);
163 if (!hbmpRealize)
164 {
165 return FALSE;
166 }
167
168 /* Lock the bitmap */
169 psoRealize = EngLockSurface(hbmpRealize);
170 if (!psoRealize)
171 {
172 EngDeleteSurface(hbmpRealize);
173 return FALSE;
174 }
175
176 /* Copy the bits to the new format bitmap */
177 rclDest.left = rclDest.top = 0;
178 rclDest.right = psoPattern->sizlBitmap.cx;
179 rclDest.bottom = psoPattern->sizlBitmap.cy;
180 EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc);
181
182 /* Unlock the bitmap again */
183 EngUnlockSurface(psoRealize);
184
185 pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
186 pebo->pengbrush = (PVOID)hbmpRealize;
187
188 return TRUE;
189 }
190
191 BOOL
192 NTAPI
193 EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver)
194 {
195 BOOL bResult;
196 PFN_DrvRealizeBrush pfnRealzizeBrush = NULL;
197 PSURFACE psurfPattern, psurfMask;
198 PPDEVOBJ ppdev = NULL;
199 EXLATEOBJ exlo;
200
201 // FIXME: all EBRUSHOBJs need a surface, see EBRUSHOBJ_vInit
202 if (!pebo->psurfTrg)
203 {
204 DPRINT1("Pattern brush has no target surface!\n");
205 return FALSE;
206 }
207
208 ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
209
210 // FIXME: all SURFACEs need a PDEV
211 if (ppdev && bCallDriver)
212 pfnRealzizeBrush = ppdev->DriverFunctions.RealizeBrush;
213
214 if (!pfnRealzizeBrush)
215 pfnRealzizeBrush = EngRealizeBrush;
216
217 psurfPattern = SURFACE_ShareLockSurface(pebo->pbrush->hbmPattern);
218 ASSERT(psurfPattern);
219
220 /* FIXME: implement mask */
221 psurfMask = NULL;
222
223 /* Initialize XLATEOBJ for the brush */
224 EXLATEOBJ_vInitBrushXlate(&exlo,
225 pebo->pbrush,
226 pebo->psurfTrg,
227 pebo->crCurrentText,
228 pebo->crCurrentBack);
229
230 /* Create the realization */
231 bResult = pfnRealzizeBrush(&pebo->BrushObject,
232 &pebo->psurfTrg->SurfObj,
233 &psurfPattern->SurfObj,
234 psurfMask ? &psurfMask->SurfObj : NULL,
235 &exlo.xlo,
236 -1); // FIXME: what about hatch brushes?
237
238 /* Cleanup the XLATEOBJ */
239 EXLATEOBJ_vCleanup(&exlo);
240
241 /* Unlock surfaces */
242 if (psurfPattern)
243 SURFACE_ShareUnlockSurface(psurfPattern);
244 if (psurfMask)
245 SURFACE_ShareUnlockSurface(psurfMask);
246
247 return bResult;
248 }
249
250 PVOID
251 NTAPI
252 EBRUSHOBJ_pvGetEngBrush(EBRUSHOBJ *pebo)
253 {
254 BOOL bResult;
255
256 if (!pebo->pengbrush)
257 {
258 bResult = EBRUSHOBJ_bRealizeBrush(pebo, FALSE);
259 if (!bResult)
260 {
261 if (pebo->pengbrush)
262 EngDeleteSurface(pebo->pengbrush);
263 pebo->pengbrush = NULL;
264 }
265 }
266
267 return pebo->pengbrush;
268 }
269
270
271 /** Exported DDI functions ****************************************************/
272
273 /*
274 * @implemented
275 */
276 PVOID APIENTRY
277 BRUSHOBJ_pvAllocRbrush(
278 IN BRUSHOBJ *pbo,
279 IN ULONG cj)
280 {
281 pbo->pvRbrush = EngAllocMem(0, cj, 'rbdG');
282 return pbo->pvRbrush;
283 }
284
285 /*
286 * @implemented
287 */
288 PVOID APIENTRY
289 BRUSHOBJ_pvGetRbrush(
290 IN BRUSHOBJ *pbo)
291 {
292 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
293 BOOL bResult;
294
295 if (!pbo->pvRbrush)
296 {
297 bResult = EBRUSHOBJ_bRealizeBrush(pebo, TRUE);
298 if (!bResult)
299 {
300 if (pbo->pvRbrush)
301 {
302 EngFreeMem(pbo->pvRbrush);
303 pbo->pvRbrush = NULL;
304 }
305 }
306 }
307
308 return pbo->pvRbrush;
309 }
310
311 /*
312 * @implemented
313 */
314 ULONG APIENTRY
315 BRUSHOBJ_ulGetBrushColor(
316 IN BRUSHOBJ *pbo)
317 {
318 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
319 return pebo->ulRGBColor;
320 }
321
322 /* EOF */