[YAROTOWS] Reintegrate the branch. For a brighter future.
[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_IncrementShareCount(&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 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 PALETTE_ShareUnlockPalette(pebo->ppalSurf);
113 }
114
115 VOID
116 NTAPI
117 EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
118 {
119 /* Cleanup the brush */
120 EBRUSHOBJ_vCleanup(pebo);
121
122 /* Reinitialize */
123 EBRUSHOBJ_vInit(pebo, pbrush, pdc);
124 }
125
126 /**
127 * This function is not exported, because it makes no sense for
128 * The driver to punt back to this function */
129 BOOL
130 APIENTRY
131 EngRealizeBrush(
132 BRUSHOBJ *pbo,
133 SURFOBJ *psoDst,
134 SURFOBJ *psoPattern,
135 SURFOBJ *psoMask,
136 XLATEOBJ *pxlo,
137 ULONG iHatch)
138 {
139 EBRUSHOBJ *pebo;
140 HBITMAP hbmpRealize;
141 SURFOBJ *psoRealize;
142 POINTL ptlSrc = {0, 0};
143 RECTL rclDest;
144 ULONG lWidth;
145
146 /* Calculate width in bytes of the realized brush */
147 lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx,
148 BitsPerFormat(psoDst->iBitmapFormat));
149
150 /* Allocate a bitmap */
151 hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap,
152 lWidth,
153 psoDst->iBitmapFormat,
154 BMF_NOZEROINIT,
155 NULL);
156 if (!hbmpRealize)
157 {
158 return FALSE;
159 }
160
161 /* Lock the bitmap */
162 psoRealize = EngLockSurface(hbmpRealize);
163 if (!psoRealize)
164 {
165 EngDeleteSurface(hbmpRealize);
166 return FALSE;
167 }
168
169 /* Copy the bits to the new format bitmap */
170 rclDest.left = rclDest.top = 0;
171 rclDest.right = psoPattern->sizlBitmap.cx;
172 rclDest.bottom = psoPattern->sizlBitmap.cy;
173 EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc);
174
175 /* Unlock the bitmap again */
176 EngUnlockSurface(psoRealize);
177
178 pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
179 pebo->pengbrush = (PVOID)hbmpRealize;
180
181 return TRUE;
182 }
183
184 BOOL
185 NTAPI
186 EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver)
187 {
188 BOOL bResult;
189 PFN_DrvRealizeBrush pfnRealzizeBrush = NULL;
190 PSURFACE psurfPattern, psurfMask;
191 PPDEVOBJ ppdev = NULL;
192 EXLATEOBJ exlo;
193
194 /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */
195 ASSERT(pebo->psurfTrg);
196
197 ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
198
199 // FIXME: all SURFACEs need a PDEV
200 if (ppdev && bCallDriver)
201 pfnRealzizeBrush = ppdev->DriverFunctions.RealizeBrush;
202
203 if (!pfnRealzizeBrush)
204 pfnRealzizeBrush = EngRealizeBrush;
205
206 psurfPattern = SURFACE_ShareLockSurface(pebo->pbrush->hbmPattern);
207 ASSERT(psurfPattern);
208 ASSERT(psurfPattern->ppal);
209
210 /* FIXME: implement mask */
211 psurfMask = NULL;
212
213 /* Initialize XLATEOBJ for the brush */
214 EXLATEOBJ_vInitialize(&exlo,
215 psurfPattern->ppal,
216 pebo->psurfTrg->ppal,
217 0,
218 pebo->crCurrentBack,
219 pebo->crCurrentText);
220
221 /* Create the realization */
222 bResult = pfnRealzizeBrush(&pebo->BrushObject,
223 &pebo->psurfTrg->SurfObj,
224 &psurfPattern->SurfObj,
225 psurfMask ? &psurfMask->SurfObj : NULL,
226 &exlo.xlo,
227 -1); // FIXME: what about hatch brushes?
228
229 /* Cleanup the XLATEOBJ */
230 EXLATEOBJ_vCleanup(&exlo);
231
232 /* Unlock surfaces */
233 if (psurfPattern)
234 SURFACE_ShareUnlockSurface(psurfPattern);
235 if (psurfMask)
236 SURFACE_ShareUnlockSurface(psurfMask);
237
238 return bResult;
239 }
240
241 PVOID
242 NTAPI
243 EBRUSHOBJ_pvGetEngBrush(EBRUSHOBJ *pebo)
244 {
245 BOOL bResult;
246
247 if (!pebo->pengbrush)
248 {
249 bResult = EBRUSHOBJ_bRealizeBrush(pebo, FALSE);
250 if (!bResult)
251 {
252 if (pebo->pengbrush)
253 EngDeleteSurface(pebo->pengbrush);
254 pebo->pengbrush = NULL;
255 }
256 }
257
258 return pebo->pengbrush;
259 }
260
261
262 /** Exported DDI functions ****************************************************/
263
264 /*
265 * @implemented
266 */
267 PVOID APIENTRY
268 BRUSHOBJ_pvAllocRbrush(
269 IN BRUSHOBJ *pbo,
270 IN ULONG cj)
271 {
272 pbo->pvRbrush = EngAllocMem(0, cj, GDITAG_RBRUSH);
273 return pbo->pvRbrush;
274 }
275
276 /*
277 * @implemented
278 */
279 PVOID APIENTRY
280 BRUSHOBJ_pvGetRbrush(
281 IN BRUSHOBJ *pbo)
282 {
283 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
284 BOOL bResult;
285
286 if (!pbo->pvRbrush)
287 {
288 bResult = EBRUSHOBJ_bRealizeBrush(pebo, TRUE);
289 if (!bResult)
290 {
291 if (pbo->pvRbrush)
292 {
293 EngFreeMem(pbo->pvRbrush);
294 pbo->pvRbrush = NULL;
295 }
296 }
297 }
298
299 return pbo->pvRbrush;
300 }
301
302 /*
303 * @implemented
304 */
305 ULONG APIENTRY
306 BRUSHOBJ_ulGetBrushColor(
307 IN BRUSHOBJ *pbo)
308 {
309 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
310 return pebo->ulRGBColor;
311 }
312
313 /* EOF */