ReactOS 0.4.15-dev-7961-gdcf9eb0
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;
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{
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;
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] =
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] =
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
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] =
313 path->newfigure = FALSE;
314 path->pathdata.Count += count;
315
316 return Ok;
317}
318
320 INT count)
321{
322 GpPointF *ptsF;
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
341 heap_free(ptsF);
342
343 return ret;
344}
345
347 INT count)
348{
349 TRACE("(%p, %p, %d)\n", path, points, count);
350
352}
353
355 INT count)
356{
357 TRACE("(%p, %p, %d)\n", path, points, count);
358
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;
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;
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;
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;
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
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;
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] =
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
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
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;
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
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
897static 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;
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;
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
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
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;
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
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 */
1317 startidx = i;
1318
1319 /* always add line points and start points */
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 */
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
1374memout:
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
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;
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;
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
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
1806static 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
1837static 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:
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
1879static 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,
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,
1976 }
1977 if (add_last_point)
1978 add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
1979 break;
1980 }
1981 }
1982}
1983
1984static 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
2017static 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
2059static 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;
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;
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))
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))
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
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
2336fail:
2337 /* reverting */
2338 heap_free(path->pathdata.Points);
2339 heap_free(path->pathdata.Types);
2340 memcpy(path, backup, sizeof(*path));
2342
2343 return retstat;
2344}
2345
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
2382fail:
2383 /* reverting */
2384 heap_free(path->pathdata.Points);
2385 heap_free(path->pathdata.Types);
2386 memcpy(path, backup, sizeof(*path));
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}
static HFONT hfont
static HRGN hrgn
unsigned short UINT16
_STLP_MOVE_TO_STD_NAMESPACE void fill(_ForwardIter __first, _ForwardIter __last, const _Tp &__val)
Definition: _algobase.h:449
#define stat
Definition: acwin.h:99
Arabic default style
Definition: afstyles.h:94
static long backup()
Definition: maze.c:403
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:37
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
float REAL
Definition: types.h:41
#define Y(I)
GpStatus WINGDIPAPI GdipDeleteFont(GpFont *font)
Definition: font.c:270
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, REAL emSize, INT style, Unit unit, GpFont **font)
Definition: font.c:144
GpStatus WINGDIPAPI GdipGetEmHeight(GDIPCONST GpFontFamily *family, INT style, UINT16 *EmHeight)
Definition: font.c:918
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
Definition: graphics.c:2395
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
GpStatus WINGDIPAPI GdipAddPathCurve3(GpPath *path, GDIPCONST GpPointF *points, INT count, INT offset, INT nseg, REAL tension)
Definition: graphicspath.c:561
static INT path_list_count(path_list_node_t *node)
Definition: graphicspath.c:94
GpStatus WINGDIPAPI GdipGetPathWorldBoundsI(GpPath *path, GpRect *bounds, GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end, path_list_node_t **last_point)
GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath *path)
GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPointI(GpPath *path, INT x, INT y, GpPen *pen, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipAddPathRectangleI(GpPath *path, INT x, INT y, INT width, INT height)
static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end, int closed, path_list_node_t **last_point)
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
GpStatus WINGDIPAPI GdipCreatePath2I(GDIPCONST GpPoint *points, GDIPCONST BYTE *types, INT count, GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipAddPathPie(GpPath *path, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:776
#define FLAGS_INTPATH
DWORD write_path_data(GpPath *path, void *data)
GpStatus WINGDIPAPI GdipAddPathEllipseI(GpPath *path, INT x, INT y, INT width, INT height)
Definition: graphicspath.c:615
GpStatus WINGDIPAPI GdipAddPathLine(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2)
Definition: graphicspath.c:704
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
static void free_path_list(path_list_node_t *node)
Definition: graphicspath.c:59
static float fromfixedpoint(const FIXED v)
Definition: graphicspath.c:897
GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:195
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y, REAL width, REAL height)
GpStatus WINGDIPAPI GdipAddPathCurve(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:460
GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPoint(GpPath *path, REAL x, REAL y, GpPen *pen, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipGetPathData(GpPath *path, GpPathData *pathData)
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)
GpStatus WINGDIPAPI GdipResetPath(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathPieI(GpPath *path, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:835
GpStatus WINGDIPAPI GdipCreatePath2(GDIPCONST GpPointF *points, GDIPCONST BYTE *types, INT count, GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:623
GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix *matrix, REAL flatness)
GpStatus WINGDIPAPI GdipAddPathClosedCurve2I(GpPath *path, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphicspath.c:432
GpStatus WINGDIPAPI GdipAddPathArcI(GpPath *path, INT x1, INT y1, INT x2, INT y2, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:234
GpStatus WINGDIPAPI GdipAddPathStringI(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST Rect *layoutRect, GDIPCONST GpStringFormat *format)
GpStatus WINGDIPAPI GdipGetPathLastPoint(GpPath *path, GpPointF *lastPoint)
GpStatus WINGDIPAPI GdipClosePathFigure(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:844
static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint, GpPen *pen, int right_side, path_list_node_t **last_point)
static BOOL init_path_list(path_list_node_t **node, REAL x, REAL y)
Definition: graphicspath.c:44
GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix *matrix, GDIPCONST GpPointF *points, INT count, REAL x, REAL y, REAL width, REAL height, WarpMode warpmode, REAL flatness)
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
GpStatus WINGDIPAPI GdipClonePath(GpPath *path, GpPath **clone)
GpStatus WINGDIPAPI GdipAddPathCurve2I(GpPath *path, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphicspath.c:533
GpStatus WINGDIPAPI GdipTransformPath(GpPath *path, GpMatrix *matrix)
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
GpStatus WINGDIPAPI GdipAddPathLineI(GpPath *path, INT x1, INT y1, INT x2, INT y2)
Definition: graphicspath.c:738
GpStatus WINGDIPAPI GdipGetPathPointsI(GpPath *path, GpPoint *points, INT count)
GpStatus WINGDIPAPI GdipSetPathFillMode(GpPath *path, GpFillMode fill)
static BOOL is_integer_path(const GpPath *path)
GpStatus WINGDIPAPI GdipAddPathPath(GpPath *path, GDIPCONST GpPath *addingPath, BOOL connect)
Definition: graphicspath.c:745
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix, REAL flatness)
GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:290
GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:654
GpStatus WINGDIPAPI GdipGetPathWorldBounds(GpPath *path, GpRectF *bounds, GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
GpStatus WINGDIPAPI GdipAddPathRectangles(GpPath *path, GDIPCONST GpRectF *rects, INT count)
GpStatus WINGDIPAPI GdipWindingModeOutline(GpPath *path, GpMatrix *matrix, REAL flatness)
GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:870
GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath *path, REAL x, REAL y, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipAddPathCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:480
GpStatus WINGDIPAPI GdipAddPathBeziersI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:319
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 GdipGetPointCount(GpPath *path, INT *count)
GpStatus WINGDIPAPI GdipGetPathPoints(GpPath *path, GpPointF *points, INT count)
GpStatus WINGDIPAPI GdipIsVisiblePathPointI(GpPath *path, INT x, INT y, GpGraphics *graphics, BOOL *result)
GpStatus WINGDIPAPI GdipAddPathClosedCurveI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:354
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)
static path_list_node_t * add_path_list_node(path_list_node_t *node, REAL x, REAL y, BOOL type)
Definition: graphicspath.c:76
GpStatus WINGDIPAPI GdipReversePath(GpPath *path)
GpStatus WINGDIPAPI GdipClosePathFigures(GpPath *path)
GpStatus WINGDIPAPI GdipGetPathTypes(GpPath *path, BYTE *types, INT count)
GpStatus WINGDIPAPI GdipStartPathFigure(GpPath *path)
GpStatus WINGDIPAPI GdipGetPathFillMode(GpPath *path, GpFillMode *fillmode)
GpStatus WINGDIPAPI GdipAddPathEllipse(GpPath *path, REAL x, REAL y, REAL width, REAL height)
Definition: graphicspath.c:583
GpStatus WINGDIPAPI GdipAddPathClosedCurve(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:346
GpStatus WINGDIPAPI GdipAddPathClosedCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:362
static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3, GpPen *pen, path_list_node_t **last_point)
GpStatus WINGDIPAPI GdipAddPathString(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *format)
GpStatus WINGDIPAPI GdipSetPathMarker(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathCurve3I(GpPath *path, GDIPCONST GpPoint *points, INT count, INT offset, INT nseg, REAL tension)
Definition: graphicspath.c:572
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
Definition: matrix.c:160
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:363
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
Definition: matrix.c:140
GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
Definition: matrix.c:185
GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:1194
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
Definition: region.c:425
GpStatus WINGDIPAPI GdipDeleteRegion(GpRegion *region)
Definition: region.c:571
#define pt(x, y)
Definition: drawing.c:79
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
BOOL lengthen_path(GpPath *path, INT len)
Definition: gdiplus.c:405
void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2)
Definition: gdiplus.c:379
void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, REAL tension, REAL *x, REAL *y)
Definition: gdiplus.c:396
INT arc2polybezier(GpPointF *points, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle)
Definition: gdiplus.c:223
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
static INT gdip_round(REAL x)
#define VERSION_MAGIC2
GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN
Definition: graphics.c:6871
#define TENSION_CONST
#define MAX_ARC_PTS
void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN
Definition: graphics.c:2305
@ DashCapFlat
Definition: gdiplusenums.h:171
@ LineJoinMiter
Definition: gdiplusenums.h:106
@ LineJoinMiterClipped
Definition: gdiplusenums.h:109
@ LineJoinBevel
Definition: gdiplusenums.h:107
@ LineJoinRound
Definition: gdiplusenums.h:108
@ StringAlignmentCenter
Definition: gdiplusenums.h:266
@ StringAlignmentFar
Definition: gdiplusenums.h:267
LineCap
Definition: gdiplusenums.h:60
@ LineCapTriangle
Definition: gdiplusenums.h:64
@ LineCapNoAnchor
Definition: gdiplusenums.h:66
@ LineCapSquare
Definition: gdiplusenums.h:62
@ LineCapRound
Definition: gdiplusenums.h:63
@ LineCapFlat
Definition: gdiplusenums.h:61
FillMode
Definition: gdiplusenums.h:54
@ FillModeAlternate
Definition: gdiplusenums.h:55
@ FillModeWinding
Definition: gdiplusenums.h:56
@ DashStyleSolid
Definition: gdiplusenums.h:178
@ DashStyleDot
Definition: gdiplusenums.h:180
@ DashStyleDashDot
Definition: gdiplusenums.h:181
@ DashStyleCustom
Definition: gdiplusenums.h:183
@ DashStyleDash
Definition: gdiplusenums.h:179
@ DashStyleDashDotDot
Definition: gdiplusenums.h:182
WarpMode
Definition: gdiplusenums.h:200
@ PenAlignmentCenter
Definition: gdiplusenums.h:155
@ UnitPixel
Definition: gdiplusenums.h:29
@ PathPointTypePathMarker
Definition: gdiplusenums.h:89
@ PathPointTypePathTypeMask
Definition: gdiplusenums.h:87
@ PathPointTypeBezier
Definition: gdiplusenums.h:86
@ PathPointTypeLine
Definition: gdiplusenums.h:85
@ PathPointTypeCloseSubpath
Definition: gdiplusenums.h:90
@ PathPointTypeStart
Definition: gdiplusenums.h:84
@ CoordinateSpaceDevice
Definition: gdiplusenums.h:369
@ CoordinateSpaceWorld
Definition: gdiplusenums.h:367
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
@ InvalidParameter
Definition: gdiplustypes.h:28
@ OutOfMemory
Definition: gdiplustypes.h:29
@ InsufficientBuffer
Definition: gdiplustypes.h:31
@ NotImplemented
Definition: gdiplustypes.h:32
@ GenericError
Definition: gdiplustypes.h:27
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLuint index
Definition: glext.h:6031
GLfloat f
Definition: glext.h:7540
GLsizei GLsizei GLfloat distance
Definition: glext.h:11755
GLuint GLenum matrix
Definition: glext.h:9407
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLenum cap
Definition: glext.h:9639
GLsizei const GLfloat * points
Definition: glext.h:8112
GLintptr offset
Definition: glext.h:5920
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
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
_Check_return_ float __cdecl powf(_In_ float b, _In_ float e)
Definition: math.h:232
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define debugstr_w
Definition: kernel32.h:32
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
static const WCHAR dc[]
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HDC
Definition: imagelist.c:92
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static float(__cdecl *square_half_float)(float x
#define min(a, b)
Definition: monoChain.cc:55
#define sqrtf(x)
Definition: mymath.h:59
Definition: mk_font.cpp:20
int Count
Definition: noreturn.cpp:7
#define list
Definition: rosglue.h:35
static calc_node_t temp
Definition: rpn_ieee.c:38
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
GpPathData pathdata
GpDashStyle dash
GpLineCap startcap
INT numdashes
REAL * dashes
GpCustomLineCap * customend
REAL miterlimit
GpLineCap endcap
GpLineJoin join
GpDashCap dashcap
GpPenAlignment align
GpUnit unit
REAL width
GpCustomLineCap * customstart
PointF * Points
Definition: gdiplustypes.h:655
BYTE * Types
Definition: gdiplustypes.h:656
REAL Y
Definition: gdiplustypes.h:649
REAL X
Definition: gdiplustypes.h:648
REAL Height
Definition: gdiplustypes.h:664
REAL X
Definition: gdiplustypes.h:661
REAL Width
Definition: gdiplustypes.h:663
REAL Y
Definition: gdiplustypes.h:662
INT Width
Definition: gdiplustypes.h:671
INT Height
Definition: gdiplustypes.h:672
INT X
Definition: gdiplustypes.h:669
INT Y
Definition: gdiplustypes.h:670
short gmCellIncX
Definition: wingdi.h:2445
short gmCellIncY
Definition: wingdi.h:2446
Definition: wingdi.h:2472
Definition: match.c:390
Definition: nis.h:10
path_list_node_t * next
Definition: graphicspath.c:40
Definition: stat.h:55
Definition: ps.c:97
FIXED y
Definition: wingdi.h:2709
FIXED x
Definition: wingdi.h:2708
LONG tmAscent
Definition: wingdi.h:2384
POINTFX apfx[1]
Definition: wingdi.h:2714
POINTFX pfxStart
Definition: wingdi.h:2719
Definition: cmds.c:130
#define max(a, b)
Definition: svc.c:63
int32_t INT
Definition: typedefs.h:58
Definition: dlist.c:348
void * next
Definition: dlist.c:360
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_In_ HFONT _Out_ PUINT Height
Definition: font.h:88
int ret
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
struct tagPOINTFX POINTFX
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
#define TT_PRIM_CSPLINE
Definition: wingdi.h:1321
struct tagTTPOLYCURVE TTPOLYCURVE
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI PtInRegion(_In_ HRGN, _In_ int, _In_ int)
#define GDI_ERROR
Definition: wingdi.h:1309
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
BOOL WINAPI DeleteDC(_In_ HDC)
#define TT_PRIM_LINE
Definition: wingdi.h:1319
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)
#define GGO_BEZIER
Definition: wingdi.h:851
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193