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