1 /*
2  * Unit test suite for gdiplus regions
3  *
4  * Copyright (C) 2008 Huw Davies
5  * Copyright (C) 2013 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "precomp.h"
23 
24 #define RGNDATA_RECT            0x10000000
25 #define RGNDATA_PATH            0x10000001
26 #define RGNDATA_EMPTY_RECT      0x10000002
27 #define RGNDATA_INFINITE_RECT   0x10000003
28 
29 #define RGNDATA_MAGIC           0xdbc01001
30 #define RGNDATA_MAGIC2          0xdbc01002
31 
32 #define expect(expected, got) ok((got) == (expected), "Expected %.8x, got %.8x\n", (expected), (got))
33 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) < (precision), "Expected %f, got %f\n", (expected), (got))
34 #define expectf(expected, got) expectf_((expected), (got), 0.001)
35 
36 #define expect_magic(value) ok(broken(*(value) == RGNDATA_MAGIC) || *(value) == RGNDATA_MAGIC2, "Expected a known magic value, got %8x\n", *(value))
37 #define expect_dword(value, expected) expect((expected), *(value))
38 #define expect_float(value, expected) expectf((expected), *(FLOAT *)(value))
39 
40 /* We get shorts back, not INTs like a GpPoint */
41 typedef struct RegionDataPoint
42 {
43     short X, Y;
44 } RegionDataPoint;
45 
46 static void verify_region(HRGN hrgn, const RECT *rc)
47 {
48     union
49     {
50         RGNDATA data;
51         char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
52     } rgn;
53     const RECT *rect;
54     DWORD ret;
55 
56     ret = GetRegionData(hrgn, 0, NULL);
57     if (IsRectEmpty(rc))
58         ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
59     else
60         ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
61 
62     if (!ret) return;
63 
64     ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data);
65     if (IsRectEmpty(rc))
66         ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
67     else
68         ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
69 
70     trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
71           rgn.data.rdh.dwSize, rgn.data.rdh.iType,
72           rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize,
73           wine_dbgstr_rect(&rgn.data.rdh.rcBound));
74     if (rgn.data.rdh.nCount != 0)
75     {
76         rect = (const RECT *)rgn.data.Buffer;
77         trace("rect %s\n", wine_dbgstr_rect(rect));
78         ok(EqualRect(rect, rc), "expected %s, got %s\n",
79            wine_dbgstr_rect(rc), wine_dbgstr_rect(rect));
80     }
81 
82     ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", rgn.data.rdh.dwSize);
83     ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType);
84     if (IsRectEmpty(rc))
85     {
86         ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount);
87         ok(rgn.data.rdh.nRgnSize == 0,  "expected 0, got %u\n", rgn.data.rdh.nRgnSize);
88     }
89     else
90     {
91         ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount);
92         ok(rgn.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize);
93     }
94     ok(EqualRect(&rgn.data.rdh.rcBound, rc), "expected %s, got %s\n",
95        wine_dbgstr_rect(rc), wine_dbgstr_rect(&rgn.data.rdh.rcBound));
96 }
97 
98 static void test_region_data(DWORD *data, UINT size, INT line)
99 {
100     GpStatus status;
101     GpRegion *region;
102     DWORD buf[256];
103     UINT needed, i;
104 
105     status = GdipCreateRegionRgnData((BYTE *)data, size, &region);
106     /* Windows always fails to create an empty path in a region */
107     if (data[4] == RGNDATA_PATH)
108     {
109         struct path_header
110         {
111             DWORD size;
112             DWORD magic;
113             DWORD count;
114             DWORD flags;
115         } *path_header = (struct path_header *)(data + 5);
116         if (!path_header->count)
117         {
118             ok_(__FILE__, line)(status == GenericError, "expected GenericError, got %d\n", status);
119             return;
120         }
121     }
122 
123     ok_(__FILE__, line)(status == Ok, "GdipCreateRegionRgnData error %d\n", status);
124     if (status != Ok) return;
125 
126     needed = 0;
127     status = GdipGetRegionDataSize(region, &needed);
128     ok_(__FILE__, line)(status == Ok, "status %d\n", status);
129     ok_(__FILE__, line)(needed == size, "data size mismatch: %u != %u\n", needed, size);
130 
131     memset(buf, 0xee, sizeof(buf));
132     needed = 0;
133     status = GdipGetRegionData(region, (BYTE *)buf, sizeof(buf), &needed);
134     ok_(__FILE__, line)(status == Ok, "status %08x\n", status);
135     ok_(__FILE__, line)(needed == size, "data size mismatch: %u != %u\n", needed, size);
136 
137     size /= sizeof(DWORD);
138     for (i = 0; i < size - 1; i++)
139     {
140         if (i == 1) continue; /* data[1] never matches */
141         ok_(__FILE__, line)(data[i] == buf[i], "off %u: %#x != %#x\n", i, data[i], buf[i]);
142     }
143     /* some Windows versions fail to properly clear the aligned DWORD */
144     ok_(__FILE__, line)(data[size - 1] == buf[size - 1] || broken(data[size - 1] != buf[size - 1]),
145         "off %u: %#x != %#x\n", size - 1, data[size - 1], buf[size - 1]);
146 
147     GdipDeleteRegion(region);
148 }
149 
150 static void test_getregiondata(void)
151 {
152     GpStatus status;
153     GpRegion *region, *region2;
154     RegionDataPoint *point;
155     UINT needed;
156     DWORD buf[256];
157     GpRect rect;
158     GpPath *path;
159     GpMatrix *matrix;
160 
161     status = GdipCreateRegion(&region);
162     ok(status == Ok, "status %08x\n", status);
163 
164     needed = 0;
165     status = GdipGetRegionDataSize(region, &needed);
166     ok(status == Ok, "status %08x\n", status);
167     expect(20, needed);
168 
169     needed = 0;
170     status = GdipGetRegionData(region, (BYTE*)buf, 0, &needed);
171     ok(status == InvalidParameter, "status %08x\n", status);
172 
173     memset(buf, 0xee, sizeof(buf));
174     needed = 0;
175     status = GdipGetRegionData(region, (BYTE*)buf, 4, &needed);
176     ok(status == InsufficientBuffer, "status %08x\n", status);
177     expect(4, needed);
178     expect_dword(buf, 0xeeeeeeee);
179 
180     memset(buf, 0xee, sizeof(buf));
181     needed = 0;
182     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
183     ok(status == Ok, "status %08x\n", status);
184     expect(20, needed);
185     expect_dword(buf, 12);
186     trace("buf[1] = %08x\n", buf[1]);
187     expect_magic(buf + 2);
188     expect_dword(buf + 3, 0);
189     expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
190     expect_dword(buf + 6, 0xeeeeeeee);
191     test_region_data(buf, needed, __LINE__);
192 
193     status = GdipSetEmpty(region);
194     ok(status == Ok, "status %08x\n", status);
195     status = GdipGetRegionDataSize(region, &needed);
196     ok(status == Ok, "status %08x\n", status);
197     expect(20, needed);
198     memset(buf, 0xee, sizeof(buf));
199     needed = 0;
200     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
201     ok(status == Ok, "status %08x\n", status);
202     expect(20, needed);
203     expect_dword(buf, 12);
204     trace("buf[1] = %08x\n", buf[1]);
205     expect_magic(buf + 2);
206     expect_dword(buf + 3, 0);
207     expect_dword(buf + 4, RGNDATA_EMPTY_RECT);
208     expect_dword(buf + 6, 0xeeeeeeee);
209     test_region_data(buf, needed, __LINE__);
210 
211     status = GdipSetInfinite(region);
212     ok(status == Ok, "status %08x\n", status);
213     status = GdipGetRegionDataSize(region, &needed);
214     ok(status == Ok, "status %08x\n", status);
215     expect(20, needed);
216     memset(buf, 0xee, sizeof(buf));
217     needed = 0;
218     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
219     ok(status == Ok, "status %08x\n", status);
220     expect(20, needed);
221     expect_dword(buf, 12);
222     trace("buf[1] = %08x\n", buf[1]);
223     expect_magic(buf + 2);
224     expect_dword(buf + 3, 0);
225     expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
226     expect_dword(buf + 6, 0xeeeeeeee);
227     test_region_data(buf, needed, __LINE__);
228 
229     status = GdipDeleteRegion(region);
230     ok(status == Ok, "status %08x\n", status);
231 
232     rect.X = 10;
233     rect.Y = 20;
234     rect.Width = 100;
235     rect.Height = 200;
236     status = GdipCreateRegionRectI(&rect, &region);
237     ok(status == Ok, "status %08x\n", status);
238     status = GdipGetRegionDataSize(region, &needed);
239     ok(status == Ok, "status %08x\n", status);
240     expect(36, needed);
241     memset(buf, 0xee, sizeof(buf));
242     needed = 0;
243     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
244     ok(status == Ok, "status %08x\n", status);
245     expect(36, needed);
246     expect_dword(buf, 28);
247     trace("buf[1] = %08x\n", buf[1]);
248     expect_magic(buf + 2);
249     expect_dword(buf + 3, 0);
250     expect_dword(buf + 4, RGNDATA_RECT);
251     expect_float(buf + 5, 10.0);
252     expect_float(buf + 6, 20.0);
253     expect_float(buf + 7, 100.0);
254     expect_float(buf + 8, 200.0);
255     expect_dword(buf + 10, 0xeeeeeeee);
256     test_region_data(buf, needed, __LINE__);
257 
258     rect.X = 50;
259     rect.Y = 30;
260     rect.Width = 10;
261     rect.Height = 20;
262     status = GdipCombineRegionRectI(region, &rect, CombineModeIntersect);
263     ok(status == Ok, "status %08x\n", status);
264     rect.X = 100;
265     rect.Y = 300;
266     rect.Width = 30;
267     rect.Height = 50;
268     status = GdipCombineRegionRectI(region, &rect, CombineModeXor);
269     ok(status == Ok, "status %08x\n", status);
270 
271     rect.X = 200;
272     rect.Y = 100;
273     rect.Width = 133;
274     rect.Height = 266;
275     status = GdipCreateRegionRectI(&rect, &region2);
276     ok(status == Ok, "status %08x\n", status);
277     rect.X = 20;
278     rect.Y = 10;
279     rect.Width = 40;
280     rect.Height = 66;
281     status = GdipCombineRegionRectI(region2, &rect, CombineModeUnion);
282     ok(status == Ok, "status %08x\n", status);
283 
284     status = GdipCombineRegionRegion(region, region2, CombineModeComplement);
285     ok(status == Ok, "status %08x\n", status);
286 
287     rect.X = 400;
288     rect.Y = 500;
289     rect.Width = 22;
290     rect.Height = 55;
291     status = GdipCombineRegionRectI(region, &rect, CombineModeExclude);
292     ok(status == Ok, "status %08x\n", status);
293 
294     status = GdipGetRegionDataSize(region, &needed);
295     ok(status == Ok, "status %08x\n", status);
296     expect(156, needed);
297     memset(buf, 0xee, sizeof(buf));
298     needed = 0;
299     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
300     ok(status == Ok, "status %08x\n", status);
301     expect(156, needed);
302     expect_dword(buf, 148);
303     trace("buf[1] = %08x\n", buf[1]);
304     expect_magic(buf + 2);
305     expect_dword(buf + 3, 10);
306     expect_dword(buf + 4, CombineModeExclude);
307     expect_dword(buf + 5, CombineModeComplement);
308     expect_dword(buf + 6, CombineModeXor);
309     expect_dword(buf + 7, CombineModeIntersect);
310     expect_dword(buf + 8, RGNDATA_RECT);
311     expect_float(buf + 9, 10.0);
312     expect_float(buf + 10, 20.0);
313     expect_float(buf + 11, 100.0);
314     expect_float(buf + 12, 200.0);
315     expect_dword(buf + 13, RGNDATA_RECT);
316     expect_float(buf + 14, 50.0);
317     expect_float(buf + 15, 30.0);
318     expect_float(buf + 16, 10.0);
319     expect_float(buf + 17, 20.0);
320     expect_dword(buf + 18, RGNDATA_RECT);
321     expect_float(buf + 19, 100.0);
322     expect_float(buf + 20, 300.0);
323     expect_float(buf + 21, 30.0);
324     expect_float(buf + 22, 50.0);
325     expect_dword(buf + 23, CombineModeUnion);
326     expect_dword(buf + 24, RGNDATA_RECT);
327     expect_float(buf + 25, 200.0);
328     expect_float(buf + 26, 100.0);
329     expect_float(buf + 27, 133.0);
330     expect_float(buf + 28, 266.0);
331     expect_dword(buf + 29, RGNDATA_RECT);
332     expect_float(buf + 30, 20.0);
333     expect_float(buf + 31, 10.0);
334     expect_float(buf + 32, 40.0);
335     expect_float(buf + 33, 66.0);
336     expect_dword(buf + 34, RGNDATA_RECT);
337     expect_float(buf + 35, 400.0);
338     expect_float(buf + 36, 500.0);
339     expect_float(buf + 37, 22.0);
340     expect_float(buf + 38, 55.0);
341     expect_dword(buf + 39, 0xeeeeeeee);
342     test_region_data(buf, needed, __LINE__);
343 
344     status = GdipDeleteRegion(region2);
345     ok(status == Ok, "status %08x\n", status);
346     status = GdipDeleteRegion(region);
347     ok(status == Ok, "status %08x\n", status);
348 
349     /* Try some paths */
350 
351     status = GdipCreatePath(FillModeAlternate, &path);
352     ok(status == Ok, "status %08x\n", status);
353     GdipAddPathRectangle(path, 12.5, 13.0, 14.0, 15.0);
354 
355     status = GdipCreateRegionPath(path, &region);
356     ok(status == Ok, "status %08x\n", status);
357     status = GdipGetRegionDataSize(region, &needed);
358     ok(status == Ok, "status %08x\n", status);
359     expect(72, needed);
360     memset(buf, 0xee, sizeof(buf));
361     needed = 0;
362     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
363     ok(status == Ok, "status %08x\n", status);
364     expect(72, needed);
365     expect_dword(buf, 64);
366     trace("buf[1] = %08x\n", buf[1]);
367     expect_magic(buf + 2);
368     expect_dword(buf + 3, 0);
369     expect_dword(buf + 4, RGNDATA_PATH);
370     expect_dword(buf + 5, 0x00000030);
371     expect_magic(buf + 6);
372     expect_dword(buf + 7, 0x00000004);
373     expect_dword(buf + 8, 0x00000000);
374     expect_float(buf + 9, 12.5);
375     expect_float(buf + 10, 13.0);
376     expect_float(buf + 11, 26.5);
377     expect_float(buf + 12, 13.0);
378     expect_float(buf + 13, 26.5);
379     expect_float(buf + 14, 28.0);
380     expect_float(buf + 15, 12.5);
381     expect_float(buf + 16, 28.0);
382     expect_dword(buf + 17, 0x81010100);
383     expect_dword(buf + 18, 0xeeeeeeee);
384     test_region_data(buf, needed, __LINE__);
385 
386     rect.X = 50;
387     rect.Y = 30;
388     rect.Width = 10;
389     rect.Height = 20;
390     status = GdipCombineRegionRectI(region, &rect, CombineModeIntersect);
391     ok(status == Ok, "status %08x\n", status);
392     status = GdipGetRegionDataSize(region, &needed);
393     ok(status == Ok, "status %08x\n", status);
394     expect(96, needed);
395     memset(buf, 0xee, sizeof(buf));
396     needed = 0;
397     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
398     ok(status == Ok, "status %08x\n", status);
399     expect(96, needed);
400     expect_dword(buf, 88);
401     trace("buf[1] = %08x\n", buf[1]);
402     expect_magic(buf + 2);
403     expect_dword(buf + 3, 2);
404     expect_dword(buf + 4, CombineModeIntersect);
405     expect_dword(buf + 5, RGNDATA_PATH);
406     expect_dword(buf + 6, 0x00000030);
407     expect_magic(buf + 7);
408     expect_dword(buf + 8, 0x00000004);
409     expect_dword(buf + 9, 0x00000000);
410     expect_float(buf + 10, 12.5);
411     expect_float(buf + 11, 13.0);
412     expect_float(buf + 12, 26.5);
413     expect_float(buf + 13, 13.0);
414     expect_float(buf + 14, 26.5);
415     expect_float(buf + 15, 28.0);
416     expect_float(buf + 16, 12.5);
417     expect_float(buf + 17, 28.0);
418     expect_dword(buf + 18, 0x81010100);
419     expect_dword(buf + 19, RGNDATA_RECT);
420     expect_float(buf + 20, 50.0);
421     expect_float(buf + 21, 30.0);
422     expect_float(buf + 22, 10.0);
423     expect_float(buf + 23, 20.0);
424     expect_dword(buf + 24, 0xeeeeeeee);
425     test_region_data(buf, needed, __LINE__);
426 
427     status = GdipDeleteRegion(region);
428     ok(status == Ok, "status %08x\n", status);
429     status = GdipDeletePath(path);
430     ok(status == Ok, "status %08x\n", status);
431 
432     /* Test an empty path */
433     status = GdipCreatePath(FillModeAlternate, &path);
434     expect(Ok, status);
435     status = GdipCreateRegionPath(path, &region);
436     expect(Ok, status);
437     status = GdipGetRegionDataSize(region, &needed);
438     expect(Ok, status);
439     expect(36, needed);
440     memset(buf, 0xee, sizeof(buf));
441     needed = 0;
442     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
443     expect(Ok, status);
444     expect(36, needed);
445     expect_dword(buf, 28);
446     trace("buf[1] = %08x\n", buf[1]);
447     expect_magic(buf + 2);
448     expect_dword(buf + 3, 0);
449     expect_dword(buf + 4, RGNDATA_PATH);
450     /* Second signature for pathdata */
451     expect_dword(buf + 5, 12);
452     expect_magic(buf + 6);
453     expect_dword(buf + 7, 0);
454     /* flags 0 means that a path is an array of FLOATs */
455     ok(*(buf + 8) == 0x4000 /* before win7 */ || *(buf + 8) == 0,
456        "expected 0x4000 or 0, got %08x\n", *(buf + 8));
457     expect_dword(buf + 10, 0xeeeeeeee);
458     test_region_data(buf, needed, __LINE__);
459 
460     /* Transform an empty region */
461     status = GdipCreateMatrix(&matrix);
462     expect(Ok, status);
463     status = GdipTransformRegion(region, matrix);
464     expect(Ok, status);
465     GdipDeleteMatrix(matrix);
466 
467     status = GdipDeleteRegion(region);
468     expect(Ok, status);
469 
470     /* Test a simple triangle of INTs */
471     status = GdipAddPathLine(path, 5, 6, 7, 8);
472     expect(Ok, status);
473     status = GdipAddPathLine(path, 8, 1, 5, 6);
474     expect(Ok, status);
475     status = GdipClosePathFigure(path);
476     expect(Ok, status);
477     status = GdipCreateRegionPath(path, &region);
478     expect(Ok, status);
479     status = GdipGetRegionDataSize(region, &needed);
480     expect(Ok, status);
481     expect(56, needed);
482     memset(buf, 0xee, sizeof(buf));
483     needed = 0;
484     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
485     expect(Ok, status);
486     expect(56, needed);
487     expect_dword(buf, 48);
488     trace("buf[1] = %08x\n", buf[1]);
489     expect_magic(buf + 2);
490     expect_dword(buf + 3 , 0);
491     expect_dword(buf + 4 , RGNDATA_PATH);
492     expect_dword(buf + 5, 32);
493     expect_magic(buf + 6);
494     expect_dword(buf + 7, 4);
495     /* flags 0x4000 means that a path is an array of shorts instead of FLOATs */
496     expect_dword(buf + 8, 0x4000);
497 
498     point = (RegionDataPoint*)(buf + 9);
499     expect(5, point[0].X);
500     expect(6, point[0].Y);
501     expect(7, point[1].X); /* buf + 10 */
502     expect(8, point[1].Y);
503     expect(8, point[2].X); /* buf + 11 */
504     expect(1, point[2].Y);
505     expect(5, point[3].X); /* buf + 12 */
506     expect(6, point[3].Y);
507     expect_dword(buf + 13, 0x81010100); /* 0x01010100 if we don't close the path */
508     expect_dword(buf + 14, 0xeeeeeeee);
509     test_region_data(buf, needed, __LINE__);
510 
511     status = GdipTranslateRegion(region, 0.6, 0.8);
512     expect(Ok, status);
513     memset(buf, 0xee, sizeof(buf));
514     needed = 0;
515     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
516     expect(Ok, status);
517     expect(72, needed);
518     expect_dword(buf, 64);
519     expect_magic(buf + 2);
520     expect_dword(buf + 3 , 0);
521     expect_dword(buf + 4 , RGNDATA_PATH);
522     expect_dword(buf + 5, 48);
523     expect_magic(buf + 6);
524     expect_dword(buf + 7, 4);
525     /* flags 0 means that a path is an array of FLOATs */
526     expect_dword(buf + 8, 0);
527     expect_float(buf + 9, 5.6);
528     expect_float(buf + 10, 6.8);
529     expect_float(buf + 11, 7.6);
530     expect_float(buf + 12, 8.8);
531     expect_float(buf + 13, 8.6);
532     expect_float(buf + 14, 1.8);
533     expect_float(buf + 15, 5.6);
534     expect_float(buf + 16, 6.8);
535     expect_dword(buf + 17, 0x81010100); /* 0x01010100 if we don't close the path */
536     expect_dword(buf + 18, 0xeeeeeeee);
537     test_region_data(buf, needed, __LINE__);
538 
539     status = GdipDeletePath(path);
540     expect(Ok, status);
541     status = GdipDeleteRegion(region);
542     expect(Ok, status);
543 
544     /* Test a floating-point triangle */
545     status = GdipCreatePath(FillModeAlternate, &path);
546     expect(Ok, status);
547     status = GdipAddPathLine(path, 5.6, 6.2, 7.2, 8.9);
548     expect(Ok, status);
549     status = GdipAddPathLine(path, 8.1, 1.6, 5.6, 6.2);
550     expect(Ok, status);
551     status = GdipCreateRegionPath(path, &region);
552     expect(Ok, status);
553     status = GdipGetRegionDataSize(region, &needed);
554     expect(Ok, status);
555     expect(72, needed);
556     memset(buf, 0xee, sizeof(buf));
557     needed = 0;
558     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
559     expect(Ok, status);
560     expect(72, needed);
561     expect_dword(buf, 64);
562     trace("buf[1] = %08x\n", buf[1]);
563     expect_magic(buf + 2);
564     expect_dword(buf + 3, 0);
565     expect_dword(buf + 4, RGNDATA_PATH);
566     expect_dword(buf + 5, 48);
567     expect_magic(buf + 6);
568     expect_dword(buf + 7, 4);
569     expect_dword(buf + 8, 0);
570     expect_float(buf + 9, 5.6);
571     expect_float(buf + 10, 6.2);
572     expect_float(buf + 11, 7.2);
573     expect_float(buf + 12, 8.9);
574     expect_float(buf + 13, 8.1);
575     expect_float(buf + 14, 1.6);
576     expect_float(buf + 15, 5.6);
577     expect_float(buf + 16, 6.2);
578     expect_dword(buf + 17, 0x01010100);
579     expect_dword(buf + 18, 0xeeeeeeee);
580     test_region_data(buf, needed, __LINE__);
581 
582     status = GdipDeletePath(path);
583     expect(Ok, status);
584     status = GdipDeleteRegion(region);
585     expect(Ok, status);
586 
587     /* Test for a path with > 4 points, and CombineRegionPath */
588     GdipCreatePath(FillModeAlternate, &path);
589     status = GdipAddPathLine(path, 50, 70.2, 60, 102.8);
590     expect(Ok, status);
591     status = GdipAddPathLine(path, 55.4, 122.4, 40.4, 60.2);
592     expect(Ok, status);
593     status = GdipAddPathLine(path, 45.6, 20.2, 50, 70.2);
594     expect(Ok, status);
595     rect.X = 20;
596     rect.Y = 25;
597     rect.Width = 60;
598     rect.Height = 120;
599     status = GdipCreateRegionRectI(&rect, &region);
600     expect(Ok, status);
601     status = GdipCombineRegionPath(region, path, CombineModeUnion);
602     expect(Ok, status);
603 
604     status = GdipGetRegionDataSize(region, &needed);
605     expect(Ok, status);
606     expect(116, needed);
607     memset(buf, 0xee, sizeof(buf));
608     needed = 0;
609     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
610     expect(Ok, status);
611     expect(116, needed);
612     expect_dword(buf, 108);
613     trace("buf[1] = %08x\n", buf[1]);
614     expect_magic(buf + 2);
615     expect_dword(buf + 3, 2);
616     expect_dword(buf + 4, CombineModeUnion);
617     expect_dword(buf + 5, RGNDATA_RECT);
618     expect_float(buf + 6, 20.0);
619     expect_float(buf + 7, 25.0);
620     expect_float(buf + 8, 60.0);
621     expect_float(buf + 9, 120.0);
622     expect_dword(buf + 10, RGNDATA_PATH);
623     expect_dword(buf + 11, 68);
624     expect_magic(buf + 12);
625     expect_dword(buf + 13, 6);
626     expect_float(buf + 14, 0.0);
627     expect_float(buf + 15, 50.0);
628     expect_float(buf + 16, 70.2);
629     expect_float(buf + 17, 60.0);
630     expect_float(buf + 18, 102.8);
631     expect_float(buf + 19, 55.4);
632     expect_float(buf + 20, 122.4);
633     expect_float(buf + 21, 40.4);
634     expect_float(buf + 22, 60.2);
635     expect_float(buf + 23, 45.6);
636     expect_float(buf + 24, 20.2);
637     expect_float(buf + 25, 50.0);
638     expect_float(buf + 26, 70.2);
639     expect_dword(buf + 27, 0x01010100);
640     ok(*(buf + 28) == 0x00000101 || *(buf + 28) == 0x43050101 /* Win 7 */,
641        "expected 00000101 or 43050101 got %08x\n", *(buf + 28));
642     expect_dword(buf + 29, 0xeeeeeeee);
643     test_region_data(buf, needed, __LINE__);
644 
645     status = GdipDeletePath(path);
646     expect(Ok, status);
647     status = GdipDeleteRegion(region);
648     expect(Ok, status);
649 
650     /* Test how shorts are stored in the region path data */
651     status = GdipCreatePath(FillModeAlternate, &path);
652     ok(status == Ok, "status %08x\n", status);
653     GdipAddPathRectangleI(path, -1969, -1974, 1995, 1997);
654 
655     status = GdipCreateRegionPath(path, &region);
656     ok(status == Ok, "status %08x\n", status);
657     needed = 0;
658     status = GdipGetRegionDataSize(region, &needed);
659     ok(status == Ok, "status %08x\n", status);
660     expect(56, needed);
661     memset(buf, 0xee, sizeof(buf));
662     needed = 0;
663     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
664     ok(status == Ok, "status %08x\n", status);
665     expect(56, needed);
666     expect_dword(buf, 48);
667     trace("buf[1] = %08x\n", buf[1]);
668     expect_magic(buf + 2);
669     expect_dword(buf + 3, 0);
670     expect_dword(buf + 4, RGNDATA_PATH);
671     expect_dword(buf + 5, 32);
672     expect_magic(buf + 6);
673     expect_dword(buf + 7, 4);
674     /* flags 0x4000 means that a path is an array of shorts instead of FLOATs */
675     expect_dword(buf + 8, 0x4000);
676     point = (RegionDataPoint*)(buf + 9);
677     expect(-1969, point[0].X);
678     expect(-1974, point[0].Y);
679     expect(26, point[1].X); /* buf + 10 */
680     expect(-1974, point[1].Y);
681     expect(26, point[2].X); /* buf + 11 */
682     expect(23, point[2].Y);
683     expect(-1969, point[3].X); /* buf + 12 */
684     expect(23, point[3].Y);
685     expect_dword(buf + 13, 0x81010100); /* 0x01010100 if we don't close the path */
686     expect_dword(buf + 14, 0xeeeeeeee);
687     test_region_data(buf, needed, __LINE__);
688 
689     status = GdipDeletePath(path);
690     expect(Ok, status);
691     status = GdipDeleteRegion(region);
692     expect(Ok, status);
693 
694     /* Test with integers that can't be stored as shorts */
695     status = GdipCreatePath(FillModeAlternate, &path);
696     ok(status == Ok, "status %08x\n", status);
697     GdipAddPathRectangleI(path, -196900, -197400, 199500, 199700);
698 
699     status = GdipCreateRegionPath(path, &region);
700     ok(status == Ok, "status %08x\n", status);
701     needed = 0;
702     status = GdipGetRegionDataSize(region, &needed);
703     ok(status == Ok, "status %08x\n", status);
704     expect(72, needed);
705     memset(buf, 0xee, sizeof(buf));
706     needed = 0;
707     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
708     ok(status == Ok, "status %08x\n", status);
709     expect(72, needed);
710     expect_dword(buf, 64);
711     trace("buf[1] = %08x\n", buf[1]);
712     expect_magic(buf + 2);
713     expect_dword(buf + 3, 0);
714     expect_dword(buf + 4, RGNDATA_PATH);
715     expect_dword(buf + 5, 48);
716     expect_magic(buf + 6);
717     expect_dword(buf + 7, 4);
718     /* flags 0 means that a path is an array of FLOATs */
719     expect_dword(buf + 8, 0);
720     expect_float(buf + 9, -196900.0);
721     expect_float(buf + 10, -197400.0);
722     expect_float(buf + 11, 2600.0);
723     expect_float(buf + 12, -197400.0);
724     expect_float(buf + 13, 2600.0);
725     expect_float(buf + 14, 2300.0);
726     expect_float(buf + 15, -196900.0);
727     expect_float(buf + 16, 2300.0);
728     expect_dword(buf + 17, 0x81010100); /* 0x01010100 if we don't close the path */
729     expect_dword(buf + 18, 0xeeeeeeee);
730     test_region_data(buf, needed, __LINE__);
731 
732     status = GdipDeletePath(path);
733     expect(Ok, status);
734     status = GdipDeleteRegion(region);
735     expect(Ok, status);
736 
737     /* Test beziers */
738     GdipCreatePath(FillModeAlternate, &path);
739       /* Exactly 90 degrees */
740     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
741     expect(Ok, status);
742     /* Over 90 degrees */
743     status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
744     expect(Ok, status);
745     status = GdipCreateRegionPath(path, &region);
746     ok(status == Ok, "status %08x\n", status);
747     needed = 0;
748     status = GdipGetRegionDataSize(region, &needed);
749     ok(status == Ok, "status %08x\n", status);
750     expect(136, needed);
751     memset(buf, 0xee, sizeof(buf));
752     needed = 0;
753     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
754     ok(status == Ok, "status %08x\n", status);
755     expect(136, needed);
756     expect_dword(buf, 128);
757     trace("buf[1] = %08x\n", buf[1]);
758     expect_magic(buf + 2);
759     expect_dword(buf + 3, 0);
760     expect_dword(buf + 4, RGNDATA_PATH);
761     expect_dword(buf + 5, 112);
762     expect_magic(buf + 6);
763     expect_dword(buf + 7, 11);
764     /* flags 0 means that a path is an array of FLOATs */
765     expect_dword(buf + 8, 0);
766     expect_float(buf + 9, 600.0);
767     expect_float(buf + 10, 450.0);
768     expect_float(buf + 11, 600.0);
769     expect_float(buf + 12, 643.299561);
770     expect_float(buf + 13, 488.071198);
771     expect_float(buf + 14, 800.0);
772     expect_float(buf + 15, 350.0);
773     expect_float(buf + 16, 800.0);
774     expect_float(buf + 17, 600.0);
775     expect_float(buf + 18, 450.0);
776     expect_float(buf + 19, 600.0);
777     expect_float(buf + 20, 643.299622);
778     expect_float(buf + 21, 488.071167);
779     expect_float(buf + 22, 800.0);
780     expect_float(buf + 23, 350.0);
781     expect_float(buf + 24, 800.0);
782     expect_float(buf + 25, 329.807129);
783     expect_float(buf + 26, 800.0);
784     expect_float(buf + 27, 309.688568);
785     expect_float(buf + 28, 796.574890);
786     expect_float(buf + 29, 290.084167);
787     expect_float(buf + 30, 789.799561);
788     expect_dword(buf + 31, 0x03030300);
789     expect_dword(buf + 32, 0x03030301);
790     ok(*(buf + 33) == 0x00030303 /* before win7 */ ||
791        *(buf + 33) == 0x43030303 /* 32-bit win7 */ || *(buf + 33) == 0x4c030303 /* 64-bit win7 */,
792        "expected 0x00030303 or 0x43030303 or 0x4c030303 got %08x\n", *(buf + 33));
793     expect_dword(buf + 34, 0xeeeeeeee);
794     test_region_data(buf, needed, __LINE__);
795 
796     status = GdipDeletePath(path);
797     expect(Ok, status);
798     status = GdipDeleteRegion(region);
799     expect(Ok, status);
800 }
801 
802 static void test_isinfinite(void)
803 {
804     GpStatus status;
805     GpRegion *region;
806     GpGraphics *graphics = NULL;
807     GpMatrix *m;
808     HDC hdc = GetDC(0);
809     BOOL res;
810 
811     status = GdipCreateFromHDC(hdc, &graphics);
812     expect(Ok, status);
813     GdipCreateRegion(&region);
814 
815     GdipCreateMatrix2(3.0, 0.0, 0.0, 1.0, 20.0, 30.0, &m);
816 
817     /* NULL arguments */
818     status = GdipIsInfiniteRegion(NULL, NULL, NULL);
819     expect(InvalidParameter, status);
820     status = GdipIsInfiniteRegion(region, NULL, NULL);
821     expect(InvalidParameter, status);
822     status = GdipIsInfiniteRegion(NULL, graphics, NULL);
823     expect(InvalidParameter, status);
824     status = GdipIsInfiniteRegion(NULL, NULL, &res);
825     expect(InvalidParameter, status);
826     status = GdipIsInfiniteRegion(region, NULL, &res);
827     expect(InvalidParameter, status);
828 
829     res = FALSE;
830     status = GdipIsInfiniteRegion(region, graphics, &res);
831     expect(Ok, status);
832     expect(TRUE, res);
833 
834     /* after world transform */
835     status = GdipSetWorldTransform(graphics, m);
836     expect(Ok, status);
837 
838     res = FALSE;
839     status = GdipIsInfiniteRegion(region, graphics, &res);
840     expect(Ok, status);
841     expect(TRUE, res);
842 
843     GdipDeleteMatrix(m);
844     GdipDeleteRegion(region);
845     GdipDeleteGraphics(graphics);
846     ReleaseDC(0, hdc);
847 }
848 
849 static void test_isempty(void)
850 {
851     GpStatus status;
852     GpRegion *region;
853     GpGraphics *graphics = NULL;
854     HDC hdc = GetDC(0);
855     BOOL res;
856 
857     status = GdipCreateFromHDC(hdc, &graphics);
858     expect(Ok, status);
859     GdipCreateRegion(&region);
860 
861     /* NULL arguments */
862     status = GdipIsEmptyRegion(NULL, NULL, NULL);
863     expect(InvalidParameter, status);
864     status = GdipIsEmptyRegion(region, NULL, NULL);
865     expect(InvalidParameter, status);
866     status = GdipIsEmptyRegion(NULL, graphics, NULL);
867     expect(InvalidParameter, status);
868     status = GdipIsEmptyRegion(NULL, NULL, &res);
869     expect(InvalidParameter, status);
870     status = GdipIsEmptyRegion(region, NULL, &res);
871     expect(InvalidParameter, status);
872 
873     /* default is infinite */
874     res = TRUE;
875     status = GdipIsEmptyRegion(region, graphics, &res);
876     expect(Ok, status);
877     expect(FALSE, res);
878 
879     status = GdipSetEmpty(region);
880     expect(Ok, status);
881 
882     res = FALSE;
883     status = GdipIsEmptyRegion(region, graphics, &res);
884     expect(Ok, status);
885     expect(TRUE, res);
886 
887     GdipDeleteRegion(region);
888     GdipDeleteGraphics(graphics);
889     ReleaseDC(0, hdc);
890 }
891 
892 static void test_combinereplace(void)
893 {
894     GpStatus status;
895     GpRegion *region, *region2;
896     GpPath *path;
897     GpRectF rectf;
898     UINT needed;
899     DWORD buf[50];
900 
901     rectf.X = rectf.Y = 0.0;
902     rectf.Width = rectf.Height = 100.0;
903 
904     status = GdipCreateRegionRect(&rectf, &region);
905     expect(Ok, status);
906 
907     /* replace with the same rectangle */
908     status = GdipCombineRegionRect(region, &rectf,CombineModeReplace);
909     expect(Ok, status);
910 
911     status = GdipGetRegionDataSize(region, &needed);
912     expect(Ok, status);
913     expect(36, needed);
914     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
915     expect(Ok, status);
916     expect(36, needed);
917     expect_dword(buf, 28);
918     trace("buf[1] = %08x\n", buf[1]);
919     expect_magic(buf + 2);
920     expect_dword(buf + 3, 0);
921     expect_dword(buf + 4, RGNDATA_RECT);
922 
923     /* replace with path */
924     status = GdipCreatePath(FillModeAlternate, &path);
925     expect(Ok, status);
926     status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
927     expect(Ok, status);
928     status = GdipCombineRegionPath(region, path, CombineModeReplace);
929     expect(Ok, status);
930 
931     status = GdipGetRegionDataSize(region, &needed);
932     expect(Ok, status);
933     expect(156, needed);
934     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
935     expect(Ok, status);
936     expect(156, needed);
937     expect_dword(buf, 148);
938     trace("buf[1] = %08x\n", buf[1]);
939     expect_magic(buf + 2);
940     expect_dword(buf + 3, 0);
941     expect_dword(buf + 4, RGNDATA_PATH);
942     GdipDeletePath(path);
943 
944     /* replace with infinite rect */
945     status = GdipCreateRegion(&region2);
946     expect(Ok, status);
947     status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
948     expect(Ok, status);
949 
950     status = GdipGetRegionDataSize(region, &needed);
951     expect(Ok, status);
952     expect(20, needed);
953     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
954     expect(Ok, status);
955     expect(20, needed);
956     expect_dword(buf, 12);
957     trace("buf[1] = %08x\n", buf[1]);
958     expect_magic(buf + 2);
959     expect_dword(buf + 3, 0);
960     expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
961     GdipDeleteRegion(region2);
962 
963     /* more complex case : replace with a combined region */
964     status = GdipCreateRegionRect(&rectf, &region2);
965     expect(Ok, status);
966     status = GdipCreatePath(FillModeAlternate, &path);
967     expect(Ok, status);
968     status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
969     expect(Ok, status);
970     status = GdipCombineRegionPath(region2, path, CombineModeUnion);
971     expect(Ok, status);
972     GdipDeletePath(path);
973     status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
974     expect(Ok, status);
975     GdipDeleteRegion(region2);
976 
977     status = GdipGetRegionDataSize(region, &needed);
978     expect(Ok, status);
979     expect(180, needed);
980     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
981     expect(Ok, status);
982     expect(180, needed);
983     expect_dword(buf, 172);
984     trace("buf[1] = %08x\n", buf[1]);
985     expect_magic(buf + 2);
986     expect_dword(buf + 3, 2);
987     expect_dword(buf + 4, CombineModeUnion);
988 
989     GdipDeleteRegion(region);
990 }
991 
992 static void test_fromhrgn(void)
993 {
994     GpStatus status;
995     GpRegion *region = (GpRegion*)0xabcdef01;
996     HRGN hrgn;
997     UINT needed;
998     DWORD buf[220];
999     RegionDataPoint *point;
1000     GpGraphics *graphics = NULL;
1001     HDC hdc;
1002     BOOL res;
1003 
1004     /* NULL */
1005     status = GdipCreateRegionHrgn(NULL, NULL);
1006     expect(InvalidParameter, status);
1007     status = GdipCreateRegionHrgn(NULL, &region);
1008     expect(InvalidParameter, status);
1009     status = GdipCreateRegionHrgn((HRGN)0xdeadbeef, &region);
1010     expect(InvalidParameter, status);
1011     ok(region == (GpRegion*)0xabcdef01, "Expected region not to be created\n");
1012 
1013     /* empty rectangle */
1014     hrgn = CreateRectRgn(0, 0, 0, 0);
1015     status = GdipCreateRegionHrgn(hrgn, &region);
1016     expect(Ok, status);
1017     if(status == Ok) {
1018 
1019     hdc = GetDC(0);
1020     status = GdipCreateFromHDC(hdc, &graphics);
1021     expect(Ok, status);
1022     res = FALSE;
1023     status = GdipIsEmptyRegion(region, graphics, &res);
1024     expect(Ok, status);
1025     expect(TRUE, res);
1026     GdipDeleteGraphics(graphics);
1027     ReleaseDC(0, hdc);
1028     GdipDeleteRegion(region);
1029 
1030     }
1031     DeleteObject(hrgn);
1032 
1033     /* rectangle */
1034     hrgn = CreateRectRgn(0, 0, 100, 10);
1035     status = GdipCreateRegionHrgn(hrgn, &region);
1036     expect(Ok, status);
1037 
1038     status = GdipGetRegionDataSize(region, &needed);
1039     expect(Ok, status);
1040     expect(56, needed);
1041 
1042     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
1043     expect(Ok, status);
1044 
1045     if(status == Ok){
1046 
1047     expect(56, needed);
1048     expect_dword(buf, 48);
1049     expect_magic(buf + 2);
1050     expect_dword(buf + 3, 0);
1051     expect_dword(buf + 4, RGNDATA_PATH);
1052     expect_dword(buf + 5, 0x00000020);
1053     expect_magic(buf + 6);
1054     expect_dword(buf + 7, 0x00000004);
1055     todo_wine expect_dword(buf + 8, 0x00006000); /* ?? */
1056 
1057     point = (RegionDataPoint*)buf + 9;
1058 
1059     expect(0,  point[0].X);
1060     expect(0,  point[0].Y);
1061 
1062     expect(100,point[1].X); /* buf + 10 */
1063     expect(0,  point[1].Y);
1064     expect(100,point[2].X); /* buf + 11 */
1065     expect(10, point[2].Y);
1066 
1067     expect(0,  point[3].X); /* buf + 12 */
1068 
1069     expect(10, point[3].Y);
1070     expect_dword(buf + 13, 0x81010100); /* closed */
1071 
1072     }
1073 
1074     GdipDeleteRegion(region);
1075     DeleteObject(hrgn);
1076 
1077     /* ellipse */
1078     hrgn = CreateEllipticRgn(0, 0, 100, 10);
1079     status = GdipCreateRegionHrgn(hrgn, &region);
1080     expect(Ok, status);
1081 
1082     status = GdipGetRegionDataSize(region, &needed);
1083     expect(Ok, status);
1084     ok(needed == 216 ||
1085        needed == 196, /* win98 */
1086        "Got %.8x\n", needed);
1087 
1088     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
1089     expect(Ok, status);
1090 
1091     if(status == Ok && needed == 216) /* Don't try to test win98 layout */
1092     {
1093     expect(Ok, status);
1094     expect(216, needed);
1095     expect_dword(buf, 208);
1096     expect_magic(buf + 2);
1097     expect_dword(buf + 3, 0);
1098     expect_dword(buf + 4, RGNDATA_PATH);
1099     expect_dword(buf + 5, 0x000000C0);
1100     expect_magic(buf + 6);
1101     expect_dword(buf + 7, 0x00000024);
1102     todo_wine expect_dword(buf + 8, 0x00006000); /* ?? */
1103     }
1104 
1105     GdipDeleteRegion(region);
1106     DeleteObject(hrgn);
1107 }
1108 
1109 static void test_gethrgn(void)
1110 {
1111     GpStatus status;
1112     GpRegion *region, *region2;
1113     GpPath *path;
1114     GpGraphics *graphics;
1115     HRGN hrgn;
1116     HDC hdc=GetDC(0);
1117     INT rgntype;
1118     RECT rgnbox;
1119     static const RECT empty_rect = {0,0,0,0};
1120     static const RECT test_rect = {10, 11, 20, 21};
1121     static const GpRectF test_rectF = {10.0, 11.0, 10.0, 10.0};
1122     static const RECT scaled_rect = {20, 22, 40, 42};
1123     static const RECT test_rect2 = {10, 21, 20, 31};
1124     static const GpRectF test_rect2F = {10.0, 21.0, 10.0, 10.0};
1125     static const RECT test_rect3 = {10, 11, 20, 31};
1126     static const GpRectF test_rect3F = {10.0, 11.0, 10.0, 20.0};
1127 
1128     status = GdipCreateFromHDC(hdc, &graphics);
1129     ok(status == Ok, "status %08x\n", status);
1130 
1131     status = GdipCreateRegion(&region);
1132     ok(status == Ok, "status %08x\n", status);
1133 
1134     status = GdipGetRegionHRgn(NULL, graphics, &hrgn);
1135     ok(status == InvalidParameter, "status %08x\n", status);
1136     status = GdipGetRegionHRgn(region, graphics, NULL);
1137     ok(status == InvalidParameter, "status %08x\n", status);
1138 
1139     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1140     ok(status == Ok, "status %08x\n", status);
1141     ok(hrgn == NULL, "hrgn=%p\n", hrgn);
1142 
1143     status = GdipGetRegionHRgn(region, graphics, &hrgn);
1144     ok(status == Ok, "status %08x\n", status);
1145     ok(hrgn == NULL, "hrgn=%p\n", hrgn);
1146 
1147     status = GdipSetEmpty(region);
1148     ok(status == Ok, "status %08x\n", status);
1149     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1150     ok(status == Ok, "status %08x\n", status);
1151     verify_region(hrgn, &empty_rect);
1152     DeleteObject(hrgn);
1153 
1154     status = GdipCreatePath(FillModeAlternate, &path);
1155     ok(status == Ok, "status %08x\n", status);
1156     status = GdipAddPathRectangle(path, 10.0, 11.0, 10.0, 10.0);
1157     ok(status == Ok, "status %08x\n", status);
1158 
1159     status = GdipCreateRegionPath(path, &region2);
1160     ok(status == Ok, "status %08x\n", status);
1161     status = GdipGetRegionHRgn(region2, NULL, &hrgn);
1162     ok(status == Ok, "status %08x\n", status);
1163     verify_region(hrgn, &test_rect);
1164     DeleteObject(hrgn);
1165 
1166     /* resulting HRGN is in device coordinates */
1167     status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
1168     ok(status == Ok, "status %08x\n", status);
1169     status = GdipGetRegionHRgn(region2, graphics, &hrgn);
1170     ok(status == Ok, "status %08x\n", status);
1171     verify_region(hrgn, &scaled_rect);
1172     DeleteObject(hrgn);
1173 
1174     status = GdipCombineRegionRect(region2, &test_rectF, CombineModeReplace);
1175     ok(status == Ok, "status %08x\n", status);
1176     status = GdipGetRegionHRgn(region2, NULL, &hrgn);
1177     ok(status == Ok, "status %08x\n", status);
1178     verify_region(hrgn, &test_rect);
1179     DeleteObject(hrgn);
1180 
1181     status = GdipGetRegionHRgn(region2, graphics, &hrgn);
1182     ok(status == Ok, "status %08x\n", status);
1183     verify_region(hrgn, &scaled_rect);
1184     DeleteObject(hrgn);
1185 
1186     status = GdipSetInfinite(region);
1187     ok(status == Ok, "status %08x\n", status);
1188     status = GdipCombineRegionRect(region, &test_rectF, CombineModeIntersect);
1189     ok(status == Ok, "status %08x\n", status);
1190     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1191     ok(status == Ok, "status %08x\n", status);
1192     verify_region(hrgn, &test_rect);
1193     DeleteObject(hrgn);
1194 
1195     status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
1196     ok(status == Ok, "status %08x\n", status);
1197     status = GdipCombineRegionRect(region, &test_rect2F, CombineModeUnion);
1198     ok(status == Ok, "status %08x\n", status);
1199     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1200     ok(status == Ok, "status %08x\n", status);
1201     verify_region(hrgn, &test_rect3);
1202     DeleteObject(hrgn);
1203 
1204     status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
1205     ok(status == Ok, "status %08x\n", status);
1206     status = GdipCombineRegionRect(region, &test_rect2F, CombineModeXor);
1207     ok(status == Ok, "status %08x\n", status);
1208     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1209     ok(status == Ok, "status %08x\n", status);
1210     verify_region(hrgn, &test_rect);
1211     DeleteObject(hrgn);
1212 
1213     status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
1214     ok(status == Ok, "status %08x\n", status);
1215     status = GdipCombineRegionRect(region, &test_rectF, CombineModeExclude);
1216     ok(status == Ok, "status %08x\n", status);
1217     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1218     ok(status == Ok, "status %08x\n", status);
1219     verify_region(hrgn, &test_rect2);
1220     DeleteObject(hrgn);
1221 
1222     status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
1223     ok(status == Ok, "status %08x\n", status);
1224     status = GdipCombineRegionRect(region, &test_rect3F, CombineModeComplement);
1225     ok(status == Ok, "status %08x\n", status);
1226     status = GdipGetRegionHRgn(region, NULL, &hrgn);
1227     ok(status == Ok, "status %08x\n", status);
1228     verify_region(hrgn, &test_rect2);
1229     DeleteObject(hrgn);
1230 
1231     status = GdipDeletePath(path);
1232     ok(status == Ok, "status %08x\n", status);
1233     status = GdipDeleteRegion(region);
1234     ok(status == Ok, "status %08x\n", status);
1235     status = GdipDeleteRegion(region2);
1236     ok(status == Ok, "status %08x\n", status);
1237     status = GdipDeleteGraphics(graphics);
1238     ok(status == Ok, "status %08x\n", status);
1239 
1240     /* test with gdi32 transform */
1241     SetViewportOrgEx(hdc, 10, 10, NULL);
1242 
1243     status = GdipCreateFromHDC(hdc, &graphics);
1244     expect(Ok, status);
1245 
1246     status = GdipCreateRegionRect(&test_rectF, &region);
1247     expect(Ok, status);
1248 
1249     status = GdipGetRegionHRgn(region, graphics, &hrgn);
1250     expect(Ok, status);
1251 
1252     rgntype = GetRgnBox(hrgn, &rgnbox);
1253     DeleteObject(hrgn);
1254 
1255     expect(SIMPLEREGION, rgntype);
1256     expect(20, rgnbox.left);
1257     expect(21, rgnbox.top);
1258     expect(30, rgnbox.right);
1259     expect(31, rgnbox.bottom);
1260 
1261     status = GdipDeleteRegion(region);
1262     expect(Ok, status);
1263     status = GdipDeleteGraphics(graphics);
1264     expect(Ok, status);
1265 
1266     SetViewportOrgEx(hdc, 0, 0, NULL);
1267 
1268     ReleaseDC(0, hdc);
1269 }
1270 
1271 static void test_isequal(void)
1272 {
1273     GpRegion *region1, *region2;
1274     GpGraphics *graphics;
1275     GpRectF rectf;
1276     GpStatus status;
1277     HDC hdc = GetDC(0);
1278     BOOL res;
1279 
1280     status = GdipCreateFromHDC(hdc, &graphics);
1281     ok(status == Ok, "status %08x\n", status);
1282 
1283     status = GdipCreateRegion(&region1);
1284     ok(status == Ok, "status %08x\n", status);
1285     status = GdipCreateRegion(&region2);
1286     ok(status == Ok, "status %08x\n", status);
1287 
1288     /* NULL */
1289     status = GdipIsEqualRegion(NULL, NULL, NULL, NULL);
1290     ok(status == InvalidParameter, "status %08x\n", status);
1291     status = GdipIsEqualRegion(region1, region2, NULL, NULL);
1292     ok(status == InvalidParameter, "status %08x\n", status);
1293     status = GdipIsEqualRegion(region1, region2, graphics, NULL);
1294     ok(status == InvalidParameter, "status %08x\n", status);
1295     status = GdipIsEqualRegion(region1, region2, NULL, &res);
1296     ok(status == InvalidParameter, "status %08x\n", status);
1297 
1298     /* infinite regions */
1299     res = FALSE;
1300     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1301     ok(status == Ok, "status %08x\n", status);
1302     ok(res, "Expected to be equal.\n");
1303     /* empty regions */
1304     status = GdipSetEmpty(region1);
1305     ok(status == Ok, "status %08x\n", status);
1306     status = GdipSetEmpty(region2);
1307     ok(status == Ok, "status %08x\n", status);
1308     res = FALSE;
1309     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1310     ok(status == Ok, "status %08x\n", status);
1311     ok(res, "Expected to be equal.\n");
1312     /* empty & infinite */
1313     status = GdipSetInfinite(region1);
1314     ok(status == Ok, "status %08x\n", status);
1315     res = TRUE;
1316     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1317     ok(status == Ok, "status %08x\n", status);
1318     ok(!res, "Expected to be unequal.\n");
1319     /* rect & (inf/empty) */
1320     rectf.X = rectf.Y = 0.0;
1321     rectf.Width = rectf.Height = 100.0;
1322     status = GdipCombineRegionRect(region1, &rectf, CombineModeReplace);
1323     ok(status == Ok, "status %08x\n", status);
1324     res = TRUE;
1325     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1326     ok(status == Ok, "status %08x\n", status);
1327     ok(!res, "Expected to be unequal.\n");
1328     status = GdipSetInfinite(region2);
1329     ok(status == Ok, "status %08x\n", status);
1330     res = TRUE;
1331     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1332     ok(status == Ok, "status %08x\n", status);
1333     ok(!res, "Expected to be unequal.\n");
1334     /* roughly equal rectangles */
1335     rectf.X = rectf.Y = 0.0;
1336     rectf.Width = rectf.Height = 100.001;
1337     status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace);
1338     ok(status == Ok, "status %08x\n", status);
1339     res = FALSE;
1340     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1341     ok(status == Ok, "status %08x\n", status);
1342     ok(res, "Expected to be equal.\n");
1343     /* equal rectangles */
1344     rectf.X = rectf.Y = 0.0;
1345     rectf.Width = rectf.Height = 100.0;
1346     status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace);
1347     ok(status == Ok, "status %08x\n", status);
1348     res = FALSE;
1349     status = GdipIsEqualRegion(region1, region2, graphics, &res);
1350     ok(status == Ok, "status %08x\n", status);
1351     ok(res, "Expected to be equal.\n");
1352 
1353     /* cleanup */
1354     status = GdipDeleteRegion(region1);
1355     ok(status == Ok, "status %08x\n", status);
1356     status = GdipDeleteRegion(region2);
1357     ok(status == Ok, "status %08x\n", status);
1358     status = GdipDeleteGraphics(graphics);
1359     ok(status == Ok, "status %08x\n", status);
1360     ReleaseDC(0, hdc);
1361 }
1362 
1363 static void test_translate(void)
1364 {
1365     GpRegion *region, *region2;
1366     GpGraphics *graphics;
1367     GpPath *path;
1368     GpRectF rectf;
1369     GpStatus status;
1370     HDC hdc = GetDC(0);
1371     BOOL res;
1372 
1373     status = GdipCreateFromHDC(hdc, &graphics);
1374     ok(status == Ok, "status %08x\n", status);
1375 
1376     status = GdipCreatePath(FillModeAlternate, &path);
1377     ok(status == Ok, "status %08x\n", status);
1378 
1379     status = GdipCreateRegion(&region);
1380     ok(status == Ok, "status %08x\n", status);
1381     status = GdipCreateRegion(&region2);
1382     ok(status == Ok, "status %08x\n", status);
1383 
1384     /* NULL */
1385     status = GdipTranslateRegion(NULL, 0.0, 0.0);
1386     ok(status == InvalidParameter, "status %08x\n", status);
1387 
1388     /* infinite */
1389     status = GdipTranslateRegion(region, 10.0, 10.0);
1390     ok(status == Ok, "status %08x\n", status);
1391     /* empty */
1392     status = GdipSetEmpty(region);
1393     ok(status == Ok, "status %08x\n", status);
1394     status = GdipTranslateRegion(region, 10.0, 10.0);
1395     ok(status == Ok, "status %08x\n", status);
1396     /* rect */
1397     rectf.X = 10.0; rectf.Y = 0.0;
1398     rectf.Width = rectf.Height = 100.0;
1399     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1400     ok(status == Ok, "status %08x\n", status);
1401     rectf.X = 15.0; rectf.Y = -2.0;
1402     rectf.Width = rectf.Height = 100.0;
1403     status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace);
1404     ok(status == Ok, "status %08x\n", status);
1405     status = GdipTranslateRegion(region, 5.0, -2.0);
1406     ok(status == Ok, "status %08x\n", status);
1407     res = FALSE;
1408     status = GdipIsEqualRegion(region, region2, graphics, &res);
1409     ok(status == Ok, "status %08x\n", status);
1410     ok(res, "Expected to be equal.\n");
1411     /* path */
1412     status = GdipAddPathEllipse(path, 0.0, 10.0, 100.0, 150.0);
1413     ok(status == Ok, "status %08x\n", status);
1414     status = GdipCombineRegionPath(region, path, CombineModeReplace);
1415     ok(status == Ok, "status %08x\n", status);
1416     status = GdipResetPath(path);
1417     ok(status == Ok, "status %08x\n", status);
1418     status = GdipAddPathEllipse(path, 10.0, 21.0, 100.0, 150.0);
1419     ok(status == Ok, "status %08x\n", status);
1420     status = GdipCombineRegionPath(region2, path, CombineModeReplace);
1421     ok(status == Ok, "status %08x\n", status);
1422     status = GdipTranslateRegion(region, 10.0, 11.0);
1423     ok(status == Ok, "status %08x\n", status);
1424     res = FALSE;
1425     status = GdipIsEqualRegion(region, region2, graphics, &res);
1426     ok(status == Ok, "status %08x\n", status);
1427     ok(res, "Expected to be equal.\n");
1428 
1429     status = GdipDeleteRegion(region);
1430     ok(status == Ok, "status %08x\n", status);
1431     status = GdipDeleteRegion(region2);
1432     ok(status == Ok, "status %08x\n", status);
1433     status = GdipDeleteGraphics(graphics);
1434     ok(status == Ok, "status %08x\n", status);
1435     status = GdipDeletePath(path);
1436     ok(status == Ok, "status %08x\n", status);
1437     ReleaseDC(0, hdc);
1438 }
1439 
1440 static void test_transform(void)
1441 {
1442     GpRegion *region, *region2;
1443     GpMatrix *matrix;
1444     GpGraphics *graphics;
1445     GpPath *path;
1446     GpRectF rectf;
1447     GpStatus status;
1448     HDC hdc = GetDC(0);
1449     BOOL res;
1450 
1451     status = GdipCreateFromHDC(hdc, &graphics);
1452     expect(Ok, status);
1453 
1454     status = GdipCreatePath(FillModeAlternate, &path);
1455     expect(Ok, status);
1456 
1457     status = GdipCreateRegion(&region);
1458     expect(Ok, status);
1459     status = GdipCreateRegion(&region2);
1460     expect(Ok, status);
1461 
1462     status = GdipCreateMatrix(&matrix);
1463     expect(Ok, status);
1464     status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend);
1465     expect(Ok, status);
1466 
1467     /* NULL */
1468     status = GdipTransformRegion(NULL, matrix);
1469     expect(InvalidParameter, status);
1470 
1471     status = GdipTransformRegion(region, NULL);
1472     expect(InvalidParameter, status);
1473 
1474     /* infinite */
1475     status = GdipTransformRegion(region, matrix);
1476     expect(Ok, status);
1477 
1478     res = FALSE;
1479     status = GdipIsEqualRegion(region, region2, graphics, &res);
1480     expect(Ok, status);
1481     ok(res, "Expected to be equal.\n");
1482 
1483     /* empty */
1484     status = GdipSetEmpty(region);
1485     expect(Ok, status);
1486     status = GdipTransformRegion(region, matrix);
1487     expect(Ok, status);
1488 
1489     status = GdipSetEmpty(region2);
1490     expect(Ok, status);
1491 
1492     res = FALSE;
1493     status = GdipIsEqualRegion(region, region2, graphics, &res);
1494     expect(Ok, status);
1495     ok(res, "Expected to be equal.\n");
1496 
1497     /* rect */
1498     rectf.X = 10.0;
1499     rectf.Y = 0.0;
1500     rectf.Width = rectf.Height = 100.0;
1501     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1502     expect(Ok, status);
1503     rectf.X = 20.0;
1504     rectf.Y = 0.0;
1505     rectf.Width = 200.0;
1506     rectf.Height = 300.0;
1507     status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace);
1508     expect(Ok, status);
1509     status = GdipTransformRegion(region, matrix);
1510     expect(Ok, status);
1511     res = FALSE;
1512     status = GdipIsEqualRegion(region, region2, graphics, &res);
1513     expect(Ok, status);
1514     ok(res, "Expected to be equal.\n");
1515 
1516     /* path */
1517     status = GdipAddPathEllipse(path, 0.0, 10.0, 100.0, 150.0);
1518     expect(Ok, status);
1519     status = GdipCombineRegionPath(region, path, CombineModeReplace);
1520     expect(Ok, status);
1521     status = GdipResetPath(path);
1522     expect(Ok, status);
1523     status = GdipAddPathEllipse(path, 0.0, 30.0, 200.0, 450.0);
1524     expect(Ok, status);
1525     status = GdipCombineRegionPath(region2, path, CombineModeReplace);
1526     expect(Ok, status);
1527     status = GdipTransformRegion(region, matrix);
1528     expect(Ok, status);
1529     res = FALSE;
1530     status = GdipIsEqualRegion(region, region2, graphics, &res);
1531     expect(Ok, status);
1532     ok(res, "Expected to be equal.\n");
1533 
1534     status = GdipDeleteRegion(region);
1535     expect(Ok, status);
1536     status = GdipDeleteRegion(region2);
1537     expect(Ok, status);
1538     status = GdipDeleteGraphics(graphics);
1539     expect(Ok, status);
1540     status = GdipDeletePath(path);
1541     expect(Ok, status);
1542     status = GdipDeleteMatrix(matrix);
1543     expect(Ok, status);
1544     ReleaseDC(0, hdc);
1545 }
1546 
1547 static void test_scans(void)
1548 {
1549     GpRegion *region;
1550     GpMatrix *matrix;
1551     GpRectF rectf;
1552     GpStatus status;
1553     ULONG count=80085;
1554     INT icount;
1555     GpRectF scans[2];
1556     GpRect scansi[2];
1557 
1558     status = GdipCreateRegion(&region);
1559     expect(Ok, status);
1560 
1561     status = GdipCreateMatrix(&matrix);
1562     expect(Ok, status);
1563 
1564     /* test NULL values */
1565     status = GdipGetRegionScansCount(NULL, &count, matrix);
1566     expect(InvalidParameter, status);
1567 
1568     status = GdipGetRegionScansCount(region, NULL, matrix);
1569     expect(InvalidParameter, status);
1570 
1571     status = GdipGetRegionScansCount(region, &count, NULL);
1572     expect(InvalidParameter, status);
1573 
1574     status = GdipGetRegionScans(NULL, scans, &icount, matrix);
1575     expect(InvalidParameter, status);
1576 
1577     status = GdipGetRegionScans(region, scans, NULL, matrix);
1578     expect(InvalidParameter, status);
1579 
1580     status = GdipGetRegionScans(region, scans, &icount, NULL);
1581     expect(InvalidParameter, status);
1582 
1583     /* infinite */
1584     status = GdipGetRegionScansCount(region, &count, matrix);
1585     expect(Ok, status);
1586     expect(1, count);
1587 
1588     status = GdipGetRegionScans(region, NULL, &icount, matrix);
1589     expect(Ok, status);
1590     expect(1, icount);
1591 
1592     status = GdipGetRegionScans(region, scans, &icount, matrix);
1593     expect(Ok, status);
1594     expect(1, icount);
1595 
1596     status = GdipGetRegionScansI(region, scansi, &icount, matrix);
1597     expect(Ok, status);
1598     expect(1, icount);
1599     expect(-0x400000, scansi[0].X);
1600     expect(-0x400000, scansi[0].Y);
1601     expect(0x800000, scansi[0].Width);
1602     expect(0x800000, scansi[0].Height);
1603 
1604     status = GdipGetRegionScans(region, scans, &icount, matrix);
1605     expect(Ok, status);
1606     expect(1, icount);
1607     expectf((double)-0x400000, scans[0].X);
1608     expectf((double)-0x400000, scans[0].Y);
1609     expectf((double)0x800000, scans[0].Width);
1610     expectf((double)0x800000, scans[0].Height);
1611 
1612     /* empty */
1613     status = GdipSetEmpty(region);
1614     expect(Ok, status);
1615 
1616     status = GdipGetRegionScansCount(region, &count, matrix);
1617     expect(Ok, status);
1618     expect(0, count);
1619 
1620     status = GdipGetRegionScans(region, scans, &icount, matrix);
1621     expect(Ok, status);
1622     expect(0, icount);
1623 
1624     /* single rectangle */
1625     rectf.X = rectf.Y = 0.0;
1626     rectf.Width = rectf.Height = 5.0;
1627     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1628     expect(Ok, status);
1629 
1630     status = GdipGetRegionScansCount(region, &count, matrix);
1631     expect(Ok, status);
1632     expect(1, count);
1633 
1634     status = GdipGetRegionScans(region, scans, &icount, matrix);
1635     expect(Ok, status);
1636     expect(1, icount);
1637     expectf(0.0, scans[0].X);
1638     expectf(0.0, scans[0].Y);
1639     expectf(5.0, scans[0].Width);
1640     expectf(5.0, scans[0].Height);
1641 
1642     /* two rectangles */
1643     rectf.X = rectf.Y = 5.0;
1644     rectf.Width = rectf.Height = 5.0;
1645     status = GdipCombineRegionRect(region, &rectf, CombineModeUnion);
1646     expect(Ok, status);
1647 
1648     status = GdipGetRegionScansCount(region, &count, matrix);
1649     expect(Ok, status);
1650     expect(2, count);
1651 
1652     /* Native ignores the initial value of count */
1653     scans[1].X = scans[1].Y = scans[1].Width = scans[1].Height = 8.0;
1654     icount = 1;
1655     status = GdipGetRegionScans(region, scans, &icount, matrix);
1656     expect(Ok, status);
1657     expect(2, icount);
1658     expectf(0.0, scans[0].X);
1659     expectf(0.0, scans[0].Y);
1660     expectf(5.0, scans[0].Width);
1661     expectf(5.0, scans[0].Height);
1662     expectf(5.0, scans[1].X);
1663     expectf(5.0, scans[1].Y);
1664     expectf(5.0, scans[1].Width);
1665     expectf(5.0, scans[1].Height);
1666 
1667     status = GdipGetRegionScansI(region, scansi, &icount, matrix);
1668     expect(Ok, status);
1669     expect(2, icount);
1670     expect(0, scansi[0].X);
1671     expect(0, scansi[0].Y);
1672     expect(5, scansi[0].Width);
1673     expect(5, scansi[0].Height);
1674     expect(5, scansi[1].X);
1675     expect(5, scansi[1].Y);
1676     expect(5, scansi[1].Width);
1677     expect(5, scansi[1].Height);
1678 
1679     status = GdipDeleteRegion(region);
1680     expect(Ok, status);
1681     status = GdipDeleteMatrix(matrix);
1682     expect(Ok, status);
1683 }
1684 
1685 static void test_getbounds(void)
1686 {
1687     GpRegion *region;
1688     GpGraphics *graphics;
1689     GpStatus status;
1690     GpRectF rectf;
1691     HDC hdc = GetDC(0);
1692 
1693     status = GdipCreateFromHDC(hdc, &graphics);
1694     ok(status == Ok, "status %08x\n", status);
1695     status = GdipCreateRegion(&region);
1696     ok(status == Ok, "status %08x\n", status);
1697 
1698     /* NULL */
1699     status = GdipGetRegionBounds(NULL, NULL, NULL);
1700     ok(status == InvalidParameter, "status %08x\n", status);
1701     status = GdipGetRegionBounds(region, NULL, NULL);
1702     ok(status == InvalidParameter, "status %08x\n", status);
1703     status = GdipGetRegionBounds(region, graphics, NULL);
1704     ok(status == InvalidParameter, "status %08x\n", status);
1705     /* infinite */
1706     rectf.X = rectf.Y = 0.0;
1707     rectf.Height = rectf.Width = 100.0;
1708     status = GdipGetRegionBounds(region, graphics, &rectf);
1709     ok(status == Ok, "status %08x\n", status);
1710     ok(rectf.X == -(REAL)(1 << 22), "Expected X = %.2f, got %.2f\n", -(REAL)(1 << 22), rectf.X);
1711     ok(rectf.Y == -(REAL)(1 << 22), "Expected Y = %.2f, got %.2f\n", -(REAL)(1 << 22), rectf.Y);
1712     ok(rectf.Width  == (REAL)(1 << 23), "Expected width = %.2f, got %.2f\n", (REAL)(1 << 23), rectf.Width);
1713     ok(rectf.Height == (REAL)(1 << 23), "Expected height = %.2f, got %.2f\n",(REAL)(1 << 23), rectf.Height);
1714     /* empty */
1715     rectf.X = rectf.Y = 0.0;
1716     rectf.Height = rectf.Width = 100.0;
1717     status = GdipSetEmpty(region);
1718     ok(status == Ok, "status %08x\n", status);
1719     status = GdipGetRegionBounds(region, graphics, &rectf);
1720     ok(status == Ok, "status %08x\n", status);
1721     ok(rectf.X == 0.0, "Expected X = 0.0, got %.2f\n", rectf.X);
1722     ok(rectf.Y == 0.0, "Expected Y = 0.0, got %.2f\n", rectf.Y);
1723     ok(rectf.Width  == 0.0, "Expected width = 0.0, got %.2f\n", rectf.Width);
1724     ok(rectf.Height == 0.0, "Expected height = 0.0, got %.2f\n", rectf.Height);
1725     /* rect */
1726     rectf.X = 10.0; rectf.Y = 0.0;
1727     rectf.Width = rectf.Height = 100.0;
1728     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1729     ok(status == Ok, "status %08x\n", status);
1730     rectf.X = rectf.Y = 0.0;
1731     rectf.Height = rectf.Width = 0.0;
1732     status = GdipGetRegionBounds(region, graphics, &rectf);
1733     ok(status == Ok, "status %08x\n", status);
1734     ok(rectf.X == 10.0, "Expected X = 0.0, got %.2f\n", rectf.X);
1735     ok(rectf.Y == 0.0, "Expected Y = 0.0, got %.2f\n", rectf.Y);
1736     ok(rectf.Width  == 100.0, "Expected width = 0.0, got %.2f\n", rectf.Width);
1737     ok(rectf.Height == 100.0, "Expected height = 0.0, got %.2f\n", rectf.Height);
1738 
1739     /* the world and page transforms are ignored */
1740     GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
1741     GdipSetPageUnit(graphics, UnitInch);
1742     GdipSetPageScale(graphics, 2.0);
1743     status = GdipGetRegionBounds(region, graphics, &rectf);
1744     ok(status == Ok, "status %08x\n", status);
1745     ok(rectf.X == 10.0, "Expected X = 0.0, got %.2f\n", rectf.X);
1746     ok(rectf.Y == 0.0, "Expected Y = 0.0, got %.2f\n", rectf.Y);
1747     ok(rectf.Width  == 100.0, "Expected width = 0.0, got %.2f\n", rectf.Width);
1748 
1749     rectf.X = 10.0; rectf.Y = 0.0;
1750     rectf.Width = rectf.Height = 100.0;
1751     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1752     ok(status == Ok, "status %08x\n", status);
1753     rectf.X = rectf.Y = 0.0;
1754     rectf.Height = rectf.Width = 0.0;
1755     status = GdipGetRegionBounds(region, graphics, &rectf);
1756     ok(status == Ok, "status %08x\n", status);
1757     ok(rectf.X == 10.0, "Expected X = 0.0, got %.2f\n", rectf.X);
1758     ok(rectf.Y == 0.0, "Expected Y = 0.0, got %.2f\n", rectf.Y);
1759     ok(rectf.Width  == 100.0, "Expected width = 0.0, got %.2f\n", rectf.Width);
1760     ok(rectf.Height == 100.0, "Expected height = 0.0, got %.2f\n", rectf.Height);
1761 
1762     status = GdipDeleteRegion(region);
1763     ok(status == Ok, "status %08x\n", status);
1764     status = GdipDeleteGraphics(graphics);
1765     ok(status == Ok, "status %08x\n", status);
1766     ReleaseDC(0, hdc);
1767 }
1768 
1769 static void test_isvisiblepoint(void)
1770 {
1771     HDC hdc = GetDC(0);
1772     GpGraphics* graphics;
1773     GpRegion* region;
1774     GpPath* path;
1775     GpRectF rectf;
1776     GpStatus status;
1777     BOOL res;
1778     REAL x, y;
1779 
1780     status = GdipCreateFromHDC(hdc, &graphics);
1781     expect(Ok, status);
1782 
1783     status = GdipCreateRegion(&region);
1784     expect(Ok, status);
1785 
1786     /* null parameters */
1787     status = GdipIsVisibleRegionPoint(NULL, 0, 0, graphics, &res);
1788     expect(InvalidParameter, status);
1789     status = GdipIsVisibleRegionPointI(NULL, 0, 0, graphics, &res);
1790     expect(InvalidParameter, status);
1791 
1792     status = GdipIsVisibleRegionPoint(region, 0, 0, NULL, &res);
1793     expect(Ok, status);
1794     status = GdipIsVisibleRegionPointI(region, 0, 0, NULL, &res);
1795     expect(Ok, status);
1796 
1797     status = GdipIsVisibleRegionPoint(region, 0, 0, graphics, NULL);
1798     expect(InvalidParameter, status);
1799     status = GdipIsVisibleRegionPointI(region, 0, 0, graphics, NULL);
1800     expect(InvalidParameter, status);
1801 
1802     /* infinite region */
1803     status = GdipIsInfiniteRegion(region, graphics, &res);
1804     expect(Ok, status);
1805     ok(res == TRUE, "Region should be infinite\n");
1806 
1807     x = 10;
1808     y = 10;
1809     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1810     expect(Ok, status);
1811     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1812     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1813     expect(Ok, status);
1814     ok(res == TRUE, "Expected (%d, %d) to be visible\n", (INT)x, (INT)y);
1815 
1816     x = -10;
1817     y = -10;
1818     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1819     expect(Ok, status);
1820     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1821     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1822     expect(Ok, status);
1823     ok(res == TRUE, "Expected (%d, %d) to be visible\n", (INT)x, (INT)y);
1824 
1825     /* rectangular region */
1826     rectf.X = 10;
1827     rectf.Y = 20;
1828     rectf.Width = 30;
1829     rectf.Height = 40;
1830 
1831     status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
1832     expect(Ok, status);
1833 
1834     x = 0;
1835     y = 0;
1836     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1837     expect(Ok, status);
1838     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1839     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1840     expect(Ok, status);
1841     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1842 
1843     x = 9;
1844     y = 19;
1845     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1846     expect(Ok, status);
1847     ok(res == FALSE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1848 
1849     x = 9.25;
1850     y = 19.25;
1851     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1852     expect(Ok, status);
1853     ok(res == FALSE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1854 
1855     x = 9.5;
1856     y = 19.5;
1857     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1858     expect(Ok, status);
1859     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1860 
1861     x = 9.75;
1862     y = 19.75;
1863     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1864     expect(Ok, status);
1865     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1866 
1867     x = 10;
1868     y = 20;
1869     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1870     expect(Ok, status);
1871     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1872 
1873     x = 25;
1874     y = 40;
1875     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1876     expect(Ok, status);
1877     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1878     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1879     expect(Ok, status);
1880     ok(res == TRUE, "Expected (%d, %d) to be visible\n", (INT)x, (INT)y);
1881 
1882     x = 40;
1883     y = 60;
1884     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1885     expect(Ok, status);
1886     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1887     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1888     expect(Ok, status);
1889     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1890 
1891     /* translate into the center of the rectangle */
1892     status = GdipTranslateWorldTransform(graphics, 25, 40, MatrixOrderAppend);
1893     expect(Ok, status);
1894 
1895     /* native ignores the world transform, so treat these as if
1896      * no transform exists */
1897     x = -20;
1898     y = -30;
1899     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1900     expect(Ok, status);
1901     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1902     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1903     expect(Ok, status);
1904     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1905 
1906     x = 0;
1907     y = 0;
1908     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1909     expect(Ok, status);
1910     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1911     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1912     expect(Ok, status);
1913     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1914 
1915     x = 25;
1916     y = 40;
1917     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1918     expect(Ok, status);
1919     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1920     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1921     expect(Ok, status);
1922     ok(res == TRUE, "Expected (%d, %d) to be visible\n", (INT)x, (INT)y);
1923 
1924     /* translate back to origin */
1925     status = GdipTranslateWorldTransform(graphics, -25, -40, MatrixOrderAppend);
1926     expect(Ok, status);
1927 
1928     /* region from path */
1929     status = GdipCreatePath(FillModeAlternate, &path);
1930     expect(Ok, status);
1931 
1932     status = GdipAddPathEllipse(path, 10, 20, 30, 40);
1933     expect(Ok, status);
1934 
1935     status = GdipCombineRegionPath(region, path, CombineModeReplace);
1936     expect(Ok, status);
1937 
1938     x = 11;
1939     y = 21;
1940     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1941     expect(Ok, status);
1942     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1943     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1944     expect(Ok, status);
1945     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1946 
1947     x = 25;
1948     y = 40;
1949     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1950     expect(Ok, status);
1951     ok(res == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
1952     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1953     expect(Ok, status);
1954     ok(res == TRUE, "Expected (%d, %d) to be visible\n", (INT)x, (INT)y);
1955 
1956     x = 40;
1957     y = 60;
1958     status = GdipIsVisibleRegionPoint(region, x, y, graphics, &res);
1959     expect(Ok, status);
1960     ok(res == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
1961     status = GdipIsVisibleRegionPointI(region, (INT)x, (INT)y, graphics, &res);
1962     expect(Ok, status);
1963     ok(res == FALSE, "Expected (%d, %d) not to be visible\n", (INT)x, (INT)y);
1964 
1965     GdipDeletePath(path);
1966 
1967     GdipDeleteRegion(region);
1968     GdipDeleteGraphics(graphics);
1969     ReleaseDC(0, hdc);
1970 }
1971 
1972 static void test_isvisiblerect(void)
1973 {
1974     HDC hdc = GetDC(0);
1975     GpGraphics* graphics;
1976     GpRegion* region;
1977     GpPath* path;
1978     GpRectF rectf;
1979     GpStatus status;
1980     BOOL res;
1981     REAL x, y, w, h;
1982 
1983     status = GdipCreateFromHDC(hdc, &graphics);
1984     expect(Ok, status);
1985 
1986     status = GdipCreateRegion(&region);
1987     expect(Ok, status);
1988 
1989     /* null parameters */
1990     status = GdipIsVisibleRegionRect(NULL, 0, 0, 0, 0, graphics, &res);
1991     expect(InvalidParameter, status);
1992     status = GdipIsVisibleRegionRectI(NULL, 0, 0, 0, 0, graphics, &res);
1993     expect(InvalidParameter, status);
1994 
1995     status = GdipIsVisibleRegionRect(region, 0, 0, 0, 0, NULL, &res);
1996     expect(Ok, status);
1997     status = GdipIsVisibleRegionRectI(region, 0, 0, 0, 0, NULL, &res);
1998     expect(Ok, status);
1999 
2000     status = GdipIsVisibleRegionRect(region, 0, 0, 0, 0, graphics, NULL);
2001     expect(InvalidParameter, status);
2002     status = GdipIsVisibleRegionRectI(region, 0, 0, 0, 0, graphics, NULL);
2003     expect(InvalidParameter, status);
2004 
2005     /* infinite region */
2006     status = GdipIsInfiniteRegion(region, graphics, &res);
2007     expect(Ok, status);
2008     ok(res == TRUE, "Region should be infinite\n");
2009 
2010     x = 10; w = 10;
2011     y = 10; h = 10;
2012     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2013     expect(Ok, status);
2014     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2015 
2016     x = -10; w = 5;
2017     y = -10; h = 5;
2018     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2019     expect(Ok, status);
2020     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2021 
2022     /* rectangular region */
2023     rectf.X = 10;
2024     rectf.Y = 20;
2025     rectf.Width = 30;
2026     rectf.Height = 40;
2027 
2028     status = GdipCombineRegionRect(region, &rectf, CombineModeIntersect);
2029     expect(Ok, status);
2030 
2031     /* entirely within the region */
2032     x = 11; w = 10;
2033     y = 12; h = 10;
2034     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2035     expect(Ok, status);
2036     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2037     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2038     expect(Ok, status);
2039     ok(res == TRUE, "Expected (%d, %d, %d, %d) to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2040 
2041     /* entirely outside of the region */
2042     x = 0; w = 5;
2043     y = 0; h = 5;
2044     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2045     expect(Ok, status);
2046     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2047     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2048     expect(Ok, status);
2049     ok(res == FALSE, "Expected (%d, %d, %d, %d) not to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2050 
2051     /* corner cases */
2052     x = 0; w = 10;
2053     y = 0; h = 20;
2054     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2055     expect(Ok, status);
2056     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2057 
2058     x = 0; w = 10.25;
2059     y = 0; h = 20.25;
2060     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2061     expect(Ok, status);
2062     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2063 
2064     x = 39; w = 10;
2065     y = 59; h = 10;
2066     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2067     expect(Ok, status);
2068     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2069 
2070     x = 39.25; w = 10;
2071     y = 59.25; h = 10;
2072     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2073     expect(Ok, status);
2074     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2075 
2076     /* corners outside, but some intersection */
2077     x = 0; w = 100;
2078     y = 0; h = 100;
2079     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2080     expect(Ok, status);
2081     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2082 
2083     x = 0; w = 100;
2084     y = 0; h = 40;
2085     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2086     expect(Ok, status);
2087     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2088 
2089     x = 0; w = 25;
2090     y = 0; h = 100;
2091     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2092     expect(Ok, status);
2093     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2094 
2095     /* translate into the center of the rectangle */
2096     status = GdipTranslateWorldTransform(graphics, 25, 40, MatrixOrderAppend);
2097     expect(Ok, status);
2098 
2099     /* native ignores the world transform, so treat these as if
2100      * no transform exists */
2101     x = 0; w = 5;
2102     y = 0; h = 5;
2103     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2104     expect(Ok, status);
2105     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2106     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2107     expect(Ok, status);
2108     ok(res == FALSE, "Expected (%d, %d, %d, %d) not to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2109 
2110     x = 11; w = 10;
2111     y = 12; h = 10;
2112     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2113     expect(Ok, status);
2114     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2115     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2116     expect(Ok, status);
2117     ok(res == TRUE, "Expected (%d, %d, %d, %d) to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2118 
2119     /* translate back to origin */
2120     status = GdipTranslateWorldTransform(graphics, -25, -40, MatrixOrderAppend);
2121     expect(Ok, status);
2122 
2123     /* region from path */
2124     status = GdipCreatePath(FillModeAlternate, &path);
2125     expect(Ok, status);
2126 
2127     status = GdipAddPathEllipse(path, 10, 20, 30, 40);
2128     expect(Ok, status);
2129 
2130     status = GdipCombineRegionPath(region, path, CombineModeReplace);
2131     expect(Ok, status);
2132 
2133     x = 0; w = 12;
2134     y = 0; h = 22;
2135     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2136     expect(Ok, status);
2137     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2138     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2139     expect(Ok, status);
2140     ok(res == FALSE, "Expected (%d, %d, %d, %d) not to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2141 
2142     x = 0; w = 25;
2143     y = 0; h = 40;
2144     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2145     expect(Ok, status);
2146     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2147     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2148     expect(Ok, status);
2149     ok(res == TRUE, "Expected (%d, %d, %d, %d) to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2150 
2151     x = 38; w = 10;
2152     y = 55; h = 10;
2153     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2154     expect(Ok, status);
2155     ok(res == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, w, h);
2156     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2157     expect(Ok, status);
2158     ok(res == FALSE, "Expected (%d, %d, %d, %d) not to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2159 
2160     x = 0; w = 100;
2161     y = 0; h = 100;
2162     status = GdipIsVisibleRegionRect(region, x, y, w, h, graphics, &res);
2163     expect(Ok, status);
2164     ok(res == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, w, h);
2165     status = GdipIsVisibleRegionRectI(region, (INT)x, (INT)y, (INT)w, (INT)h, graphics, &res);
2166     expect(Ok, status);
2167     ok(res == TRUE, "Expected (%d, %d, %d, %d) to be visible\n", (INT)x, (INT)y, (INT)w, (INT)h);
2168 
2169     GdipDeletePath(path);
2170 
2171     GdipDeleteRegion(region);
2172     GdipDeleteGraphics(graphics);
2173     ReleaseDC(0, hdc);
2174 }
2175 
2176 static void test_excludeinfinite(void)
2177 {
2178     GpStatus status;
2179     GpRegion *region;
2180     UINT count=0xdeadbeef;
2181     GpRectF scans[4];
2182     GpMatrix *identity;
2183     static const RectF rect_exclude = {0.0, 0.0, 1.0, 1.0};
2184 
2185     status = GdipCreateMatrix(&identity);
2186     expect(Ok, status);
2187 
2188     status = GdipCreateRegion(&region);
2189     expect(Ok, status);
2190 
2191     status = GdipCombineRegionRect(region, &rect_exclude, CombineModeExclude);
2192     expect(Ok, status);
2193 
2194     status = GdipGetRegionScansCount(region, &count, identity);
2195     expect(Ok, status);
2196     expect(4, count);
2197 
2198     count = 4;
2199     status = GdipGetRegionScans(region, scans, (INT*)&count, identity);
2200     expect(Ok, status);
2201 
2202     expectf(-4194304.0, scans[0].X);
2203     expectf(-4194304.0, scans[0].Y);
2204     expectf(8388608.0, scans[0].Width);
2205     expectf(4194304.0, scans[0].Height);
2206 
2207     expectf(-4194304.0, scans[1].X);
2208     expectf(0.0, scans[1].Y);
2209     expectf(4194304.0, scans[1].Width);
2210     expectf(1.0, scans[1].Height);
2211 
2212     expectf(1.0, scans[2].X);
2213     expectf(0.0, scans[2].Y);
2214     expectf(4194303.0, scans[2].Width);
2215     expectf(1.0, scans[2].Height);
2216 
2217     expectf(-4194304.0, scans[3].X);
2218     expectf(1.0, scans[3].Y);
2219     expectf(8388608.0, scans[3].Width);
2220     expectf(4194303.0, scans[3].Height);
2221 
2222     GdipDeleteRegion(region);
2223     GdipDeleteMatrix(identity);
2224 }
2225 
2226 static void test_GdipCreateRegionRgnData(void)
2227 {
2228     GpGraphics *graphics = NULL;
2229     GpRegion *region, *region2;
2230     HDC hdc = GetDC(0);
2231     GpStatus status;
2232     BYTE buf[512];
2233     UINT needed;
2234     BOOL ret;
2235 
2236     status = GdipCreateRegionRgnData(NULL, 0, NULL);
2237     ok(status == InvalidParameter, "status %d\n", status);
2238 
2239     status = GdipCreateFromHDC(hdc, &graphics);
2240     ok(status == Ok, "status %d\n", status);
2241 
2242     status = GdipCreateRegion(&region);
2243     ok(status == Ok, "status %d\n", status);
2244 
2245     /* infinite region */
2246     memset(buf, 0xee, sizeof(buf));
2247     needed = 0;
2248     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
2249     ok(status == Ok, "status %d\n", status);
2250     expect(20, needed);
2251 
2252     status = GdipCreateRegionRgnData(buf, needed, NULL);
2253     ok(status == InvalidParameter, "status %d\n", status);
2254 
2255     status = GdipCreateRegionRgnData(buf, needed, &region2);
2256     ok(status == Ok, "status %d\n", status);
2257 
2258     ret = FALSE;
2259     status = GdipIsInfiniteRegion(region2, graphics, &ret);
2260     ok(status == Ok, "status %d\n", status);
2261     ok(ret, "got %d\n", ret);
2262     GdipDeleteRegion(region2);
2263 
2264     /* empty region */
2265     status = GdipSetEmpty(region);
2266     ok(status == Ok, "status %d\n", status);
2267 
2268     memset(buf, 0xee, sizeof(buf));
2269     needed = 0;
2270     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
2271     ok(status == Ok, "status %d\n", status);
2272     expect(20, needed);
2273 
2274     status = GdipCreateRegionRgnData(buf, needed, &region2);
2275     ok(status == Ok, "status %d\n", status);
2276 
2277     ret = FALSE;
2278     status = GdipIsEmptyRegion(region2, graphics, &ret);
2279     ok(status == Ok, "status %d\n", status);
2280     ok(ret, "got %d\n", ret);
2281     GdipDeleteRegion(region2);
2282 
2283     GdipDeleteGraphics(graphics);
2284     GdipDeleteRegion(region);
2285     ReleaseDC(0, hdc);
2286 }
2287 
2288 START_TEST(region)
2289 {
2290     struct GdiplusStartupInput gdiplusStartupInput;
2291     ULONG_PTR gdiplusToken;
2292     HMODULE hmsvcrt;
2293     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
2294 
2295     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
2296     hmsvcrt = LoadLibraryA("msvcrt");
2297     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
2298     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
2299 
2300     gdiplusStartupInput.GdiplusVersion              = 1;
2301     gdiplusStartupInput.DebugEventCallback          = NULL;
2302     gdiplusStartupInput.SuppressBackgroundThread    = 0;
2303     gdiplusStartupInput.SuppressExternalCodecs      = 0;
2304 
2305     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
2306 
2307     test_getregiondata();
2308     test_isinfinite();
2309     test_isempty();
2310     test_combinereplace();
2311     test_fromhrgn();
2312     test_gethrgn();
2313     test_isequal();
2314     test_translate();
2315     test_transform();
2316     test_scans();
2317     test_getbounds();
2318     test_isvisiblepoint();
2319     test_isvisiblerect();
2320     test_excludeinfinite();
2321     test_GdipCreateRegionRgnData();
2322 
2323     GdiplusShutdown(gdiplusToken);
2324 }
2325