Branch setupapi
[reactos.git] / reactos / subsys / win32k / objects / brush.c
1 /*
2 * ReactOS Win32 Subsystem
3 *
4 * Copyright (C) 1998 - 2004 ReactOS Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id$
21 */
22 #include <w32k.h>
23
24 static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
25 {
26 {0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, /* HS_HORIZONTAL */
27 {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /* HS_VERTICAL */
28 {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* HS_FDIAGONAL */
29 {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* HS_BDIAGONAL */
30 {0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08}, /* HS_CROSS */
31 {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81} /* HS_DIAGCROSS */
32 };
33
34 BOOL INTERNAL_CALL
35 BRUSH_Cleanup(PVOID ObjectBody)
36 {
37 PGDIBRUSHOBJ pBrush = (PGDIBRUSHOBJ)ObjectBody;
38 if(pBrush->flAttrs & (GDIBRUSH_IS_HATCH | GDIBRUSH_IS_BITMAP))
39 {
40 ASSERT(pBrush->hbmPattern);
41 GDIOBJ_SetOwnership(pBrush->hbmPattern, PsGetCurrentProcess());
42 NtGdiDeleteObject(pBrush->hbmPattern);
43 }
44
45 return TRUE;
46 }
47
48 XLATEOBJ* FASTCALL
49 IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
50 {
51 XLATEOBJ *Result = NULL;
52
53 if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
54 {
55 Result = NULL;
56 *Failed = FALSE;
57 }
58 else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
59 {
60 Result = IntEngCreateXlate(0, PAL_RGB, Dc->w.hPalette, NULL);
61 *Failed = FALSE;
62 }
63 else
64 {
65 BITMAPOBJ *Pattern = BITMAPOBJ_LockBitmap(BrushObj->hbmPattern);
66 if (Pattern == NULL)
67 return NULL;
68
69 /* Special case: 1bpp pattern */
70 if (Pattern->SurfObj.iBitmapFormat == BMF_1BPP)
71 {
72 if (Dc->w.bitsPerPixel != 1)
73 Result = IntEngCreateSrcMonoXlate(Dc->w.hPalette, Dc->w.textColor, Dc->w.backgroundColor);
74 }
75
76 BITMAPOBJ_UnlockBitmap(BrushObj->hbmPattern);
77 *Failed = FALSE;
78 }
79
80 return Result;
81 }
82
83 VOID FASTCALL
84 IntGdiInitBrushInstance(GDIBRUSHINST *BrushInst, PGDIBRUSHOBJ BrushObj, XLATEOBJ *XlateObj)
85 {
86 ASSERT(BrushInst);
87 ASSERT(BrushObj);
88 if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
89 BrushInst->BrushObject.iSolidColor = 0;
90 else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
91 BrushInst->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, BrushObj->BrushAttr.lbColor);
92 else
93 BrushInst->BrushObject.iSolidColor = 0xFFFFFFFF;
94 BrushInst->BrushObject.pvRbrush = BrushObj->ulRealization;
95 BrushInst->BrushObject.flColorType = 0;
96 BrushInst->GdiBrushObject = BrushObj;
97 BrushInst->XlateObject = XlateObj;
98 }
99
100 HBRUSH FASTCALL
101 IntGdiCreateBrushIndirect(PLOGBRUSH LogBrush)
102 {
103 PGDIBRUSHOBJ BrushObject;
104 HBRUSH hBrush;
105 HBITMAP hPattern = 0;
106
107 switch (LogBrush->lbStyle)
108 {
109 case BS_HATCHED:
110 hPattern = NtGdiCreateBitmap(8, 8, 1, 1, HatchBrushes[LogBrush->lbHatch]);
111 if (hPattern == NULL)
112 {
113 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
114 return NULL;
115 }
116 break;
117
118 case BS_PATTERN:
119 hPattern = BITMAPOBJ_CopyBitmap((HBITMAP)LogBrush->lbHatch);
120 if (hPattern == NULL)
121 {
122 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
123 return NULL;
124 }
125 break;
126 }
127
128 hBrush = BRUSHOBJ_AllocBrush();
129 if (hBrush == NULL)
130 {
131 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
132 return NULL;
133 }
134
135 BrushObject = BRUSHOBJ_LockBrush(hBrush);
136 if(BrushObject != NULL)
137 {
138 switch (LogBrush->lbStyle)
139 {
140 case BS_NULL:
141 BrushObject->flAttrs |= GDIBRUSH_IS_NULL;
142 break;
143
144 case BS_SOLID:
145 BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
146 BrushObject->BrushAttr.lbColor = LogBrush->lbColor & 0xFFFFFF;
147 /* FIXME: Fill in the rest of fields!!! */
148 break;
149
150 case BS_HATCHED:
151 BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
152 BrushObject->hbmPattern = hPattern;
153 BrushObject->BrushAttr.lbColor = LogBrush->lbColor & 0xFFFFFF;
154 break;
155
156 case BS_PATTERN:
157 BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP;
158 BrushObject->hbmPattern = hPattern;
159 /* FIXME: Fill in the rest of fields!!! */
160 break;
161
162 default:
163 DPRINT1("Brush Style: %d\n", LogBrush->lbStyle);
164 UNIMPLEMENTED;
165 break;
166 }
167
168 BRUSHOBJ_UnlockBrush(hBrush);
169 }
170
171 if (hPattern != 0)
172 GDIOBJ_SetOwnership(hPattern, NULL);
173
174 return hBrush;
175 }
176
177 BOOL FASTCALL
178 IntPatBlt(
179 PDC dc,
180 INT XLeft,
181 INT YLeft,
182 INT Width,
183 INT Height,
184 DWORD ROP,
185 PGDIBRUSHOBJ BrushObj)
186 {
187 RECTL DestRect;
188 BITMAPOBJ *BitmapObj;
189 GDIBRUSHINST BrushInst;
190 POINTL BrushOrigin;
191 BOOL ret = TRUE;
192
193 ASSERT(BrushObj);
194
195 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
196 if (BitmapObj == NULL)
197 {
198 SetLastWin32Error(ERROR_INVALID_HANDLE);
199 return FALSE;
200 }
201
202 if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
203 {
204 if (Width > 0)
205 {
206 DestRect.left = XLeft + dc->w.DCOrgX;
207 DestRect.right = XLeft + Width + dc->w.DCOrgX;
208 }
209 else
210 {
211 DestRect.left = XLeft + Width + 1 + dc->w.DCOrgX;
212 DestRect.right = XLeft + dc->w.DCOrgX + 1;
213 }
214
215 if (Height > 0)
216 {
217 DestRect.top = YLeft + dc->w.DCOrgY;
218 DestRect.bottom = YLeft + Height + dc->w.DCOrgY;
219 }
220 else
221 {
222 DestRect.top = YLeft + Height + dc->w.DCOrgY + 1;
223 DestRect.bottom = YLeft + dc->w.DCOrgY + 1;
224 }
225
226 BrushOrigin.x = BrushObj->ptOrigin.x + dc->w.DCOrgX;
227 BrushOrigin.y = BrushObj->ptOrigin.y + dc->w.DCOrgY;
228
229 IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
230
231 ret = IntEngBitBlt(
232 BitmapObj,
233 NULL,
234 NULL,
235 dc->CombinedClip,
236 NULL,
237 &DestRect,
238 NULL,
239 NULL,
240 &BrushInst.BrushObject,
241 &BrushOrigin,
242 ROP);
243 }
244
245 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
246
247 return ret;
248 }
249
250 BOOL FASTCALL
251 IntGdiPolyPatBlt(
252 HDC hDC,
253 DWORD dwRop,
254 PPATRECT pRects,
255 int cRects,
256 ULONG Reserved)
257 {
258 int i;
259 PPATRECT r;
260 PGDIBRUSHOBJ BrushObj;
261 DC *dc;
262
263 dc = DC_LockDc(hDC);
264 if (dc == NULL)
265 {
266 SetLastWin32Error(ERROR_INVALID_HANDLE);
267 return FALSE;
268 }
269
270 for (r = pRects, i = 0; i < cRects; i++)
271 {
272 BrushObj = BRUSHOBJ_LockBrush(r->hBrush);
273 if(BrushObj != NULL)
274 {
275 IntPatBlt(
276 dc,
277 r->r.left,
278 r->r.top,
279 r->r.right,
280 r->r.bottom,
281 dwRop,
282 BrushObj);
283 BRUSHOBJ_UnlockBrush(r->hBrush);
284 }
285 r++;
286 }
287
288 DC_UnlockDc( hDC );
289
290 return TRUE;
291 }
292
293 /* PUBLIC FUNCTIONS ***********************************************************/
294
295 HBRUSH STDCALL
296 NtGdiCreateBrushIndirect(CONST LOGBRUSH *LogBrush)
297 {
298 LOGBRUSH SafeLogBrush;
299 NTSTATUS Status;
300
301 Status = MmCopyFromCaller(&SafeLogBrush, LogBrush, sizeof(LOGBRUSH));
302 if (!NT_SUCCESS(Status))
303 {
304 SetLastNtError(Status);
305 return 0;
306 }
307
308 return IntGdiCreateBrushIndirect(&SafeLogBrush);
309 }
310
311 HBRUSH STDCALL
312 NtGdiCreateDIBPatternBrush(HGLOBAL hDIBPacked, UINT ColorSpec)
313 {
314 UNIMPLEMENTED;
315 return 0;
316 }
317
318 HBRUSH STDCALL
319 NtGdiCreateDIBPatternBrushPt(CONST VOID *PackedDIB, UINT Usage)
320 {
321 UNIMPLEMENTED;
322 return 0;
323 }
324
325 HBRUSH STDCALL
326 NtGdiCreateHatchBrush(INT Style, COLORREF Color)
327 {
328 LOGBRUSH LogBrush;
329
330 if (Style < 0 || Style >= NB_HATCH_STYLES)
331 {
332 return 0;
333 }
334
335 LogBrush.lbStyle = BS_HATCHED;
336 LogBrush.lbColor = Color;
337 LogBrush.lbHatch = Style;
338
339 return IntGdiCreateBrushIndirect(&LogBrush);
340 }
341
342 HBRUSH STDCALL
343 NtGdiCreatePatternBrush(HBITMAP hBitmap)
344 {
345 LOGBRUSH LogBrush;
346
347 LogBrush.lbStyle = BS_PATTERN;
348 LogBrush.lbColor = 0;
349 LogBrush.lbHatch = (ULONG)hBitmap;
350
351 return IntGdiCreateBrushIndirect(&LogBrush);
352 }
353
354 HBRUSH STDCALL
355 NtGdiCreateSolidBrush(COLORREF Color)
356 {
357 LOGBRUSH LogBrush;
358
359 LogBrush.lbStyle = BS_SOLID;
360 LogBrush.lbColor = Color;
361 LogBrush.lbHatch = 0;
362
363 return IntGdiCreateBrushIndirect(&LogBrush);
364 }
365
366 BOOL STDCALL
367 NtGdiFixBrushOrgEx(VOID)
368 {
369 return FALSE;
370 }
371
372 /*
373 * NtGdiSetBrushOrgEx
374 *
375 * The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
376 * the next brush an application selects into the specified device context.
377 *
378 * Status
379 * @implemented
380 */
381
382 BOOL STDCALL
383 NtGdiSetBrushOrgEx(HDC hDC, INT XOrg, INT YOrg, LPPOINT Point)
384 {
385 PDC dc = DC_LockDc(hDC);
386 if (dc == NULL)
387 {
388 SetLastWin32Error(ERROR_INVALID_HANDLE);
389 return FALSE;
390 }
391
392 if (Point != NULL)
393 {
394 NTSTATUS Status;
395 POINT SafePoint;
396 SafePoint.x = dc->w.brushOrgX;
397 SafePoint.y = dc->w.brushOrgY;
398 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
399 if(!NT_SUCCESS(Status))
400 {
401 DC_UnlockDc(hDC);
402 SetLastNtError(Status);
403 return FALSE;
404 }
405 }
406
407 dc->w.brushOrgX = XOrg;
408 dc->w.brushOrgY = YOrg;
409 DC_UnlockDc(hDC);
410
411 return TRUE;
412 }
413
414 BOOL STDCALL
415 NtGdiPolyPatBlt(
416 HDC hDC,
417 DWORD dwRop,
418 PPATRECT pRects,
419 INT cRects,
420 ULONG Reserved)
421 {
422 PPATRECT rb = NULL;
423 NTSTATUS Status;
424 BOOL Ret;
425
426 if (cRects > 0)
427 {
428 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
429 if (!rb)
430 {
431 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
432 return FALSE;
433 }
434 Status = MmCopyFromCaller(rb, pRects, sizeof(PATRECT) * cRects);
435 if (!NT_SUCCESS(Status))
436 {
437 ExFreePool(rb);
438 SetLastNtError(Status);
439 return FALSE;
440 }
441 }
442
443 Ret = IntGdiPolyPatBlt(hDC, dwRop, pRects, cRects, Reserved);
444
445 if (cRects > 0)
446 ExFreePool(rb);
447
448 return Ret;
449 }
450
451 BOOL STDCALL
452 NtGdiPatBlt(
453 HDC hDC,
454 INT XLeft,
455 INT YLeft,
456 INT Width,
457 INT Height,
458 DWORD ROP)
459 {
460 PGDIBRUSHOBJ BrushObj;
461 DC *dc = DC_LockDc(hDC);
462 BOOL ret;
463
464 if (dc == NULL)
465 {
466 SetLastWin32Error(ERROR_INVALID_HANDLE);
467 return FALSE;
468 }
469
470 BrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
471 if (BrushObj == NULL)
472 {
473 SetLastWin32Error(ERROR_INVALID_HANDLE);
474 DC_UnlockDc(hDC);
475 return FALSE;
476 }
477
478 ret = IntPatBlt(
479 dc,
480 XLeft,
481 YLeft,
482 Width,
483 Height,
484 ROP,
485 BrushObj);
486
487 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
488 DC_UnlockDc(hDC);
489
490 return ret;
491 }
492
493 /* EOF */