xref: /reactos/win32ss/gdi/gdi32/objects/brush.c (revision 84344399)
1 #include <precomp.h>
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 
7 
8 /*
9  * @implemented
10  */
11 HPEN
12 APIENTRY
13 ExtCreatePen(DWORD dwPenStyle,
14              DWORD dwWidth,
15              CONST LOGBRUSH *lplb,
16              DWORD dwStyleCount,
17              CONST DWORD *lpStyle)
18 {
19     PVOID lpPackedDIB = NULL;
20     HPEN hPen = NULL;
21     PBITMAPINFO pConvertedInfo = NULL;
22     UINT ConvertedInfoSize = 0, lbStyle;
23     BOOL Hit = FALSE;
24 
25     if ((dwPenStyle & PS_STYLE_MASK) == PS_USERSTYLE)
26     {
27         if(!lpStyle)
28         {
29             SetLastError(ERROR_INVALID_PARAMETER);
30             return 0;
31         }
32     } // This is an enhancement and prevents a call to kernel space.
33     else if ((dwPenStyle & PS_STYLE_MASK) == PS_INSIDEFRAME &&
34              (dwPenStyle & PS_TYPE_MASK) != PS_GEOMETRIC)
35     {
36         SetLastError(ERROR_INVALID_PARAMETER);
37         return 0;
38     }
39     else if ((dwPenStyle & PS_STYLE_MASK) == PS_ALTERNATE &&
40              (dwPenStyle & PS_TYPE_MASK) != PS_COSMETIC)
41     {
42         SetLastError(ERROR_INVALID_PARAMETER);
43         return 0;
44     }
45     else
46     {
47         if (dwStyleCount || lpStyle)
48         {
49             SetLastError(ERROR_INVALID_PARAMETER);
50             return 0;
51         }
52     }
53 
54     lbStyle = lplb->lbStyle;
55 
56     if (lplb->lbStyle > BS_HATCHED)
57     {
58         if (lplb->lbStyle == BS_PATTERN)
59         {
60             pConvertedInfo = (PBITMAPINFO)lplb->lbHatch;
61             if (!pConvertedInfo) return 0;
62         }
63         else
64         {
65             if ((lplb->lbStyle == BS_DIBPATTERN) || (lplb->lbStyle == BS_DIBPATTERNPT))
66             {
67                 if (lplb->lbStyle == BS_DIBPATTERN)
68                 {
69                     lbStyle = BS_DIBPATTERNPT;
70                     lpPackedDIB = GlobalLock((HGLOBAL)lplb->lbHatch);
71                     if (lpPackedDIB == NULL) return 0;
72                 }
73                 pConvertedInfo = ConvertBitmapInfo((PBITMAPINFO)lpPackedDIB,
74                                                    lplb->lbColor,
75                                                    &ConvertedInfoSize,
76                                                    TRUE);
77                 Hit = TRUE; // We converted DIB.
78             }
79             else
80                 pConvertedInfo = (PBITMAPINFO)lpStyle;
81         }
82     }
83     else
84         pConvertedInfo = (PBITMAPINFO)lplb->lbHatch;
85 
86 
87     hPen = NtGdiExtCreatePen(dwPenStyle,
88                              dwWidth,
89                              lbStyle,
90                              lplb->lbColor,
91                              lplb->lbHatch,
92                              (ULONG_PTR)pConvertedInfo,
93                              dwStyleCount,
94                              (PULONG)lpStyle,
95                              ConvertedInfoSize,
96                              FALSE,
97                              NULL);
98 
99 
100     if (lplb->lbStyle == BS_DIBPATTERN) GlobalUnlock((HGLOBAL)lplb->lbHatch);
101 
102     if (Hit)
103     {
104         if ((PBITMAPINFO)lpPackedDIB != pConvertedInfo)
105             RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
106     }
107     return hPen;
108 }
109 
110 /*
111  * @implemented
112  */
113 HBRUSH WINAPI
114 CreateDIBPatternBrush(
115     HGLOBAL hglbDIBPacked,
116     UINT fuColorSpec)
117 {
118     PVOID lpPackedDIB;
119     HBRUSH hBrush = NULL;
120     PBITMAPINFO pConvertedInfo;
121     UINT ConvertedInfoSize;
122 
123     lpPackedDIB = GlobalLock(hglbDIBPacked);
124     if (lpPackedDIB == NULL)
125         return 0;
126 
127     pConvertedInfo = ConvertBitmapInfo((PBITMAPINFO)lpPackedDIB, fuColorSpec,
128                                        &ConvertedInfoSize, TRUE);
129     if (pConvertedInfo)
130     {
131         hBrush = NtGdiCreateDIBBrush(pConvertedInfo, fuColorSpec,
132                                      ConvertedInfoSize, FALSE, FALSE, lpPackedDIB);
133         if ((PBITMAPINFO)lpPackedDIB != pConvertedInfo)
134             RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
135     }
136 
137     GlobalUnlock(hglbDIBPacked);
138 
139     return hBrush;
140 }
141 
142 /*
143  * @implemented
144  */
145 HBRUSH WINAPI
146 CreateDIBPatternBrushPt(
147     CONST VOID *lpPackedDIB,
148     UINT fuColorSpec)
149 {
150     HBRUSH hBrush = NULL;
151     PBITMAPINFO pConvertedInfo;
152     UINT ConvertedInfoSize;
153 
154     if (lpPackedDIB == NULL)
155         return 0;
156 
157     pConvertedInfo = ConvertBitmapInfo((PBITMAPINFO)lpPackedDIB, fuColorSpec,
158                                        &ConvertedInfoSize, TRUE);
159     if (pConvertedInfo)
160     {
161         hBrush = NtGdiCreateDIBBrush(pConvertedInfo, fuColorSpec,
162                                      ConvertedInfoSize, FALSE, FALSE, (PVOID)lpPackedDIB);
163         if ((PBITMAPINFO)lpPackedDIB != pConvertedInfo)
164             RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
165     }
166 
167     return hBrush;
168 }
169 
170 /*
171  * @implemented
172  */
173 HBRUSH
174 WINAPI
175 CreateHatchBrush(INT fnStyle,
176                  COLORREF clrref)
177 {
178     return NtGdiCreateHatchBrushInternal(fnStyle, clrref, FALSE);
179 }
180 
181 /*
182  * @implemented
183  */
184 HBRUSH
185 WINAPI
186 CreatePatternBrush(HBITMAP hbmp)
187 {
188     return NtGdiCreatePatternBrushInternal(hbmp, FALSE, FALSE);
189 }
190 
191 /*
192  * @implemented
193  */
194 HBRUSH
195 WINAPI
196 CreateSolidBrush(IN COLORREF crColor)
197 {
198     /* Call Server-Side API */
199     return NtGdiCreateSolidBrush(crColor, NULL);
200 }
201 
202 /*
203  * @implemented
204  */
205 HBRUSH WINAPI
206 CreateBrushIndirect(
207     CONST LOGBRUSH *LogBrush)
208 {
209     HBRUSH hBrush;
210 
211     switch (LogBrush->lbStyle)
212     {
213     case BS_DIBPATTERN:
214         hBrush = CreateDIBPatternBrush((HGLOBAL)LogBrush->lbHatch,
215                                        LogBrush->lbColor);
216         break;
217 
218     case BS_DIBPATTERNPT:
219         hBrush = CreateDIBPatternBrushPt((PVOID)LogBrush->lbHatch,
220                                          LogBrush->lbColor);
221         break;
222 
223     case BS_PATTERN:
224         hBrush = NtGdiCreatePatternBrushInternal((HBITMAP)LogBrush->lbHatch,
225                  FALSE,
226                  FALSE);
227         break;
228 
229     case BS_PATTERN8X8:
230         hBrush = NtGdiCreatePatternBrushInternal((HBITMAP)LogBrush->lbHatch,
231                  FALSE,
232                  TRUE);
233         break;
234 
235     case BS_SOLID:
236 /*        hBrush = hGetPEBHandle(hctBrushHandle, LogBrush->lbColor);
237         if (!hBrush)*/
238         hBrush = NtGdiCreateSolidBrush(LogBrush->lbColor, 0);
239         break;
240 
241     case BS_HATCHED:
242         hBrush = NtGdiCreateHatchBrushInternal(LogBrush->lbHatch,
243                                                LogBrush->lbColor,
244                                                FALSE);
245         break;
246 
247     case BS_NULL:
248         hBrush = NtGdiGetStockObject(NULL_BRUSH);
249         break;
250 
251     default:
252         SetLastError(ERROR_INVALID_PARAMETER);
253         hBrush = NULL;
254         break;
255     }
256 
257     return hBrush;
258 }
259 
260 /*
261  * @implemented
262  *
263  */
264 BOOL
265 WINAPI
266 GetBrushOrgEx(HDC hdc,LPPOINT pt)
267 {
268     PDC_ATTR Dc_Attr;
269 
270     if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return FALSE;
271     if (pt)
272     {
273         pt->x = Dc_Attr->ptlBrushOrigin.x;
274         pt->y = Dc_Attr->ptlBrushOrigin.y;
275     }
276     return TRUE;
277 }
278 
279 /*
280  * @implemented
281  */
282 BOOL
283 WINAPI
284 SetBrushOrgEx(HDC hdc,
285               int nXOrg,
286               int nYOrg,
287               LPPOINT lppt)
288 {
289     PDC_ATTR Dc_Attr;
290 #if 0
291 // Handle something other than a normal dc object.
292     if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
293     {
294         PLDC pLDC = GdiGetLDC(hdc);
295         if ( (pLDC == NULL) || (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC))
296         {
297             SetLastError(ERROR_INVALID_HANDLE);
298             return FALSE;
299         }
300         if (pLDC->iType == LDC_EMFLDC)
301         {
302             return EMFDRV_SetBrushOrg(hdc, nXOrg, nYOrg); // ReactOS only.
303         }
304         return FALSE;
305     }
306 #endif
307     if (GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID)&Dc_Attr))
308     {
309         PGDIBSSETBRHORG pgSBO;
310 
311         /* Does the caller want the current brush origin to be returned? */
312         if (lppt)
313         {
314             lppt->x = Dc_Attr->ptlBrushOrigin.x;
315             lppt->y = Dc_Attr->ptlBrushOrigin.y;
316         }
317 
318         /* Check if we have nothing to do */
319         if ((nXOrg == Dc_Attr->ptlBrushOrigin.x) &&
320             (nYOrg == Dc_Attr->ptlBrushOrigin.y))
321             return TRUE;
322 
323         /* Allocate a batch command buffer */
324         pgSBO = GdiAllocBatchCommand(hdc, GdiBCSetBrushOrg);
325         if (pgSBO != NULL)
326         {
327             /* Set current brush origin in the DC attribute */
328             Dc_Attr->ptlBrushOrigin.x = nXOrg;
329             Dc_Attr->ptlBrushOrigin.y = nYOrg;
330 
331             /* Setup the GDI batch command */
332             pgSBO->ptlBrushOrigin = Dc_Attr->ptlBrushOrigin;
333 
334             return TRUE;
335         }
336     }
337 
338     /* Fall back to the slower kernel path */
339     return NtGdiSetBrushOrg(hdc, nXOrg, nYOrg, lppt);
340 }
341 
342 /*
343  * @implemented
344  */
345 DWORD
346 WINAPI
347 GetBrushAttributes(HBRUSH hbr)
348 {
349     if ( GDI_HANDLE_IS_STOCKOBJ(hbr) )
350     {
351         return SC_BB_STOCKOBJ;
352     }
353     return 0;
354 }
355 
356 /*
357  * @implemented
358  */
359 HBRUSH
360 WINAPI
361 SetBrushAttributes(HBRUSH hbm, DWORD dwFlags)
362 {
363     if ( dwFlags & ~SC_BB_STOCKOBJ )
364     {
365         return NULL;
366     }
367     return NtGdiSetBrushAttributes(hbm, dwFlags);
368 }
369 
370 /*
371  * @implemented
372  */
373 HBRUSH
374 WINAPI
375 ClearBrushAttributes(HBRUSH hbm, DWORD dwFlags)
376 {
377     if ( dwFlags & ~SC_BB_STOCKOBJ )
378     {
379         return NULL;
380     }
381     return NtGdiClearBrushAttributes(hbm, dwFlags);
382 }
383 
384 /*
385  * @implemented
386  */
387 BOOL
388 WINAPI
389 UnrealizeObject(HGDIOBJ  hgdiobj)
390 {
391     BOOL retValue = TRUE;
392     /*
393        Win 2k Graphics API, Black Book. by coriolis.com
394        Page 62, Note that Steps 3, 5, and 6 are not required for Windows NT(tm)
395        and Windows 2000(tm).
396 
397        Step 5. UnrealizeObject(hTrackBrush);
398      */
399     /*
400         msdn.microsoft.com,
401         "Windows 2000/XP: If hgdiobj is a brush, UnrealizeObject does nothing,
402         and the function returns TRUE. Use SetBrushOrgEx to set the origin of
403         a brush."
404      */
405     if (GDI_HANDLE_GET_TYPE(hgdiobj) != GDI_OBJECT_TYPE_BRUSH)
406     {
407         retValue = NtGdiUnrealizeObject(hgdiobj);
408     }
409 
410     return retValue;
411 }
412