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