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