ReactOS  0.4.14-dev-98-gb0d4763
graphicspath.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Google (Evan Stade)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  */
19 
20 #include <stdarg.h>
21 #include <math.h>
22 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "wingdi.h"
27 
28 #include "objbase.h"
29 
30 #include "gdiplus.h"
31 #include "gdiplus_private.h"
32 #include "wine/debug.h"
33 
35 
39  BYTE type; /* PathPointTypeStart or PathPointTypeLine */
41 };
42 
43 /* init list */
45 {
46  *node = heap_alloc_zero(sizeof(path_list_node_t));
47  if(!*node)
48  return FALSE;
49 
50  (*node)->pt.X = x;
51  (*node)->pt.Y = y;
52  (*node)->type = PathPointTypeStart;
53  (*node)->next = NULL;
54 
55  return TRUE;
56 }
57 
58 /* free all nodes including argument */
60 {
62 
63  while(n){
64  n = n->next;
65  heap_free(node);
66  node = n;
67  }
68 }
69 
70 /* Add a node after 'node' */
71 /*
72  * Returns
73  * pointer on success
74  * NULL on allocation problems
75  */
77 {
78  path_list_node_t *new;
79 
80  new = heap_alloc_zero(sizeof(path_list_node_t));
81  if(!new)
82  return NULL;
83 
84  new->pt.X = x;
85  new->pt.Y = y;
86  new->type = type;
87  new->next = node->next;
88  node->next = new;
89 
90  return new;
91 }
92 
93 /* returns element count */
95 {
96  INT count = 1;
97 
98  while((node = node->next))
99  ++count;
100 
101  return count;
102 }
103 
104 /* GdipFlattenPath helper */
105 /*
106  * Used to recursively flatten single Bezier curve
107  * Parameters:
108  * - start : pointer to start point node;
109  * - (x2, y2): first control point;
110  * - (x3, y3): second control point;
111  * - end : pointer to end point node
112  * - flatness: admissible error of linear approximation.
113  *
114  * Return value:
115  * TRUE : success
116  * FALSE: out of memory
117  *
118  * TODO: used quality criteria should be revised to match native as
119  * closer as possible.
120  */
122  path_list_node_t *end, REAL flatness)
123 {
124  /* this 5 middle points with start/end define to half-curves */
125  GpPointF mp[5];
126  GpPointF pt, pt_st;
128 
129  /* calculate bezier curve middle points == new control points */
130  mp[0].X = (start->pt.X + x2) / 2.0;
131  mp[0].Y = (start->pt.Y + y2) / 2.0;
132  /* middle point between control points */
133  pt.X = (x2 + x3) / 2.0;
134  pt.Y = (y2 + y3) / 2.0;
135  mp[1].X = (mp[0].X + pt.X) / 2.0;
136  mp[1].Y = (mp[0].Y + pt.Y) / 2.0;
137  mp[4].X = (end->pt.X + x3) / 2.0;
138  mp[4].Y = (end->pt.Y + y3) / 2.0;
139  mp[3].X = (mp[4].X + pt.X) / 2.0;
140  mp[3].Y = (mp[4].Y + pt.Y) / 2.0;
141 
142  mp[2].X = (mp[1].X + mp[3].X) / 2.0;
143  mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0;
144 
145  if ((x2 == mp[0].X && y2 == mp[0].Y && x3 == mp[1].X && y3 == mp[1].Y) ||
146  (x2 == mp[3].X && y2 == mp[3].Y && x3 == mp[4].X && y3 == mp[4].Y))
147  return TRUE;
148 
149  pt = end->pt;
150  pt_st = start->pt;
151  /* check flatness as a half of distance between middle point and a linearized path */
152  if(fabs(((pt.Y - pt_st.Y)*mp[2].X + (pt_st.X - pt.X)*mp[2].Y +
153  (pt_st.Y*pt.X - pt_st.X*pt.Y))) <=
154  (0.5 * flatness*sqrtf((powf(pt.Y - pt_st.Y, 2.0) + powf(pt_st.X - pt.X, 2.0))))){
155  return TRUE;
156  }
157  else
158  /* add a middle point */
159  if(!(node = add_path_list_node(start, mp[2].X, mp[2].Y, PathPointTypeLine)))
160  return FALSE;
161 
162  /* do the same with halves */
163  flatten_bezier(start, mp[0].X, mp[0].Y, mp[1].X, mp[1].Y, node, flatness);
164  flatten_bezier(node, mp[3].X, mp[3].Y, mp[4].X, mp[4].Y, end, flatness);
165 
166  return TRUE;
167 }
168 
169 /*******************************************************************************
170  * GdipAddPathArc [GDIPLUS.1]
171  *
172  * Add an elliptical arc to the given path.
173  *
174  * PARAMS
175  * path [I/O] Path that the arc is appended to
176  * x1 [I] X coordinate of the boundary box
177  * y1 [I] Y coordinate of the boundary box
178  * x2 [I] Width of the boundary box
179  * y2 [I] Height of the boundary box
180  * startAngle [I] Starting angle of the arc, clockwise
181  * sweepAngle [I] Angle of the arc, clockwise
182  *
183  * RETURNS
184  * InvalidParameter If the given path is invalid
185  * OutOfMemory If memory allocation fails, i.e. the path cannot be lengthened
186  * Ok If everything works out as expected
187  *
188  * NOTES
189  * This functions takes the newfigure value of the given path into account,
190  * i.e. the arc is connected to the end of the given path if it was set to
191  * FALSE, otherwise the arc's first point gets the PathPointTypeStart value.
192  * In both cases, the value of newfigure of the given path is FALSE
193  * afterwards.
194  */
196  REAL y2, REAL startAngle, REAL sweepAngle)
197 {
198  INT count, old_count, i;
199 
200  TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
201  path, x1, y1, x2, y2, startAngle, sweepAngle);
202 
203  if(!path)
204  return InvalidParameter;
205 
206  count = arc2polybezier(NULL, x1, y1, x2, y2, startAngle, sweepAngle);
207 
208  if(count == 0)
209  return Ok;
210  if(!lengthen_path(path, count))
211  return OutOfMemory;
212 
213  old_count = path->pathdata.Count;
214  arc2polybezier(&path->pathdata.Points[old_count], x1, y1, x2, y2,
215  startAngle, sweepAngle);
216 
217  for(i = 0; i < count; i++){
218  path->pathdata.Types[old_count + i] = PathPointTypeBezier;
219  }
220 
221  path->pathdata.Types[old_count] =
222  (path->newfigure ? PathPointTypeStart : PathPointTypeLine);
223  path->newfigure = FALSE;
224  path->pathdata.Count += count;
225 
226  return Ok;
227 }
228 
229 /*******************************************************************************
230  * GdipAddPathArcI [GDUPLUS.2]
231  *
232  * See GdipAddPathArc
233  */
235  INT y2, REAL startAngle, REAL sweepAngle)
236 {
237  TRACE("(%p, %d, %d, %d, %d, %.2f, %.2f)\n",
238  path, x1, y1, x2, y2, startAngle, sweepAngle);
239 
240  return GdipAddPathArc(path,(REAL)x1,(REAL)y1,(REAL)x2,(REAL)y2,startAngle,sweepAngle);
241 }
242 
244  REAL y2, REAL x3, REAL y3, REAL x4, REAL y4)
245 {
246  INT old_count;
247 
248  TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
249  path, x1, y1, x2, y2, x3, y3, x4, y4);
250 
251  if(!path)
252  return InvalidParameter;
253 
254  if(!lengthen_path(path, 4))
255  return OutOfMemory;
256 
257  old_count = path->pathdata.Count;
258 
259  path->pathdata.Points[old_count].X = x1;
260  path->pathdata.Points[old_count].Y = y1;
261  path->pathdata.Points[old_count + 1].X = x2;
262  path->pathdata.Points[old_count + 1].Y = y2;
263  path->pathdata.Points[old_count + 2].X = x3;
264  path->pathdata.Points[old_count + 2].Y = y3;
265  path->pathdata.Points[old_count + 3].X = x4;
266  path->pathdata.Points[old_count + 3].Y = y4;
267 
268  path->pathdata.Types[old_count] =
269  (path->newfigure ? PathPointTypeStart : PathPointTypeLine);
270  path->pathdata.Types[old_count + 1] = PathPointTypeBezier;
271  path->pathdata.Types[old_count + 2] = PathPointTypeBezier;
272  path->pathdata.Types[old_count + 3] = PathPointTypeBezier;
273 
274  path->newfigure = FALSE;
275  path->pathdata.Count += 4;
276 
277  return Ok;
278 }
279 
281  INT y2, INT x3, INT y3, INT x4, INT y4)
282 {
283  TRACE("(%p, %d, %d, %d, %d, %d, %d, %d, %d)\n",
284  path, x1, y1, x2, y2, x3, y3, x4, y4);
285 
286  return GdipAddPathBezier(path,(REAL)x1,(REAL)y1,(REAL)x2,(REAL)y2,(REAL)x3,(REAL)y3,
287  (REAL)x4,(REAL)y4);
288 }
289 
291  INT count)
292 {
293  INT i, old_count;
294 
295  TRACE("(%p, %p, %d)\n", path, points, count);
296 
297  if(!path || !points || ((count - 1) % 3))
298  return InvalidParameter;
299 
300  if(!lengthen_path(path, count))
301  return OutOfMemory;
302 
303  old_count = path->pathdata.Count;
304 
305  for(i = 0; i < count; i++){
306  path->pathdata.Points[old_count + i].X = points[i].X;
307  path->pathdata.Points[old_count + i].Y = points[i].Y;
308  path->pathdata.Types[old_count + i] = PathPointTypeBezier;
309  }
310 
311  path->pathdata.Types[old_count] =
312  (path->newfigure ? PathPointTypeStart : PathPointTypeLine);
313  path->newfigure = FALSE;
314  path->pathdata.Count += count;
315 
316  return Ok;
317 }
318 
320  INT count)
321 {
322  GpPointF *ptsF;
323  GpStatus ret;
324  INT i;
325 
326  TRACE("(%p, %p, %d)\n", path, points, count);
327 
328  if(!points || ((count - 1) % 3))
329  return InvalidParameter;
330 
331  ptsF = heap_alloc_zero(sizeof(GpPointF) * count);
332  if(!ptsF)
333  return OutOfMemory;
334 
335  for(i = 0; i < count; i++){
336  ptsF[i].X = (REAL)points[i].X;
337  ptsF[i].Y = (REAL)points[i].Y;
338  }
339 
340  ret = GdipAddPathBeziers(path, ptsF, count);
341  heap_free(ptsF);
342 
343  return ret;
344 }
345 
347  INT count)
348 {
349  TRACE("(%p, %p, %d)\n", path, points, count);
350 
351  return GdipAddPathClosedCurve2(path, points, count, 1.0);
352 }
353 
355  INT count)
356 {
357  TRACE("(%p, %p, %d)\n", path, points, count);
358 
359  return GdipAddPathClosedCurve2I(path, points, count, 1.0);
360 }
361 
363  INT count, REAL tension)
364 {
365  INT i, len_pt = (count + 1)*3-2;
366  GpPointF *pt;
367  GpPointF *pts;
368  REAL x1, x2, y1, y2;
369  GpStatus stat;
370 
371  TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
372 
373  if(!path || !points || count <= 1)
374  return InvalidParameter;
375 
376  pt = heap_alloc_zero(len_pt * sizeof(GpPointF));
377  pts = heap_alloc_zero((count + 1)*sizeof(GpPointF));
378  if(!pt || !pts){
379  heap_free(pt);
380  heap_free(pts);
381  return OutOfMemory;
382  }
383 
384  /* copy source points to extend with the last one */
385  memcpy(pts, points, sizeof(GpPointF)*count);
386  pts[count] = pts[0];
387 
388  tension = tension * TENSION_CONST;
389 
390  for(i = 0; i < count-1; i++){
391  calc_curve_bezier(&(pts[i]), tension, &x1, &y1, &x2, &y2);
392 
393  pt[3*i+2].X = x1;
394  pt[3*i+2].Y = y1;
395  pt[3*i+3].X = pts[i+1].X;
396  pt[3*i+3].Y = pts[i+1].Y;
397  pt[3*i+4].X = x2;
398  pt[3*i+4].Y = y2;
399  }
400 
401  /* points [len_pt-2] and [0] are calculated
402  separately to connect splines properly */
403  pts[0] = points[count-1];
404  pts[1] = points[0]; /* equals to start and end of a resulting path */
405  pts[2] = points[1];
406 
407  calc_curve_bezier(pts, tension, &x1, &y1, &x2, &y2);
408  pt[len_pt-2].X = x1;
409  pt[len_pt-2].Y = y1;
410  pt[0].X = pts[1].X;
411  pt[0].Y = pts[1].Y;
412  pt[1].X = x2;
413  pt[1].Y = y2;
414  /* close path */
415  pt[len_pt-1].X = pt[0].X;
416  pt[len_pt-1].Y = pt[0].Y;
417 
418  stat = GdipAddPathBeziers(path, pt, len_pt);
419 
420  /* close figure */
421  if(stat == Ok){
422  path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
423  path->newfigure = TRUE;
424  }
425 
426  heap_free(pts);
427  heap_free(pt);
428 
429  return stat;
430 }
431 
433  INT count, REAL tension)
434 {
435  GpPointF *ptf;
436  INT i;
437  GpStatus stat;
438 
439  TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
440 
441  if(!path || !points || count <= 1)
442  return InvalidParameter;
443 
444  ptf = heap_alloc_zero(sizeof(GpPointF)*count);
445  if(!ptf)
446  return OutOfMemory;
447 
448  for(i = 0; i < count; i++){
449  ptf[i].X = (REAL)points[i].X;
450  ptf[i].Y = (REAL)points[i].Y;
451  }
452 
453  stat = GdipAddPathClosedCurve2(path, ptf, count, tension);
454 
455  heap_free(ptf);
456 
457  return stat;
458 }
459 
461 {
462  TRACE("(%p, %p, %d)\n", path, points, count);
463 
464  if(!path || !points || count <= 1)
465  return InvalidParameter;
466 
467  return GdipAddPathCurve2(path, points, count, 1.0);
468 }
469 
471 {
472  TRACE("(%p, %p, %d)\n", path, points, count);
473 
474  if(!path || !points || count <= 1)
475  return InvalidParameter;
476 
477  return GdipAddPathCurve2I(path, points, count, 1.0);
478 }
479 
481  REAL tension)
482 {
483  INT i, len_pt = count*3-2;
484  GpPointF *pt;
485  REAL x1, x2, y1, y2;
486  GpStatus stat;
487 
488  TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
489 
490  if(!path || !points || count <= 1)
491  return InvalidParameter;
492 
493  pt = heap_alloc_zero(len_pt * sizeof(GpPointF));
494  if(!pt)
495  return OutOfMemory;
496 
497  tension = tension * TENSION_CONST;
498 
500  tension, &x1, &y1);
501 
502  pt[0].X = points[0].X;
503  pt[0].Y = points[0].Y;
504  pt[1].X = x1;
505  pt[1].Y = y1;
506 
507  for(i = 0; i < count-2; i++){
508  calc_curve_bezier(&(points[i]), tension, &x1, &y1, &x2, &y2);
509 
510  pt[3*i+2].X = x1;
511  pt[3*i+2].Y = y1;
512  pt[3*i+3].X = points[i+1].X;
513  pt[3*i+3].Y = points[i+1].Y;
514  pt[3*i+4].X = x2;
515  pt[3*i+4].Y = y2;
516  }
517 
519  points[count-2].X, points[count-2].Y, tension, &x1, &y1);
520 
521  pt[len_pt-2].X = x1;
522  pt[len_pt-2].Y = y1;
523  pt[len_pt-1].X = points[count-1].X;
524  pt[len_pt-1].Y = points[count-1].Y;
525 
526  stat = GdipAddPathBeziers(path, pt, len_pt);
527 
528  heap_free(pt);
529 
530  return stat;
531 }
532 
534  INT count, REAL tension)
535 {
536  GpPointF *ptf;
537  INT i;
538  GpStatus stat;
539 
540  TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
541 
542  if(!path || !points || count <= 1)
543  return InvalidParameter;
544 
545  ptf = heap_alloc_zero(sizeof(GpPointF)*count);
546  if(!ptf)
547  return OutOfMemory;
548 
549  for(i = 0; i < count; i++){
550  ptf[i].X = (REAL)points[i].X;
551  ptf[i].Y = (REAL)points[i].Y;
552  }
553 
554  stat = GdipAddPathCurve2(path, ptf, count, tension);
555 
556  heap_free(ptf);
557 
558  return stat;
559 }
560 
562  INT count, INT offset, INT nseg, REAL tension)
563 {
564  TRACE("(%p, %p, %d, %d, %d, %.2f)\n", path, points, count, offset, nseg, tension);
565 
566  if(!path || !points || offset + 1 >= count || count - offset < nseg + 1)
567  return InvalidParameter;
568 
569  return GdipAddPathCurve2(path, &points[offset], nseg + 1, tension);
570 }
571 
573  INT count, INT offset, INT nseg, REAL tension)
574 {
575  TRACE("(%p, %p, %d, %d, %d, %.2f)\n", path, points, count, offset, nseg, tension);
576 
577  if(!path || !points || offset + 1 >= count || count - offset < nseg + 1)
578  return InvalidParameter;
579 
580  return GdipAddPathCurve2I(path, &points[offset], nseg + 1, tension);
581 }
582 
584  REAL height)
585 {
586  INT old_count, numpts;
587 
588  TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x, y, width, height);
589 
590  if(!path)
591  return InvalidParameter;
592 
594  return OutOfMemory;
595 
596  old_count = path->pathdata.Count;
597  if((numpts = arc2polybezier(&path->pathdata.Points[old_count], x, y, width,
598  height, 0.0, 360.0)) != MAX_ARC_PTS){
599  ERR("expected %d points but got %d\n", MAX_ARC_PTS, numpts);
600  return GenericError;
601  }
602 
603  memset(&path->pathdata.Types[old_count + 1], PathPointTypeBezier,
604  MAX_ARC_PTS - 1);
605 
606  /* An ellipse is an intrinsic figure (always is its own subpath). */
607  path->pathdata.Types[old_count] = PathPointTypeStart;
608  path->pathdata.Types[old_count + MAX_ARC_PTS - 1] |= PathPointTypeCloseSubpath;
609  path->newfigure = TRUE;
610  path->pathdata.Count += MAX_ARC_PTS;
611 
612  return Ok;
613 }
614 
616  INT height)
617 {
618  TRACE("(%p, %d, %d, %d, %d)\n", path, x, y, width, height);
619 
621 }
622 
624  INT count)
625 {
626  INT i, old_count;
627 
628  TRACE("(%p, %p, %d)\n", path, points, count);
629 
630  if(!path || !points)
631  return InvalidParameter;
632 
633  if(!lengthen_path(path, count))
634  return OutOfMemory;
635 
636  old_count = path->pathdata.Count;
637 
638  for(i = 0; i < count; i++){
639  path->pathdata.Points[old_count + i].X = points[i].X;
640  path->pathdata.Points[old_count + i].Y = points[i].Y;
641  path->pathdata.Types[old_count + i] = PathPointTypeLine;
642  }
643 
644  if(path->newfigure){
645  path->pathdata.Types[old_count] = PathPointTypeStart;
646  path->newfigure = FALSE;
647  }
648 
649  path->pathdata.Count += count;
650 
651  return Ok;
652 }
653 
655 {
656  GpPointF *pointsF;
657  INT i;
658  GpStatus stat;
659 
660  TRACE("(%p, %p, %d)\n", path, points, count);
661 
662  if(count <= 0)
663  return InvalidParameter;
664 
665  pointsF = heap_alloc_zero(sizeof(GpPointF) * count);
666  if(!pointsF) return OutOfMemory;
667 
668  for(i = 0;i < count; i++){
669  pointsF[i].X = (REAL)points[i].X;
670  pointsF[i].Y = (REAL)points[i].Y;
671  }
672 
673  stat = GdipAddPathLine2(path, pointsF, count);
674 
675  heap_free(pointsF);
676 
677  return stat;
678 }
679 
680 /*************************************************************************
681  * GdipAddPathLine [GDIPLUS.21]
682  *
683  * Add two points to the given path.
684  *
685  * PARAMS
686  * path [I/O] Path that the line is appended to
687  * x1 [I] X coordinate of the first point of the line
688  * y1 [I] Y coordinate of the first point of the line
689  * x2 [I] X coordinate of the second point of the line
690  * y2 [I] Y coordinate of the second point of the line
691  *
692  * RETURNS
693  * InvalidParameter If the first parameter is not a valid path
694  * OutOfMemory If the path cannot be lengthened, i.e. memory allocation fails
695  * Ok If everything works out as expected
696  *
697  * NOTES
698  * This functions takes the newfigure value of the given path into account,
699  * i.e. the two new points are connected to the end of the given path if it
700  * was set to FALSE, otherwise the first point is given the PathPointTypeStart
701  * value. In both cases, the value of newfigure of the given path is FALSE
702  * afterwards.
703  */
705 {
706  INT old_count;
707 
708  TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x1, y1, x2, y2);
709 
710  if(!path)
711  return InvalidParameter;
712 
713  if(!lengthen_path(path, 2))
714  return OutOfMemory;
715 
716  old_count = path->pathdata.Count;
717 
718  path->pathdata.Points[old_count].X = x1;
719  path->pathdata.Points[old_count].Y = y1;
720  path->pathdata.Points[old_count + 1].X = x2;
721  path->pathdata.Points[old_count + 1].Y = y2;
722 
723  path->pathdata.Types[old_count] =
724  (path->newfigure ? PathPointTypeStart : PathPointTypeLine);
725  path->pathdata.Types[old_count + 1] = PathPointTypeLine;
726 
727  path->newfigure = FALSE;
728  path->pathdata.Count += 2;
729 
730  return Ok;
731 }
732 
733 /*************************************************************************
734  * GdipAddPathLineI [GDIPLUS.21]
735  *
736  * See GdipAddPathLine
737  */
739 {
740  TRACE("(%p, %d, %d, %d, %d)\n", path, x1, y1, x2, y2);
741 
742  return GdipAddPathLine(path, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
743 }
744 
746  BOOL connect)
747 {
748  INT old_count, count;
749 
750  TRACE("(%p, %p, %d)\n", path, addingPath, connect);
751 
752  if(!path || !addingPath)
753  return InvalidParameter;
754 
755  old_count = path->pathdata.Count;
756  count = addingPath->pathdata.Count;
757 
758  if(!lengthen_path(path, count))
759  return OutOfMemory;
760 
761  memcpy(&path->pathdata.Points[old_count], addingPath->pathdata.Points,
762  count * sizeof(GpPointF));
763  memcpy(&path->pathdata.Types[old_count], addingPath->pathdata.Types, count);
764 
765  if(path->newfigure || !connect)
766  path->pathdata.Types[old_count] = PathPointTypeStart;
767  else
768  path->pathdata.Types[old_count] = PathPointTypeLine;
769 
770  path->newfigure = FALSE;
771  path->pathdata.Count += count;
772 
773  return Ok;
774 }
775 
777  REAL startAngle, REAL sweepAngle)
778 {
779  GpPointF *ptf;
781  INT i, count;
782 
783  TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
784  path, x, y, width, height, startAngle, sweepAngle);
785 
786  if(!path)
787  return InvalidParameter;
788 
789  /* on zero width/height only start point added */
790  if(width <= 1e-7 || height <= 1e-7){
791  if(!lengthen_path(path, 1))
792  return OutOfMemory;
793  path->pathdata.Points[0].X = x + width / 2.0;
794  path->pathdata.Points[0].Y = y + height / 2.0;
795  path->pathdata.Types[0] = PathPointTypeStart | PathPointTypeCloseSubpath;
796  path->pathdata.Count = 1;
797  return InvalidParameter;
798  }
799 
800  count = arc2polybezier(NULL, x, y, width, height, startAngle, sweepAngle);
801 
802  if(count == 0)
803  return Ok;
804 
805  ptf = heap_alloc_zero(sizeof(GpPointF)*count);
806  if(!ptf)
807  return OutOfMemory;
808 
809  arc2polybezier(ptf, x, y, width, height, startAngle, sweepAngle);
810 
811  status = GdipAddPathLine(path, x + width/2, y + height/2, ptf[0].X, ptf[0].Y);
812  if(status != Ok){
813  heap_free(ptf);
814  return status;
815  }
816  /* one spline is already added as a line endpoint */
817  if(!lengthen_path(path, count - 1)){
818  heap_free(ptf);
819  return OutOfMemory;
820  }
821 
822  memcpy(&(path->pathdata.Points[path->pathdata.Count]), &(ptf[1]),sizeof(GpPointF)*(count-1));
823  for(i = 0; i < count-1; i++)
824  path->pathdata.Types[path->pathdata.Count+i] = PathPointTypeBezier;
825 
826  path->pathdata.Count += count-1;
827 
829 
830  heap_free(ptf);
831 
832  return status;
833 }
834 
836  REAL startAngle, REAL sweepAngle)
837 {
838  TRACE("(%p, %d, %d, %d, %d, %.2f, %.2f)\n",
839  path, x, y, width, height, startAngle, sweepAngle);
840 
841  return GdipAddPathPie(path, (REAL)x, (REAL)y, (REAL)width, (REAL)height, startAngle, sweepAngle);
842 }
843 
845 {
846  INT old_count;
847 
848  TRACE("(%p, %p, %d)\n", path, points, count);
849 
850  if(!path || !points || count < 3)
851  return InvalidParameter;
852 
853  if(!lengthen_path(path, count))
854  return OutOfMemory;
855 
856  old_count = path->pathdata.Count;
857 
858  memcpy(&path->pathdata.Points[old_count], points, count*sizeof(GpPointF));
859  memset(&path->pathdata.Types[old_count + 1], PathPointTypeLine, count - 1);
860 
861  /* A polygon is an intrinsic figure */
862  path->pathdata.Types[old_count] = PathPointTypeStart;
863  path->pathdata.Types[old_count + count - 1] |= PathPointTypeCloseSubpath;
864  path->newfigure = TRUE;
865  path->pathdata.Count += count;
866 
867  return Ok;
868 }
869 
871 {
872  GpPointF *ptf;
874  INT i;
875 
876  TRACE("(%p, %p, %d)\n", path, points, count);
877 
878  if(!points || count < 3)
879  return InvalidParameter;
880 
881  ptf = heap_alloc_zero(sizeof(GpPointF) * count);
882  if(!ptf)
883  return OutOfMemory;
884 
885  for(i = 0; i < count; i++){
886  ptf[i].X = (REAL)points[i].X;
887  ptf[i].Y = (REAL)points[i].Y;
888  }
889 
891 
892  heap_free(ptf);
893 
894  return status;
895 }
896 
897 static float fromfixedpoint(const FIXED v)
898 {
899  float f = ((float)v.fract) / (1<<(sizeof(v.fract)*8));
900  f += v.value;
901  return f;
902 }
903 
905 {
907  float maxY;
908  float scale;
909  float ascent;
910 };
911 
915  INT lineno, const RectF *bounds, INT *underlined_indexes,
916  INT underlined_index_count, void *priv)
917 {
918  static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
919  struct format_string_args *args = priv;
920  GpPath *path = args->path;
921  GpStatus status = Ok;
922  float x = rect->X + (bounds->X - rect->X) * args->scale;
923  float y = rect->Y + (bounds->Y - rect->Y) * args->scale;
924  int i;
925 
926  if (underlined_index_count)
927  FIXME("hotkey underlines not drawn yet\n");
928 
929  if (y + bounds->Height * args->scale > args->maxY)
930  args->maxY = y + bounds->Height * args->scale;
931 
932  for (i = index; i < length; ++i)
933  {
934  GLYPHMETRICS gm;
935  TTPOLYGONHEADER *ph = NULL, *origph;
936  char *start;
937  DWORD len, ofs = 0;
938  len = GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity);
939  if (len == GDI_ERROR)
940  {
942  break;
943  }
944  origph = ph = heap_alloc_zero(len);
945  start = (char *)ph;
946  if (!ph || !lengthen_path(path, len / sizeof(POINTFX)))
947  {
948  heap_free(ph);
950  break;
951  }
952  GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, len, start, &identity);
953 
954  ofs = 0;
955  while (ofs < len)
956  {
957  DWORD ofs_start = ofs;
958  ph = (TTPOLYGONHEADER*)&start[ofs];
959  path->pathdata.Types[path->pathdata.Count] = PathPointTypeStart;
960  path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(ph->pfxStart.x) * args->scale;
961  path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(ph->pfxStart.y) * args->scale;
962  TRACE("Starting at count %i with pos %f, %f)\n", path->pathdata.Count, x, y);
963  ofs += sizeof(*ph);
964  while (ofs - ofs_start < ph->cb)
965  {
966  TTPOLYCURVE *curve = (TTPOLYCURVE*)&start[ofs];
967  int j;
968  ofs += sizeof(TTPOLYCURVE) + (curve->cpfx - 1) * sizeof(POINTFX);
969 
970  switch (curve->wType)
971  {
972  case TT_PRIM_LINE:
973  for (j = 0; j < curve->cpfx; ++j)
974  {
975  path->pathdata.Types[path->pathdata.Count] = PathPointTypeLine;
976  path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
977  path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
978  }
979  break;
980  case TT_PRIM_CSPLINE:
981  for (j = 0; j < curve->cpfx; ++j)
982  {
983  path->pathdata.Types[path->pathdata.Count] = PathPointTypeBezier;
984  path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
985  path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
986  }
987  break;
988  default:
989  ERR("Unhandled type: %u\n", curve->wType);
991  }
992  }
993  path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
994  }
995  path->newfigure = TRUE;
996  x += gm.gmCellIncX * args->scale;
997  y += gm.gmCellIncY * args->scale;
998 
999  heap_free(origph);
1000  if (status != Ok)
1001  break;
1002  }
1003 
1004  return status;
1005 }
1006 
1008 {
1009  GpFont *font;
1010  GpStatus status;
1011  LOGFONTW lfw;
1012  HANDLE hfont;
1013  HDC dc;
1014  GpGraphics *graphics;
1015  GpPath *backup;
1016  struct format_string_args args;
1017  int i;
1018  UINT16 native_height;
1019  RectF scaled_layout_rect;
1020  TEXTMETRICW textmetric;
1021 
1022  TRACE("(%p, %s, %d, %p, %d, %f, %p, %p)\n", path, debugstr_w(string), length, family, style, emSize, layoutRect, format);
1023  if (!path || !string || !family || !emSize || !layoutRect || !format)
1024  return InvalidParameter;
1025 
1026  status = GdipGetEmHeight(family, style, &native_height);
1027  if (status != Ok)
1028  return status;
1029 
1030  scaled_layout_rect.X = layoutRect->X;
1031  scaled_layout_rect.Y = layoutRect->Y;
1032  scaled_layout_rect.Width = layoutRect->Width * native_height / emSize;
1033  scaled_layout_rect.Height = layoutRect->Height * native_height / emSize;
1034 
1035  if ((status = GdipClonePath(path, &backup)) != Ok)
1036  return status;
1037 
1038  dc = CreateCompatibleDC(0);
1039  status = GdipCreateFromHDC(dc, &graphics);
1040  if (status != Ok)
1041  {
1042  DeleteDC(dc);
1044  return status;
1045  }
1046 
1047  status = GdipCreateFont(family, native_height, style, UnitPixel, &font);
1048  if (status != Ok)
1049  {
1050  GdipDeleteGraphics(graphics);
1051  DeleteDC(dc);
1053  return status;
1054  }
1055 
1056  get_log_fontW(font, graphics, &lfw);
1058  GdipDeleteGraphics(graphics);
1059 
1060  hfont = CreateFontIndirectW(&lfw);
1061  if (!hfont)
1062  {
1063  WARN("Failed to create font\n");
1064  DeleteDC(dc);
1066  return GenericError;
1067  }
1068 
1069  SelectObject(dc, hfont);
1070 
1071  GetTextMetricsW(dc, &textmetric);
1072 
1073  args.path = path;
1074  args.maxY = 0;
1075  args.scale = emSize / native_height;
1076  args.ascent = textmetric.tmAscent * args.scale;
1077  status = gdip_format_string(dc, string, length, NULL, &scaled_layout_rect,
1079 
1080  DeleteDC(dc);
1082 
1083  if (status != Ok) /* free backup */
1084  {
1085  heap_free(path->pathdata.Points);
1086  heap_free(path->pathdata.Types);
1087  *path = *backup;
1088  heap_free(backup);
1089  return status;
1090  }
1091  if (format && format->line_align == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height)
1092  {
1093  float inc = layoutRect->Height + layoutRect->Y - args.maxY;
1094  inc /= 2;
1095  for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
1096  path->pathdata.Points[i].Y += inc;
1097  } else if (format && format->line_align == StringAlignmentFar) {
1098  float inc = layoutRect->Height + layoutRect->Y - args.maxY;
1099  for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
1100  path->pathdata.Points[i].Y += inc;
1101  }
1103  return status;
1104 }
1105 
1107 {
1108  if (layoutRect)
1109  {
1110  RectF layoutRectF = {
1111  (REAL)layoutRect->X,
1112  (REAL)layoutRect->Y,
1113  (REAL)layoutRect->Width,
1114  (REAL)layoutRect->Height
1115  };
1116  return GdipAddPathString(path, string, length, family, style, emSize, &layoutRectF, format);
1117  }
1118  return InvalidParameter;
1119 }
1120 
1121 /*************************************************************************
1122  * GdipClonePath [GDIPLUS.53]
1123  *
1124  * Duplicate the given path in memory.
1125  *
1126  * PARAMS
1127  * path [I] The path to be duplicated
1128  * clone [O] Pointer to the new path
1129  *
1130  * RETURNS
1131  * InvalidParameter If the input path is invalid
1132  * OutOfMemory If allocation of needed memory fails
1133  * Ok If everything works out as expected
1134  */
1136 {
1137  TRACE("(%p, %p)\n", path, clone);
1138 
1139  if(!path || !clone)
1140  return InvalidParameter;
1141 
1142  *clone = heap_alloc_zero(sizeof(GpPath));
1143  if(!*clone) return OutOfMemory;
1144 
1145  **clone = *path;
1146 
1147  (*clone)->pathdata.Points = heap_alloc_zero(path->datalen * sizeof(PointF));
1148  (*clone)->pathdata.Types = heap_alloc_zero(path->datalen);
1149  if(!(*clone)->pathdata.Points || !(*clone)->pathdata.Types){
1150  heap_free((*clone)->pathdata.Points);
1151  heap_free((*clone)->pathdata.Types);
1152  heap_free(*clone);
1153  return OutOfMemory;
1154  }
1155 
1156  memcpy((*clone)->pathdata.Points, path->pathdata.Points,
1157  path->datalen * sizeof(PointF));
1158  memcpy((*clone)->pathdata.Types, path->pathdata.Types, path->datalen);
1159 
1160  return Ok;
1161 }
1162 
1164 {
1165  TRACE("(%p)\n", path);
1166 
1167  if(!path)
1168  return InvalidParameter;
1169 
1170  if(path->pathdata.Count > 0){
1171  path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
1172  path->newfigure = TRUE;
1173  }
1174 
1175  return Ok;
1176 }
1177 
1179 {
1180  INT i;
1181 
1182  TRACE("(%p)\n", path);
1183 
1184  if(!path)
1185  return InvalidParameter;
1186 
1187  for(i = 1; i < path->pathdata.Count; i++){
1188  if(path->pathdata.Types[i] == PathPointTypeStart)
1189  path->pathdata.Types[i-1] |= PathPointTypeCloseSubpath;
1190  }
1191 
1192  path->newfigure = TRUE;
1193 
1194  return Ok;
1195 }
1196 
1198 {
1199  TRACE("(%d, %p)\n", fill, path);
1200 
1201  if(!path)
1202  return InvalidParameter;
1203 
1204  *path = heap_alloc_zero(sizeof(GpPath));
1205  if(!*path) return OutOfMemory;
1206 
1207  (*path)->fill = fill;
1208  (*path)->newfigure = TRUE;
1209 
1210  return Ok;
1211 }
1212 
1215 {
1216  TRACE("(%p, %p, %d, %d, %p)\n", points, types, count, fill, path);
1217 
1218  if(!path)
1219  return InvalidParameter;
1220 
1221  *path = heap_alloc_zero(sizeof(GpPath));
1222  if(!*path) return OutOfMemory;
1223 
1224  (*path)->pathdata.Points = heap_alloc_zero(count * sizeof(PointF));
1225  (*path)->pathdata.Types = heap_alloc_zero(count);
1226 
1227  if(!(*path)->pathdata.Points || !(*path)->pathdata.Types){
1228  heap_free((*path)->pathdata.Points);
1229  heap_free((*path)->pathdata.Types);
1230  heap_free(*path);
1231  return OutOfMemory;
1232  }
1233 
1234  memcpy((*path)->pathdata.Points, points, count * sizeof(PointF));
1235  memcpy((*path)->pathdata.Types, types, count);
1236  (*path)->pathdata.Count = count;
1237  (*path)->datalen = count;
1238 
1239  (*path)->fill = fill;
1240  (*path)->newfigure = TRUE;
1241 
1242  return Ok;
1243 }
1244 
1247 {
1248  GpPointF *ptF;
1249  GpStatus ret;
1250  INT i;
1251 
1252  TRACE("(%p, %p, %d, %d, %p)\n", points, types, count, fill, path);
1253 
1254  ptF = heap_alloc_zero(sizeof(GpPointF)*count);
1255 
1256  for(i = 0;i < count; i++){
1257  ptF[i].X = (REAL)points[i].X;
1258  ptF[i].Y = (REAL)points[i].Y;
1259  }
1260 
1261  ret = GdipCreatePath2(ptF, types, count, fill, path);
1262 
1263  heap_free(ptF);
1264 
1265  return ret;
1266 }
1267 
1269 {
1270  TRACE("(%p)\n", path);
1271 
1272  if(!path)
1273  return InvalidParameter;
1274 
1275  heap_free(path->pathdata.Points);
1276  heap_free(path->pathdata.Types);
1277  heap_free(path);
1278 
1279  return Ok;
1280 }
1281 
1283 {
1285  GpPointF pt;
1286  INT i = 1;
1287  INT startidx = 0;
1288  GpStatus stat;
1289 
1290  TRACE("(%p, %p, %.2f)\n", path, matrix, flatness);
1291 
1292  if(!path)
1293  return InvalidParameter;
1294 
1295  if(path->pathdata.Count == 0)
1296  return Ok;
1297 
1299  if(stat != Ok)
1300  return stat;
1301 
1302  pt = path->pathdata.Points[0];
1303  if(!init_path_list(&list, pt.X, pt.Y))
1304  return OutOfMemory;
1305 
1306  node = list;
1307 
1308  while(i < path->pathdata.Count){
1309 
1310  BYTE type = path->pathdata.Types[i] & PathPointTypePathTypeMask;
1312 
1313  pt = path->pathdata.Points[i];
1314 
1315  /* save last start point index */
1316  if(type == PathPointTypeStart)
1317  startidx = i;
1318 
1319  /* always add line points and start points */
1320  if((type == PathPointTypeStart) || (type == PathPointTypeLine)){
1321  if(!add_path_list_node(node, pt.X, pt.Y, path->pathdata.Types[i]))
1322  goto memout;
1323 
1324  node = node->next;
1325  ++i;
1326  continue;
1327  }
1328 
1329  /* Bezier curve */
1330 
1331  /* test for closed figure */
1332  if(path->pathdata.Types[i+1] & PathPointTypeCloseSubpath){
1333  pt = path->pathdata.Points[startidx];
1334  ++i;
1335  }
1336  else
1337  {
1338  i += 2;
1339  pt = path->pathdata.Points[i];
1340  };
1341 
1342  start = node;
1343  /* add Bezier end point */
1344  type = (path->pathdata.Types[i] & ~PathPointTypePathTypeMask) | PathPointTypeLine;
1345  if(!add_path_list_node(node, pt.X, pt.Y, type))
1346  goto memout;
1347  node = node->next;
1348 
1349  /* flatten curve */
1350  if(!flatten_bezier(start, path->pathdata.Points[i-2].X, path->pathdata.Points[i-2].Y,
1351  path->pathdata.Points[i-1].X, path->pathdata.Points[i-1].Y,
1352  node, flatness))
1353  goto memout;
1354 
1355  ++i;
1356  }/* while */
1357 
1358  /* store path data back */
1359  i = path_list_count(list);
1360  if(!lengthen_path(path, i))
1361  goto memout;
1362  path->pathdata.Count = i;
1363 
1364  node = list;
1365  for(i = 0; i < path->pathdata.Count; i++){
1366  path->pathdata.Points[i] = node->pt;
1367  path->pathdata.Types[i] = node->type;
1368  node = node->next;
1369  }
1370 
1372  return Ok;
1373 
1374 memout:
1376  return OutOfMemory;
1377 }
1378 
1380 {
1381  TRACE("(%p, %p)\n", path, pathData);
1382 
1383  if(!path || !pathData)
1384  return InvalidParameter;
1385 
1386  /* Only copy data. pathData allocation/freeing controlled by wrapper class.
1387  Assumed that pathData is enough wide to get all data - controlled by wrapper too. */
1388  memcpy(pathData->Points, path->pathdata.Points, sizeof(PointF) * pathData->Count);
1389  memcpy(pathData->Types , path->pathdata.Types , pathData->Count);
1390 
1391  return Ok;
1392 }
1393 
1395 {
1396  TRACE("(%p, %p)\n", path, fillmode);
1397 
1398  if(!path || !fillmode)
1399  return InvalidParameter;
1400 
1401  *fillmode = path->fill;
1402 
1403  return Ok;
1404 }
1405 
1407 {
1408  INT count;
1409 
1410  TRACE("(%p, %p)\n", path, lastPoint);
1411 
1412  if(!path || !lastPoint)
1413  return InvalidParameter;
1414 
1415  count = path->pathdata.Count;
1416  if(count > 0)
1417  *lastPoint = path->pathdata.Points[count-1];
1418 
1419  return Ok;
1420 }
1421 
1423 {
1424  TRACE("(%p, %p, %d)\n", path, points, count);
1425 
1426  if(!path)
1427  return InvalidParameter;
1428 
1429  if(count < path->pathdata.Count)
1430  return InsufficientBuffer;
1431 
1432  memcpy(points, path->pathdata.Points, path->pathdata.Count * sizeof(GpPointF));
1433 
1434  return Ok;
1435 }
1436 
1438 {
1439  GpStatus ret;
1440  GpPointF *ptf;
1441  INT i;
1442 
1443  TRACE("(%p, %p, %d)\n", path, points, count);
1444 
1445  if(count <= 0)
1446  return InvalidParameter;
1447 
1448  ptf = heap_alloc_zero(sizeof(GpPointF)*count);
1449  if(!ptf) return OutOfMemory;
1450 
1452  if(ret == Ok)
1453  for(i = 0;i < count;i++){
1454  points[i].X = gdip_round(ptf[i].X);
1455  points[i].Y = gdip_round(ptf[i].Y);
1456  };
1457  heap_free(ptf);
1458 
1459  return ret;
1460 }
1461 
1463 {
1464  TRACE("(%p, %p, %d)\n", path, types, count);
1465 
1466  if(!path)
1467  return InvalidParameter;
1468 
1469  if(count < path->pathdata.Count)
1470  return InsufficientBuffer;
1471 
1472  memcpy(types, path->pathdata.Types, path->pathdata.Count);
1473 
1474  return Ok;
1475 }
1476 
1477 /* Windows expands the bounding box to the maximum possible bounding box
1478  * for a given pen. For example, if a line join can extend past the point
1479  * it's joining by x units, the bounding box is extended by x units in every
1480  * direction (even though this is too conservative for most cases). */
1483 {
1484  GpPointF * points, temp_pts[4];
1485  INT count, i;
1486  REAL path_width = 1.0, width, height, temp, low_x, low_y, high_x, high_y;
1487 
1488  TRACE("(%p, %p, %p, %p)\n", path, bounds, matrix, pen);
1489 
1490  /* Matrix and pen can be null. */
1491  if(!path || !bounds)
1492  return InvalidParameter;
1493 
1494  /* If path is empty just return. */
1495  count = path->pathdata.Count;
1496  if(count == 0){
1497  bounds->X = bounds->Y = bounds->Width = bounds->Height = 0.0;
1498  return Ok;
1499  }
1500 
1501  points = path->pathdata.Points;
1502 
1503  low_x = high_x = points[0].X;
1504  low_y = high_y = points[0].Y;
1505 
1506  for(i = 1; i < count; i++){
1507  low_x = min(low_x, points[i].X);
1508  low_y = min(low_y, points[i].Y);
1509  high_x = max(high_x, points[i].X);
1510  high_y = max(high_y, points[i].Y);
1511  }
1512 
1513  width = high_x - low_x;
1514  height = high_y - low_y;
1515 
1516  /* This looks unusual but it's the only way I can imitate windows. */
1517  if(matrix){
1518  temp_pts[0].X = low_x;
1519  temp_pts[0].Y = low_y;
1520  temp_pts[1].X = low_x;
1521  temp_pts[1].Y = high_y;
1522  temp_pts[2].X = high_x;
1523  temp_pts[2].Y = high_y;
1524  temp_pts[3].X = high_x;
1525  temp_pts[3].Y = low_y;
1526 
1527  GdipTransformMatrixPoints((GpMatrix*)matrix, temp_pts, 4);
1528  low_x = temp_pts[0].X;
1529  low_y = temp_pts[0].Y;
1530 
1531  for(i = 1; i < 4; i++){
1532  low_x = min(low_x, temp_pts[i].X);
1533  low_y = min(low_y, temp_pts[i].Y);
1534  }
1535 
1536  temp = width;
1537  width = height * fabs(matrix->matrix[2]) + width * fabs(matrix->matrix[0]);
1538  height = height * fabs(matrix->matrix[3]) + temp * fabs(matrix->matrix[1]);
1539  }
1540 
1541  if(pen){
1542  path_width = pen->width / 2.0;
1543 
1544  if(count > 2)
1545  path_width = max(path_width, pen->width * pen->miterlimit / 2.0);
1546  /* FIXME: this should probably also check for the startcap */
1547  if(pen->endcap & LineCapNoAnchor)
1548  path_width = max(path_width, pen->width * 2.2);
1549 
1550  low_x -= path_width;
1551  low_y -= path_width;
1552  width += 2.0 * path_width;
1553  height += 2.0 * path_width;
1554  }
1555 
1556  bounds->X = low_x;
1557  bounds->Y = low_y;
1558  bounds->Width = width;
1559  bounds->Height = height;
1560 
1561  return Ok;
1562 }
1563 
1566 {
1567  GpStatus ret;
1568  GpRectF boundsF;
1569 
1570  TRACE("(%p, %p, %p, %p)\n", path, bounds, matrix, pen);
1571 
1572  ret = GdipGetPathWorldBounds(path,&boundsF,matrix,pen);
1573 
1574  if(ret == Ok){
1575  bounds->X = gdip_round(boundsF.X);
1576  bounds->Y = gdip_round(boundsF.Y);
1577  bounds->Width = gdip_round(boundsF.Width);
1578  bounds->Height = gdip_round(boundsF.Height);
1579  }
1580 
1581  return ret;
1582 }
1583 
1585 {
1586  TRACE("(%p, %p)\n", path, count);
1587 
1588  if(!path)
1589  return InvalidParameter;
1590 
1591  *count = path->pathdata.Count;
1592 
1593  return Ok;
1594 }
1595 
1597 {
1598  INT i, count;
1599  INT start = 0; /* position in reversed path */
1600  GpPathData revpath;
1601 
1602  TRACE("(%p)\n", path);
1603 
1604  if(!path)
1605  return InvalidParameter;
1606 
1607  count = path->pathdata.Count;
1608 
1609  if(count == 0) return Ok;
1610 
1611  revpath.Points = heap_alloc_zero(sizeof(GpPointF)*count);
1612  revpath.Types = heap_alloc_zero(sizeof(BYTE)*count);
1613  revpath.Count = count;
1614  if(!revpath.Points || !revpath.Types){
1615  heap_free(revpath.Points);
1616  heap_free(revpath.Types);
1617  return OutOfMemory;
1618  }
1619 
1620  for(i = 0; i < count; i++){
1621 
1622  /* find next start point */
1623  if(path->pathdata.Types[count-i-1] == PathPointTypeStart){
1624  INT j;
1625  for(j = start; j <= i; j++){
1626  revpath.Points[j] = path->pathdata.Points[count-j-1];
1627  revpath.Types[j] = path->pathdata.Types[count-j-1];
1628  }
1629  /* mark start point */
1630  revpath.Types[start] = PathPointTypeStart;
1631  /* set 'figure' endpoint type */
1632  if(i-start > 1){
1633  revpath.Types[i] = path->pathdata.Types[count-start-1] & ~PathPointTypePathTypeMask;
1634  revpath.Types[i] |= revpath.Types[i-1];
1635  }
1636  else
1637  revpath.Types[i] = path->pathdata.Types[start];
1638 
1639  start = i+1;
1640  }
1641  }
1642 
1643  memcpy(path->pathdata.Points, revpath.Points, sizeof(GpPointF)*count);
1644  memcpy(path->pathdata.Types, revpath.Types, sizeof(BYTE)*count);
1645 
1646  heap_free(revpath.Points);
1647  heap_free(revpath.Types);
1648 
1649  return Ok;
1650 }
1651 
1653  GpPen *pen, GpGraphics *graphics, BOOL *result)
1654 {
1655  TRACE("(%p, %d, %d, %p, %p, %p)\n", path, x, y, pen, graphics, result);
1656 
1657  return GdipIsOutlineVisiblePathPoint(path, x, y, pen, graphics, result);
1658 }
1659 
1661  GpPen *pen, GpGraphics *graphics, BOOL *result)
1662 {
1663  GpStatus stat;
1664  GpPath *wide_path;
1665  GpMatrix *transform = NULL;
1666 
1667  TRACE("(%p,%0.2f,%0.2f,%p,%p,%p)\n", path, x, y, pen, graphics, result);
1668 
1669  if(!path || !pen)
1670  return InvalidParameter;
1671 
1672  stat = GdipClonePath(path, &wide_path);
1673 
1674  if (stat != Ok)
1675  return stat;
1676 
1677  if (pen->unit == UnitPixel && graphics != NULL)
1678  {
1680 
1681  if (stat == Ok)
1684  }
1685 
1686  if (stat == Ok)
1687  stat = GdipWidenPath(wide_path, pen, transform, 1.0);
1688 
1689  if (pen->unit == UnitPixel && graphics != NULL)
1690  {
1691  if (stat == Ok)
1693 
1694  if (stat == Ok)
1695  stat = GdipTransformPath(wide_path, transform);
1696  }
1697 
1698  if (stat == Ok)
1699  stat = GdipIsVisiblePathPoint(wide_path, x, y, graphics, result);
1700 
1702 
1703  GdipDeletePath(wide_path);
1704 
1705  return stat;
1706 }
1707 
1709 {
1710  TRACE("(%p, %d, %d, %p, %p)\n", path, x, y, graphics, result);
1711 
1712  return GdipIsVisiblePathPoint(path, x, y, graphics, result);
1713 }
1714 
1715 /*****************************************************************************
1716  * GdipIsVisiblePathPoint [GDIPLUS.@]
1717  */
1719 {
1720  GpRegion *region;
1721  HRGN hrgn;
1722  GpStatus status;
1723 
1724  if(!path || !result) return InvalidParameter;
1725 
1726  status = GdipCreateRegionPath(path, &region);
1727  if(status != Ok)
1728  return status;
1729 
1730  status = GdipGetRegionHRgn(region, graphics, &hrgn);
1731  if(status != Ok){
1732  GdipDeleteRegion(region);
1733  return status;
1734  }
1735 
1737 
1738  DeleteObject(hrgn);
1739  GdipDeleteRegion(region);
1740 
1741  return Ok;
1742 }
1743 
1745 {
1746  TRACE("(%p)\n", path);
1747 
1748  if(!path)
1749  return InvalidParameter;
1750 
1751  path->newfigure = TRUE;
1752 
1753  return Ok;
1754 }
1755 
1757 {
1758  TRACE("(%p)\n", path);
1759 
1760  if(!path)
1761  return InvalidParameter;
1762 
1763  path->pathdata.Count = 0;
1764  path->newfigure = TRUE;
1765  path->fill = FillModeAlternate;
1766 
1767  return Ok;
1768 }
1769 
1771 {
1772  TRACE("(%p, %d)\n", path, fill);
1773 
1774  if(!path)
1775  return InvalidParameter;
1776 
1777  path->fill = fill;
1778 
1779  return Ok;
1780 }
1781 
1783 {
1784  TRACE("(%p, %p)\n", path, matrix);
1785 
1786  if(!path)
1787  return InvalidParameter;
1788 
1789  if(path->pathdata.Count == 0 || !matrix)
1790  return Ok;
1791 
1792  return GdipTransformMatrixPoints(matrix, path->pathdata.Points,
1793  path->pathdata.Count);
1794 }
1795 
1798  REAL height, WarpMode warpmode, REAL flatness)
1799 {
1800  FIXME("(%p,%p,%p,%i,%0.2f,%0.2f,%0.2f,%0.2f,%i,%0.2f)\n", path, matrix,
1801  points, count, x, y, width, height, warpmode, flatness);
1802 
1803  return NotImplemented;
1804 }
1805 
1806 static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
1807  GpPen *pen, int right_side, path_list_node_t **last_point)
1808 {
1809  REAL segment_dy = nextpoint->Y-endpoint->Y;
1810  REAL segment_dx = nextpoint->X-endpoint->X;
1811  REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
1812  REAL distance = pen->width/2.0;
1813  REAL bevel_dx, bevel_dy;
1814 
1815  if (segment_length == 0.0)
1816  {
1817  *last_point = add_path_list_node(*last_point, endpoint->X,
1819  return;
1820  }
1821 
1822  if (right_side)
1823  {
1824  bevel_dx = -distance * segment_dy / segment_length;
1825  bevel_dy = distance * segment_dx / segment_length;
1826  }
1827  else
1828  {
1829  bevel_dx = distance * segment_dy / segment_length;
1830  bevel_dy = -distance * segment_dx / segment_length;
1831  }
1832 
1833  *last_point = add_path_list_node(*last_point, endpoint->X + bevel_dx,
1834  endpoint->Y + bevel_dy, PathPointTypeLine);
1835 }
1836 
1837 static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3,
1838  GpPen* pen, path_list_node_t **last_point)
1839 {
1840  switch (pen->join)
1841  {
1842  case LineJoinMiter:
1843  case LineJoinMiterClipped:
1844  if ((p2->X - p1->X) * (p3->Y - p1->Y) > (p2->Y - p1->Y) * (p3->X - p1->X))
1845  {
1846  float distance = pen->width/2.0;
1847  float length_0 = sqrtf((p2->X-p1->X)*(p2->X-p1->X)+(p2->Y-p1->Y)*(p2->Y-p1->Y));
1848  float length_1 = sqrtf((p3->X-p2->X)*(p3->X-p2->X)+(p3->Y-p2->Y)*(p3->Y-p2->Y));
1849  float dx0 = distance * (p2->X - p1->X) / length_0;
1850  float dy0 = distance * (p2->Y - p1->Y) / length_0;
1851  float dx1 = distance * (p3->X - p2->X) / length_1;
1852  float dy1 = distance * (p3->Y - p2->Y) / length_1;
1853  float det = (dy0*dx1 - dx0*dy1);
1854  float dx = (dx0*dx1*(dx0-dx1) + dy0*dy0*dx1 - dy1*dy1*dx0)/det;
1855  float dy = (dy0*dy1*(dy0-dy1) + dx0*dx0*dy1 - dx1*dx1*dy0)/det;
1856  if (dx*dx + dy*dy < pen->miterlimit*pen->miterlimit * distance*distance)
1857  {
1858  *last_point = add_path_list_node(*last_point, p2->X + dx,
1859  p2->Y + dy, PathPointTypeLine);
1860  break;
1861  }
1862  else if (pen->join == LineJoinMiter)
1863  {
1864  static int once;
1865  if (!once++)
1866  FIXME("should add a clipped corner\n");
1867  }
1868  /* else fall-through */
1869  }
1870  /* else fall-through */
1871  default:
1872  case LineJoinBevel:
1873  add_bevel_point(p2, p1, pen, 1, last_point);
1874  add_bevel_point(p2, p3, pen, 0, last_point);
1875  break;
1876  }
1877 }
1878 
1879 static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
1880  GpPen *pen, GpLineCap cap, GpCustomLineCap *custom, int add_first_points,
1881  int add_last_point, path_list_node_t **last_point)
1882 {
1883  switch (cap)
1884  {
1885  default:
1886  case LineCapFlat:
1887  if (add_first_points)
1888  add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
1889  if (add_last_point)
1890  add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
1891  break;
1892  case LineCapSquare:
1893  {
1894  REAL segment_dy = nextpoint->Y-endpoint->Y;
1895  REAL segment_dx = nextpoint->X-endpoint->X;
1896  REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
1897  REAL distance = pen->width/2.0;
1898  REAL bevel_dx, bevel_dy;
1899  REAL extend_dx, extend_dy;
1900 
1901  extend_dx = -distance * segment_dx / segment_length;
1902  extend_dy = -distance * segment_dy / segment_length;
1903 
1904  bevel_dx = -distance * segment_dy / segment_length;
1905  bevel_dy = distance * segment_dx / segment_length;
1906 
1907  if (add_first_points)
1908  *last_point = add_path_list_node(*last_point, endpoint->X + extend_dx + bevel_dx,
1909  endpoint->Y + extend_dy + bevel_dy, PathPointTypeLine);
1910 
1911  if (add_last_point)
1912  *last_point = add_path_list_node(*last_point, endpoint->X + extend_dx - bevel_dx,
1913  endpoint->Y + extend_dy - bevel_dy, PathPointTypeLine);
1914 
1915  break;
1916  }
1917  case LineCapRound:
1918  {
1919  REAL segment_dy = nextpoint->Y-endpoint->Y;
1920  REAL segment_dx = nextpoint->X-endpoint->X;
1921  REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
1922  REAL distance = pen->width/2.0;
1923  REAL dx, dy, dx2, dy2;
1924  const REAL control_point_distance = 0.5522847498307935; /* 4/3 * (sqrt(2) - 1) */
1925 
1926  if (add_first_points)
1927  {
1928  dx = -distance * segment_dx / segment_length;
1929  dy = -distance * segment_dy / segment_length;
1930 
1931  dx2 = dx * control_point_distance;
1932  dy2 = dy * control_point_distance;
1933 
1934  /* first 90-degree arc */
1935  *last_point = add_path_list_node(*last_point, endpoint->X + dy,
1936  endpoint->Y - dx, PathPointTypeLine);
1937 
1938  *last_point = add_path_list_node(*last_point, endpoint->X + dy + dx2,
1939  endpoint->Y - dx + dy2, PathPointTypeBezier);
1940 
1941  *last_point = add_path_list_node(*last_point, endpoint->X + dx + dy2,
1942  endpoint->Y + dy - dx2, PathPointTypeBezier);
1943 
1944  /* midpoint */
1945  *last_point = add_path_list_node(*last_point, endpoint->X + dx,
1947 
1948  /* second 90-degree arc */
1949  *last_point = add_path_list_node(*last_point, endpoint->X + dx - dy2,
1950  endpoint->Y + dy + dx2, PathPointTypeBezier);
1951 
1952  *last_point = add_path_list_node(*last_point, endpoint->X - dy + dx2,
1953  endpoint->Y + dx + dy2, PathPointTypeBezier);
1954 
1955  *last_point = add_path_list_node(*last_point, endpoint->X - dy,
1957  }
1958  break;
1959  }
1960  case LineCapTriangle:
1961  {
1962  REAL segment_dy = nextpoint->Y-endpoint->Y;
1963  REAL segment_dx = nextpoint->X-endpoint->X;
1964  REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
1965  REAL distance = pen->width/2.0;
1966  REAL dx, dy;
1967 
1968  dx = distance * segment_dx / segment_length;
1969  dy = distance * segment_dy / segment_length;
1970 
1971  if (add_first_points) {
1972  add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
1973 
1974  *last_point = add_path_list_node(*last_point, endpoint->X - dx,
1975  endpoint->Y - dy, PathPointTypeLine);
1976  }
1977  if (add_last_point)
1978  add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
1979  break;
1980  }
1981  }
1982 }
1983 
1984 static void widen_open_figure(const GpPointF *points, GpPen *pen, int start, int end,
1985  GpLineCap start_cap, GpCustomLineCap *start_custom, GpLineCap end_cap,
1986  GpCustomLineCap *end_custom, path_list_node_t **last_point)
1987 {
1988  int i;
1989  path_list_node_t *prev_point;
1990 
1991  if (end <= start)
1992  return;
1993 
1994  prev_point = *last_point;
1995 
1997  pen, start_cap, start_custom, FALSE, TRUE, last_point);
1998 
1999  for (i=start+1; i<end; i++)
2000  widen_joint(&points[i-1], &points[i],
2001  &points[i+1], pen, last_point);
2002 
2003  widen_cap(&points[end], &points[end-1],
2004  pen, end_cap, end_custom, TRUE, TRUE, last_point);
2005 
2006  for (i=end-1; i>start; i--)
2007  widen_joint(&points[i+1], &points[i],
2008  &points[i-1], pen, last_point);
2009 
2011  pen, start_cap, start_custom, TRUE, FALSE, last_point);
2012 
2013  prev_point->next->type = PathPointTypeStart;
2014  (*last_point)->type |= PathPointTypeCloseSubpath;
2015 }
2016 
2017 static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
2018  path_list_node_t **last_point)
2019 {
2020  int i;
2021  path_list_node_t *prev_point;
2022 
2023  if (end <= start)
2024  return;
2025 
2026  /* left outline */
2027  prev_point = *last_point;
2028 
2029  widen_joint(&path->pathdata.Points[end], &path->pathdata.Points[start],
2030  &path->pathdata.Points[start+1], pen, last_point);
2031 
2032  for (i=start+1; i<end; i++)
2033  widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
2034  &path->pathdata.Points[i+1], pen, last_point);
2035 
2036  widen_joint(&path->pathdata.Points[end-1], &path->pathdata.Points[end],
2037  &path->pathdata.Points[start], pen, last_point);
2038 
2039  prev_point->next->type = PathPointTypeStart;
2040  (*last_point)->type |= PathPointTypeCloseSubpath;
2041 
2042  /* right outline */
2043  prev_point = *last_point;
2044 
2045  widen_joint(&path->pathdata.Points[start], &path->pathdata.Points[end],
2046  &path->pathdata.Points[end-1], pen, last_point);
2047 
2048  for (i=end-1; i>start; i--)
2049  widen_joint(&path->pathdata.Points[i+1], &path->pathdata.Points[i],
2050  &path->pathdata.Points[i-1], pen, last_point);
2051 
2052  widen_joint(&path->pathdata.Points[start+1], &path->pathdata.Points[start],
2053  &path->pathdata.Points[end], pen, last_point);
2054 
2055  prev_point->next->type = PathPointTypeStart;
2056  (*last_point)->type |= PathPointTypeCloseSubpath;
2057 }
2058 
2059 static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
2060  int closed, path_list_node_t **last_point)
2061 {
2062  int i, j;
2063  REAL dash_pos=0.0;
2064  int dash_index=0;
2065  const REAL *dash_pattern;
2066  REAL *dash_pattern_scaled;
2067  int dash_count;
2068  GpPointF *tmp_points;
2069  REAL segment_dy;
2070  REAL segment_dx;
2071  REAL segment_length;
2072  REAL segment_pos;
2073  int num_tmp_points=0;
2074  int draw_start_cap=0;
2075  static const REAL dash_dot_dot[6] = { 3.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
2076 
2077  if (end <= start)
2078  return;
2079 
2080  switch (pen->dash)
2081  {
2082  case DashStyleDash:
2083  default:
2084  dash_pattern = dash_dot_dot;
2085  dash_count = 2;
2086  break;
2087  case DashStyleDot:
2088  dash_pattern = &dash_dot_dot[2];
2089  dash_count = 2;
2090  break;
2091  case DashStyleDashDot:
2092  dash_pattern = dash_dot_dot;
2093  dash_count = 4;
2094  break;
2095  case DashStyleDashDotDot:
2096  dash_pattern = dash_dot_dot;
2097  dash_count = 6;
2098  break;
2099  case DashStyleCustom:
2100  dash_pattern = pen->dashes;
2101  dash_count = pen->numdashes;
2102  break;
2103  }
2104 
2105  dash_pattern_scaled = heap_alloc(dash_count * sizeof(REAL));
2106  if (!dash_pattern_scaled) return;
2107 
2108  for (i = 0; i < dash_count; i++)
2109  dash_pattern_scaled[i] = pen->width * dash_pattern[i];
2110 
2111  tmp_points = heap_alloc_zero((end - start + 2) * sizeof(GpPoint));
2112  if (!tmp_points) {
2113  heap_free(dash_pattern_scaled);
2114  return; /* FIXME */
2115  }
2116 
2117  if (!closed)
2118  draw_start_cap = 1;
2119 
2120  for (j=start; j <= end; j++)
2121  {
2122  if (j == start)
2123  {
2124  if (closed)
2125  i = end;
2126  else
2127  continue;
2128  }
2129  else
2130  i = j-1;
2131 
2132  segment_dy = path->pathdata.Points[j].Y - path->pathdata.Points[i].Y;
2133  segment_dx = path->pathdata.Points[j].X - path->pathdata.Points[i].X;
2134  segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
2135  segment_pos = 0.0;
2136 
2137  while (1)
2138  {
2139  if (dash_pos == 0.0)
2140  {
2141  if ((dash_index % 2) == 0)
2142  {
2143  /* start dash */
2144  num_tmp_points = 1;
2145  tmp_points[0].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
2146  tmp_points[0].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
2147  }
2148  else
2149  {
2150  /* end dash */
2151  tmp_points[num_tmp_points].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
2152  tmp_points[num_tmp_points].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
2153 
2154  widen_open_figure(tmp_points, pen, 0, num_tmp_points,
2155  draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
2156  LineCapFlat, NULL, last_point);
2157  draw_start_cap = 0;
2158  num_tmp_points = 0;
2159  }
2160  }
2161 
2162  if (dash_pattern_scaled[dash_index] - dash_pos > segment_length - segment_pos)
2163  {
2164  /* advance to next segment */
2165  if ((dash_index % 2) == 0)
2166  {
2167  tmp_points[num_tmp_points] = path->pathdata.Points[j];
2168  num_tmp_points++;
2169  }
2170  dash_pos += segment_length - segment_pos;
2171  break;
2172  }
2173  else
2174  {
2175  /* advance to next dash in pattern */
2176  segment_pos += dash_pattern_scaled[dash_index] - dash_pos;
2177  dash_pos = 0.0;
2178  if (++dash_index == dash_count)
2179  dash_index = 0;
2180  continue;
2181  }
2182  }
2183  }
2184 
2185  if (dash_index % 2 == 0 && num_tmp_points != 0)
2186  {
2187  /* last dash overflows last segment */
2188  widen_open_figure(tmp_points, pen, 0, num_tmp_points-1,
2189  draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
2190  closed ? LineCapFlat : pen->endcap, pen->customend, last_point);
2191  }
2192 
2193  heap_free(dash_pattern_scaled);
2194  heap_free(tmp_points);
2195 }
2196 
2198  REAL flatness)
2199 {
2200  GpPath *flat_path=NULL;
2201  GpStatus status;
2202  path_list_node_t *points=NULL, *last_point=NULL;
2203  int i, subpath_start=0, new_length;
2204  BYTE type;
2205 
2206  TRACE("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
2207 
2208  if (!path || !pen)
2209  return InvalidParameter;
2210 
2211  if (path->pathdata.Count <= 1)
2212  return OutOfMemory;
2213 
2214  status = GdipClonePath(path, &flat_path);
2215 
2216  if (status == Ok)
2217  status = GdipFlattenPath(flat_path, pen->unit == UnitPixel ? matrix : NULL, flatness);
2218 
2219  if (status == Ok && !init_path_list(&points, 314.0, 22.0))
2220  status = OutOfMemory;
2221 
2222  if (status == Ok)
2223  {
2224  last_point = points;
2225 
2226  if (pen->endcap > LineCapTriangle)
2227  FIXME("unimplemented end cap %x\n", pen->endcap);
2228 
2229  if (pen->startcap > LineCapTriangle)
2230  FIXME("unimplemented start cap %x\n", pen->startcap);
2231 
2232  if (pen->dashcap != DashCapFlat)
2233  FIXME("unimplemented dash cap %d\n", pen->dashcap);
2234 
2235  if (pen->join == LineJoinRound)
2236  FIXME("unimplemented line join %d\n", pen->join);
2237 
2238  if (pen->align != PenAlignmentCenter)
2239  FIXME("unimplemented pen alignment %d\n", pen->align);
2240 
2241  for (i=0; i < flat_path->pathdata.Count; i++)
2242  {
2243  type = flat_path->pathdata.Types[i];
2244 
2246  subpath_start = i;
2247 
2249  {
2250  if (pen->dash != DashStyleSolid)
2251  widen_dashed_figure(flat_path, pen, subpath_start, i, 1, &last_point);
2252  else
2253  widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
2254  }
2255  else if (i == flat_path->pathdata.Count-1 ||
2257  {
2258  if (pen->dash != DashStyleSolid)
2259  widen_dashed_figure(flat_path, pen, subpath_start, i, 0, &last_point);
2260  else
2261  widen_open_figure(flat_path->pathdata.Points, pen, subpath_start, i, pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point);
2262  }
2263  }
2264 
2265  new_length = path_list_count(points)-1;
2266 
2267  if (!lengthen_path(path, new_length))
2268  status = OutOfMemory;
2269  }
2270 
2271  if (status == Ok)
2272  {
2273  path->pathdata.Count = new_length;
2274 
2275  last_point = points->next;
2276  for (i = 0; i < new_length; i++)
2277  {
2278  path->pathdata.Points[i] = last_point->pt;
2279  path->pathdata.Types[i] = last_point->type;
2280  last_point = last_point->next;
2281  }
2282 
2283  path->fill = FillModeWinding;
2284  }
2285 
2287 
2288  GdipDeletePath(flat_path);
2289 
2290  if (status == Ok && pen->unit != UnitPixel)
2292 
2293  return status;
2294 }
2295 
2297  REAL width, REAL height)
2298 {
2299  GpPath *backup;
2300  GpPointF ptf[2];
2301  GpStatus retstat;
2302  BOOL old_new;
2303 
2304  TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x, y, width, height);
2305 
2306  if(!path)
2307  return InvalidParameter;
2308 
2309  if (width <= 0.0 || height <= 0.0)
2310  return Ok;
2311 
2312  /* make a backup copy of path data */
2313  if((retstat = GdipClonePath(path, &backup)) != Ok)
2314  return retstat;
2315 
2316  /* rectangle should start as new path */
2317  old_new = path->newfigure;
2318  path->newfigure = TRUE;
2319  if((retstat = GdipAddPathLine(path,x,y,x+width,y)) != Ok){
2320  path->newfigure = old_new;
2321  goto fail;
2322  }
2323 
2324  ptf[0].X = x+width;
2325  ptf[0].Y = y+height;
2326  ptf[1].X = x;
2327  ptf[1].Y = y+height;
2328 
2329  if((retstat = GdipAddPathLine2(path, ptf, 2)) != Ok) goto fail;
2330  path->pathdata.Types[path->pathdata.Count-1] |= PathPointTypeCloseSubpath;
2331 
2332  /* free backup */
2334  return Ok;
2335 
2336 fail:
2337  /* reverting */
2338  heap_free(path->pathdata.Points);
2339  heap_free(path->pathdata.Types);
2340  memcpy(path, backup, sizeof(*path));
2341  heap_free(backup);
2342 
2343  return retstat;
2344 }
2345 
2347  INT width, INT height)
2348 {
2349  TRACE("(%p, %d, %d, %d, %d)\n", path, x, y, width, height);
2350 
2352 }
2353 
2355 {
2356  GpPath *backup;
2357  GpStatus retstat;
2358  INT i;
2359 
2360  TRACE("(%p, %p, %d)\n", path, rects, count);
2361 
2362  /* count == 0 - verified condition */
2363  if(!path || !rects || count == 0)
2364  return InvalidParameter;
2365 
2366  if(count < 0)
2367  return OutOfMemory;
2368 
2369  /* make a backup copy */
2370  if((retstat = GdipClonePath(path, &backup)) != Ok)
2371  return retstat;
2372 
2373  for(i = 0; i < count; i++){
2374  if((retstat = GdipAddPathRectangle(path,rects[i].X,rects[i].Y,rects[i].Width,rects[i].Height)) != Ok)
2375  goto fail;
2376  }
2377 
2378  /* free backup */
2380  return Ok;
2381 
2382 fail:
2383  /* reverting */
2384  heap_free(path->pathdata.Points);
2385  heap_free(path->pathdata.Types);
2386  memcpy(path, backup, sizeof(*path));
2387  heap_free(backup);
2388 
2389  return retstat;
2390 }
2391 
2393 {
2394  GpRectF *rectsF;
2395  GpStatus retstat;
2396  INT i;
2397 
2398  TRACE("(%p, %p, %d)\n", path, rects, count);
2399 
2400  if(!rects || count == 0)
2401  return InvalidParameter;
2402 
2403  if(count < 0)
2404  return OutOfMemory;
2405 
2406  rectsF = heap_alloc_zero(sizeof(GpRectF)*count);
2407 
2408  for(i = 0;i < count;i++){
2409  rectsF[i].X = (REAL)rects[i].X;
2410  rectsF[i].Y = (REAL)rects[i].Y;
2411  rectsF[i].Width = (REAL)rects[i].Width;
2412  rectsF[i].Height = (REAL)rects[i].Height;
2413  }
2414 
2415  retstat = GdipAddPathRectangles(path, rectsF, count);
2416  heap_free(rectsF);
2417 
2418  return retstat;
2419 }
2420 
2422 {
2423  INT count;
2424 
2425  TRACE("(%p)\n", path);
2426 
2427  if(!path)
2428  return InvalidParameter;
2429 
2430  count = path->pathdata.Count;
2431 
2432  /* set marker flag */
2433  if(count > 0)
2434  path->pathdata.Types[count-1] |= PathPointTypePathMarker;
2435 
2436  return Ok;
2437 }
2438 
2440 {
2441  INT count;
2442  INT i;
2443 
2444  TRACE("(%p)\n", path);
2445 
2446  if(!path)
2447  return InvalidParameter;
2448 
2449  count = path->pathdata.Count;
2450 
2451  for(i = 0; i < count - 1; i++){
2452  path->pathdata.Types[i] &= ~PathPointTypePathMarker;
2453  }
2454 
2455  return Ok;
2456 }
2457 
2459 {
2460  FIXME("stub: %p, %p, %.2f\n", path, matrix, flatness);
2461  return NotImplemented;
2462 }
2463 
2464 #define FLAGS_INTPATH 0x4000
2465 
2467 {
2471 };
2472 
2473 /* Test to see if the path could be stored as an array of shorts */
2475 {
2476  int i;
2477 
2478  if (!path->pathdata.Count) return FALSE;
2479 
2480  for (i = 0; i < path->pathdata.Count; i++)
2481  {
2482  short x, y;
2483  x = gdip_round(path->pathdata.Points[i].X);
2484  y = gdip_round(path->pathdata.Points[i].Y);
2485  if (path->pathdata.Points[i].X != (REAL)x || path->pathdata.Points[i].Y != (REAL)y)
2486  return FALSE;
2487  }
2488  return TRUE;
2489 }
2490 
2492 {
2493  struct path_header *header = data;
2494  BOOL integer_path = is_integer_path(path);
2495  DWORD i, size;
2496  BYTE *types;
2497 
2498  size = sizeof(struct path_header) + path->pathdata.Count;
2499  if (integer_path)
2500  size += sizeof(short[2]) * path->pathdata.Count;
2501  else
2502  size += sizeof(float[2]) * path->pathdata.Count;
2503  size = (size + 3) & ~3;
2504 
2505  if (!data) return size;
2506 
2507  header->version = VERSION_MAGIC2;
2508  header->count = path->pathdata.Count;
2509  header->flags = integer_path ? FLAGS_INTPATH : 0;
2510 
2511  if (integer_path)
2512  {
2513  short *points = (short*)(header + 1);
2514  for (i = 0; i < path->pathdata.Count; i++)
2515  {
2516  points[2*i] = path->pathdata.Points[i].X;
2517  points[2*i + 1] = path->pathdata.Points[i].Y;
2518  }
2519  types = (BYTE*)(points + 2*i);
2520  }
2521  else
2522  {
2523  float *points = (float*)(header + 1);
2524  for (i = 0; i < path->pathdata.Count; i++)
2525  {
2526  points[2*i] = path->pathdata.Points[i].X;
2527  points[2*i + 1] = path->pathdata.Points[i].Y;
2528  }
2529  types = (BYTE*)(points + 2*i);
2530  }
2531 
2532  for (i=0; i<path->pathdata.Count; i++)
2533  types[i] = path->pathdata.Types[i];
2534  memset(types + i, 0, ((path->pathdata.Count + 3) & ~3) - path->pathdata.Count);
2535  return size;
2536 }
GpStatus WINGDIPAPI GdipGetPathData(GpPath *path, GpPathData *pathData)
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3706
static BOOL init_path_list(path_list_node_t **node, REAL x, REAL y)
Definition: graphicspath.c:44
GpUnit unit
GpStatus WINGDIPAPI GdipDeleteFont(GpFont *font)
Definition: font.c:270
GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:844
GLint GLint GLsizei width
Definition: gl.h:1546
path_list_node_t * next
Definition: graphicspath.c:40
#define max(a, b)
Definition: svc.c:63
static long backup()
Definition: maze.c:403
#define TRUE
Definition: types.h:120
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
GpStatus WINGDIPAPI GdipAddPathCurve(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:460
static INT path_list_count(path_list_node_t *node)
Definition: graphicspath.c:94
GpStatus WINGDIPAPI GdipSetPathFillMode(GpPath *path, GpFillMode fill)
GpLineCap startcap
#define Y(I)
GpStatus WINGDIPAPI GdipAddPathClosedCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:362
GpCustomLineCap * customend
#define MAX_ARC_PTS
static void widen_open_figure(const GpPointF *points, GpPen *pen, int start, int end, GpLineCap start_cap, GpCustomLineCap *start_custom, GpLineCap end_cap, GpCustomLineCap *end_custom, path_list_node_t **last_point)
BYTE * Types
Definition: gdiplustypes.h:256
Definition: mk_font.cpp:20
GpStatus WINGDIPAPI GdipAddPathRectangles(GpPath *path, GDIPCONST GpRectF *rects, INT count)
#define pt(x, y)
Definition: drawing.c:79
GLsizei const GLchar ** path
Definition: glext.h:7234
GpDashStyle dash
GLuint GLenum matrix
Definition: glext.h:9407
INT Width
Definition: gdiplustypes.h:271
GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:1194
GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPointI(GpPath *path, INT x, INT y, GpPen *pen, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipGetPathWorldBounds(GpPath *path, GpRectF *bounds, GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
GpStatus WINGDIPAPI GdipTransformPath(GpPath *path, GpMatrix *matrix)
GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:290
WarpMode
Definition: gdiplusenums.h:198
GLuint GLuint GLsizei count
Definition: gl.h:1545
GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPoint(GpPath *path, REAL x, REAL y, GpPen *pen, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix *matrix, GDIPCONST GpPointF *points, INT count, REAL x, REAL y, REAL width, REAL height, WarpMode warpmode, REAL flatness)
GLint dy
Definition: linetemp.h:97
GpStatus WINGDIPAPI GdipAddPathArcI(GpPath *path, INT x1, INT y1, INT x2, INT y2, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:234
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
#define WARN(fmt,...)
Definition: debug.h:111
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
Definition: matrix.c:140
static HDC
Definition: imagelist.c:92
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum GLenum * types
Definition: glext.h:7753
GpPathData pathdata
GpStatus WINGDIPAPI GdipGetPathWorldBoundsI(GpPath *path, GpRect *bounds, GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
GpStatus WINGDIPAPI GdipGetPathPointsI(GpPath *path, GpPoint *points, INT count)
GLdouble n
Definition: glext.h:7729
void * next
Definition: dlist.c:360
GpStatus WINGDIPAPI GdipAddPathEllipseI(GpPath *path, INT x, INT y, INT width, INT height)
Definition: graphicspath.c:615
GpStatus WINGDIPAPI GdipGetPathLastPoint(GpPath *path, GpPointF *lastPoint)
GpStatus WINGDIPAPI GdipAddPathRectangleI(GpPath *path, INT x, INT y, INT width, INT height)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
GpStatus WINGDIPAPI GdipAddPathStringI(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST Rect *layoutRect, GDIPCONST GpStringFormat *format)
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
HDC dc
Definition: cylfrac.c:34
static BOOL is_integer_path(const GpPath *path)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
GLuint GLuint end
Definition: gl.h:1545
short gmCellIncY
Definition: wingdi.h:2441
Definition: wingdi.h:2467
LONG tmAscent
Definition: wingdi.h:2379
GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix *matrix, REAL flatness)
#define GDIPCONST
Definition: gdiplusflat.h:24
Definition: match.c:390
GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:870
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
int32_t INT
Definition: typedefs.h:56
#define VERSION_MAGIC2
GpStatus WINGDIPAPI GdipAddPathString(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *format)
& rect
Definition: startmenu.cpp:1413
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
REAL width
#define GGO_BEZIER
Definition: wingdi.h:850
FillMode
Definition: gdiplusenums.h:53
GLsizei GLsizei GLfloat distance
Definition: glext.h:11755
INT arc2polybezier(GpPointF *points, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle)
Definition: gdiplus.c:223
GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath *path)
FIXED y
Definition: wingdi.h:2704
struct node node
GpStatus gdip_format_string(HDC hdc, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip, gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN
Definition: graphics.c:5201
GpStatus WINGDIPAPI GdipGetPathTypes(GpPath *path, BYTE *types, INT count)
GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:195
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GpStatus WINGDIPAPI GdipCreatePath2(GDIPCONST GpPointF *points, GDIPCONST BYTE *types, INT count, GpFillMode fill, GpPath **path)
GLenum cap
Definition: glext.h:9639
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, REAL emSize, INT style, Unit unit, GpFont **font)
Definition: font.c:144
unsigned int BOOL
Definition: ntddk_ex.h:94
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
#define e
Definition: ke_i.h:82
INT X
Definition: gdiplustypes.h:269
static GpStatus format_string_callback(HDC dc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *priv)
Definition: graphicspath.c:912
struct tagPOINTFX POINTFX
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus)
GpStatus WINGDIPAPI GdipAddPathPieI(GpPath *path, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:835
GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN
Definition: graphics.c:6871
#define WINGDIPAPI
Definition: gdiplusflat.h:22
DWORD WINAPI GetGlyphOutlineW(_In_ HDC hdc, _In_ UINT uChar, _In_ UINT fuFormat, _Out_ LPGLYPHMETRICS lpgm, _In_ DWORD cjBuffer, _Out_writes_bytes_opt_(cjBuffer) LPVOID pvBuffer, _In_ CONST MAT2 *lpmat2)
BOOL WINAPI PtInRegion(_In_ HRGN, _In_ int, _In_ int)
smooth NULL
Definition: ftsmooth.c:416
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
GpLineCap endcap
GLuint index
Definition: glext.h:6031
GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:623
REAL Height
Definition: gdiplustypes.h:264
static INT gdip_round(REAL x)
void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2)
Definition: gdiplus.c:379
#define TT_PRIM_CSPLINE
Definition: wingdi.h:1320
static HFONT hfont
REAL * dashes
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
GpStatus WINGDIPAPI GdipGetPathPoints(GpPath *path, GpPointF *points, INT count)
_Check_return_ __CRT_INLINE float powf(_In_ float x, _In_ float y)
Definition: math.h:216
GpStatus WINGDIPAPI GdipAddPathLineI(GpPath *path, INT x1, INT y1, INT x2, INT y2)
Definition: graphicspath.c:738
GLfloat f
Definition: glext.h:7540
#define TRACE(s)
Definition: solgame.cpp:4
static path_list_node_t * add_path_list_node(path_list_node_t *node, REAL x, REAL y, BOOL type)
Definition: graphicspath.c:76
GLsizeiptr size
Definition: glext.h:5919
GpStatus WINGDIPAPI GdipAddPathClosedCurve2I(GpPath *path, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphicspath.c:432
GpStatus WINGDIPAPI GdipAddPathCurve3I(GpPath *path, GDIPCONST GpPoint *points, INT count, INT offset, INT nseg, REAL tension)
Definition: graphicspath.c:572
Definition: cmds.c:130
POINTFX apfx[1]
Definition: wingdi.h:2709
__wchar_t WCHAR
Definition: xmlstorage.h:180
GpStatus WINGDIPAPI GdipAddPathCurve2I(GpPath *path, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphicspath.c:533
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
_STLP_MOVE_TO_STD_NAMESPACE void fill(_ForwardIter __first, _ForwardIter __last, const _Tp &__val)
Definition: _algobase.h:449
REAL X
Definition: gdiplustypes.h:261
GpStatus WINGDIPAPI GdipGetPointCount(GpPath *path, INT *count)
GpStatus WINGDIPAPI GdipAddPathClosedCurve(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:346
GpStatus WINGDIPAPI GdipAddPathBeziersI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:319
LineCap
Definition: gdiplusenums.h:59
struct tagTTPOLYCURVE TTPOLYCURVE
REAL Y
Definition: gdiplustypes.h:249
unsigned long DWORD
Definition: ntddk_ex.h:95
GpStatus WINGDIPAPI GdipIsVisiblePathPointI(GpPath *path, INT x, INT y, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipClosePathFigure(GpPath *path)
static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint, GpPen *pen, int right_side, path_list_node_t **last_point)
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y, REAL width, REAL height)
static DWORD cb
Definition: integrity.c:41
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
POINTFX pfxStart
Definition: wingdi.h:2714
GpStatus WINGDIPAPI GdipClosePathFigures(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathPath(GpPath *path, GDIPCONST GpPath *addingPath, BOOL connect)
Definition: graphicspath.c:745
static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3, GpPen *pen, path_list_node_t **last_point)
GLsizei const GLfloat * points
Definition: glext.h:8112
GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:654
int ret
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
Definition: matrix.c:160
GpStatus WINGDIPAPI GdipWindingModeOutline(GpPath *path, GpMatrix *matrix, REAL flatness)
void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN
Definition: graphics.c:2305
GpStatus WINGDIPAPI GdipAddPathCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:480
static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint, GpPen *pen, GpLineCap cap, GpCustomLineCap *custom, int add_first_points, int add_last_point, path_list_node_t **last_point)
GpStatus WINGDIPAPI GdipAddPathClosedCurveI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:354
GpPenAlignment align
static HRGN hrgn
Definition: win.c:55
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
Definition: stat.h:55
REAL X
Definition: gdiplustypes.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
Definition: _list.h:228
static void free_path_list(path_list_node_t *node)
Definition: graphicspath.c:59
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3706
GpStatus WINGDIPAPI GdipAddPathBezier(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL x3, REAL y3, REAL x4, REAL y4)
Definition: graphicspath.c:243
GpStatus WINGDIPAPI GdipAddPathRectanglesI(GpPath *path, GDIPCONST GpRect *rects, INT count)
short gmCellIncX
Definition: wingdi.h:2440
static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, REAL y3, path_list_node_t *end, REAL flatness)
Definition: graphicspath.c:121
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:363
INT numdashes
Status
Definition: gdiplustypes.h:24
REAL Width
Definition: gdiplustypes.h:263
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
Definition: matrix.c:185
#define ERR(fmt,...)
Definition: debug.h:109
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
Definition: nis.h:10
const GLdouble * v
Definition: gl.h:2040
GpStatus WINGDIPAPI GdipCreatePath2I(GDIPCONST GpPoint *points, GDIPCONST BYTE *types, INT count, GpFillMode fill, GpPath **path)
BOOL WINAPI DeleteDC(_In_ HDC)
static calc_node_t temp
Definition: rpn_ieee.c:38
GLuint start
Definition: gl.h:1545
REAL miterlimit
GpLineJoin join
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
Definition: region.c:425
#define f
Definition: ke_i.h:83
GpStatus WINGDIPAPI GdipAddPathLine(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2)
Definition: graphicspath.c:704
Definition: services.c:325
#define list
Definition: rosglue.h:35
static float fromfixedpoint(const FIXED v)
Definition: graphicspath.c:897
GpStatus WINGDIPAPI GdipResetPath(GpPath *path)
unsigned short UINT16
#define min(a, b)
Definition: monoChain.cc:55
GpDashCap dashcap
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
Definition: graphics.c:2395
GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath *path, REAL x, REAL y, GpGraphics *graphics, BOOL *result)
PointF * Points
Definition: gdiplustypes.h:255
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint dx
Definition: linetemp.h:97
INT Height
Definition: gdiplustypes.h:272
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
GpStatus WINGDIPAPI GdipSetPathMarker(GpPath *path)
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix, REAL flatness)
#define FLAGS_INTPATH
#define sqrtf(x)
Definition: mymath.h:59
GpStatus WINGDIPAPI GdipAddPathCurve3(GpPath *path, GDIPCONST GpPointF *points, INT count, INT offset, INT nseg, REAL tension)
Definition: graphicspath.c:561
DWORD write_path_data(GpPath *path, void *data)
GpCustomLineCap * customstart
GLuint GLenum GLenum transform
Definition: glext.h:9407
GpStatus WINGDIPAPI GdipClonePath(GpPath *path, GpPath **clone)
INT Y
Definition: gdiplustypes.h:270
GpStatus WINGDIPAPI GdipAddPathPie(GpPath *path, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:776
float REAL
Definition: types.h:41
GpStatus WINGDIPAPI GdipGetPathFillMode(GpPath *path, GpFillMode *fillmode)
GpStatus WINGDIPAPI GdipStartPathFigure(GpPath *path)
static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end, path_list_node_t **last_point)
Arabic default style
Definition: afstyles.h:93
REAL Y
Definition: gdiplustypes.h:262
#define GDI_ERROR
Definition: wingdi.h:1308
GpStatus WINGDIPAPI GdipAddPathCurveI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:470
GpStatus WINGDIPAPI GdipAddPathBezierI(GpPath *path, INT x1, INT y1, INT x2, INT y2, INT x3, INT y3, INT x4, INT y4)
Definition: graphicspath.c:280
GLuint64EXT * result
Definition: glext.h:11304
#define TT_PRIM_LINE
Definition: wingdi.h:1318
#define memset(x, y, z)
Definition: compat.h:39
BOOL lengthen_path(GpPath *path, INT len)
Definition: gdiplus.c:405
static SERVICE_STATUS status
Definition: service.c:31
GpStatus WINGDIPAPI GdipAddPathEllipse(GpPath *path, REAL x, REAL y, REAL width, REAL height)
Definition: graphicspath.c:583
GpStatus WINGDIPAPI GdipDeleteRegion(GpRegion *region)
Definition: region.c:571
GpStatus WINGDIPAPI GdipGetEmHeight(GDIPCONST GpFontFamily *family, INT style, UINT16 *EmHeight)
Definition: font.c:918
struct CFHEADER header
Definition: fdi.c:109
static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end, int closed, path_list_node_t **last_point)
void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, REAL tension, REAL *x, REAL *y)
Definition: gdiplus.c:396
#define TENSION_CONST
GpStatus WINGDIPAPI GdipReversePath(GpPath *path)
FIXED x
Definition: wingdi.h:2703
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
Definition: dlist.c:348
Definition: ps.c:97