xref: /reactos/win32ss/gdi/eng/pathobj.c (revision 2196a06f)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS win32 subsystem
4  * PURPOSE:          PATHOBJ service routines
5  * FILE:             win32ss/gdi/eng/pathobj.c
6  * PROGRAMERS:       Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <win32k.h>
12 #undef XFORMOBJ
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* FUNCTIONS *****************************************************************/
18 
19 /* FIXME: set last error */
20 /* FIXME: PATHOBJ_vEnumStartClipLines and PATHOBJ_bEnumClipLines */
21 
22 /*
23  * @implemented
24  */
25 PATHOBJ*
26 APIENTRY
27 EngCreatePath(VOID)
28 {
29     PEPATHOBJ pPathObj;
30     const ULONG size = sizeof(EPATHOBJ);
31 
32     PPATH pPath = PATH_AllocPathWithHandle();
33     if (pPath == NULL)
34     {
35         return NULL;
36     }
37 
38     pPathObj = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
39     if (pPathObj == NULL)
40     {
41         return NULL;
42     }
43     RtlZeroMemory(pPathObj, size);
44 
45     pPathObj->pPath = pPath;
46 
47     pPath->flType = PATHTYPE_KEEPME;
48     pPath->epo = pPathObj;
49 
50     return &pPathObj->po;
51 }
52 
53 /*
54  * @implemented
55  */
56 VOID
57 APIENTRY
58 EngDeletePath(IN PATHOBJ *ppo)
59 {
60     PEPATHOBJ pPathObj;
61     PEXTPATHDATA ppd, ppdNext;
62     PPATH pPath;
63 
64     pPathObj = (PEPATHOBJ)ppo;
65     if (pPathObj == NULL || pPathObj->pPath == NULL)
66         return;
67 
68     pPath = pPathObj->pPath;
69 
70     for (ppd = pPath->ppdFirst; ppd; ppd = ppdNext)
71     {
72         ppdNext = ppd->ppdNext;
73         ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
74     }
75     ExFreePoolWithTag(pPathObj, GDITAG_PATHOBJ);
76     GDIOBJ_vDeleteObject(&pPath->BaseObject);
77 }
78 
79 /*
80  * @implemented
81  */
82 BOOL
83 APIENTRY
84 PATHOBJ_bCloseFigure(IN PATHOBJ *ppo)
85 {
86     PEXTPATHDATA ppd;
87     PEPATHOBJ pPathObj = (PEPATHOBJ)ppo;
88     if (pPathObj == NULL || pPathObj->pPath == NULL)
89         return FALSE;
90 
91     ppd = pPathObj->pPath->ppdLast;
92     if (ppd == NULL)
93         return FALSE;
94 
95     ppd->pd.flags |= PD_CLOSEFIGURE | PD_ENDSUBPATH;
96     return TRUE;
97 }
98 
99 /*
100  * @implemented
101  */
102 VOID
103 APIENTRY
104 PATHOBJ_vEnumStart(IN PATHOBJ *ppo)
105 {
106     PEPATHOBJ pPathObj = (PEPATHOBJ)ppo;
107     if (pPathObj == NULL || pPathObj->pPath == NULL)
108         return;
109 
110     pPathObj->pPath->ppdCurrent = pPathObj->pPath->ppdFirst;
111 }
112 
113 /*
114  * @implemented
115  */
116 BOOL
117 APIENTRY
118 PATHOBJ_bEnum(
119     IN  PATHOBJ   *ppo,
120     OUT PATHDATA  *ppd)
121 {
122     PEPATHOBJ pPathObj = (PEPATHOBJ)ppo;
123     if (pPathObj == NULL|| pPathObj->pPath == NULL || pPathObj->pPath->ppdCurrent == NULL)
124         return FALSE;
125 
126     *ppd = pPathObj->pPath->ppdCurrent->pd;
127 
128     pPathObj->pPath->ppdCurrent = pPathObj->pPath->ppdCurrent->ppdNext;
129     return (pPathObj->pPath->ppdCurrent != NULL);
130 }
131 
132 /*
133  * @implemented
134  */
135 BOOL
136 APIENTRY
137 PATHOBJ_bMoveTo(
138     IN PATHOBJ  *ppo,
139     IN POINTFIX  ptfx)
140 {
141     PEPATHOBJ pPathObj;
142     PEXTPATHDATA ppd, ppdLast;
143 
144     pPathObj = (PEPATHOBJ)ppo;
145     if (pPathObj == NULL || pPathObj->pPath == NULL)
146         return FALSE;
147 
148     /* allocate a subpath data */
149     ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ);
150     if (ppd == NULL)
151         return FALSE;
152 
153     RtlZeroMemory(ppd, sizeof(EXTPATHDATA));
154 
155     /* add the first point to the subpath */
156     ppd->pd.flags = PD_BEGINSUBPATH;
157     ppd->pd.count = 1;
158     ppd->pd.pptfx = ExAllocatePoolWithTag(PagedPool, sizeof(POINTFIX), GDITAG_PATHOBJ);
159     if (ppd->pd.pptfx == NULL)
160     {
161         ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
162         return FALSE;
163     }
164     ppd->pd.pptfx[0] = ptfx;
165 
166     ppdLast = pPathObj->pPath->ppdLast;
167     if (ppdLast)
168     {
169         /* end the last subpath */
170         ppdLast->pd.flags |= PD_ENDSUBPATH;
171 
172         /* add the subpath to the last */
173         ppdLast->ppdNext = ppd;
174         pPathObj->pPath->ppdLast = ppd;
175     }
176     else
177     {
178         /* add the subpath */
179         pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd;
180     }
181 
182     pPathObj->po.cCurves++;
183 
184     return TRUE;
185 }
186 
187 /*
188  * @implemented
189  */
190 BOOL
191 APIENTRY
192 PATHOBJ_bPolyLineTo(
193     IN PATHOBJ  *ppo,
194     IN POINTFIX  *pptfx,
195     IN ULONG  cptfx)
196 {
197     PEPATHOBJ pPathObj;
198     PEXTPATHDATA ppd, ppdLast;
199     PPOINTFIX pptfxNew, pptfxOld;
200     ULONG size;
201 
202     pPathObj = (PEPATHOBJ)ppo;
203     if (pPathObj == NULL || pPathObj->pPath == NULL || pptfx == NULL || cptfx == 0)
204         return FALSE;
205 
206     ppdLast = pPathObj->pPath->ppdLast;
207     if (ppdLast == NULL)
208     {
209         /* allocate a subpath data */
210         ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ);
211         if (ppd == NULL)
212             return FALSE;
213 
214         /* store data */
215         RtlZeroMemory(ppd, sizeof(EXTPATHDATA));
216         ppd->pd.flags = PD_BEGINSUBPATH;
217 
218         size = cptfx * sizeof(POINTFIX);
219         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
220         if (pptfxNew == NULL)
221         {
222             ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
223             return FALSE;
224         }
225         RtlCopyMemory(pptfxNew, pptfx, size);
226         ppd->pd.pptfx = pptfxNew;
227         ppd->pd.count = cptfx;
228 
229         /* set the subpath */
230         pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd;
231 
232         pPathObj->po.cCurves++;
233     }
234     else if (ppdLast->pd.flags & (PD_BEZIERS | PD_ENDSUBPATH))
235     {
236         /* allocate a subpath data */
237         ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ);
238         if (ppd == NULL)
239             return FALSE;
240 
241         /* store data */
242         RtlZeroMemory(ppd, sizeof(EXTPATHDATA));
243         ppd->pd.flags = 0;
244         ppd->pd.count = cptfx;
245 
246         size = cptfx * sizeof(POINTFIX);
247         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
248         if (pptfxNew == NULL)
249         {
250             ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
251             return FALSE;
252         }
253         RtlCopyMemory(pptfxNew, pptfx, size);
254         ppd->pd.pptfx = pptfxNew;
255 
256         /* add to last */
257         ppdLast->ppdNext = ppd;
258         pPathObj->pPath->ppdLast = ppd;
259 
260         pPathObj->po.cCurves++;
261     }
262     else
263     {
264         /* concatenate ppdLast->pd.pptfx and pptfx */
265         size = (ppdLast->pd.count + cptfx) * sizeof(POINTFIX);
266         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
267         if (pptfxNew == NULL)
268             return FALSE;
269 
270         size = ppdLast->pd.count * sizeof(POINTFIX);
271         RtlCopyMemory(&pptfxNew[0], ppdLast->pd.pptfx, size);
272         size = cptfx * sizeof(POINTFIX);
273         RtlCopyMemory(&pptfxNew[ppdLast->pd.count], pptfx, size);
274 
275         pptfxOld = ppdLast->pd.pptfx;
276         ppdLast->pd.pptfx = pptfxNew;
277         ppdLast->pd.count += cptfx;
278         ExFreePoolWithTag(pptfxOld, GDITAG_PATHOBJ);
279     }
280 
281     return TRUE;
282 }
283 
284 /*
285  * @implemented
286  */
287 BOOL
288 APIENTRY
289 PATHOBJ_bPolyBezierTo(
290     IN PATHOBJ  *ppo,
291     IN POINTFIX  *pptfx,
292     IN ULONG  cptfx)
293 {
294     PEPATHOBJ pPathObj;
295     PEXTPATHDATA ppd, ppdLast;
296     PPOINTFIX pptfxNew, pptfxOld;
297     ULONG size;
298 
299     pPathObj = (PEPATHOBJ)ppo;
300     if (pPathObj == NULL || pPathObj->pPath == NULL || pptfx == NULL || cptfx == 0)
301         return FALSE;
302 
303     ppdLast = pPathObj->pPath->ppdLast;
304     if (ppdLast == NULL)
305     {
306         /* allocate a subpath data */
307         ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ);
308         if (ppd == NULL)
309             return FALSE;
310 
311         /* store data */
312         RtlZeroMemory(ppd, sizeof(EXTPATHDATA));
313         ppd->pd.flags = PD_BEGINSUBPATH | PD_BEZIERS;
314 
315         size = cptfx * sizeof(POINTFIX);
316         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
317         if (pptfxNew == NULL)
318         {
319             ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
320             return FALSE;
321         }
322         RtlCopyMemory(pptfxNew, pptfx, size);
323         ppd->pd.pptfx = pptfxNew;
324         ppd->pd.count = cptfx;
325 
326         /* set the subpath */
327         pPathObj->pPath->ppdLast = pPathObj->pPath->ppdFirst = ppd;
328 
329         pPathObj->po.cCurves++;
330     }
331     else if (!(ppdLast->pd.flags & PD_BEZIERS) || (ppdLast->pd.flags & PD_ENDSUBPATH))
332     {
333         /* allocate a subpath data */
334         ppd = ExAllocatePoolWithTag(PagedPool, sizeof(EXTPATHDATA), GDITAG_PATHOBJ);
335         if (ppd == NULL)
336             return FALSE;
337 
338         /* store data */
339         RtlZeroMemory(ppd, sizeof(EXTPATHDATA));
340         ppd->pd.flags = PD_BEZIERS;
341         ppd->pd.count = cptfx;
342 
343         size = cptfx * sizeof(POINTFIX);
344         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
345         if (pptfxNew == NULL)
346         {
347             ExFreePoolWithTag(ppd, GDITAG_PATHOBJ);
348             return FALSE;
349         }
350         RtlCopyMemory(pptfxNew, pptfx, size);
351         ppd->pd.pptfx = pptfxNew;
352 
353         /* add to last */
354         ppdLast->ppdNext = ppd;
355         pPathObj->pPath->ppdLast = ppd;
356 
357         pPathObj->po.cCurves++;
358     }
359     else
360     {
361         /* concatenate ppdLast->pd.pptfx and pptfx */
362         size = (ppdLast->pd.count + cptfx) * sizeof(POINTFIX);
363         pptfxNew = ExAllocatePoolWithTag(PagedPool, size, GDITAG_PATHOBJ);
364         if (pptfxNew == NULL)
365             return FALSE;
366 
367         size = ppdLast->pd.count * sizeof(POINTFIX);
368         RtlCopyMemory(&pptfxNew[0], ppdLast->pd.pptfx, size);
369         size = cptfx * sizeof(POINTFIX);
370         RtlCopyMemory(&pptfxNew[ppdLast->pd.count], pptfx, size);
371 
372         pptfxOld = ppdLast->pd.pptfx;
373         ppdLast->pd.pptfx = pptfxNew;
374         ppdLast->pd.count += cptfx;
375         ExFreePoolWithTag(pptfxOld, GDITAG_PATHOBJ);
376     }
377 
378     pPathObj->po.fl |= PO_BEZIERS;
379 
380     return TRUE;
381 }
382 
383 VOID
384 APIENTRY
385 PATHOBJ_vEnumStartClipLines(
386     IN PATHOBJ  *ppo,
387     IN CLIPOBJ  *pco,
388     IN SURFOBJ  *pso,
389     IN LINEATTRS  *pla)
390 {
391     UNIMPLEMENTED;
392 }
393 
394 BOOL
395 APIENTRY
396 PATHOBJ_bEnumClipLines(
397     IN PATHOBJ  *ppo,
398     IN ULONG  cb,
399     OUT CLIPLINE  *pcl)
400 {
401     UNIMPLEMENTED;
402     return FALSE;
403 }
404 
405 /*
406  * @implemented
407  */
408 VOID
409 APIENTRY
410 PATHOBJ_vGetBounds(
411     IN PATHOBJ  *ppo,
412     OUT PRECTFX  prectfx)
413 {
414     FIX xLeft, yTop, xRight, yBottom;
415     PEPATHOBJ pPathObj;
416     PEXTPATHDATA ppd, ppdNext;
417     ULONG i;
418 
419     pPathObj = (PEPATHOBJ)ppo;
420     if (pPathObj == NULL || pPathObj->pPath == NULL || prectfx == NULL)
421         return;
422 
423     yTop = xLeft = MAXLONG;
424     yBottom = xRight = MINLONG;
425 
426     for (ppd = pPathObj->pPath->ppdFirst; ppd; ppd = ppdNext)
427     {
428         ppdNext = ppd->ppdNext;
429         for (i = 0; i < ppd->pd.count; ++i)
430         {
431             PPOINTFIX pptfx = &ppd->pd.pptfx[i];
432             if (pptfx->x < xLeft)
433                 xLeft = pptfx->x;
434             if (pptfx->x > xRight)
435                 xRight = pptfx->x;
436             if (pptfx->y < yTop)
437                 yTop = pptfx->y;
438             if (pptfx->y > yBottom)
439                 yBottom = pptfx->y;
440         }
441     }
442 
443     if (xLeft <= xRight && yTop <= yBottom)
444     {
445         prectfx->xLeft = xLeft;
446         prectfx->yTop = yTop;
447         prectfx->xRight = xRight + 1;
448         prectfx->yBottom = yBottom + 1;
449     }
450     else
451     {
452         RtlZeroMemory(prectfx, sizeof(*prectfx));
453     }
454 }
455 
456 /* EOF */
457