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 ULONG aulStyleAlternate
[] = { 1, 1 };
90 static ULONG aulStyleDash
[] = { 6, 2 };
91 static ULONG aulStyleDot
[] = { 1, 1 };
92 static ULONG aulStyleDashDot
[] = { 3, 2, 1, 2 };
93 static ULONG aulStyleDashDotDot
[] = { 3, 1, 1, 1, 1, 1 };
96 dwWidth
= abs(dwWidth
);
98 if ( (dwPenStyle
& PS_STYLE_MASK
) == PS_NULL
)
100 return StockObjects
[NULL_PEN
];
105 pbrushPen
= PEN_AllocPenWithHandle();
109 pbrushPen
= PEN_AllocExtPenWithHandle();
114 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
115 DPRINT("Can't allocate pen\n");
118 hPen
= pbrushPen
->BaseObject
.hHmgr
;
120 // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
121 if ((bOldStylePen
) && (!dwWidth
) && ((dwPenStyle
& PS_STYLE_MASK
) != PS_SOLID
))
124 pbrushPen
->lWidth
= dwWidth
;
125 FLOATOBJ_SetLong(&pbrushPen
->eWidth
, pbrushPen
->lWidth
);
126 pbrushPen
->ulPenStyle
= dwPenStyle
;
127 pbrushPen
->BrushAttr
.lbColor
= ulColor
;
128 pbrushPen
->iBrushStyle
= ulBrushStyle
;
129 // FIXME: Copy the bitmap first ?
130 pbrushPen
->hbmClient
= (HANDLE
)ulClientHatch
;
131 pbrushPen
->dwStyleCount
= 0;
132 pbrushPen
->pStyle
= NULL
;
133 pbrushPen
->ulStyleSize
= 0;
135 pbrushPen
->flAttrs
= bOldStylePen
? BR_IS_OLDSTYLEPEN
: BR_IS_PEN
;
137 // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
138 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && ( dwWidth
!= 1) )
140 // If dwPenStyle is PS_COSMETIC, the brush style must be BS_SOLID.
141 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && (ulBrushStyle
!= BS_SOLID
) )
144 switch (dwPenStyle
& PS_STYLE_MASK
)
147 pbrushPen
->flAttrs
|= BR_IS_NULL
;
151 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
155 pbrushPen
->flAttrs
|= BR_IS_SOLID
| BR_IS_DEFAULTSTYLE
;
156 pbrushPen
->pStyle
= aulStyleAlternate
;
157 pbrushPen
->dwStyleCount
= _countof(aulStyleAlternate
);
161 pbrushPen
->flAttrs
|= BR_IS_SOLID
| BR_IS_DEFAULTSTYLE
;
162 pbrushPen
->pStyle
= aulStyleDot
;
163 pbrushPen
->dwStyleCount
= _countof(aulStyleDot
);
167 pbrushPen
->flAttrs
|= BR_IS_SOLID
| BR_IS_DEFAULTSTYLE
;
168 pbrushPen
->pStyle
= aulStyleDash
;
169 pbrushPen
->dwStyleCount
= _countof(aulStyleDash
);
173 pbrushPen
->flAttrs
|= BR_IS_SOLID
| BR_IS_DEFAULTSTYLE
;
174 pbrushPen
->pStyle
= aulStyleDashDot
;
175 pbrushPen
->dwStyleCount
= _countof(aulStyleDashDot
);
179 pbrushPen
->flAttrs
|= BR_IS_SOLID
| BR_IS_DEFAULTSTYLE
;
180 pbrushPen
->pStyle
= aulStyleDashDotDot
;
181 pbrushPen
->dwStyleCount
= _countof(aulStyleDashDotDot
);
185 pbrushPen
->flAttrs
|= (BR_IS_SOLID
| BR_IS_INSIDEFRAME
);
191 BOOL has_neg
= FALSE
, all_zero
= TRUE
;
193 for(i
= 0; (i
< dwStyleCount
) && !has_neg
; i
++)
195 has_neg
= has_neg
|| (((INT
)(pStyle
[i
])) < 0);
196 all_zero
= all_zero
&& (pStyle
[i
] == 0);
199 if(all_zero
|| has_neg
)
204 /* FIXME: What style here? */
205 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
206 pbrushPen
->dwStyleCount
= dwStyleCount
;
207 pbrushPen
->pStyle
= pStyle
;
211 DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle
);
215 if (pbrushPen
->pStyle
!= NULL
)
217 for (i
= 0; i
< pbrushPen
->dwStyleCount
; i
++)
219 pbrushPen
->ulStyleSize
+= pbrushPen
->pStyle
[i
];
223 NT_ASSERT((pbrushPen
->dwStyleCount
== 0) || (pbrushPen
->pStyle
!= NULL
));
225 PEN_UnlockPen(pbrushPen
);
229 EngSetLastError(ERROR_INVALID_PARAMETER
);
230 pbrushPen
->pStyle
= NULL
;
231 GDIOBJ_vDeleteObject(&pbrushPen
->BaseObject
);
238 IntGdiSetSolidPenColor(HPEN hPen
, COLORREF Color
)
242 pbrPen
= PEN_ShareLockPen(hPen
);
245 if (pbrPen
->flAttrs
& BR_IS_SOLID
)
247 pbrPen
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
249 PEN_ShareUnlockPen(pbrPen
);
255 PEN_GetObject(PBRUSH pbrushPen
, INT cbCount
, PLOGPEN pBuffer
)
258 PEXTLOGPEN pExtLogPen
;
261 if (pbrushPen
->flAttrs
& BR_IS_OLDSTYLEPEN
)
263 cbRetCount
= sizeof(LOGPEN
);
266 if (cbCount
< cbRetCount
) return 0;
268 if (((pbrushPen
->ulPenStyle
& PS_STYLE_MASK
) == PS_NULL
) &&
269 (cbCount
== sizeof(EXTLOGPEN
)))
271 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
272 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
273 pExtLogPen
->elpWidth
= 0;
274 pExtLogPen
->elpBrushStyle
= pbrushPen
->iBrushStyle
;
275 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
276 pExtLogPen
->elpHatch
= 0;
277 pExtLogPen
->elpNumEntries
= 0;
278 cbRetCount
= sizeof(EXTLOGPEN
);
282 pLogPen
= (PLOGPEN
)pBuffer
;
283 pLogPen
->lopnWidth
.x
= pbrushPen
->lWidth
;
284 pLogPen
->lopnWidth
.y
= 0;
285 pLogPen
->lopnStyle
= pbrushPen
->ulPenStyle
;
286 pLogPen
->lopnColor
= pbrushPen
->BrushAttr
.lbColor
;
292 DWORD dwStyleCount
= (pbrushPen
->flAttrs
& BR_IS_DEFAULTSTYLE
) ?
293 0 : pbrushPen
->dwStyleCount
;
294 cbRetCount
= sizeof(EXTLOGPEN
) - sizeof(DWORD
) + dwStyleCount
* sizeof(DWORD
);
299 if (cbCount
< cbRetCount
) return 0;
300 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
301 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
302 pExtLogPen
->elpWidth
= pbrushPen
->lWidth
;
303 pExtLogPen
->elpBrushStyle
= pbrushPen
->iBrushStyle
;
304 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
305 pExtLogPen
->elpHatch
= (ULONG_PTR
)pbrushPen
->hbmClient
;
306 pExtLogPen
->elpNumEntries
= dwStyleCount
;
307 for (i
= 0; i
< dwStyleCount
; i
++)
309 pExtLogPen
->elpStyleEntry
[i
] = pbrushPen
->pStyle
[i
];
318 /* PUBLIC FUNCTIONS ***********************************************************/
328 if ((PenStyle
< PS_SOLID
) ||( PenStyle
> PS_INSIDEFRAME
))
330 EngSetLastError(ERROR_INVALID_PARAMETER
);
334 return IntGdiExtCreatePen(PenStyle
,
352 IN ULONG ulBrushStyle
,
354 IN ULONG_PTR ulClientHatch
,
355 IN ULONG_PTR ulHatch
,
359 IN BOOL bOldStylePen
,
360 IN OPTIONAL HBRUSH hBrush
)
362 NTSTATUS Status
= STATUS_SUCCESS
;
363 DWORD
* pSafeStyle
= NULL
;
366 if ((int)dwStyleCount
< 0) return 0;
367 if (dwStyleCount
> 16)
369 EngSetLastError(ERROR_INVALID_PARAMETER
);
373 if (((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) &&
374 (ulBrushStyle
!= BS_SOLID
))
376 EngSetLastError(ERROR_INVALID_PARAMETER
);
380 if (((dwPenStyle
& PS_STYLE_MASK
) == PS_NULL
) ||
381 (ulBrushStyle
== BS_NULL
))
383 return StockObjects
[NULL_PEN
];
387 if ((ulBrushStyle
== BS_PATTERN
) ||
388 (ulBrushStyle
== BS_DIBPATTERN
) ||
389 (ulBrushStyle
== BS_DIBPATTERNPT
))
393 else if ((ulBrushStyle
!= BS_SOLID
) &&
394 (ulBrushStyle
!= BS_HATCHED
))
396 EngSetLastError(ERROR_INVALID_PARAMETER
);
400 if ((dwPenStyle
& PS_STYLE_MASK
) != PS_USERSTYLE
)
406 if (dwStyleCount
> 0)
408 if (pUnsafeStyle
== NULL
)
410 EngSetLastError(ERROR_INVALID_PARAMETER
);
414 pSafeStyle
= ExAllocatePoolWithTag(NonPagedPool
,
415 dwStyleCount
* sizeof(DWORD
),
419 SetLastNtError(ERROR_NOT_ENOUGH_MEMORY
);
424 ProbeForRead(pUnsafeStyle
, dwStyleCount
* sizeof(DWORD
), 1);
425 RtlCopyMemory(pSafeStyle
,
427 dwStyleCount
* sizeof(DWORD
));
429 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
431 Status
= _SEH2_GetExceptionCode();
434 if(!NT_SUCCESS(Status
))
436 SetLastNtError(Status
);
437 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
442 if (ulBrushStyle
== BS_PATTERN
)
446 ProbeForRead((PVOID
)ulHatch
, cjDIB
, 1);
448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
450 Status
= _SEH2_GetExceptionCode();
453 if(!NT_SUCCESS(Status
))
455 SetLastNtError(Status
);
456 if (pSafeStyle
) ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
461 hPen
= IntGdiExtCreatePen(dwPenStyle
,
473 if (!hPen
&& pSafeStyle
)
475 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);