[GDI32] Update Gdi Driver Header.
[reactos.git] / 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 /* 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 */