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.
28 static const USHORT HatchBrushes
[NB_HATCH_STYLES
][8] =
30 {0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, /* HS_HORIZONTAL */
31 {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /* HS_VERTICAL */
32 {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* HS_FDIAGONAL */
33 {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* HS_BDIAGONAL */
34 {0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08}, /* HS_CROSS */
35 {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81} /* HS_DIAGCROSS */
39 BRUSH_Cleanup(PVOID ObjectBody
)
41 PGDIBRUSHOBJ pBrush
= (PGDIBRUSHOBJ
)ObjectBody
;
42 if(pBrush
->flAttrs
& (GDIBRUSH_IS_HATCH
| GDIBRUSH_IS_BITMAP
))
44 ASSERT(pBrush
->hbmPattern
);
45 GDIOBJ_SetOwnership(pBrush
->hbmPattern
, PsGetCurrentProcess());
46 NtGdiDeleteObject(pBrush
->hbmPattern
);
53 IntGdiCreateBrushXlate(PDC Dc
, GDIBRUSHOBJ
*BrushObj
, BOOLEAN
*Failed
)
55 XLATEOBJ
*Result
= NULL
;
57 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
62 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
64 Result
= IntEngCreateXlate(0, PAL_RGB
, Dc
->w
.hPalette
, NULL
);
69 BITMAPOBJ
*Pattern
= BITMAPOBJ_LockBitmap(BrushObj
->hbmPattern
);
73 /* Special case: 1bpp pattern */
74 if (Pattern
->SurfObj
.iBitmapFormat
== BMF_1BPP
)
76 if (Dc
->w
.bitsPerPixel
!= 1)
77 Result
= IntEngCreateSrcMonoXlate(Dc
->w
.hPalette
, Dc
->w
.textColor
, Dc
->w
.backgroundColor
);
79 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_DIB
)
81 Result
= IntEngCreateXlate(0, 0, Dc
->w
.hPalette
, Pattern
->hDIBPalette
);
84 BITMAPOBJ_UnlockBitmap(Pattern
);
92 IntGdiInitBrushInstance(GDIBRUSHINST
*BrushInst
, PGDIBRUSHOBJ BrushObj
, XLATEOBJ
*XlateObj
)
96 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
97 BrushInst
->BrushObject
.iSolidColor
= 0;
98 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
99 BrushInst
->BrushObject
.iSolidColor
= XLATEOBJ_iXlate(XlateObj
, BrushObj
->BrushAttr
.lbColor
);
101 BrushInst
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
102 BrushInst
->BrushObject
.pvRbrush
= BrushObj
->ulRealization
;
103 BrushInst
->BrushObject
.flColorType
= 0;
104 BrushInst
->GdiBrushObject
= BrushObj
;
105 BrushInst
->XlateObject
= XlateObj
;
109 * @name CalculateColorTableSize
111 * Internal routine to calculate the number of color table entries.
113 * @param BitmapInfoHeader
114 * Input bitmap information header, can be any version of
115 * BITMAPINFOHEADER or BITMAPCOREHEADER.
118 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
119 * or DIB_RGB_COLORS). On successful return this value is normalized
120 * according to the bitmap info.
122 * @param ColorTableSize
123 * On successful return this variable is filled with number of
124 * entries in color table for the image with specified parameters.
127 * TRUE if the input values together form a valid image, FALSE otherwise.
131 CalculateColorTableSize(
132 CONST BITMAPINFOHEADER
*BitmapInfoHeader
,
134 UINT
*ColorTableSize
)
141 * At first get some basic parameters from the passed BitmapInfoHeader
142 * structure. It can have one of the following formats:
143 * - BITMAPCOREHEADER (the oldest one with totally different layout
145 * - BITMAPINFOHEADER (the standard and most common header)
146 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
147 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
150 if (BitmapInfoHeader
->biSize
== sizeof(BITMAPCOREHEADER
))
152 BitCount
= ((LPBITMAPCOREHEADER
)BitmapInfoHeader
)->bcBitCount
;
154 Compression
= BI_RGB
;
158 BitCount
= BitmapInfoHeader
->biBitCount
;
159 ClrUsed
= BitmapInfoHeader
->biClrUsed
;
160 Compression
= BitmapInfoHeader
->biCompression
;
166 if (*ColorSpec
== DIB_PAL_COLORS
)
167 *ColorSpec
= DIB_RGB_COLORS
;
169 if (BitCount
!= 16 && BitCount
!= 32)
173 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
174 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
175 * For BITMAPINFOHEADER the color masks are stored in the palette.
178 if (BitmapInfoHeader
->biSize
> sizeof(BITMAPINFOHEADER
))
189 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 2) : 2;
193 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
197 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
201 if (*ColorSpec
== DIB_PAL_COLORS
)
202 *ColorSpec
= DIB_RGB_COLORS
;
203 if (BitCount
!= 16 && BitCount
!= 24 && BitCount
!= 32)
205 *ColorTableSize
= ClrUsed
;
212 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
220 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
227 *ColorTableSize
= ClrUsed
;
236 IntGdiCreateDIBBrush(
237 CONST BITMAPINFO
*BitmapInfo
,
240 CONST VOID
*PackedDIB
)
243 PGDIBRUSHOBJ BrushObject
;
246 UINT PaletteEntryCount
;
247 PBITMAPOBJ BitmapObject
;
250 if (BitmapInfo
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
252 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
256 if (!CalculateColorTableSize(&BitmapInfo
->bmiHeader
, &ColorSpec
,
259 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
263 DataPtr
= (ULONG_PTR
)BitmapInfo
+ BitmapInfo
->bmiHeader
.biSize
;
264 if (ColorSpec
== DIB_RGB_COLORS
)
265 DataPtr
+= PaletteEntryCount
* sizeof(RGBQUAD
);
267 DataPtr
+= PaletteEntryCount
* sizeof(USHORT
);
269 hPattern
= NtGdiCreateBitmap(BitmapInfo
->bmiHeader
.biWidth
,
270 BitmapInfo
->bmiHeader
.biHeight
,
271 BitmapInfo
->bmiHeader
.biPlanes
,
272 BitmapInfo
->bmiHeader
.biBitCount
,
274 if (hPattern
== NULL
)
276 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
280 BitmapObject
= BITMAPOBJ_LockBitmap(hPattern
);
281 ASSERT(BitmapObject
!= NULL
);
282 BitmapObject
->hDIBPalette
= BuildDIBPalette(BitmapInfo
, &PaletteType
);
283 BITMAPOBJ_UnlockBitmap(BitmapObject
);
285 hBrush
= BRUSHOBJ_AllocBrush();
288 NtGdiDeleteObject(hPattern
);
289 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
293 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
294 ASSERT(BrushObject
!= NULL
);
296 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
| GDIBRUSH_IS_DIB
;
297 BrushObject
->hbmPattern
= hPattern
;
298 /* FIXME: Fill in the rest of fields!!! */
300 GDIOBJ_SetOwnership(hPattern
, NULL
);
302 BRUSHOBJ_UnlockBrush(BrushObject
);
308 IntGdiCreateHatchBrush(
313 PGDIBRUSHOBJ BrushObject
;
316 if (Style
< 0 || Style
>= NB_HATCH_STYLES
)
321 hPattern
= NtGdiCreateBitmap(8, 8, 1, 1, (LPBYTE
)HatchBrushes
[Style
]);
322 if (hPattern
== NULL
)
324 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
328 hBrush
= BRUSHOBJ_AllocBrush();
331 NtGdiDeleteObject(hPattern
);
332 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
336 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
337 ASSERT(BrushObject
!= NULL
);
339 BrushObject
->flAttrs
|= GDIBRUSH_IS_HATCH
;
340 BrushObject
->hbmPattern
= hPattern
;
341 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
343 GDIOBJ_SetOwnership(hPattern
, NULL
);
345 BRUSHOBJ_UnlockBrush(BrushObject
);
351 IntGdiCreatePatternBrush(
355 PGDIBRUSHOBJ BrushObject
;
358 hPattern
= BITMAPOBJ_CopyBitmap(hBitmap
);
359 if (hPattern
== NULL
)
361 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
365 hBrush
= BRUSHOBJ_AllocBrush();
368 NtGdiDeleteObject(hPattern
);
369 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
373 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
374 ASSERT(BrushObject
!= NULL
);
376 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
377 BrushObject
->hbmPattern
= hPattern
;
378 /* FIXME: Fill in the rest of fields!!! */
380 GDIOBJ_SetOwnership(hPattern
, NULL
);
382 BRUSHOBJ_UnlockBrush(BrushObject
);
388 IntGdiCreateSolidBrush(
392 PGDIBRUSHOBJ BrushObject
;
394 hBrush
= BRUSHOBJ_AllocBrush();
397 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
401 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
402 ASSERT(BrushObject
!= NULL
);
404 BrushObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
405 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
406 /* FIXME: Fill in the rest of fields!!! */
408 BRUSHOBJ_UnlockBrush(BrushObject
);
414 IntGdiCreateNullBrush(VOID
)
417 PGDIBRUSHOBJ BrushObject
;
419 hBrush
= BRUSHOBJ_AllocBrush();
422 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
426 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
427 ASSERT(BrushObject
!= NULL
);
428 BrushObject
->flAttrs
|= GDIBRUSH_IS_NULL
;
429 BRUSHOBJ_UnlockBrush(BrushObject
);
442 PGDIBRUSHOBJ BrushObj
)
445 BITMAPOBJ
*BitmapObj
;
446 GDIBRUSHINST BrushInst
;
452 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
453 if (BitmapObj
== NULL
)
455 SetLastWin32Error(ERROR_INVALID_HANDLE
);
459 if (!(BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
463 DestRect
.left
= XLeft
+ dc
->w
.DCOrgX
;
464 DestRect
.right
= XLeft
+ Width
+ dc
->w
.DCOrgX
;
468 DestRect
.left
= XLeft
+ Width
+ 1 + dc
->w
.DCOrgX
;
469 DestRect
.right
= XLeft
+ dc
->w
.DCOrgX
+ 1;
474 DestRect
.top
= YLeft
+ dc
->w
.DCOrgY
;
475 DestRect
.bottom
= YLeft
+ Height
+ dc
->w
.DCOrgY
;
479 DestRect
.top
= YLeft
+ Height
+ dc
->w
.DCOrgY
+ 1;
480 DestRect
.bottom
= YLeft
+ dc
->w
.DCOrgY
+ 1;
483 BrushOrigin
.x
= BrushObj
->ptOrigin
.x
+ dc
->w
.DCOrgX
;
484 BrushOrigin
.y
= BrushObj
->ptOrigin
.y
+ dc
->w
.DCOrgY
;
486 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, dc
->XlateBrush
);
497 &BrushInst
.BrushObject
,
502 BITMAPOBJ_UnlockBitmap(BitmapObj
);
517 PGDIBRUSHOBJ BrushObj
;
523 SetLastWin32Error(ERROR_INVALID_HANDLE
);
529 /* Yes, Windows really returns TRUE in this case */
533 for (r
= pRects
, i
= 0; i
< cRects
; i
++)
535 BrushObj
= BRUSHOBJ_LockBrush(r
->hBrush
);
546 BRUSHOBJ_UnlockBrush(BrushObj
);
556 /* PUBLIC FUNCTIONS ***********************************************************/
560 IN PVOID BitmapInfoAndData
,
562 IN UINT BitmapInfoSize
,
567 BITMAPINFO
*SafeBitmapInfoAndData
;
568 NTSTATUS Status
= STATUS_SUCCESS
;
571 SafeBitmapInfoAndData
= EngAllocMem(0, BitmapInfoSize
, 0);
572 if (SafeBitmapInfoAndData
== NULL
)
574 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
580 ProbeForRead(BitmapInfoAndData
,
583 RtlCopyMemory(SafeBitmapInfoAndData
,
589 Status
= _SEH_GetExceptionCode();
593 if (!NT_SUCCESS(Status
))
595 EngFreeMem(SafeBitmapInfoAndData
);
596 SetLastNtError(Status
);
600 hBrush
= IntGdiCreateDIBBrush(SafeBitmapInfoAndData
, ColorSpec
,
601 BitmapInfoSize
, PackedDIB
);
603 EngFreeMem(SafeBitmapInfoAndData
);
609 NtGdiCreateHatchBrush(
613 return IntGdiCreateHatchBrush(Style
, Color
);
617 NtGdiCreatePatternBrush(
620 return IntGdiCreatePatternBrush(hBitmap
);
624 NtGdiCreateSolidBrush(COLORREF Color
,
625 IN OPTIONAL HBRUSH hbr
)
627 return IntGdiCreateSolidBrush(Color
);
633 * The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
634 * the next brush an application selects into the specified device context.
641 NtGdiSetBrushOrgEx(HDC hDC
, INT XOrg
, INT YOrg
, LPPOINT Point
)
643 PDC dc
= DC_LockDc(hDC
);
646 SetLastWin32Error(ERROR_INVALID_HANDLE
);
652 NTSTATUS Status
= STATUS_SUCCESS
;
654 SafePoint
.x
= dc
->w
.brushOrgX
;
655 SafePoint
.y
= dc
->w
.brushOrgY
;
665 Status
= _SEH_GetExceptionCode();
669 if(!NT_SUCCESS(Status
))
672 SetLastNtError(Status
);
677 dc
->w
.brushOrgX
= XOrg
;
678 dc
->w
.brushOrgY
= YOrg
;
688 IN PPOLYPATBLT pRects
,
693 NTSTATUS Status
= STATUS_SUCCESS
;
698 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, TAG_PATBLT
);
701 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
707 cRects
* sizeof(PATRECT
),
711 cRects
* sizeof(PATRECT
));
715 Status
= _SEH_GetExceptionCode();
719 if (!NT_SUCCESS(Status
))
722 SetLastNtError(Status
);
727 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, (PPATRECT
)pRects
, cRects
, Mode
);
744 PGDIBRUSHOBJ BrushObj
;
745 DC
*dc
= DC_LockDc(hDC
);
750 SetLastWin32Error(ERROR_INVALID_HANDLE
);
756 /* Yes, Windows really returns TRUE in this case */
760 BrushObj
= BRUSHOBJ_LockBrush(dc
->w
.hBrush
);
761 if (BrushObj
== NULL
)
763 SetLastWin32Error(ERROR_INVALID_HANDLE
);
777 BRUSHOBJ_UnlockBrush(BrushObj
);