2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Pen functiona
5 * FILE: subsys/win32k/objects/pen.c
14 /* PRIVATE FUNCTIONS **********************************************************/
18 PEN_ShareLockPen(HGDIOBJ hobj
)
20 if (GDI_HANDLE_GET_TYPE(hobj
) != GDILoObjType_LO_PEN_TYPE
&&
21 GDI_HANDLE_GET_TYPE(hobj
) != GDILoObjType_LO_EXTPEN_TYPE
)
26 return (PBRUSH
)GDIOBJ_ReferenceObjectByHandle(hobj
, GDIObjType_BRUSH_TYPE
);
33 IN ULONG ulBrushStyle
,
35 IN ULONG_PTR ulClientHatch
,
41 IN OPTIONAL HBRUSH hbrush
)
45 static const BYTE PatternAlternate
[] = {0x55, 0x55, 0x55, 0};
46 static const BYTE PatternDash
[] = {0xFF, 0xFF, 0xC0, 0};
47 static const BYTE PatternDot
[] = {0xE3, 0x8E, 0x38, 0};
48 static const BYTE PatternDashDot
[] = {0xFF, 0x81, 0xC0, 0};
49 static const BYTE PatternDashDotDot
[] = {0xFF, 0x8E, 0x38, 0};
51 dwWidth
= abs(dwWidth
);
53 if ( (dwPenStyle
& PS_STYLE_MASK
) == PS_NULL
)
55 return StockObjects
[NULL_PEN
];
60 pbrushPen
= PEN_AllocPenWithHandle();
64 pbrushPen
= PEN_AllocExtPenWithHandle();
69 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
70 DPRINT("Can't allocate pen\n");
73 hPen
= pbrushPen
->BaseObject
.hHmgr
;
75 // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
76 if ((bOldStylePen
) && (!dwWidth
) && (dwPenStyle
& PS_STYLE_MASK
) != PS_SOLID
)
79 pbrushPen
->ptPenWidth
.x
= dwWidth
;
80 pbrushPen
->ptPenWidth
.y
= 0;
81 pbrushPen
->ulPenStyle
= dwPenStyle
;
82 pbrushPen
->BrushAttr
.lbColor
= ulColor
;
83 pbrushPen
->ulStyle
= ulBrushStyle
;
84 // FIXME: Copy the bitmap first ?
85 pbrushPen
->hbmClient
= (HANDLE
)ulClientHatch
;
86 pbrushPen
->dwStyleCount
= dwStyleCount
;
87 pbrushPen
->pStyle
= pStyle
;
89 pbrushPen
->flAttrs
= bOldStylePen
? BR_IS_OLDSTYLEPEN
: BR_IS_PEN
;
91 // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
92 if ( !(bOldStylePen
) && ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
) && ( dwWidth
!= 1) )
95 switch (dwPenStyle
& PS_STYLE_MASK
)
98 pbrushPen
->flAttrs
|= BR_IS_NULL
;
102 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
106 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
107 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternAlternate
);
111 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
112 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDot
);
116 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
117 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDash
);
121 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
122 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDot
);
126 pbrushPen
->flAttrs
|= BR_IS_BITMAP
;
127 pbrushPen
->hbmPattern
= GreCreateBitmap(24, 1, 1, 1, (LPBYTE
)PatternDashDotDot
);
131 pbrushPen
->flAttrs
|= (BR_IS_SOLID
|BR_IS_INSIDEFRAME
);
135 if ((dwPenStyle
& PS_TYPE_MASK
) == PS_COSMETIC
)
137 /* FIXME: PS_USERSTYLE workaround */
138 DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n");
139 pbrushPen
->flAttrs
|= BR_IS_SOLID
;
145 BOOL has_neg
= FALSE
, all_zero
= TRUE
;
147 for(i
= 0; (i
< dwStyleCount
) && !has_neg
; i
++)
149 has_neg
= has_neg
|| (((INT
)(pStyle
[i
])) < 0);
150 all_zero
= all_zero
&& (pStyle
[i
] == 0);
153 if(all_zero
|| has_neg
)
158 /* FIXME: What style here? */
159 pbrushPen
->flAttrs
|= 0;
163 DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle
);
165 PEN_UnlockPen(pbrushPen
);
169 EngSetLastError(ERROR_INVALID_PARAMETER
);
170 pbrushPen
->pStyle
= NULL
;
171 GDIOBJ_vDeleteObject(&pbrushPen
->BaseObject
);
176 IntGdiSetSolidPenColor(HPEN hPen
, COLORREF Color
)
180 pbrPen
= PEN_ShareLockPen(hPen
);
183 if (pbrPen
->flAttrs
& BR_IS_SOLID
)
185 pbrPen
->BrushAttr
.lbColor
= Color
& 0xFFFFFF;
187 PEN_ShareUnlockPen(pbrPen
);
192 PEN_GetObject(PBRUSH pbrushPen
, INT cbCount
, PLOGPEN pBuffer
)
195 PEXTLOGPEN pExtLogPen
;
198 if (pbrushPen
->flAttrs
& BR_IS_OLDSTYLEPEN
)
200 cbRetCount
= sizeof(LOGPEN
);
204 if (cbCount
< cbRetCount
) return 0;
206 if ( (pbrushPen
->ulPenStyle
& PS_STYLE_MASK
) == PS_NULL
&&
207 cbCount
== sizeof(EXTLOGPEN
))
209 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
210 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
211 pExtLogPen
->elpWidth
= 0;
212 pExtLogPen
->elpBrushStyle
= pbrushPen
->ulStyle
;
213 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
214 pExtLogPen
->elpHatch
= 0;
215 pExtLogPen
->elpNumEntries
= 0;
216 cbRetCount
= sizeof(EXTLOGPEN
);
220 pLogPen
= (PLOGPEN
)pBuffer
;
221 pLogPen
->lopnWidth
= pbrushPen
->ptPenWidth
;
222 pLogPen
->lopnStyle
= pbrushPen
->ulPenStyle
;
223 pLogPen
->lopnColor
= pbrushPen
->BrushAttr
.lbColor
;
229 // FIXME: Can we trust in dwStyleCount being <= 16?
230 cbRetCount
= sizeof(EXTLOGPEN
) - sizeof(DWORD
) + pbrushPen
->dwStyleCount
* sizeof(DWORD
);
235 if (cbCount
< cbRetCount
) return 0;
236 pExtLogPen
= (PEXTLOGPEN
)pBuffer
;
237 pExtLogPen
->elpPenStyle
= pbrushPen
->ulPenStyle
;
238 pExtLogPen
->elpWidth
= pbrushPen
->ptPenWidth
.x
;
239 pExtLogPen
->elpBrushStyle
= pbrushPen
->ulStyle
;
240 pExtLogPen
->elpColor
= pbrushPen
->BrushAttr
.lbColor
;
241 pExtLogPen
->elpHatch
= (ULONG_PTR
)pbrushPen
->hbmClient
;
242 pExtLogPen
->elpNumEntries
= pbrushPen
->dwStyleCount
;
243 for (i
= 0; i
< pExtLogPen
->elpNumEntries
; i
++)
245 pExtLogPen
->elpStyleEntry
[i
] = pbrushPen
->pStyle
[i
];
254 /* PUBLIC FUNCTIONS ***********************************************************/
263 if ( PenStyle
< PS_SOLID
|| PenStyle
> PS_INSIDEFRAME
)
265 EngSetLastError(ERROR_INVALID_PARAMETER
);
269 return IntGdiExtCreatePen(PenStyle
,
286 IN ULONG ulBrushStyle
,
288 IN ULONG_PTR ulClientHatch
,
289 IN ULONG_PTR ulHatch
,
293 IN BOOL bOldStylePen
,
294 IN OPTIONAL HBRUSH hBrush
)
296 NTSTATUS Status
= STATUS_SUCCESS
;
297 DWORD
* pSafeStyle
= NULL
;
300 if ((int)dwStyleCount
< 0) return 0;
301 if (dwStyleCount
> 16)
303 EngSetLastError(ERROR_INVALID_PARAMETER
);
307 if (dwStyleCount
> 0)
309 pSafeStyle
= ExAllocatePoolWithTag(NonPagedPool
, dwStyleCount
* sizeof(DWORD
), GDITAG_PENSTYLE
);
312 SetLastNtError(ERROR_NOT_ENOUGH_MEMORY
);
317 ProbeForRead(pUnsafeStyle
, dwStyleCount
* sizeof(DWORD
), 1);
318 RtlCopyMemory(pSafeStyle
,
320 dwStyleCount
* sizeof(DWORD
));
322 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
324 Status
= _SEH2_GetExceptionCode();
327 if(!NT_SUCCESS(Status
))
329 SetLastNtError(Status
);
330 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
335 if (ulBrushStyle
== BS_PATTERN
)
339 ProbeForRead((PVOID
)ulHatch
, cjDIB
, 1);
341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
343 Status
= _SEH2_GetExceptionCode();
346 if(!NT_SUCCESS(Status
))
348 SetLastNtError(Status
);
349 if (pSafeStyle
) ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);
354 hPen
= IntGdiExtCreatePen(dwPenStyle
,
366 if (!hPen
&& pSafeStyle
)
368 ExFreePoolWithTag(pSafeStyle
, GDITAG_PENSTYLE
);