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
);
49 /* Free the kmode styles array of EXTPENS */
52 ExFreePool(pBrush
->pStyle
);
59 BRUSH_GetObject (PGDIBRUSHOBJ BrushObject
, INT Count
, LPLOGBRUSH Buffer
)
61 if( Buffer
== NULL
) return sizeof(LOGBRUSH
);
62 if (Count
== 0) return 0;
65 Buffer
->lbColor
= BrushObject
->BrushAttr
.lbColor
;
68 if ((BrushObject
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
70 /* FIXME : is this right value */
71 Buffer
->lbHatch
= (LONG
)BrushObject
->hbmPattern
;
80 /* Get the type of style */
81 if ((BrushObject
->flAttrs
& GDIBRUSH_IS_SOLID
)!=0)
83 Buffer
->lbStyle
= BS_SOLID
;
85 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_NULL
)!=0)
87 Buffer
->lbStyle
= BS_NULL
; // BS_HOLLOW
89 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_HATCH
)!=0)
91 Buffer
->lbStyle
= BS_HATCHED
;
93 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_BITMAP
)!=0)
95 Buffer
->lbStyle
= BS_PATTERN
;
97 else if ((BrushObject
->flAttrs
& GDIBRUSH_IS_DIB
)!=0)
99 Buffer
->lbStyle
= BS_DIBPATTERN
;
103 else if ((BrushObject->flAttrs & )!=0)
105 Buffer->lbStyle = BS_INDEXED;
107 else if ((BrushObject->flAttrs & )!=0)
109 Buffer->lbStyle = BS_DIBPATTERNPT;
114 return sizeof(LOGBRUSH
);
119 IntGdiCreateBrushXlate(PDC Dc
, GDIBRUSHOBJ
*BrushObj
, BOOLEAN
*Failed
)
121 XLATEOBJ
*Result
= NULL
;
122 BITMAPOBJ
* pSurface
;
123 HPALETTE hPalette
= NULL
;
125 pSurface
= BITMAPOBJ_LockBitmap(Dc
->w
.hBitmap
);
128 hPalette
= pSurface
->hDIBPalette
;
129 BITMAPOBJ_UnlockBitmap(pSurface
);
131 if (!hPalette
) hPalette
= pPrimarySurface
->DevInfo
.hpalDefault
;
133 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
138 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
140 Result
= IntEngCreateXlate(0, PAL_RGB
, hPalette
, NULL
);
145 BITMAPOBJ
*Pattern
= BITMAPOBJ_LockBitmap(BrushObj
->hbmPattern
);
149 /* Special case: 1bpp pattern */
150 if (Pattern
->SurfObj
.iBitmapFormat
== BMF_1BPP
)
152 PDC_ATTR Dc_Attr
= Dc
->pDc_Attr
;
153 if (!Dc_Attr
) Dc_Attr
= &Dc
->Dc_Attr
;
155 if (Dc
->w
.bitsPerPixel
!= 1)
156 Result
= IntEngCreateSrcMonoXlate(hPalette
, Dc_Attr
->crForegroundClr
, Dc_Attr
->crBackgroundClr
);
158 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_DIB
)
160 Result
= IntEngCreateXlate(0, 0, hPalette
, Pattern
->hDIBPalette
);
163 BITMAPOBJ_UnlockBitmap(Pattern
);
171 IntGdiInitBrushInstance(GDIBRUSHINST
*BrushInst
, PGDIBRUSHOBJ BrushObj
, XLATEOBJ
*XlateObj
)
175 if (BrushObj
->flAttrs
& GDIBRUSH_IS_NULL
)
177 BrushInst
->BrushObject
.iSolidColor
= 0;
179 else if (BrushObj
->flAttrs
& GDIBRUSH_IS_SOLID
)
181 BrushInst
->BrushObject
.iSolidColor
= XLATEOBJ_iXlate(XlateObj
, BrushObj
->BrushAttr
.lbColor
);
185 BrushInst
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
188 BrushInst
->BrushObject
.pvRbrush
= BrushObj
->ulRealization
;
189 BrushInst
->BrushObject
.flColorType
= 0;
190 BrushInst
->GdiBrushObject
= BrushObj
;
191 BrushInst
->XlateObject
= XlateObj
;
195 * @name CalculateColorTableSize
197 * Internal routine to calculate the number of color table entries.
199 * @param BitmapInfoHeader
200 * Input bitmap information header, can be any version of
201 * BITMAPINFOHEADER or BITMAPCOREHEADER.
204 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
205 * or DIB_RGB_COLORS). On successful return this value is normalized
206 * according to the bitmap info.
208 * @param ColorTableSize
209 * On successful return this variable is filled with number of
210 * entries in color table for the image with specified parameters.
213 * TRUE if the input values together form a valid image, FALSE otherwise.
217 CalculateColorTableSize(
218 CONST BITMAPINFOHEADER
*BitmapInfoHeader
,
220 UINT
*ColorTableSize
)
227 * At first get some basic parameters from the passed BitmapInfoHeader
228 * structure. It can have one of the following formats:
229 * - BITMAPCOREHEADER (the oldest one with totally different layout
231 * - BITMAPINFOHEADER (the standard and most common header)
232 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
233 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
236 if (BitmapInfoHeader
->biSize
== sizeof(BITMAPCOREHEADER
))
238 BitCount
= ((LPBITMAPCOREHEADER
)BitmapInfoHeader
)->bcBitCount
;
240 Compression
= BI_RGB
;
244 BitCount
= BitmapInfoHeader
->biBitCount
;
245 ClrUsed
= BitmapInfoHeader
->biClrUsed
;
246 Compression
= BitmapInfoHeader
->biCompression
;
252 if (*ColorSpec
== DIB_PAL_COLORS
)
253 *ColorSpec
= DIB_RGB_COLORS
;
255 if (BitCount
!= 16 && BitCount
!= 32)
259 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
260 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
261 * For BITMAPINFOHEADER the color masks are stored in the palette.
264 if (BitmapInfoHeader
->biSize
> sizeof(BITMAPINFOHEADER
))
275 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 2) : 2;
279 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
283 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
287 if (*ColorSpec
== DIB_PAL_COLORS
)
288 *ColorSpec
= DIB_RGB_COLORS
;
289 if (BitCount
!= 16 && BitCount
!= 24 && BitCount
!= 32)
291 *ColorTableSize
= ClrUsed
;
298 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 16) : 16;
306 *ColorTableSize
= ClrUsed
? min(ClrUsed
, 256) : 256;
313 *ColorTableSize
= ClrUsed
;
322 IntGdiCreateDIBBrush(
323 CONST BITMAPINFO
*BitmapInfo
,
326 CONST VOID
*PackedDIB
)
329 PGDIBRUSHOBJ BrushObject
;
332 UINT PaletteEntryCount
;
333 PBITMAPOBJ BitmapObject
;
336 if (BitmapInfo
->bmiHeader
.biSize
< sizeof(BITMAPINFOHEADER
))
338 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
342 if (!CalculateColorTableSize(&BitmapInfo
->bmiHeader
, &ColorSpec
,
345 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
349 DataPtr
= (ULONG_PTR
)BitmapInfo
+ BitmapInfo
->bmiHeader
.biSize
;
350 if (ColorSpec
== DIB_RGB_COLORS
)
351 DataPtr
+= PaletteEntryCount
* sizeof(RGBQUAD
);
353 DataPtr
+= PaletteEntryCount
* sizeof(USHORT
);
355 hPattern
= IntGdiCreateBitmap(BitmapInfo
->bmiHeader
.biWidth
,
356 BitmapInfo
->bmiHeader
.biHeight
,
357 BitmapInfo
->bmiHeader
.biPlanes
,
358 BitmapInfo
->bmiHeader
.biBitCount
,
360 if (hPattern
== NULL
)
362 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
366 BitmapObject
= BITMAPOBJ_LockBitmap(hPattern
);
367 ASSERT(BitmapObject
!= NULL
);
368 BitmapObject
->hDIBPalette
= BuildDIBPalette(BitmapInfo
, &PaletteType
);
369 BITMAPOBJ_UnlockBitmap(BitmapObject
);
371 BrushObject
= BRUSHOBJ_AllocBrushWithHandle();
372 if (BrushObject
== NULL
)
374 NtGdiDeleteObject(hPattern
);
375 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
378 hBrush
= BrushObject
->BaseObject
.hHmgr
;
380 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
| GDIBRUSH_IS_DIB
;
381 BrushObject
->hbmPattern
= hPattern
;
382 /* FIXME: Fill in the rest of fields!!! */
384 GDIOBJ_SetOwnership(hPattern
, NULL
);
386 BRUSHOBJ_UnlockBrush(BrushObject
);
392 IntGdiCreateHatchBrush(
397 PGDIBRUSHOBJ BrushObject
;
400 if (Style
< 0 || Style
>= NB_HATCH_STYLES
)
405 hPattern
= IntGdiCreateBitmap(8, 8, 1, 1, (LPBYTE
)HatchBrushes
[Style
]);
406 if (hPattern
== NULL
)
408 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
412 BrushObject
= BRUSHOBJ_AllocBrushWithHandle();
413 if (BrushObject
== NULL
)
415 NtGdiDeleteObject(hPattern
);
416 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
419 hBrush
= BrushObject
->BaseObject
.hHmgr
;
421 BrushObject
->flAttrs
|= GDIBRUSH_IS_HATCH
;
422 BrushObject
->hbmPattern
= hPattern
;
423 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
425 GDIOBJ_SetOwnership(hPattern
, NULL
);
427 BRUSHOBJ_UnlockBrush(BrushObject
);
433 IntGdiCreatePatternBrush(
437 PGDIBRUSHOBJ BrushObject
;
440 hPattern
= BITMAPOBJ_CopyBitmap(hBitmap
);
441 if (hPattern
== NULL
)
443 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
447 BrushObject
= BRUSHOBJ_AllocBrushWithHandle();
448 if (BrushObject
== NULL
)
450 NtGdiDeleteObject(hPattern
);
451 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
454 hBrush
= BrushObject
->BaseObject
.hHmgr
;
456 BrushObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
457 BrushObject
->hbmPattern
= hPattern
;
458 /* FIXME: Fill in the rest of fields!!! */
460 GDIOBJ_SetOwnership(hPattern
, NULL
);
462 BRUSHOBJ_UnlockBrush(BrushObject
);
468 IntGdiCreateSolidBrush(
472 PGDIBRUSHOBJ BrushObject
;
474 BrushObject
= BRUSHOBJ_AllocBrushWithHandle();
475 if (BrushObject
== NULL
)
477 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
480 hBrush
= BrushObject
->BaseObject
.hHmgr
;
482 BrushObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
484 BrushObject
->BrushAttr
.lbColor
= Color
;
485 /* FIXME: Fill in the rest of fields!!! */
487 BRUSHOBJ_UnlockBrush(BrushObject
);
493 IntGdiCreateNullBrush(VOID
)
496 PGDIBRUSHOBJ BrushObject
;
498 BrushObject
= BRUSHOBJ_AllocBrushWithHandle();
499 if (BrushObject
== NULL
)
501 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
504 hBrush
= BrushObject
->BaseObject
.hHmgr
;
506 BrushObject
->flAttrs
|= GDIBRUSH_IS_NULL
;
507 BRUSHOBJ_UnlockBrush(BrushObject
);
512 /* PUBLIC FUNCTIONS ***********************************************************/
516 IN PVOID BitmapInfoAndData
,
518 IN UINT BitmapInfoSize
,
523 BITMAPINFO
*SafeBitmapInfoAndData
;
524 NTSTATUS Status
= STATUS_SUCCESS
;
527 SafeBitmapInfoAndData
= EngAllocMem(FL_ZERO_MEMORY
, BitmapInfoSize
, TAG_DIB
);
528 if (SafeBitmapInfoAndData
== NULL
)
530 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
536 ProbeForRead(BitmapInfoAndData
,
539 RtlCopyMemory(SafeBitmapInfoAndData
,
545 Status
= _SEH_GetExceptionCode();
549 if (!NT_SUCCESS(Status
))
551 EngFreeMem(SafeBitmapInfoAndData
);
552 SetLastNtError(Status
);
556 hBrush
= IntGdiCreateDIBBrush(SafeBitmapInfoAndData
, ColorSpec
,
557 BitmapInfoSize
, PackedDIB
);
559 EngFreeMem(SafeBitmapInfoAndData
);
565 NtGdiCreateHatchBrushInternal(
570 return IntGdiCreateHatchBrush(Style
, Color
);
574 NtGdiCreatePatternBrushInternal(
579 return IntGdiCreatePatternBrush(hBitmap
);
583 NtGdiCreateSolidBrush(COLORREF Color
,
584 IN OPTIONAL HBRUSH hbr
)
586 return IntGdiCreateSolidBrush(Color
);
592 * The NtGdiSetBrushOrg function sets the brush origin that GDI assigns to
593 * the next brush an application selects into the specified device context.
600 NtGdiSetBrushOrg(HDC hDC
, INT XOrg
, INT YOrg
, LPPOINT Point
)
608 SetLastWin32Error(ERROR_INVALID_HANDLE
);
611 Dc_Attr
= dc
->pDc_Attr
;
612 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
616 NTSTATUS Status
= STATUS_SUCCESS
;
618 SafePoint
.x
= Dc_Attr
->ptlBrushOrigin
.x
;
619 SafePoint
.y
= Dc_Attr
->ptlBrushOrigin
.y
;
629 Status
= _SEH_GetExceptionCode();
633 if(!NT_SUCCESS(Status
))
636 SetLastNtError(Status
);
640 Dc_Attr
->ptlBrushOrigin
.x
= XOrg
;
641 Dc_Attr
->ptlBrushOrigin
.y
= YOrg
;
647 IntGdiSetSolidBrushColor(HBRUSH hBrush
, COLORREF Color
)
649 PGDIBRUSHOBJ BrushObject
;
651 BrushObject
= BRUSHOBJ_LockBrush(hBrush
);
652 if (BrushObject
->flAttrs
& GDIBRUSH_IS_SOLID
)
654 BrushObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
656 BRUSHOBJ_UnlockBrush(BrushObject
);