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 /* PRIVATE FUNCTIONS **********************************************************/
32 PENOBJ_LockPen(HGDIOBJ hBMObj
)
34 if (GDI_HANDLE_GET_TYPE(hBMObj
) == GDI_OBJECT_TYPE_EXTPEN
)
35 return GDIOBJ_LockObj( hBMObj
, GDI_OBJECT_TYPE_EXTPEN
);
37 return GDIOBJ_LockObj( hBMObj
, GDI_OBJECT_TYPE_PEN
);
44 IN ULONG ulBrushStyle
,
46 IN ULONG_PTR ulClientHatch
,
52 IN OPTIONAL HBRUSH hbrush
)
55 PGDIBRUSHOBJ PenObject
;
56 static const BYTE PatternAlternate
[] = {0x55, 0x55, 0x55};
57 static const BYTE PatternDash
[] = {0xFF, 0xFF, 0xC0};
58 static const BYTE PatternDot
[] = {0xE3, 0x8E, 0x38};
59 static const BYTE PatternDashDot
[] = {0xFF, 0x81, 0xC0};
60 static const BYTE PatternDashDotDot
[] = {0xFF, 0x8E, 0x38};
62 dwWidth
= abs(dwWidth
);
64 if ( (dwPenStyle
& PS_STYLE_MASK
) == PS_NULL
)
66 return StockObjects
[NULL_PEN
];
71 PenObject
= PENOBJ_AllocPenWithHandle();
75 PenObject
= PENOBJ_AllocExtPenWithHandle();
80 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
81 DPRINT("Can't allocate pen\n");
84 hPen
= PenObject
->BaseObject
.hHmgr
;
86 // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
87 if ((bOldStylePen
) && (!dwWidth
) && (dwPenStyle
& PS_STYLE_MASK
) != PS_SOLID
)
90 PenObject
->ptPenWidth
.x
= dwWidth
;
91 PenObject
->ptPenWidth
.y
= 0;
92 PenObject
->ulPenStyle
= dwPenStyle
;
93 PenObject
->BrushAttr
.lbColor
= ulColor
;
94 PenObject
->ulStyle
= ulBrushStyle
;
95 // FIXME: copy the bitmap first ?
96 PenObject
->hbmClient
= (HANDLE
)ulClientHatch
;
97 PenObject
->dwStyleCount
= dwStyleCount
;
98 PenObject
->pStyle
= pStyle
;
100 PenObject
->flAttrs
= bOldStylePen
? GDIBRUSH_IS_OLDSTYLEPEN
: GDIBRUSH_IS_PEN
;
102 // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
103 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && ( dwWidth
!= 1) )
106 switch (dwPenStyle
& PS_STYLE_MASK
)
109 PenObject
->flAttrs
|= GDIBRUSH_IS_NULL
;
113 PenObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
117 PenObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
118 PenObject
->hbmPattern
= IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternAlternate
);
122 PenObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
123 PenObject
->hbmPattern
= IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDot
);
127 PenObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
128 PenObject
->hbmPattern
= IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDash
);
132 PenObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
133 PenObject
->hbmPattern
= IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDot
);
137 PenObject
->flAttrs
|= GDIBRUSH_IS_BITMAP
;
138 PenObject
->hbmPattern
= IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDotDot
);
142 PenObject
->flAttrs
|= (GDIBRUSH_IS_SOLID
|GDIBRUSH_IS_INSIDEFRAME
);
146 if ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
)
148 /* FIXME: PS_USERSTYLE workaround */
149 DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n");
150 PenObject
->flAttrs
|= GDIBRUSH_IS_SOLID
;
156 BOOL has_neg
= FALSE
, all_zero
= TRUE
;
158 for(i
= 0; (i
< dwStyleCount
) && !has_neg
; i
++)
160 has_neg
= has_neg
|| (((INT
)(pStyle
[i
])) < 0);
161 all_zero
= all_zero
&& (pStyle
[i
] == 0);
164 if(all_zero
|| has_neg
)
169 /* FIXME: what style here? */
170 PenObject
->flAttrs
|= 0;
174 DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle
);
176 PENOBJ_UnlockPen(PenObject
);
180 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
181 PenObject
->pStyle
= NULL
;
182 PENOBJ_UnlockPen(PenObject
);
184 PENOBJ_FreePenByHandle(hPen
);
186 PENOBJ_FreeExtPenByHandle(hPen
);
191 IntGdiSetSolidPenColor(HPEN hPen
, COLORREF Color
)
193 PGDIBRUSHOBJ PenObject
;
195 PenObject
= PENOBJ_LockPen(hPen
);
198 if (PenObject
->flAttrs
& GDIBRUSH_IS_SOLID
)
200 PenObject
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
202 PENOBJ_UnlockPen(PenObject
);
207 PEN_GetObject(PGDIBRUSHOBJ pPenObject
, INT cbCount
, PLOGPEN pBuffer
)
210 PEXTLOGPEN pExtLogPen
;
213 if (pPenObject
->flAttrs
& GDIBRUSH_IS_OLDSTYLEPEN
)
215 cbRetCount
= sizeof(LOGPEN
);
219 if (cbCount
< cbRetCount
) return 0;
221 if ( (pPenObject
->ulPenStyle
& PS_STYLE_MASK
) == PS_NULL
&&
222 cbCount
== sizeof(EXTLOGPEN
))
224 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
225 pExtLogPen
->elpPenStyle
= pPenObject
->ulPenStyle
;
226 pExtLogPen
->elpWidth
= 0;
227 pExtLogPen
->elpBrushStyle
= pPenObject
->ulStyle
;
228 pExtLogPen
->elpColor
= pPenObject
->BrushAttr
.lbColor
;
229 pExtLogPen
->elpHatch
= 0;
230 pExtLogPen
->elpNumEntries
= 0;
231 cbRetCount
= sizeof(EXTLOGPEN
);
235 pLogPen
= (PLOGPEN
)pBuffer
;
236 pLogPen
->lopnWidth
= pPenObject
->ptPenWidth
;
237 pLogPen
->lopnStyle
= pPenObject
->ulPenStyle
;
238 pLogPen
->lopnColor
= pPenObject
->BrushAttr
.lbColor
;
244 // FIXME: Can we trust in dwStyleCount being <= 16?
245 cbRetCount
= sizeof(EXTLOGPEN
) - sizeof(DWORD
) + pPenObject
->dwStyleCount
* sizeof(DWORD
);
250 if (cbCount
< cbRetCount
) return 0;
251 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
252 pExtLogPen
->elpPenStyle
= pPenObject
->ulPenStyle
;
253 pExtLogPen
->elpWidth
= pPenObject
->ptPenWidth
.x
;
254 pExtLogPen
->elpBrushStyle
= pPenObject
->ulStyle
;
255 pExtLogPen
->elpColor
= pPenObject
->BrushAttr
.lbColor
;
256 pExtLogPen
->elpHatch
= (ULONG_PTR
)pPenObject
->hbmClient
;
257 pExtLogPen
->elpNumEntries
= pPenObject
->dwStyleCount
;
258 for (i
= 0; i
< pExtLogPen
->elpNumEntries
; i
++)
260 pExtLogPen
->elpStyleEntry
[i
] = pPenObject
->pStyle
[i
];
281 if (pDC
== NULL
|| hPen
== NULL
) return NULL
;
283 pDc_Attr
= pDC
->pDc_Attr
;
284 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
286 pPen
= PENOBJ_LockPen(hPen
);
292 XlateObj
= IntGdiCreateBrushXlate(pDC
, pPen
, &bFailed
);
293 PENOBJ_UnlockPen(pPen
);
296 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
300 hOrgPen
= pDc_Attr
->hpen
;
301 pDc_Attr
->hpen
= hPen
;
303 if (pDC
->XlatePen
!= NULL
)
305 EngDeleteXlate(pDC
->XlatePen
);
307 pDc_Attr
->ulDirty_
&= ~DC_PEN_DIRTY
;
309 pDC
->XlatePen
= XlateObj
;
314 /* PUBLIC FUNCTIONS ***********************************************************/
323 if ( PenStyle
< PS_SOLID
|| PenStyle
> PS_INSIDEFRAME
)
325 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
329 return IntGdiExtCreatePen(PenStyle
,
346 IN ULONG ulBrushStyle
,
348 IN ULONG_PTR ulClientHatch
,
349 IN ULONG_PTR ulHatch
,
353 IN BOOL bOldStylePen
,
354 IN OPTIONAL HBRUSH hBrush
)
356 NTSTATUS Status
= STATUS_SUCCESS
;
357 DWORD
* pSafeStyle
= NULL
;
360 if ((int)dwStyleCount
< 0) return 0;
361 if (dwStyleCount
> 16)
363 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
367 if (dwStyleCount
> 0)
369 pSafeStyle
= ExAllocatePoolWithTag(NonPagedPool
, dwStyleCount
* sizeof(DWORD
), TAG_PENSTYLES
);
372 SetLastNtError(ERROR_NOT_ENOUGH_MEMORY
);
377 ProbeForRead(pUnsafeStyle
, dwStyleCount
* sizeof(DWORD
), 1);
378 RtlCopyMemory(pSafeStyle
,
380 dwStyleCount
* sizeof(DWORD
));
384 Status
= _SEH_GetExceptionCode();
387 if(!NT_SUCCESS(Status
))
389 SetLastNtError(Status
);
390 ExFreePoolWithTag(pSafeStyle
, TAG_PENSTYLES
);
395 if (ulBrushStyle
== BS_PATTERN
)
399 ProbeForRead((PVOID
)ulHatch
, cjDIB
, 1);
403 Status
= _SEH_GetExceptionCode();
406 if(!NT_SUCCESS(Status
))
408 SetLastNtError(Status
);
409 if (pSafeStyle
) ExFreePoolWithTag(pSafeStyle
, TAG_PENSTYLES
);
414 hPen
= IntGdiExtCreatePen(dwPenStyle
,
426 if (!hPen
&& pSafeStyle
)
428 ExFreePoolWithTag(pSafeStyle
, TAG_PENSTYLES
);
445 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
447 pDC
= DC_LockDc(hDC
);
453 hOrgPen
= IntGdiSelectPen(pDC
,hPen
);