~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdiplus/tests/graphicspath.c

Version: ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Unit test suite for paths
  3  *
  4  * Copyright (C) 2007 Google (Evan Stade)
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "windows.h"
 22 #include "gdiplus.h"
 23 #include "wine/test.h"
 24 #include <math.h>
 25 
 26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 27 #define expectf(expected, got) ok(fabs(expected - got) < 2.0, "Expected %.2f, got %.2f\n", expected, got)
 28 #define POINT_TYPE_MAX_LEN (75)
 29 
 30 static void stringify_point_type(PathPointType type, char * name)
 31 {
 32     *name = '\0';
 33 
 34     switch(type & PathPointTypePathTypeMask){
 35         case PathPointTypeStart:
 36             strcat(name, "PathPointTypeStart");
 37             break;
 38         case PathPointTypeLine:
 39             strcat(name, "PathPointTypeLine");
 40             break;
 41         case PathPointTypeBezier:
 42             strcat(name, "PathPointTypeBezier");
 43             break;
 44         default:
 45             strcat(name, "Unknown type");
 46             return;
 47     }
 48 
 49     type &= ~PathPointTypePathTypeMask;
 50     if(type & ~((PathPointTypePathMarker | PathPointTypeCloseSubpath))){
 51         *name = '\0';
 52         strcat(name, "Unknown type");
 53         return;
 54     }
 55 
 56     if(type & PathPointTypePathMarker)
 57         strcat(name, " | PathPointTypePathMarker");
 58     if(type & PathPointTypeCloseSubpath)
 59         strcat(name, " | PathPointTypeCloseSubpath");
 60 }
 61 
 62 /* this helper structure and function modeled after gdi path.c test */
 63 typedef struct
 64 {
 65     REAL X, Y;
 66     BYTE type;
 67 
 68     /* How many extra entries before this one only on wine
 69      * but not on native? */
 70     int wine_only_entries_preceding;
 71 
 72     /* 0 - This entry matches on wine.
 73      * 1 - This entry corresponds to a single entry on wine that does not match the native entry.
 74      * 2 - This entry is currently skipped on wine but present on native. */
 75     int todo;
 76 } path_test_t;
 77 
 78 static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size, BOOL todo_size)
 79 {
 80     BYTE * types;
 81     INT size, idx = 0, eidx = 0, numskip;
 82     GpPointF * points;
 83     char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN];
 84 
 85     if(GdipGetPointCount(path, &size) != Ok){
 86         skip("Cannot perform path comparisons due to failure to retrieve path.\n");
 87         return;
 88     }
 89 
 90     if(todo_size) todo_wine
 91         ok(size == expected_size, "Path size %d does not match expected size %d\n",
 92             size, expected_size);
 93     else
 94         ok(size == expected_size, "Path size %d does not match expected size %d\n",
 95             size, expected_size);
 96 
 97     points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF));
 98     types = HeapAlloc(GetProcessHeap(), 0, size);
 99 
