2 * ReactOS Win32 Subsystem
4 * Copyright (C) 1998 - 2004 ReactOS Team
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.
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.
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.
24 static const USHORT HatchBrushes
[NB_HATCH_STYLES
][8] =
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 */
35 BRUSH_Cleanup(PVOID ObjectBody
)
37 PGDIBRUSHOBJ pBrush
= (PGDIBRUSHOBJ
)ObjectBody
;
38 if(pBrush
->flAttrs
& (GDIBRUSH_IS_HATCH
| GDIBRUSH_IS_BITMAP
))
40 ASSERT(pBrush
->hbmPattern
);
41 GDIOBJ_SetOwnership(pBrush
->hbmPattern
, PsGetCurrentProcess());
42 NtGdiDeleteObject(pBrush
->hbmPattern
);
49 IntGdiCreateBrushXlate(PDC Dc
, GDIBRUSHOBJ
*BrushObj
, BOOLEAN
*Failed
)
51 XLATEOBJ
*Result
= NULL
;
53 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
58 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
60 Result
= IntEngCreateXlate(0, PAL_RGB
, Dc
->w
.hPalette
, NULL
);
65 BITMAPOBJ
*Pattern
= BITMAPOBJ_LockBitmap(BrushObj
->hbmPattern
);
69 /* Special case: 1bpp pattern */
70 if (Pattern
->SurfObj
.iBitmapFormat
== BMF_1BPP
)
72 if (Dc
->w
.bitsPerPixel
!= 1)
73 Result
= IntEngCreateSrcMonoXlate(Dc
->w
.hPalette
, Dc
->w
.textColor
, Dc
->w
.backgroundColor
);
75 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_DIB
)
77 Result
= IntEngCreateXlate(0, 0, Dc
->w
.hPalette
, Pattern
->hDIBPalette
);
80 BITMAPOBJ_UnlockBitmap(Pattern
);
88 IntGdiInitBrushInstance(GDIBRUSHINST
*BrushInst
, PGDIBRUSHOBJ BrushObj
, XLATEOBJ
*XlateObj
)
92 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
93 BrushInst
->BrushObject
.iSolidColor
= 0;
94 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
95 BrushInst
->BrushObject
.iSolidColor
= XLATEOBJ_iXlate(XlateObj
, BrushObj
->BrushAttr
.lbColor
);
97 BrushInst
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
98 BrushInst
->BrushObject
.pvRbrush
= BrushObj
->ulRealization
;
99 BrushInst
->BrushObject
.flColorType
= 0;
100 BrushInst
->GdiBrushObject
= BrushObj
;
101 BrushInst
->XlateObject
= XlateObj
;
105 * @name CalculateColorTableSize
107 * Internal routine to calculate the number of color table entries.
109 * @param BitmapInfoHeader
110 * Input bitmap information header, can be any version of
111 * BITMAPINFOHEADER or BITMAPCOREHEADER.
114 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
115 * or DIB_RGB_COLORS). On successful return this value is normalized
116 * according to the bitmap info.
118 * @param ColorTableSize
119 * On successful return this variable is filled with number of
120 * entries in color table for the image with specified parameters.
123 * TRUE if the input values together form a valid image, FALSE otherwise.
127 CalculateColorTableSize(
128 CONST BITMAPINFOHEADER
*BitmapInfoHeader
,
130 UINT
*ColorTableSize
)
137 * At first get some basic parameters from the passed BitmapInfoHeader
138 * structure. It can have one of the following formats:
139 * - BITMAPCOREHEADER (the oldest one with totally different layout
141 * - BITMAPINFOHEADER (the standard and most common header)
142 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
143 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
146 if (BitmapInfoHeader
->biSize
== sizeof(BITMAPCOREHEADER
))
148 BitCount
= ((LPBITMAPCOREHEADER
)BitmapInfoHeader
)->bcBitCount
;
150 Compression
= BI_RGB
;
154 BitCount
= BitmapInfoHeader
->biBitCount
;
155 ClrUsed
= BitmapInfoHeader
->biClrUsed
;
156 Compression
= BitmapInfoHeader
->biCompression
;
162 if (*ColorSpec
== DIB_PAL_COLORS
)
163 *ColorSpec
= DIB_RGB_COLORS
;
165 if (BitCount
!= 16 && BitCount
!= 32)
169 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
170 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
171 * For BITMAPINFOHEADER the color masks are stored in the palette.
174 if (BitmapInfoHeader
->biSize
> sizeof(BITMAPINFOHEADER
))
185 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 2) : 2;
189 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
193 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
197 if (*ColorSpec
== DIB_PAL_COLORS
)
198 *ColorSpec
= DIB_RGB_COLORS
;
199 if (BitCount
!= 16 && BitCount
!= 24 && BitCount
!= 32)
201 *ColorTableSize
= ClrUsed
;
208 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
216 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
223 *ColorTableSize
= ClrUsed
;
232 IntGdiCreateDIBBrush(
233 CONST BITMAPINFO
*BitmapInfo
,
236 CONST VOID
*PackedDIB
)
239 PGDIBRUSHOBJ BrushObject
;
242 UINT PaletteEntryCount
;
243 PBITMAPOBJ BitmapObject
;
246 if (BitmapInfo
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
248 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
252 if (!CalculateColorTableSize(&BitmapInfo
->bmiHeader
, &ColorSpec
,
255 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
259 DataPtr
= (ULONG_PTR
)BitmapInfo
+ BitmapInfo
->bmiHeader
.biSize
;
260 if (ColorSpec
== DIB_RGB_COLORS
)
261 DataPtr
+= PaletteEntryCount
* sizeof(RGBQUAD
);
263 DataPtr
+= PaletteEntryCount
* sizeof(USHORT
);
265 hPattern
= NtGdiCreateBitmap(BitmapInfo
->bmiHeader
.biWidth
,
266 BitmapInfo
->bmiHeader
.biHeight
,
267 BitmapInfo
->bmiHeader
.biPlanes
,
268 BitmapInfo
->bmiHeader
.biBitCount
,
270 if (hPattern
== NULL
)
272 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
276 BitmapObject
= BITMAPOBJ_LockBitmap(hPattern
);
277 ASSERT(BitmapObject
!= NULL
);
278 BitmapObject
->hDIBPalette
= BuildDIBPalette(BitmapInfo
, &PaletteType
);
279 BITMAPOBJ_UnlockBitmap(BitmapObject
);
281 hBrush
= BRUSHOBJ_AllocBrush();
284 NtGdiDeleteObject(hPattern
);
285 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
289 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
290 ASSERT(BrushObject
!= NULL
);
292 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
| GDIBRUSH_IS_DIB
;
293 BrushObject
->hbmPattern
= hPattern
;
294 /* FIXME: Fill in the rest of fields!!! */
296 GDIOBJ_SetOwnership(hPattern
, NULL
);
298 BRUSHOBJ_UnlockBrush(BrushObject
);
304 IntGdiCreateHatchBrush(
309 PGDIBRUSHOBJ BrushObject
;
312 if (Style
< 0 || Style
>= NB_HATCH_STYLES
)
317 hPattern
= NtGdiCreateBitmap(8, 8, 1, 1, HatchBrushes
[Style
]);
318 if (hPattern
== NULL
)
320 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
324 hBrush
= BRUSHOBJ_AllocBrush();
327 NtGdiDeleteObject(hPattern
);
328 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
332 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
333 ASSERT(BrushObject
!= NULL
);
335 BrushObject
->flAttrs
|= GDIBRUSH_IS_HATCH
;
336 BrushObject
->hbmPattern
= hPattern
;
337 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
339 GDIOBJ_SetOwnership(hPattern
, NULL
);
341 BRUSHOBJ_UnlockBrush(BrushObject
);
347 IntGdiCreatePatternBrush(
351 PGDIBRUSHOBJ BrushObject
;
354 hPattern
= BITMAPOBJ_CopyBitmap(hBitmap
);
355 if (hPattern
== NULL
)
357 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
361 hBrush
= BRUSHOBJ_AllocBrush();
364 NtGdiDeleteObject(hPattern
);
365 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
369 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
370 ASSERT(BrushObject
!= NULL
);
372 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
373 BrushObject
->hbmPattern
= hPattern
;
374 /* FIXME: Fill in the rest of fields!!! */
376 GDIOBJ_SetOwnership(hPattern
, NULL
);
378 BRUSHOBJ_UnlockBrush(BrushObject
);
384 IntGdiCreateSolidBrush(
388 PGDIBRUSHOBJ BrushObject
;
390 hBrush
= BRUSHOBJ_AllocBrush();
393 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
397 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
398 ASSERT(BrushObject
!= NULL
);
400 BrushObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
401 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
402 /* FIXME: Fill in the rest of fields!!! */
404 BRUSHOBJ_UnlockBrush(BrushObject
);
410 IntGdiCreateNullBrush(VOID
)
413 PGDIBRUSHOBJ BrushObject
;
415 hBrush
= BRUSHOBJ_AllocBrush();
418 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
422 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
423 ASSERT(BrushObject
!= NULL
);
424 BrushObject
->flAttrs
|= GDIBRUSH_IS_NULL
;
425 BRUSHOBJ_UnlockBrush(BrushObject
);
438 PGDIBRUSHOBJ BrushObj
)
441 BITMAPOBJ
*BitmapObj
;
442 GDIBRUSHINST BrushInst
;
448 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
449 if (BitmapObj
== NULL
)
451 SetLastWin32Error(ERROR_INVALID_HANDLE
);
455 if (!(BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
459 DestRect
.left
= XLeft
+ dc
->w
.DCOrgX
;
460 DestRect
.right
= XLeft
+ Width
+ dc
->w
.DCOrgX
;
464 DestRect
.left
= XLeft
+ Width
+ 1 + dc
->w
.DCOrgX
;
465 DestRect
.right
= XLeft
+ dc
->w
.DCOrgX
+ 1;
470 DestRect
.top
= YLeft
+ dc
->w
.DCOrgY
;
471 DestRect
.bottom
= YLeft
+ Height
+ dc
->w
.DCOrgY
;
475 DestRect
.top
= YLeft
+ Height
+ dc
->w
.DCOrgY
+ 1;
476 DestRect
.bottom
= YLeft
+ dc
->w
.DCOrgY
+ 1;
479 BrushOrigin
.x
= BrushObj
->ptOrigin
.x
+ dc
->w
.DCOrgX
;
480 BrushOrigin
.y
= BrushObj
->ptOrigin
.y
+ dc
->w
.DCOrgY
;
482 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, dc
->XlateBrush
);
493 &BrushInst
.BrushObject
,
498 BITMAPOBJ_UnlockBitmap(BitmapObj
);
513 PGDIBRUSHOBJ BrushObj
;
519 SetLastWin32Error(ERROR_INVALID_HANDLE
);
525 /* Yes, Windows really returns TRUE in this case */
529 for (r
= pRects
, i
= 0; i
< cRects
; i
++)
531 BrushObj
= BRUSHOBJ_LockBrush(r
->hBrush
);
542 BRUSHOBJ_UnlockBrush(BrushObj
);
552 /* PUBLIC FUNCTIONS ***********************************************************/
556 CONST BITMAPINFO
*BitmapInfoAndData
,
559 CONST VOID
*PackedDIB
)
561 BITMAPINFO
*SafeBitmapInfoAndData
;
565 SafeBitmapInfoAndData
= EngAllocMem(0, BitmapInfoSize
, 0);
566 if (SafeBitmapInfoAndData
== NULL
)
568 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
572 Status
= MmCopyFromCaller(SafeBitmapInfoAndData
, BitmapInfoAndData
,
574 if (!NT_SUCCESS(Status
))
576 SetLastNtError(Status
);
580 hBrush
= IntGdiCreateDIBBrush(SafeBitmapInfoAndData
, ColorSpec
,
581 BitmapInfoSize
, PackedDIB
);
583 EngFreeMem(SafeBitmapInfoAndData
);
589 NtGdiCreateHatchBrush(
593 return IntGdiCreateHatchBrush(Style
, Color
);
597 NtGdiCreatePatternBrush(
600 return IntGdiCreatePatternBrush(hBitmap
);
604 NtGdiCreateSolidBrush(COLORREF Color
)
606 return IntGdiCreateSolidBrush(Color
);
612 * The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
613 * the next brush an application selects into the specified device context.
620 NtGdiSetBrushOrgEx(HDC hDC
, INT XOrg
, INT YOrg
, LPPOINT Point
)
622 PDC dc
= DC_LockDc(hDC
);
625 SetLastWin32Error(ERROR_INVALID_HANDLE
);
633 SafePoint
.x
= dc
->w
.brushOrgX
;
634 SafePoint
.y
= dc
->w
.brushOrgY
;
635 Status
= MmCopyToCaller(Point
, &SafePoint
, sizeof(POINT
));
636 if(!NT_SUCCESS(Status
))
639 SetLastNtError(Status
);
644 dc
->w
.brushOrgX
= XOrg
;
645 dc
->w
.brushOrgY
= YOrg
;
665 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, TAG_PATBLT
);
668 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
671 Status
= MmCopyFromCaller(rb
, pRects
, sizeof(PATRECT
) * cRects
);
672 if (!NT_SUCCESS(Status
))
675 SetLastNtError(Status
);
680 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, pRects
, cRects
, Reserved
);
697 PGDIBRUSHOBJ BrushObj
;
698 DC
*dc
= DC_LockDc(hDC
);
703 SetLastWin32Error(ERROR_INVALID_HANDLE
);
709 /* Yes, Windows really returns TRUE in this case */
713 BrushObj
= BRUSHOBJ_LockBrush(dc
->w
.hBrush
);
714 if (BrushObj
== NULL
)
716 SetLastWin32Error(ERROR_INVALID_HANDLE
);
730 BRUSHOBJ_UnlockBrush(BrushObj
);