2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Pen functiona
5 * FILE: win32ss/gdi/ntgdi/pen.c
14 /* PRIVATE FUNCTIONS **********************************************************/
21 /* Start with kmode brush attribute */
22 ppen
->pBrushAttr
= &ppen
->BrushAttr
;
27 PEN_AllocPenWithHandle(
32 ppen
= (PBRUSH
)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_PEN_TYPE
, sizeof(PEN
));
44 PEN_AllocExtPenWithHandle(
49 ppen
= (PBRUSH
)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_EXTPEN_TYPE
, sizeof(PEN
));
61 PEN_ShareLockPen(HPEN hobj
)
63 if ((GDI_HANDLE_GET_TYPE(hobj
) != GDILoObjType_LO_PEN_TYPE
) &&
64 (GDI_HANDLE_GET_TYPE(hobj
) != GDILoObjType_LO_EXTPEN_TYPE
))
69 return (PBRUSH
)GDIOBJ_ReferenceObjectByHandle(hobj
, GDIObjType_BRUSH_TYPE
);
77 IN ULONG ulBrushStyle
,
79 IN ULONG_PTR ulClientHatch
,
85 IN OPTIONAL HBRUSH hbrush
)
89 static const BYTE PatternAlternate
[] = {0x55, 0x55, 0x55, 0};
90 static const BYTE PatternDash
[] = {0xFF, 0xFF, 0xC0, 0};
91 static const BYTE PatternDot
[] = {0xE3, 0x8E, 0x38, 0};
92 static const BYTE PatternDashDot
[] = {0xFF, 0x81, 0xC0, 0};
93 static const BYTE PatternDashDotDot
[] = {0xFF, 0x8E, 0x38, 0};
95 dwWidth
= abs(dwWidth
);
97 if ( (dwPenStyle
& PS_STYLE_MASK
) == PS_NULL
)
99 return StockObjects
[NULL_PEN
];
104 pbrushPen
= PEN_AllocPenWithHandle();
108 pbrushPen
= PEN_AllocExtPenWithHandle();
113 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
114 DPRINT("Can't allocate pen\n");
117 hPen
= pbrushPen
->BaseObject
.hHmgr
;
119 // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
120 if ((bOldStylePen
) && (!dwWidth
) && ((dwPenStyle
& PS_STYLE_MASK
) != PS_SOLID
))
123 pbrushPen
->lWidth
= dwWidth
;
124 pbrushPen
->eWidth
= (FLOAT
)pbrushPen
->lWidth
;
125 pbrushPen
->ulPenStyle
= dwPenStyle
;
126 pbrushPen
->BrushAttr
.lbColor
= ulColor
;
127 pbrushPen
->iBrushStyle
= ulBrushStyle
;
128 // FIXME: Copy the bitmap first ?
129 pbrushPen
->hbmClient
= (HANDLE
)ulClientHatch
;
130 pbrushPen
->dwStyleCount
= dwStyleCount
;
131 pbrushPen
->pStyle
= pStyle
;
133 pbrushPen
->flAttrs
= bOldStylePen
? BR_IS_OLDSTYLEPEN
: BR_IS_PEN
;
135 // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
136 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && ( dwWidth
!= 1) )
138 // If dwPenStyle is PS_COSMETIC, the brush style must be BS_SOLID.
139 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && (ulBrushStyle
!= BS_SOLID
) )
142 switch (dwPenStyle
& PS_STYLE_MASK
)
145 pbrushPen
->flAttrs
|= BR_IS_NULL
;
149 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
153 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
154 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternAlternate
);
158 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
159 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDot
);
163 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
164 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDash
);
168 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
169 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDot
);
173 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
174 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDotDot
);
178 pbrushPen
->flAttrs
|= (BR_IS_SOLID
| BR_IS_INSIDEFRAME
);
182 if ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
)
184 /* FIXME: PS_USERSTYLE workaround */
185 DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n");
186 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
192 BOOL has_neg
= FALSE
, all_zero
= TRUE
;
194 for(i
= 0; (i
< dwStyleCount
) && !has_neg
; i
++)
196 has_neg
= has_neg
|| (((INT
)(pStyle
[i
])) < 0);
197 all_zero
= all_zero
&& (pStyle
[i
] == 0);
200 if(all_zero
|| has_neg
)
205 /* FIXME: What style here? */
206 pbrushPen
->flAttrs
|= 0;
210 DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle
);
214 PEN_UnlockPen(pbrushPen
);
218 EngSetLastError(ERROR_INVALID_PARAMETER
);
219 pbrushPen
->pStyle
= NULL
;
220 GDIOBJ_vDeleteObject(&pbrushPen
->BaseObject
);
227 IntGdiSetSolidPenColor(HPEN hPen
, COLORREF Color
)
231 pbrPen
= PEN_ShareLockPen(hPen
);
234 if (pbrPen
->flAttrs
& BR_IS_SOLID
)
236 pbrPen
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
238 PEN_ShareUnlockPen(pbrPen
);
244 PEN_GetObject(PBRUSH pbrushPen
, INT cbCount
, PLOGPEN pBuffer
)
247 PEXTLOGPEN pExtLogPen
;
250 if (pbrushPen
->flAttrs
& BR_IS_OLDSTYLEPEN
)
252 cbRetCount
= sizeof(LOGPEN
);
255 if (cbCount
< cbRetCount
) return 0;
257 if (((pbrushPen
->ulPenStyle
& PS_STYLE_MASK
) == PS_NULL
) &&
258 (cbCount
== sizeof(EXTLOGPEN
)))
260 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
261 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
262 pExtLogPen
->elpWidth
= 0;
263 pExtLogPen
->elpBrushStyle
= pbrushPen
->iBrushStyle
;
264 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
265 pExtLogPen
->elpHatch
= 0;
266 pExtLogPen
->elpNumEntries
= 0;
267 cbRetCount
= sizeof(EXTLOGPEN
);
271 pLogPen
= (PLOGPEN
)pBuffer
;
272 pLogPen
->lopnWidth
.x
= pbrushPen
->lWidth
;
273 pLogPen
->lopnWidth
.y
= 0;
274 pLogPen
->lopnStyle
= pbrushPen
->ulPenStyle
;
275 pLogPen
->lopnColor
= pbrushPen
->BrushAttr
.lbColor
;
281 // FIXME: Can we trust in dwStyleCount being <= 16?
282 cbRetCount
= sizeof(EXTLOGPEN
) - sizeof(DWORD
) + pbrushPen
->dwStyleCount
* sizeof(DWORD
);
287 if (cbCount
< cbRetCount
) return 0;
288 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
289 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
290 pExtLogPen
->elpWidth
= pbrushPen
->lWidth
;
291 pExtLogPen
->elpBrushStyle
= pbrushPen
->iBrushStyle
;
292 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
293 pExtLogPen
->elpHatch
= (ULONG_PTR
)pbrushPen
->hbmClient
;
294 pExtLogPen
->elpNumEntries
= pbrushPen
->dwStyleCount
;
295 for (i
= 0; i
< pExtLogPen
->elpNumEntries
; i
++)
297 pExtLogPen
->elpStyleEntry
[i
] = pbrushPen
->pStyle
[i
];
306 /* PUBLIC FUNCTIONS ***********************************************************/
316 if ((PenStyle
< PS_SOLID
) ||( PenStyle
> PS_INSIDEFRAME
))
318 EngSetLastError(ERROR_INVALID_PARAMETER
);
322 return IntGdiExtCreatePen(PenStyle
,
340 IN ULONG ulBrushStyle
,
342 IN ULONG_PTR ulClientHatch
,
343 IN ULONG_PTR ulHatch
,
347 IN BOOL bOldStylePen
,
348 IN OPTIONAL HBRUSH hBrush
)
350 NTSTATUS Status
= STATUS_SUCCESS
;
351 DWORD
* pSafeStyle
= NULL
;
354 if ((int)dwStyleCount
< 0) return 0;
355 if (dwStyleCount
> 16)
357 EngSetLastError(ERROR_INVALID_PARAMETER
);
361 if (dwStyleCount
> 0)
363 if (pUnsafeStyle
== NULL
)
365 EngSetLastError(ERROR_INVALID_PARAMETER
);
369 pSafeStyle
= ExAllocatePoolWithTag(NonPagedPool
,
370 dwStyleCount
* sizeof(DWORD
),
374 SetLastNtError(ERROR_NOT_ENOUGH_MEMORY
);
379 ProbeForRead(pUnsafeStyle
, dwStyleCount
* sizeof(DWORD
), 1);
380 RtlCopyMemory(pSafeStyle
,
382 dwStyleCount
* sizeof(DWORD
));
384 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
386 Status
= _SEH2_GetExceptionCode();
389 if(!NT_SUCCESS(Status
))
391 SetLastNtError(Status
);
392 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
397 if (ulBrushStyle
== BS_PATTERN
)
401 ProbeForRead((PVOID
)ulHatch
, cjDIB
, 1);
403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
405 Status
= _SEH2_GetExceptionCode();
408 if(!NT_SUCCESS(Status
))
410 SetLastNtError(Status
);
411 if (pSafeStyle
) ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
416 hPen
= IntGdiExtCreatePen(dwPenStyle
,
428 if (!hPen
&& pSafeStyle
)
430 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);