100     if(GdipGetPathPoints(path, points, size) != Ok || GdipGetPathTypes(path, types, size) != Ok){
101         skip("Cannot perform path comparisons due to failure to retrieve path.\n");
102         goto end;
103     }
104 
105     numskip = expected_size ? expected[eidx].wine_only_entries_preceding : 0;
106     while (idx < size && eidx < expected_size){
107         /* We allow a few pixels fudge in matching X and Y coordinates to account for imprecision in
108          * floating point to integer conversion */
109         BOOL match = (types[idx] == expected[eidx].type) &&
110             fabs(points[idx].X - expected[eidx].X) <= 2.0 &&
111             fabs(points[idx].Y - expected[eidx].Y) <= 2.0;
112 
113         stringify_point_type(expected[eidx].type, ename);
114         stringify_point_type(types[idx], name);
115 
116         if (expected[eidx].todo || numskip) todo_wine
117             ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
118                ename, expected[eidx].X, expected[eidx].Y,
119                name, points[idx].X, points[idx].Y);
120         else
121             ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
122                ename, expected[eidx].X, expected[eidx].Y,
123                name, points[idx].X, points[idx].Y);
124 
125         if (match || expected[eidx].todo != 2)
126             idx++;
127         if (match || !numskip--)
128             numskip = expected[++eidx].wine_only_entries_preceding;
129     }
130 
131 end:
132     HeapFree(GetProcessHeap(), 0, types);
133     HeapFree(GetProcessHeap(), 0, points);
134 }
135 
136 static void test_constructor_destructor(void)
137 {
138     GpStatus status;
139     GpPath* path = NULL;
140 
141     status = GdipCreatePath(FillModeAlternate, &path);
142     expect(Ok, status);
143     ok(path != NULL, "Expected path to be initialized\n");
144 
145     status = GdipDeletePath(NULL);
146     expect(InvalidParameter, status);
147 
148     status = GdipDeletePath(path);
149     expect(Ok, status);
150 }
151 
152 static void test_getpathdata(void)
153 {
154     GpPath *path;
155     GpPathData data;
156     GpStatus status;
157     INT count;
158 
159     GdipCreatePath(FillModeAlternate, &path);
160     status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
161     expect(Ok, status);
162 
163     /* Prepare storage. Made by wrapper class. */
164     status = GdipGetPointCount(path, &count);
165     expect(Ok, status);
166 
167     data.Count  = 2;
168     data.Types  = GdipAlloc(sizeof(BYTE) * count);
169     data.Points = GdipAlloc(sizeof(PointF) * count);
170 
171     status = GdipGetPathData(path, &data);
172     expect(Ok, status);
173     expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) &&
174            (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE);
175     expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE);
176 
177     GdipFree(data.Points);
178     GdipFree(data.Types);
179     GdipDeletePath(path);
180 }
181 
182 static path_test_t line2_path[] = {
183     {0.0, 50.0, PathPointTypeStart, 0, 0}, /**/
184     {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
185     {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/
186     {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/
187     {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/
188     {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/
189     {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/
190     {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/
191     {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/
192     };
193 
194 static void test_line2(void)
195 {
196     GpStatus status;
197     GpPath* path;
198     int i;
199     GpPointF line2_points[9];
200 
201     for(i = 0; i < 9; i ++){
202         line2_points[i].X = i * 5.0 * (REAL)(i % 2);
203         line2_points[i].Y = 50.0 - i * 5.0;
204     }
205 
206     GdipCreatePath(FillModeAlternate, &path);
207     status = GdipAddPathLine2(path, line2_points, 3);
208     expect(Ok, status);
209     status = GdipAddPathLine2(path, &(line2_points[3]), 3);
210     expect(Ok, status);
211     status = GdipClosePathFigure(path);
212     expect(Ok, status);
213     status = GdipAddPathLine2(path, &(line2_points[6]), 3);
214     expect(Ok, status);
215 
216     ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE);
217 
218     GdipDeletePath(path);
219 }
220 
221 static path_test_t arc_path[] = {
222     {600.0, 450.0, PathPointTypeStart, 0, 0}, /**/
223     {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/
224     {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/
225     {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/
226     {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/
227     {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/
228     {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/
229     {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/
230     {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/
231     {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/
232     {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/
233     {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/
234     {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/
235     {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/
236     {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/
237     {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/
238     {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/
239     {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/
240     {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/
241     {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/
242     {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/
243     {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/
244     {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/
245     {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/
246     {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/
247     {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/
248     {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/
249     {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/
250     {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/
251     {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/
252     {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/
253     {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/
254     {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/
255     {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/
256     {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/
257     {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/
258     {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
259     {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
260     };
261 
262 static void test_arc(void)
263 {
264     GpStatus status;
265     GpPath* path;
266 
267     GdipCreatePath(FillModeAlternate, &path);
268     /* Exactly 90 degrees */
269     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
270     expect(Ok, status);
271     /* Over 90 degrees */
272     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
273     expect(Ok, status);
274     /* Negative start angle */
275     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
276     expect(Ok, status);
277     /* Negative sweep angle */
278     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0);
279     expect(Ok, status);
280     /* More than a full revolution */
281     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0);
282     expect(Ok, status);
283     /* 0 sweep angle */
284     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
285     expect(Ok, status);
286 
287     ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE);
288 
289     GdipDeletePath(path);
290 }
291 
292 static void test_worldbounds(void)
293 {
294     GpStatus status;
295     GpPath *path;
296     GpPen *pen;
297     GpMatrix *matrix;
298     GpRectF bounds;
299     GpPointF line2_points[10];
300     int i;
301 
302     for(i = 0; i < 10; i ++){
303         line2_points[i].X = 200.0 + i * 50.0 * (i % 2);
304         line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2);
305     }
306     GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen);
307     GdipSetPenEndCap(pen, LineCapSquareAnchor);
308     GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix);
309 
310     GdipCreatePath(FillModeAlternate, &path);
311     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
312     GdipAddPathLine2(path, &(line2_points[0]), 10);
313     status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
314     expect(Ok, status);
315     GdipDeletePath(path);
316 
317     expectf(200.0, bounds.X);
318     expectf(200.0, bounds.Y);
319     expectf(450.0, bounds.Width);
320     expectf(600.0, bounds.Height);
321 
322     GdipCreatePath(FillModeAlternate, &path);
323     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
324     GdipAddPathLine2(path, &(line2_points[0]), 10);
325     status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
326     expect(Ok, status);
327     GdipDeletePath(path);
328 
329     expectf(510.4, bounds.X);
330     expectf(250.2, bounds.Y);
331     expectf(1275.0, bounds.Width);
332     expectf(720.0, bounds.Height);
333 
334     GdipCreatePath(FillModeAlternate, &path);
335     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
336     GdipAddPathLine2(path, &(line2_points[0]), 10);
337     status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
338     expect(Ok, status);
339     GdipDeletePath(path);
340 
341     expectf(100.0, bounds.X);
342     expectf(100.0, bounds.Y);
343     expectf(650.0, bounds.Width);
344     expectf(800.0, bounds.Height);
345 
346     GdipCreatePath(FillModeAlternate, &path);
347     GdipAddPathLine2(path, &(line2_points[0]), 2);
348     status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
349     expect(Ok, status);
350     GdipDeletePath(path);
351 
352     expectf(156.0, bounds.X);
353     expectf(156.0, bounds.Y);
354     expectf(138.0, bounds.Width);
355     expectf(88.0, bounds.Height);
356 
357     line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
358     line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
359 
360     GdipCreatePath(FillModeAlternate, &path);
361     GdipAddPathLine2(path, &(line2_points[0]), 3);
362     status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
363     expect(Ok, status);
364     GdipDeletePath(path);
365 
366     expectf(100.0, bounds.X);
367     expectf(100.0, bounds.Y);
368     expectf(300.0, bounds.Width);
369     expectf(200.0, bounds.Height);
370 
371     GdipCreatePath(FillModeAlternate, &path);
372     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0);
373     status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
374     expect(Ok, status);
375     GdipDeletePath(path);
376 
377     expectf(386.7, bounds.X);
378     expectf(553.4, bounds.Y);
379     expectf(266.8, bounds.Width);
380     expectf(289.6, bounds.Height);
381 
382     GdipCreatePath(FillModeAlternate, &path);
383     status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
384     expect(Ok, status);
385     GdipDeletePath(path);
386 
387     expectf(0.0, bounds.X);
388     expectf(0.0, bounds.Y);
389     expectf(0.0, bounds.Width);
390     expectf(0.0, bounds.Height);
391 
392     GdipCreatePath(FillModeAlternate, &path);
393     GdipAddPathLine2(path, &(line2_points[0]), 2);
394     status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
395     expect(Ok, status);
396     GdipDeletePath(path);
397 
398     todo_wine{
399         expectf(427.9, bounds.X);
400         expectf(167.7, bounds.Y);
401         expectf(239.9, bounds.Width);
402         expectf(164.9, bounds.Height);
403     }
404 
405     GdipDeleteMatrix(matrix);
406     GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix);
407     GdipCreatePath(FillModeAlternate, &path);
408     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
409     GdipAddPathLine2(path, &(line2_points[0]), 10);
410     status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
411     expect(Ok, status);
412     GdipDeletePath(path);
413 
414     expectf(-209.6, bounds.X);
415     expectf(-1274.8, bounds.Y);
416     expectf(705.0, bounds.Width);
417     expectf(945.0, bounds.Height);
418 }
419 
420 static path_test_t pathpath_path[] = {
421     {600.00, 450.00, PathPointTypeStart, 0, 0}, /**/
422     {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/
423     {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/
424     {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/
425     {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/
426     {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/
427     {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/
428     {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/
429     {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/
430     {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/
431     {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/
432     {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/
433     {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/
434     {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/
435     {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/
436     {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/
437     {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/
438     {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/
439     {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/
440     {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/
441     {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/
442     {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/
443     {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/
444     {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/
445     {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/
446     };
447 
448 static void test_pathpath(void)
449 {
450     GpStatus status;
451     GpPath* path1, *path2;
452 
453     GdipCreatePath(FillModeAlternate, &path2);
454     GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0);
455 
456     GdipCreatePath(FillModeAlternate, &path1);
457     GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
458     status = GdipAddPathPath(path1, path2, FALSE);
459     expect(Ok, status);
460     GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
461     status = GdipAddPathPath(path1, path2, TRUE);
462     expect(Ok, status);
463 
464     ok_path(path1, pathpath_path, sizeof(pathpath_path)/sizeof(path_test_t), FALSE);
465 
466     GdipDeletePath(path1);
467     GdipDeletePath(path2);
468 }
469 
470 static path_test_t ellipse_path[] = {
471     {30.00, 125.25, PathPointTypeStart, 0, 0}, /**/
472     {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/
473     {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/
474     {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/
475     {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/
476     {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/
477     {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/
478     {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/
479     {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/
480     {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/
481     {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/
482     {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/
483     {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/
484     {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/
485     {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/
486     {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/
487     {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/
488     {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/
489     {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/
490     {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/
491     {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/
492     {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/
493     {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/
494     {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/
495     {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/
496     {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/
497     {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/
498     {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/
499     {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/
500     {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/
501     {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/
502     {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/
503     {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/
504     {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/
505     {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/
506     {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/
507     {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/
508     {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/
509     {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/
510     {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/
511     {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/
512     };
513 
514 static void test_ellipse(void)
515 {
516     GpStatus status;
517     GpPath *path;
518     GpPointF points[2];
519 
520     points[0].X = 7.0;
521     points[0].Y = 11.0;
522     points[1].X = 13.0;
523     points[1].Y = 17.0;
524 
525     GdipCreatePath(FillModeAlternate, &path);
526     status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5);
527     expect(Ok, status);
528     GdipAddPathLine2(path, points, 2);
529     status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0);
530     expect(Ok, status);
531     GdipClosePathFigure(path);
532     status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
533     expect(Ok, status);
534 
535     ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE);
536 
537     GdipDeletePath(path);
538 }
539 
540 static path_test_t linei_path[] = {
541     {5.00, 5.00, PathPointTypeStart, 0, 0}, /**/
542     {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/
543     {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/
544     {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/
545     {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/
546     {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/
547     {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/
548     {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/
549     {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/
550     {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/
551     {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/
552     {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/
553     {36.00, 38.00, PathPointTypeLine, 0, 0} /*12*/
554     };
555 
556 static void test_linei(void)
557 {
558     GpStatus status;
559     GpPath *path;
560     GpPointF points[2];
561 
562     points[0].X = 7.0;
563     points[0].Y = 11.0;
564     points[1].X = 13.0;
565     points[1].Y = 17.0;
566 
567     GdipCreatePath(FillModeAlternate, &path);
568     status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0);
569     expect(Ok, status);
570     GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
571     status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0);
572     expect(Ok, status);
573     GdipClosePathFigure(path);
574     status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
575     expect(Ok, status);
576 
577     ok_path(path, linei_path, sizeof(linei_path)/sizeof(path_test_t), FALSE);
578 
579     GdipDeletePath(path);
580 }
581 
582 static path_test_t poly_path[] = {
583     {5.00, 5.00, PathPointTypeStart, 0, 0},   /*1*/
584     {6.00, 8.00, PathPointTypeLine, 0, 0},    /*2*/
585     {0.00,  0.00,  PathPointTypeStart, 0, 0}, /*3*/
586     {10.00, 10.00, PathPointTypeLine, 0, 0},  /*4*/
587     {10.00, 20.00, PathPointTypeLine, 0, 0},  /*5*/
588     {30.00, 10.00, PathPointTypeLine, 0, 0},  /*6*/
589     {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/
590     };
591 
592 static void test_polygon(void)
593 {
594     GpStatus status;
595     GpPath *path;
596     GpPointF points[5];
597 
598     points[0].X = 0.0;
599     points[0].Y = 0.0;
600     points[1].X = 10.0;
601     points[1].Y = 10.0;
602     points[2].X = 10.0;
603     points[2].Y = 20.0;
604     points[3].X = 30.0;
605     points[3].Y = 10.0;
606     points[4].X = 20.0;
607     points[4].Y = 0.0;
608 
609     GdipCreatePath(FillModeAlternate, &path);
610 
611     /* NULL args */
612     status = GdipAddPathPolygon(NULL, points, 5);
613     expect(InvalidParameter, status);
614     status = GdipAddPathPolygon(path, NULL, 5);
615     expect(InvalidParameter, status);
616     /* Polygon should have 3 points at least */
617     status = GdipAddPathPolygon(path, points, 2);
618     expect(InvalidParameter, status);
619 
620     /* to test how it prolongs not empty path */
621     status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0);
622     expect(Ok, status);
623     status = GdipAddPathPolygon(path, points, 5);
624     expect(Ok, status);
625     /* check resulting path */
626     ok_path(path, poly_path, sizeof(poly_path)/sizeof(path_test_t), FALSE);
627 
628     GdipDeletePath(path);
629 }
630 
631 static path_test_t rect_path[] = {
632     {5.0, 5.0,       PathPointTypeStart, 0, 0}, /**/
633     {105.0, 5.0,     PathPointTypeLine,  0, 0}, /*1*/
634     {105.0, 55.0,    PathPointTypeLine,  0, 0}, /*2*/
635     {5.0, 55.0,      PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/
636 
637     {100.0, 50.0,    PathPointTypeStart, 0, 0}, /*4*/
638     {220.0, 50.0,    PathPointTypeLine,  0, 0}, /*5*/
639     {220.0, 80.0,    PathPointTypeLine,  0, 0}, /*6*/
640     {100.0, 80.0,    PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}  /*7*/
641     };
642 
643 static void test_rect(void)
644 {
645     GpStatus status;
646     GpPath *path;
647     GpRectF rects[2];
648 
649     GdipCreatePath(FillModeAlternate, &path);
650     status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
651     expect(Ok, status);
652     status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
653     expect(Ok, status);
654 
655     ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
656 
657     GdipDeletePath(path);
658 
659     GdipCreatePath(FillModeAlternate, &path);
660 
661     rects[0].X      = 5.0;
662     rects[0].Y      = 5.0;
663     rects[0].Width  = 100.0;
664     rects[0].Height = 50.0;
665     rects[1].X      = 100.0;
666     rects[1].Y      = 50.0;
667     rects[1].Width  = 120.0;
668     rects[1].Height = 30.0;
669 
670     status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
671     expect(Ok, status);
672 
673     ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
674 
675     GdipDeletePath(path);
676 }
677 
678 static void test_lastpoint(void)
679 {
680     GpStatus status;
681     GpPath *path;
682     GpPointF ptf;
683 
684     GdipCreatePath(FillModeAlternate, &path);
685     status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
686     expect(Ok, status);
687 
688     /* invalid args */
689     status = GdipGetPathLastPoint(NULL, &ptf);
690     expect(InvalidParameter, status);
691     status = GdipGetPathLastPoint(path, NULL);
692     expect(InvalidParameter, status);
693     status = GdipGetPathLastPoint(NULL, NULL);
694     expect(InvalidParameter, status);
695 
696     status = GdipGetPathLastPoint(path, &ptf);
697     expect(Ok, status);
698     expect(TRUE, (ptf.X == 5.0) && (ptf.Y == 55.0));
699 
700     GdipDeletePath(path);
701 }
702 
703 static path_test_t addcurve_path[] = {
704     {0.0, 0.0,   PathPointTypeStart,  0, 0}, /**/
705     {3.3, 3.3,   PathPointTypeBezier, 0, 0}, /*1*/
706     {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*2*/
707     {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
708     {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
709     {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*5*/
710     {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
711     {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
712     {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
713     {30.0, 10.0, PathPointTypeBezier, 0, 0}  /*9*/
714     };
715 static path_test_t addcurve_path2[] = {
716     {100.0,120.0,PathPointTypeStart,  0, 0}, /**/
717     {123.0,10.0, PathPointTypeLine,   0, 0}, /*1*/
718     {0.0, 0.0,   PathPointTypeLine,   0, 0}, /*2*/
719     {3.3, 3.3,   PathPointTypeBezier, 0, 0}, /*3*/
720     {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*4*/
721     {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
722     {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
723     {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*7*/
724     {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
725     {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
726     {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
727     {30.0, 10.0, PathPointTypeBezier, 0, 0}  /*11*/
728     };
729 static void test_addcurve(void)
730 {
731     GpStatus status;
732     GpPath *path;
733     GpPointF points[4];
734 
735     points[0].X = 0.0;
736     points[0].Y = 0.0;
737     points[1].X = 10.0;
738     points[1].Y = 10.0;
739     points[2].X = 10.0;
740     points[2].Y = 20.0;
741     points[3].X = 30.0;
742     points[3].Y = 10.0;
743 
744     GdipCreatePath(FillModeAlternate, &path);
745 
746     /* NULL args */
747     status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
748     expect(InvalidParameter, status);
749     status = GdipAddPathCurve2(path, NULL, 0, 0.0);
750     expect(InvalidParameter, status);
751     status = GdipAddPathCurve2(path, points, -1, 0.0);
752     expect(InvalidParameter, status);
753     status = GdipAddPathCurve2(path, points, 1, 1.0);
754     expect(InvalidParameter, status);
755 
756     /* add to empty path */
757     status = GdipAddPathCurve2(path, points, 4, 1.0);
758     expect(Ok, status);
759     ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
760     GdipDeletePath(path);
761 
762     /* add to notempty path and opened figure */
763     GdipCreatePath(FillModeAlternate, &path);
764     GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
765     status = GdipAddPathCurve2(path, points, 4, 1.0);
766     expect(Ok, status);
767     ok_path(path, addcurve_path2, sizeof(addcurve_path2)/sizeof(path_test_t), FALSE);
768     GdipDeletePath(path);
769 }
770 
771 static path_test_t addclosedcurve_path[] = {
772     {0.0, 0.0,   PathPointTypeStart,  0, 0}, /**/
773     {-6.7, 0.0,  PathPointTypeBezier, 0, 0}, /*1*/
774     {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*2*/
775     {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
776     {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
777     {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*5*/
778     {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
779     {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
780     {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
781     {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
782     {26.7, 3.3,  PathPointTypeBezier, 0, 0}, /*10*/
783     {6.7,  0.0,  PathPointTypeBezier, 0, 0}, /*11*/
784     {0.0,  0.0,  PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}  /*12*/
785     };
786