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