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(GdiHandleTable
, pBrush
->hbmPattern
, PsGetCurrentProcess());
46 NtGdiDeleteObject(pBrush
->hbmPattern
);
53 BRUSH_GetObject (PGDIBRUSHOBJ BrushObject
, INT Count
, LPLOGBRUSH Buffer
)
55 if( Buffer
== NULL
) return sizeof(BRUSHOBJ
);
56 if (Count
< sizeof(BRUSHOBJ
)) return 0;
57 if (Count
> sizeof(BRUSHOBJ
)) Count
= sizeof(BRUSHOBJ
);
60 Buffer
->lbColor
= BrushObject
->BrushAttr
.lbColor
;
63 if ((BrushObject
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
65 /* FIXME : is this right value */
66 Buffer
->lbHatch
= (LONG
)BrushObject
->hbmPattern
;
75 /* Get the type of style */
76 if ((BrushObject
->flAttrs
& GDIBRUSH_IS_SOLID
)!=0)
78 Buffer
->lbStyle
= BS_SOLID
;
80 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_NULL
)!=0)
82 Buffer
->lbStyle
= BS_NULL
; // BS_HOLLOW
84 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
86 Buffer
->lbStyle
= BS_HATCHED
;
88 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_BITMAP
)!=0)
90 Buffer
->lbStyle
= BS_PATTERN
;
92 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_DIB
)!=0)
94 Buffer
->lbStyle
= BS_DIBPATTERN
;
98 else if ((BrushObject->flAttrs & )!=0)
100 Buffer->lbStyle = BS_INDEXED;
102 else if ((BrushObject->flAttrs & )!=0)
104 Buffer->lbStyle = BS_DIBPATTERNPT;
109 return sizeof(BRUSHOBJ
);
114 IntGdiCreateBrushXlate(PDC Dc
, GDIBRUSHOBJ
*BrushObj
, BOOLEAN
*Failed
)
116 XLATEOBJ
*Result
= NULL
;
118 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
123 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
125 Result
= IntEngCreateXlate(0, PAL_RGB
, Dc
->w
.hPalette
, NULL
);
130 BITMAPOBJ
*Pattern
= BITMAPOBJ_LockBitmap(BrushObj
->hbmPattern
);
134 /* Special case: 1bpp pattern */
135 if (Pattern
->SurfObj
.iBitmapFormat
== BMF_1BPP
)
137 if (Dc
->w
.bitsPerPixel
!= 1)
138 Result
= IntEngCreateSrcMonoXlate(Dc
->w
.hPalette
, Dc
->w
.textColor
, Dc
->w
.backgroundColor
);
140 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_DIB
)
142 Result
= IntEngCreateXlate(0, 0, Dc
->w
.hPalette
, Pattern
->hDIBPalette
);
145 BITMAPOBJ_UnlockBitmap(Pattern
);
153 IntGdiInitBrushInstance(GDIBRUSHINST
*BrushInst
, PGDIBRUSHOBJ BrushObj
, XLATEOBJ
*XlateObj
)
157 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
158 BrushInst
->BrushObject
.iSolidColor
= 0;
159 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
160 BrushInst
->BrushObject
.iSolidColor
= XLATEOBJ_iXlate(XlateObj
, BrushObj
->BrushAttr
.lbColor
);
162 BrushInst
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
163 BrushInst
->BrushObject
.pvRbrush
= BrushObj
->ulRealization
;
164 BrushInst
->BrushObject
.flColorType
= 0;
165 BrushInst
->GdiBrushObject
= BrushObj
;
166 BrushInst
->XlateObject
= XlateObj
;
170 * @name CalculateColorTableSize
172 * Internal routine to calculate the number of color table entries.
174 * @param BitmapInfoHeader
175 * Input bitmap information header, can be any version of
176 * BITMAPINFOHEADER or BITMAPCOREHEADER.
179 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
180 * or DIB_RGB_COLORS). On successful return this value is normalized
181 * according to the bitmap info.
183 * @param ColorTableSize
184 * On successful return this variable is filled with number of
185 * entries in color table for the image with specified parameters.
188 * TRUE if the input values together form a valid image, FALSE otherwise.
192 CalculateColorTableSize(
193 CONST BITMAPINFOHEADER
*BitmapInfoHeader
,
195 UINT
*ColorTableSize
)
202 * At first get some basic parameters from the passed BitmapInfoHeader
203 * structure. It can have one of the following formats:
204 * - BITMAPCOREHEADER (the oldest one with totally different layout
206 * - BITMAPINFOHEADER (the standard and most common header)
207 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
208 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
211 if (BitmapInfoHeader
->biSize
== sizeof(BITMAPCOREHEADER
))
213 BitCount
= ((LPBITMAPCOREHEADER
)BitmapInfoHeader
)->bcBitCount
;
215 Compression
= BI_RGB
;
219 BitCount
= BitmapInfoHeader
->biBitCount
;
220 ClrUsed
= BitmapInfoHeader
->biClrUsed
;
221 Compression
= BitmapInfoHeader
->biCompression
;
227 if (*ColorSpec
== DIB_PAL_COLORS
)
228 *ColorSpec
= DIB_RGB_COLORS
;
230 if (BitCount
!= 16 && BitCount
!= 32)
234 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
235 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
236 * For BITMAPINFOHEADER the color masks are stored in the palette.
239 if (BitmapInfoHeader
->biSize
> sizeof(BITMAPINFOHEADER
))
250 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 2) : 2;
254 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
258 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
262 if (*ColorSpec
== DIB_PAL_COLORS
)
263 *ColorSpec
= DIB_RGB_COLORS
;
264 if (BitCount
!= 16 && BitCount
!= 24 && BitCount
!= 32)
266 *ColorTableSize
= ClrUsed
;
273 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
281 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
288 *ColorTableSize
= ClrUsed
;
297 IntGdiCreateDIBBrush(
298 CONST BITMAPINFO
*BitmapInfo
,
301 CONST VOID
*PackedDIB
)
304 PGDIBRUSHOBJ BrushObject
;
307 UINT PaletteEntryCount
;
308 PBITMAPOBJ BitmapObject
;
311 if (BitmapInfo
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
313 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
317 if (!CalculateColorTableSize(&BitmapInfo
->bmiHeader
, &ColorSpec
,
320 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
324 DataPtr
= (ULONG_PTR
)BitmapInfo
+ BitmapInfo
->bmiHeader
.biSize
;
325 if (ColorSpec
== DIB_RGB_COLORS
)
326 DataPtr
+= PaletteEntryCount
* sizeof(RGBQUAD
);
328 DataPtr
+= PaletteEntryCount
* sizeof(USHORT
);
330 hPattern
= NtGdiCreateBitmap(BitmapInfo
->bmiHeader
.biWidth
,
331 BitmapInfo
->bmiHeader
.biHeight
,
332 BitmapInfo
->bmiHeader
.biPlanes
,
333 BitmapInfo
->bmiHeader
.biBitCount
,
335 if (hPattern
== NULL
)
337 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
341 BitmapObject
= BITMAPOBJ_LockBitmap(hPattern
);
342 ASSERT(BitmapObject
!= NULL
);
343 BitmapObject
->hDIBPalette
= BuildDIBPalette(BitmapInfo
, &PaletteType
);
344 BITMAPOBJ_UnlockBitmap(BitmapObject
);
346 hBrush
= BRUSHOBJ_AllocBrush();
349 NtGdiDeleteObject(hPattern
);
350 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
354 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
355 ASSERT(BrushObject
!= NULL
);
357 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
| GDIBRUSH_IS_DIB
;
358 BrushObject
->hbmPattern
= hPattern
;
359 /* FIXME: Fill in the rest of fields!!! */
361 GDIOBJ_SetOwnership(GdiHandleTable
, hPattern
, NULL
);
363 BRUSHOBJ_UnlockBrush(BrushObject
);
369 IntGdiCreateHatchBrush(
374 PGDIBRUSHOBJ BrushObject
;
377 if (Style
< 0 || Style
>= NB_HATCH_STYLES
)
382 hPattern
= NtGdiCreateBitmap(8, 8, 1, 1, (LPBYTE
)HatchBrushes
[Style
]);
383 if (hPattern
== NULL
)
385 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
389 hBrush
= BRUSHOBJ_AllocBrush();
392 NtGdiDeleteObject(hPattern
);
393 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
397 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
398 ASSERT(BrushObject
!= NULL
);
400 BrushObject
->flAttrs
|= GDIBRUSH_IS_HATCH
;
401 BrushObject
->hbmPattern
= hPattern
;
402 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
404 GDIOBJ_SetOwnership(GdiHandleTable
, hPattern
, NULL
);
406 BRUSHOBJ_UnlockBrush(BrushObject
);
412 IntGdiCreatePatternBrush(
416 PGDIBRUSHOBJ BrushObject
;
419 hPattern
= BITMAPOBJ_CopyBitmap(hBitmap
);
420 if (hPattern
== NULL
)
422 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
426 hBrush
= BRUSHOBJ_AllocBrush();
429 NtGdiDeleteObject(hPattern
);
430 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
434 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
435 ASSERT(BrushObject
!= NULL
);
437 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
438 BrushObject
->hbmPattern
= hPattern
;
439 /* FIXME: Fill in the rest of fields!!! */
441 GDIOBJ_SetOwnership(GdiHandleTable
, hPattern
, NULL
);
443 BRUSHOBJ_UnlockBrush(BrushObject
);
449 IntGdiCreateSolidBrush(
453 PGDIBRUSHOBJ BrushObject
;
455 hBrush
= BRUSHOBJ_AllocBrush();
458 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
462 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
463 ASSERT(BrushObject
!= NULL
);
465 BrushObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
467 BrushObject
->BrushAttr
.lbColor
= Color
;
468 /* FIXME: Fill in the rest of fields!!! */
470 BRUSHOBJ_UnlockBrush(BrushObject
);
476 IntGdiCreateNullBrush(VOID
)
479 PGDIBRUSHOBJ BrushObject
;
481 hBrush
= BRUSHOBJ_AllocBrush();
484 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
488 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
489 ASSERT(BrushObject
!= NULL
);
490 BrushObject
->flAttrs
|= GDIBRUSH_IS_NULL
;
491 BRUSHOBJ_UnlockBrush(BrushObject
);
504 PGDIBRUSHOBJ BrushObj
)
507 BITMAPOBJ
*BitmapObj
;
508 GDIBRUSHINST BrushInst
;
514 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
515 if (BitmapObj
== NULL
)
517 SetLastWin32Error(ERROR_INVALID_HANDLE
);
521 if (!(BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
525 DestRect
.left
= XLeft
+ dc
->w
.DCOrgX
;
526 DestRect
.right
= XLeft
+ Width
+ dc
->w
.DCOrgX
;
530 DestRect
.left
= XLeft
+ Width
+ 1 + dc
->w
.DCOrgX
;
531 DestRect
.right
= XLeft
+ dc
->w
.DCOrgX
+ 1;
536 DestRect
.top
= YLeft
+ dc
->w
.DCOrgY
;
537 DestRect
.bottom
= YLeft
+ Height
+ dc
->w
.DCOrgY
;
541 DestRect
.top
= YLeft
+ Height
+ dc
->w
.DCOrgY
+ 1;
542 DestRect
.bottom
= YLeft
+ dc
->w
.DCOrgY
+ 1;
545 IntLPtoDP(dc
, (LPPOINT
)&DestRect
, 2);
547 BrushOrigin
.x
= BrushObj
->ptOrigin
.x
+ dc
->w
.DCOrgX
;
548 BrushOrigin
.y
= BrushObj
->ptOrigin
.y
+ dc
->w
.DCOrgY
;
550 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, dc
->XlateBrush
);
561 &BrushInst
.BrushObject
,
566 BITMAPOBJ_UnlockBitmap(BitmapObj
);
581 PGDIBRUSHOBJ BrushObj
;
587 SetLastWin32Error(ERROR_INVALID_HANDLE
);
593 /* Yes, Windows really returns TRUE in this case */
597 for (r
= pRects
, i
= 0; i
< cRects
; i
++)
599 BrushObj
= BRUSHOBJ_LockBrush(r
->hBrush
);
610 BRUSHOBJ_UnlockBrush(BrushObj
);
620 /* PUBLIC FUNCTIONS ***********************************************************/
624 IN PVOID BitmapInfoAndData
,
626 IN UINT BitmapInfoSize
,
631 BITMAPINFO
*SafeBitmapInfoAndData
;
632 NTSTATUS Status
= STATUS_SUCCESS
;
635 SafeBitmapInfoAndData
= EngAllocMem(0, BitmapInfoSize
, 0);
636 if (SafeBitmapInfoAndData
== NULL
)
638 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
644 ProbeForRead(BitmapInfoAndData
,
647 RtlCopyMemory(SafeBitmapInfoAndData
,
653 Status
= _SEH_GetExceptionCode();
657 if (!NT_SUCCESS(Status
))
659 EngFreeMem(SafeBitmapInfoAndData
);
660 SetLastNtError(Status
);
664 hBrush
= IntGdiCreateDIBBrush(SafeBitmapInfoAndData
, ColorSpec
,
665 BitmapInfoSize
, PackedDIB
);
667 EngFreeMem(SafeBitmapInfoAndData
);
673 NtGdiCreateHatchBrushInternal(
678 return IntGdiCreateHatchBrush(Style
, Color
);
682 NtGdiCreatePatternBrushInternal(
687 return IntGdiCreatePatternBrush(hBitmap
);
691 NtGdiCreateSolidBrush(COLORREF Color
,
692 IN OPTIONAL HBRUSH hbr
)
694 return IntGdiCreateSolidBrush(Color
);
700 * The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
701 * the next brush an application selects into the specified device context.
708 NtGdiSetBrushOrgEx(HDC hDC
, INT XOrg
, INT YOrg
, LPPOINT Point
)
710 PDC dc
= DC_LockDc(hDC
);
713 SetLastWin32Error(ERROR_INVALID_HANDLE
);
719 NTSTATUS Status
= STATUS_SUCCESS
;
721 SafePoint
.x
= dc
->w
.brushOrgX
;
722 SafePoint
.y
= dc
->w
.brushOrgY
;
732 Status
= _SEH_GetExceptionCode();
736 if(!NT_SUCCESS(Status
))
739 SetLastNtError(Status
);
744 dc
->w
.brushOrgX
= XOrg
;
745 dc
->w
.brushOrgY
= YOrg
;
755 IN PPOLYPATBLT pRects
,
760 NTSTATUS Status
= STATUS_SUCCESS
;
765 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, TAG_PATBLT
);
768 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
774 cRects
* sizeof(PATRECT
),
778 cRects
* sizeof(PATRECT
));
782 Status
= _SEH_GetExceptionCode();
786 if (!NT_SUCCESS(Status
))
789 SetLastNtError(Status
);
794 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, (PPATRECT
)pRects
, cRects
, Mode
);
811 PGDIBRUSHOBJ BrushObj
;
812 DC
*dc
= DC_LockDc(hDC
);
817 SetLastWin32Error(ERROR_INVALID_HANDLE
);
823 /* Yes, Windows really returns TRUE in this case */
827 BrushObj
= BRUSHOBJ_LockBrush(dc
->w
.hBrush
);
828 if (BrushObj
== NULL
)
830 SetLastWin32Error(ERROR_INVALID_HANDLE
);
844 BRUSHOBJ_UnlockBrush(BrushObj
);