1 /*
2  * Unit test suite for graphics objects
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
5  * Copyright (C) 2012 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 expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (INT)(expected), (INT)(got))
25 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
26 #define expectf(expected, got) expectf_((expected), (got), 0.001)
27 
28 static GpStatus (WINAPI *pGdipGraphicsSetAbort)(GpGraphics*,GdiplusAbort*);
29 
30 static const REAL mm_per_inch = 25.4;
31 static const REAL point_per_inch = 72.0;
32 static HWND hwnd;
33 
34 static void set_rect_empty(RectF *rc)
35 {
36     rc->X = 0.0;
37     rc->Y = 0.0;
38     rc->Width = 0.0;
39     rc->Height = 0.0;
40 }
41 
42 /* converts a given unit to its value in pixels */
43 static REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
44 {
45     switch (unit)
46     {
47     case UnitPixel:
48     case UnitDisplay:
49         return units;
50     case UnitPoint:
51         return units * dpi / point_per_inch;
52     case UnitInch:
53         return units * dpi;
54     case UnitDocument:
55         return units * dpi / 300.0; /* Per MSDN */
56     case UnitMillimeter:
57         return units * dpi / mm_per_inch;
58     default:
59         ok(0, "Unsupported unit: %d\n", unit);
60         return 0;
61     }
62 }
63 
64 /* converts value in pixels to a given unit */
65 static REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
66 {
67     switch (unit)
68     {
69     case UnitPixel:
70     case UnitDisplay:
71         return pixels;
72     case UnitPoint:
73         return pixels * point_per_inch / dpi;
74     case UnitInch:
75         return pixels / dpi;
76     case UnitDocument:
77         return pixels * 300.0 / dpi;
78     case UnitMillimeter:
79         return pixels * mm_per_inch / dpi;
80     default:
81         ok(0, "Unsupported unit: %d\n", unit);
82         return 0;
83     }
84 }
85 
86 static REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
87 {
88     REAL pixels = units_to_pixels(1.0, from, dpi);
89     return pixels_to_units(pixels, to, dpi);
90 }
91 
92 static GpGraphics *create_graphics(REAL res_x, REAL res_y, GpUnit unit, REAL scale, GpImage **image)
93 {
94     GpStatus status;
95     union
96     {
97         GpBitmap *bitmap;
98         GpImage *image;
99     } u;
100     GpGraphics *graphics = NULL;
101     REAL res;
102 
103     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, NULL, &u.bitmap);
104     expect(Ok, status);
105 
106     status = GdipBitmapSetResolution(u.bitmap, res_x, res_y);
107     expect(Ok, status);
108     status = GdipGetImageHorizontalResolution(u.image, &res);
109     expect(Ok, status);
110     expectf(res_x, res);
111     status = GdipGetImageVerticalResolution(u.image, &res);
112     expect(Ok, status);
113     expectf(res_y, res);
114 
115     status = GdipGetImageGraphicsContext(u.image, &graphics);
116     expect(Ok, status);
117 
118     *image = u.image;
119 
120     status = GdipGetDpiX(graphics, &res);
121     expect(Ok, status);
122     expectf(res_x, res);
123     status = GdipGetDpiY(graphics, &res);
124     expect(Ok, status);
125     expectf(res_y, res);
126 
127     status = GdipSetPageUnit(graphics, unit);
128     expect(Ok, status);
129     status = GdipSetPageScale(graphics, scale);
130     expect(Ok, status);
131 
132     return graphics;
133 }
134 
135 static void test_constructor_destructor(void)
136 {
137     GpStatus stat;
138     GpGraphics *graphics = NULL;
139     HDC hdc = GetDC( hwnd );
140 
141     stat = GdipCreateFromHDC(NULL, &graphics);
142     expect(OutOfMemory, stat);
143     stat = GdipDeleteGraphics(graphics);
144     expect(InvalidParameter, stat);
145 
146     stat = GdipCreateFromHDC(hdc, &graphics);
147     expect(Ok, stat);
148     stat = GdipDeleteGraphics(graphics);
149     expect(Ok, stat);
150 
151     stat = GdipCreateFromHWND(NULL, &graphics);
152     expect(Ok, stat);
153     stat = GdipDeleteGraphics(graphics);
154     expect(Ok, stat);
155 
156     stat = GdipCreateFromHWNDICM(NULL, &graphics);
157     expect(Ok, stat);
158     stat = GdipDeleteGraphics(graphics);
159     expect(Ok, stat);
160 
161     stat = GdipDeleteGraphics(NULL);
162     expect(InvalidParameter, stat);
163     ReleaseDC(hwnd, hdc);
164 }
165 
166 typedef struct node{
167     GraphicsState data;
168     struct node * next;
169 } node;
170 
171 /* Linked list prepend function. */
172 static void log_state(GraphicsState data, node ** log)
173 {
174     node * new_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(node));
175 
176     new_entry->data = data;
177     new_entry->next = *log;
178     *log = new_entry;
179 }
180 
181 /* Checks if there are duplicates in the list, and frees it. */
182 static void check_no_duplicates(node * log)
183 {
184     INT dups = 0;
185     node * temp = NULL;
186     node * temp2 = NULL;
187     node * orig = log;
188 
189     if(!log)
190         goto end;
191 
192     do{
193         temp = log;
194         while((temp = temp->next)){
195             if(log->data == temp->data){
196                 dups++;
197                 break;
198             }
199             if(dups > 0)
200                 break;
201         }
202     }while((log = log->next));
203 
204     temp = orig;
205     do{
206         temp2 = temp->next;
207         HeapFree(GetProcessHeap(), 0, temp);
208         temp = temp2;
209     }while(temp);
210 
211 end:
212     expect(0, dups);
213 }
214 
215 static void test_save_restore(void)
216 {
217     GpStatus stat;
218     GraphicsState state_a, state_b, state_c;
219     InterpolationMode mode;
220     GpGraphics *graphics1, *graphics2;
221     node * state_log = NULL;
222     HDC hdc = GetDC( hwnd );
223     state_a = state_b = state_c = 0xdeadbeef;
224 
225     /* Invalid saving. */
226     GdipCreateFromHDC(hdc, &graphics1);
227     stat = GdipSaveGraphics(graphics1, NULL);
228     expect(InvalidParameter, stat);
229     stat = GdipSaveGraphics(NULL, &state_a);
230     expect(InvalidParameter, stat);
231     GdipDeleteGraphics(graphics1);
232 
233     log_state(state_a, &state_log);
234 
235     /* Basic save/restore. */
236     GdipCreateFromHDC(hdc, &graphics1);
237     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
238     stat = GdipSaveGraphics(graphics1, &state_a);
239     expect(Ok, stat);
240     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
241     stat = GdipRestoreGraphics(graphics1, state_a);
242     expect(Ok, stat);
243     GdipGetInterpolationMode(graphics1, &mode);
244     expect(InterpolationModeBilinear, mode);
245     GdipDeleteGraphics(graphics1);
246 
247     log_state(state_a, &state_log);
248 
249     /* Restoring garbage doesn't affect saves. */
250     GdipCreateFromHDC(hdc, &graphics1);
251     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
252     GdipSaveGraphics(graphics1, &state_a);
253     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
254     GdipSaveGraphics(graphics1, &state_b);
255     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
256     stat = GdipRestoreGraphics(graphics1, 0xdeadbeef);
257     expect(Ok, stat);
258     GdipRestoreGraphics(graphics1, state_b);
259     GdipGetInterpolationMode(graphics1, &mode);
260     expect(InterpolationModeBicubic, mode);
261     GdipRestoreGraphics(graphics1, state_a);
262     GdipGetInterpolationMode(graphics1, &mode);
263     expect(InterpolationModeBilinear, mode);
264     GdipDeleteGraphics(graphics1);
265 
266     log_state(state_a, &state_log);
267     log_state(state_b, &state_log);
268 
269     /* Restoring older state invalidates newer saves (but not older saves). */
270     GdipCreateFromHDC(hdc, &graphics1);
271     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
272     GdipSaveGraphics(graphics1, &state_a);
273     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
274     GdipSaveGraphics(graphics1, &state_b);
275     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
276     GdipSaveGraphics(graphics1, &state_c);
277     GdipSetInterpolationMode(graphics1, InterpolationModeHighQualityBilinear);
278     GdipRestoreGraphics(graphics1, state_b);
279     GdipGetInterpolationMode(graphics1, &mode);
280     expect(InterpolationModeBicubic, mode);
281     GdipRestoreGraphics(graphics1, state_c);
282     GdipGetInterpolationMode(graphics1, &mode);
283     expect(InterpolationModeBicubic, mode);
284     GdipRestoreGraphics(graphics1, state_a);
285     GdipGetInterpolationMode(graphics1, &mode);
286     expect(InterpolationModeBilinear, mode);
287     GdipDeleteGraphics(graphics1);
288 
289     log_state(state_a, &state_log);
290     log_state(state_b, &state_log);
291     log_state(state_c, &state_log);
292 
293     /* Restoring older save from one graphics object does not invalidate
294      * newer save from other graphics object. */
295     GdipCreateFromHDC(hdc, &graphics1);
296     GdipCreateFromHDC(hdc, &graphics2);
297     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
298     GdipSaveGraphics(graphics1, &state_a);
299     GdipSetInterpolationMode(graphics2, InterpolationModeBicubic);
300     GdipSaveGraphics(graphics2, &state_b);
301     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
302     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
303     GdipRestoreGraphics(graphics1, state_a);
304     GdipGetInterpolationMode(graphics1, &mode);
305     expect(InterpolationModeBilinear, mode);
306     GdipRestoreGraphics(graphics2, state_b);
307     GdipGetInterpolationMode(graphics2, &mode);
308     expect(InterpolationModeBicubic, mode);
309     GdipDeleteGraphics(graphics1);
310     GdipDeleteGraphics(graphics2);
311 
312     /* You can't restore a state to a graphics object that didn't save it. */
313     GdipCreateFromHDC(hdc, &graphics1);
314     GdipCreateFromHDC(hdc, &graphics2);
315     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
316     GdipSaveGraphics(graphics1, &state_a);
317     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
318     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
319     GdipRestoreGraphics(graphics2, state_a);
320     GdipGetInterpolationMode(graphics2, &mode);
321     expect(InterpolationModeNearestNeighbor, mode);
322     GdipDeleteGraphics(graphics1);
323     GdipDeleteGraphics(graphics2);
324 
325     log_state(state_a, &state_log);
326 
327     /* A state created by SaveGraphics cannot be restored with EndContainer. */
328     GdipCreateFromHDC(hdc, &graphics1);
329     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
330     stat = GdipSaveGraphics(graphics1, &state_a);
331     expect(Ok, stat);
332     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
333     stat = GdipEndContainer(graphics1, state_a);
334     expect(Ok, stat);
335     GdipGetInterpolationMode(graphics1, &mode);
336     expect(InterpolationModeBicubic, mode);
337     stat = GdipRestoreGraphics(graphics1, state_a);
338     expect(Ok, stat);
339     GdipGetInterpolationMode(graphics1, &mode);
340     expect(InterpolationModeBilinear, mode);
341     GdipDeleteGraphics(graphics1);
342 
343     log_state(state_a, &state_log);
344 
345     /* A state created by BeginContainer cannot be restored with RestoreGraphics. */
346     GdipCreateFromHDC(hdc, &graphics1);
347     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
348     stat = GdipBeginContainer2(graphics1, &state_a);
349     expect(Ok, stat);
350     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
351     stat = GdipRestoreGraphics(graphics1, state_a);
352     expect(Ok, stat);
353     GdipGetInterpolationMode(graphics1, &mode);
354     expect(InterpolationModeBicubic, mode);
355     stat = GdipEndContainer(graphics1, state_a);
356     expect(Ok, stat);
357     GdipGetInterpolationMode(graphics1, &mode);
358     expect(InterpolationModeBilinear, mode);
359     GdipDeleteGraphics(graphics1);
360 
361     log_state(state_a, &state_log);
362 
363     /* BeginContainer and SaveGraphics use the same stack. */
364     GdipCreateFromHDC(hdc, &graphics1);
365     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
366     stat = GdipBeginContainer2(graphics1, &state_a);
367     expect(Ok, stat);
368     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
369     stat = GdipSaveGraphics(graphics1, &state_b);
370     expect(Ok, stat);
371     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
372     stat = GdipEndContainer(graphics1, state_a);
373     expect(Ok, stat);
374     GdipGetInterpolationMode(graphics1, &mode);
375     expect(InterpolationModeBilinear, mode);
376     stat = GdipRestoreGraphics(graphics1, state_b);
377     expect(Ok, stat);
378     GdipGetInterpolationMode(graphics1, &mode);
379     expect(InterpolationModeBilinear, mode);
380     GdipDeleteGraphics(graphics1);
381 
382     log_state(state_a, &state_log);
383     log_state(state_b, &state_log);
384 
385     /* The same state value should never be returned twice. */
386     todo_wine
387         check_no_duplicates(state_log);
388 
389     ReleaseDC(hwnd, hdc);
390 }
391 
392 static void test_GdipFillClosedCurve2(void)
393 {
394     GpStatus status;
395     GpGraphics *graphics = NULL;
396     GpSolidFill *brush = NULL;
397     HDC hdc = GetDC( hwnd );
398     GpPointF points[3];
399 
400     points[0].X = 0;
401     points[0].Y = 0;
402 
403     points[1].X = 40;
404     points[1].Y = 20;
405 
406     points[2].X = 10;
407     points[2].Y = 40;
408 
409     /* make a graphics object and brush object */
410     ok(hdc != NULL, "Expected HDC to be initialized\n");
411 
412     status = GdipCreateFromHDC(hdc, &graphics);
413     expect(Ok, status);
414     ok(graphics != NULL, "Expected graphics to be initialized\n");
415 
416     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
417 
418     /* InvalidParameter cases: null graphics, null brush, null points */
419     status = GdipFillClosedCurve2(NULL, NULL, NULL, 3, 0.5, FillModeAlternate);
420     expect(InvalidParameter, status);
421 
422     status = GdipFillClosedCurve2(graphics, NULL, NULL, 3, 0.5, FillModeAlternate);
423     expect(InvalidParameter, status);
424 
425     status = GdipFillClosedCurve2(NULL, (GpBrush*)brush, NULL, 3, 0.5, FillModeAlternate);
426     expect(InvalidParameter, status);
427 
428     status = GdipFillClosedCurve2(NULL, NULL, points, 3, 0.5, FillModeAlternate);
429     expect(InvalidParameter, status);
430 
431     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, NULL, 3, 0.5, FillModeAlternate);
432     expect(InvalidParameter, status);
433 
434     status = GdipFillClosedCurve2(graphics, NULL, points, 3, 0.5, FillModeAlternate);
435     expect(InvalidParameter, status);
436 
437     status = GdipFillClosedCurve2(NULL, (GpBrush*)brush, points, 3, 0.5, FillModeAlternate);
438     expect(InvalidParameter, status);
439 
440     /* InvalidParameter cases: invalid count */
441     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, points, -1, 0.5, FillModeAlternate);
442     expect(InvalidParameter, status);
443 
444     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, points, 0, 0.5, FillModeAlternate);
445     expect(InvalidParameter, status);
446 
447     /* Valid test cases */
448     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, points, 1, 0.5, FillModeAlternate);
449     expect(Ok, status);
450 
451     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, points, 2, 0.5, FillModeAlternate);
452     expect(Ok, status);
453 
454     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, points, 3, 0.5, FillModeAlternate);
455     expect(Ok, status);
456 
457     GdipDeleteGraphics(graphics);
458     GdipDeleteBrush((GpBrush*)brush);
459 
460     ReleaseDC(hwnd, hdc);
461 }
462 
463 static void test_GdipFillClosedCurve2I(void)
464 {
465     GpStatus status;
466     GpGraphics *graphics = NULL;
467     GpSolidFill *brush = NULL;
468     HDC hdc = GetDC( hwnd );
469     GpPoint points[3];
470 
471     points[0].X = 0;
472     points[0].Y = 0;
473 
474     points[1].X = 40;
475     points[1].Y = 20;
476 
477     points[2].X = 10;
478     points[2].Y = 40;
479 
480     /* make a graphics object and brush object */
481     ok(hdc != NULL, "Expected HDC to be initialized\n");
482 
483     status = GdipCreateFromHDC(hdc, &graphics);
484     expect(Ok, status);
485     ok(graphics != NULL, "Expected graphics to be initialized\n");
486 
487     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
488 
489     /* InvalidParameter cases: null graphics, null brush */
490     /* Note: GdipFillClosedCurveI and GdipFillClosedCurve2I hang in Windows
491              when points == NULL, so don't test this condition */
492     status = GdipFillClosedCurve2I(NULL, NULL, points, 3, 0.5, FillModeAlternate);
493     expect(InvalidParameter, status);
494 
495     status = GdipFillClosedCurve2I(graphics, NULL, points, 3, 0.5, FillModeAlternate);
496     expect(InvalidParameter, status);
497 
498     status = GdipFillClosedCurve2I(NULL, (GpBrush*)brush, points, 3, 0.5, FillModeAlternate);
499     expect(InvalidParameter, status);
500 
501     /* InvalidParameter cases: invalid count */
502     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, points, 0, 0.5, FillModeAlternate);
503     expect(InvalidParameter, status);
504 
505     /* OutOfMemory cases: large (unsigned) int */
506     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, points, -1, 0.5, FillModeAlternate);
507     expect(OutOfMemory, status);
508 
509     /* Valid test cases */
510     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, points, 1, 0.5, FillModeAlternate);
511     expect(Ok, status);
512 
513     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, points, 2, 0.5, FillModeAlternate);
514     expect(Ok, status);
515 
516     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, points, 3, 0.5, FillModeAlternate);
517     expect(Ok, status);
518 
519     GdipDeleteGraphics(graphics);
520     GdipDeleteBrush((GpBrush*)brush);
521 
522     ReleaseDC(hwnd, hdc);
523 }
524 
525 static void test_GdipDrawArc(void)
526 {
527     GpStatus status;
528     GpGraphics *graphics = NULL;
529     GpPen *pen = NULL;
530     HDC hdc = GetDC( hwnd );
531 
532     /* make a graphics object and pen object */
533     ok(hdc != NULL, "Expected HDC to be initialized\n");
534 
535     status = GdipCreateFromHDC(hdc, &graphics);
536     expect(Ok, status);
537     ok(graphics != NULL, "Expected graphics to be initialized\n");
538 
539     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
540     expect(Ok, status);
541     ok(pen != NULL, "Expected pen to be initialized\n");
542 
543     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
544     status = GdipDrawArc(NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
545     expect(InvalidParameter, status);
546 
547     status = GdipDrawArc(graphics, NULL, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
548     expect(InvalidParameter, status);
549 
550     status = GdipDrawArc(NULL, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
551     expect(InvalidParameter, status);
552 
553     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
554     expect(InvalidParameter, status);
555 
556     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
557     expect(InvalidParameter, status);
558 
559     /* successful case */
560     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
561     expect(Ok, status);
562 
563     GdipDeletePen(pen);
564     GdipDeleteGraphics(graphics);
565 
566     ReleaseDC(hwnd, hdc);
567 }
568 
569 static void test_GdipDrawArcI(void)
570 {
571     GpStatus status;
572     GpGraphics *graphics = NULL;
573     GpPen *pen = NULL;
574     HDC hdc = GetDC( hwnd );
575 
576     /* make a graphics object and pen object */
577     ok(hdc != NULL, "Expected HDC to be initialized\n");
578 
579     status = GdipCreateFromHDC(hdc, &graphics);
580     expect(Ok, status);
581     ok(graphics != NULL, "Expected graphics to be initialized\n");
582 
583     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
584     expect(Ok, status);
585     ok(pen != NULL, "Expected pen to be initialized\n");
586 
587     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
588     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
589     expect(InvalidParameter, status);
590 
591     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
592     expect(InvalidParameter, status);
593 
594     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
595     expect(InvalidParameter, status);
596 
597     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
598     expect(InvalidParameter, status);
599 
600     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
601     expect(InvalidParameter, status);
602 
603     /* successful case */
604     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
605     expect(Ok, status);
606 
607     GdipDeletePen(pen);
608     GdipDeleteGraphics(graphics);
609 
610     ReleaseDC(hwnd, hdc);
611 }
612 
613 static void test_BeginContainer2(void)
614 {
615     GpMatrix *transform;
616     GpRectF clip;
617     REAL defClip[] = {5, 10, 15, 20};
618     REAL elems[6], defTrans[] = {1, 2, 3, 4, 5, 6};
619     GraphicsContainer cont1, cont2, cont3, cont4;
620     CompositingQuality compqual, defCompqual = CompositingQualityHighSpeed;
621     CompositingMode compmode, defCompmode = CompositingModeSourceOver;
622     InterpolationMode interp, defInterp = InterpolationModeHighQualityBicubic;
623     REAL scale, defScale = 17;
624     GpUnit unit, defUnit = UnitPixel;
625     PixelOffsetMode offsetmode, defOffsetmode = PixelOffsetModeHighSpeed;
626     SmoothingMode smoothmode, defSmoothmode = SmoothingModeAntiAlias;
627     UINT contrast, defContrast = 5;
628     TextRenderingHint texthint, defTexthint = TextRenderingHintAntiAlias;
629 
630     GpStatus status;
631     GpGraphics *graphics = NULL;
632     HDC hdc = GetDC( hwnd );
633 
634     ok(hdc != NULL, "Expected HDC to be initialized\n");
635 
636     status = GdipCreateFromHDC(hdc, &graphics);
637     expect(Ok, status);
638     ok(graphics != NULL, "Expected graphics to be initialized\n");
639 
640     /* null graphics, null container */
641     status = GdipBeginContainer2(NULL, &cont1);
642     expect(InvalidParameter, status);
643 
644     status = GdipBeginContainer2(graphics, NULL);
645     expect(InvalidParameter, status);
646 
647     status = GdipEndContainer(NULL, cont1);
648     expect(InvalidParameter, status);
649 
650     /* test all quality-related values */
651     GdipSetCompositingMode(graphics, defCompmode);
652     GdipSetCompositingQuality(graphics, defCompqual);
653     GdipSetInterpolationMode(graphics, defInterp);
654     GdipSetPageScale(graphics, defScale);
655     GdipSetPageUnit(graphics, defUnit);
656     GdipSetPixelOffsetMode(graphics, defOffsetmode);
657     GdipSetSmoothingMode(graphics, defSmoothmode);
658     GdipSetTextContrast(graphics, defContrast);
659     GdipSetTextRenderingHint(graphics, defTexthint);
660 
661     status = GdipBeginContainer2(graphics, &cont1);
662     expect(Ok, status);
663 
664     GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
665     GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
666     GdipSetInterpolationMode(graphics, InterpolationModeBilinear);
667     GdipSetPageScale(graphics, 10);
668     GdipSetPageUnit(graphics, UnitDocument);
669     GdipSetPixelOffsetMode(graphics, PixelOffsetModeHalf);
670     GdipSetSmoothingMode(graphics, SmoothingModeNone);
671     GdipSetTextContrast(graphics, 7);
672     GdipSetTextRenderingHint(graphics, TextRenderingHintClearTypeGridFit);
673 
674     status = GdipEndContainer(graphics, cont1);
675     expect(Ok, status);
676 
677     GdipGetCompositingMode(graphics, &compmode);
678     ok(defCompmode == compmode, "Expected Compositing Mode to be restored to %d, got %d\n", defCompmode, compmode);
679 
680     GdipGetCompositingQuality(graphics, &compqual);
681     ok(defCompqual == compqual, "Expected Compositing Quality to be restored to %d, got %d\n", defCompqual, compqual);
682 
683     GdipGetInterpolationMode(graphics, &interp);
684     ok(defInterp == interp, "Expected Interpolation Mode to be restored to %d, got %d\n", defInterp, interp);
685 
686     GdipGetPageScale(graphics, &scale);
687     ok(fabs(defScale - scale) < 0.0001, "Expected Page Scale to be restored to %f, got %f\n", defScale, scale);
688 
689     GdipGetPageUnit(graphics, &unit);
690     ok(defUnit == unit, "Expected Page Unit to be restored to %d, got %d\n", defUnit, unit);
691 
692     GdipGetPixelOffsetMode(graphics, &offsetmode);
693     ok(defOffsetmode == offsetmode, "Expected Pixel Offset Mode to be restored to %d, got %d\n", defOffsetmode, offsetmode);
694 
695     GdipGetSmoothingMode(graphics, &smoothmode);
696     ok(defSmoothmode == smoothmode, "Expected Smoothing Mode to be restored to %d, got %d\n", defSmoothmode, smoothmode);
697 
698     GdipGetTextContrast(graphics, &contrast);
699     ok(defContrast == contrast, "Expected Text Contrast to be restored to %d, got %d\n", defContrast, contrast);
700 
701     GdipGetTextRenderingHint(graphics, &texthint);
702     ok(defTexthint == texthint, "Expected Text Hint to be restored to %d, got %d\n", defTexthint, texthint);
703 
704     /* test world transform */
705     status = GdipBeginContainer2(graphics, &cont1);
706     expect(Ok, status);
707 
708     status = GdipCreateMatrix2(defTrans[0], defTrans[1], defTrans[2], defTrans[3],
709             defTrans[4], defTrans[5], &transform);
710     expect(Ok, status);
711     GdipSetWorldTransform(graphics, transform);
712     GdipDeleteMatrix(transform);
713     transform = NULL;
714 
715     status = GdipBeginContainer2(graphics, &cont2);
716     expect(Ok, status);
717 
718     status = GdipCreateMatrix2(10, 20, 30, 40, 50, 60, &transform);
719     expect(Ok, status);
720     GdipSetWorldTransform(graphics, transform);
721     GdipDeleteMatrix(transform);
722     transform = NULL;
723 
724     status = GdipEndContainer(graphics, cont2);
725     expect(Ok, status);
726 
727     status = GdipCreateMatrix(&transform);
728     expect(Ok, status);
729     GdipGetWorldTransform(graphics, transform);
730     GdipGetMatrixElements(transform, elems);
731     ok(fabs(defTrans[0] - elems[0]) < 0.0001 &&
732             fabs(defTrans[1] - elems[1]) < 0.0001 &&
733             fabs(defTrans[2] - elems[2]) < 0.0001 &&
734             fabs(defTrans[3] - elems[3]) < 0.0001 &&
735             fabs(defTrans[4] - elems[4]) < 0.0001 &&
736             fabs(defTrans[5] - elems[5]) < 0.0001,
737             "Expected World Transform Matrix to be restored to [%f, %f, %f, %f, %f, %f], got [%f, %f, %f, %f, %f, %f]\n",
738             defTrans[0], defTrans[1], defTrans[2], defTrans[3], defTrans[4], defTrans[5],
739             elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]);
740     GdipDeleteMatrix(transform);
741     transform = NULL;
742 
743     status = GdipEndContainer(graphics, cont1);
744     expect(Ok, status);
745 
746     /* test clipping */
747     status = GdipBeginContainer2(graphics, &cont1);
748     expect(Ok, status);
749 
750     GdipSetClipRect(graphics, defClip[0], defClip[1], defClip[2], defClip[3], CombineModeReplace);
751 
752     status = GdipBeginContainer2(graphics, &cont2);
753     expect(Ok, status);
754 
755     GdipSetClipRect(graphics, 2, 4, 6, 8, CombineModeReplace);
756 
757     status = GdipEndContainer(graphics, cont2);
758     expect(Ok, status);
759 
760     status = GdipGetClipBounds(graphics, &clip);
761     expect(Ok, status);
762 
763     ok(fabs(defClip[0] - clip.X) < 0.0001 &&
764             fabs(defClip[1] - clip.Y) < 0.0001 &&
765             fabs(defClip[2] - clip.Width) < 0.0001 &&
766             fabs(defClip[3] - clip.Height) < 0.0001,
767             "Expected Clipping Rectangle to be restored to [%f, %f, %f, %f], got [%f, %f, %f, %f]\n",
768             defClip[0], defClip[1], defClip[2], defClip[3],
769             clip.X, clip.Y, clip.Width, clip.Height);
770 
771     status = GdipEndContainer(graphics, cont1);
772     expect(Ok, status);
773 
774     /* nesting */
775     status = GdipBeginContainer2(graphics, &cont1);
776     expect(Ok, status);
777 
778     status = GdipBeginContainer2(graphics, &cont2);
779     expect(Ok, status);
780 
781     status = GdipBeginContainer2(graphics, &cont3);
782     expect(Ok, status);
783 
784     status = GdipEndContainer(graphics, cont3);
785     expect(Ok, status);
786 
787     status = GdipBeginContainer2(graphics, &cont4);
788     expect(Ok, status);
789 
790     status = GdipEndContainer(graphics, cont4);
791     expect(Ok, status);
792 
793     /* skip cont2 */
794     status = GdipEndContainer(graphics, cont1);
795     expect(Ok, status);
796 
797     /* end an already-ended container */
798     status = GdipEndContainer(graphics, cont1);
799     expect(Ok, status);
800 
801     GdipDeleteGraphics(graphics);
802     ReleaseDC(hwnd, hdc);
803 }
804 
805 static void test_GdipDrawBezierI(void)
806 {
807     GpStatus status;
808     GpGraphics *graphics = NULL;
809     GpPen *pen = NULL;
810     HDC hdc = GetDC( hwnd );
811 
812     /* make a graphics object and pen object */
813     ok(hdc != NULL, "Expected HDC to be initialized\n");
814 
815     status = GdipCreateFromHDC(hdc, &graphics);
816     expect(Ok, status);
817     ok(graphics != NULL, "Expected graphics to be initialized\n");
818 
819     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
820     expect(Ok, status);
821     ok(pen != NULL, "Expected pen to be initialized\n");
822 
823     /* InvalidParameter cases: null graphics, null pen */
824     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
825     expect(InvalidParameter, status);
826 
827     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
828     expect(InvalidParameter, status);
829 
830     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
831     expect(InvalidParameter, status);
832 
833     /* successful case */
834     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
835     expect(Ok, status);
836 
837     GdipDeletePen(pen);
838     GdipDeleteGraphics(graphics);
839 
840     ReleaseDC(hwnd, hdc);
841 }
842 
843 static void test_GdipDrawCurve3(void)
844 {
845     GpStatus status;
846     GpGraphics *graphics = NULL;
847     GpPen *pen = NULL;
848     HDC hdc = GetDC( hwnd );
849     GpPointF points[3];
850 
851     points[0].X = 0;
852     points[0].Y = 0;
853 
854     points[1].X = 40;
855     points[1].Y = 20;
856 
857     points[2].X = 10;
858     points[2].Y = 40;
859 
860     /* make a graphics object and pen object */
861     ok(hdc != NULL, "Expected HDC to be initialized\n");
862 
863     status = GdipCreateFromHDC(hdc, &graphics);
864     expect(Ok, status);
865     ok(graphics != NULL, "Expected graphics to be initialized\n");
866 
867     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
868     expect(Ok, status);
869     ok(pen != NULL, "Expected pen to be initialized\n");
870 
871     /* InvalidParameter cases: null graphics, null pen */
872     status = GdipDrawCurve3(NULL, NULL, points, 3, 0, 2, 1);
873     expect(InvalidParameter, status);
874 
875     status = GdipDrawCurve3(graphics, NULL, points, 3, 0, 2, 1);
876     expect(InvalidParameter, status);
877 
878     status = GdipDrawCurve3(NULL, pen, points, 3, 0, 2, 1);
879     expect(InvalidParameter, status);
880 
881     /* InvalidParameter cases: invalid count */
882     status = GdipDrawCurve3(graphics, pen, points, -1, 0, 2, 1);
883     expect(InvalidParameter, status);
884 
885     status = GdipDrawCurve3(graphics, pen, points, 0, 0, 2, 1);
886     expect(InvalidParameter, status);
887 
888     status = GdipDrawCurve3(graphics, pen, points, 1, 0, 0, 1);
889     expect(InvalidParameter, status);
890 
891     status = GdipDrawCurve3(graphics, pen, points, 3, 4, 2, 1);
892     expect(InvalidParameter, status);
893 
894     /* InvalidParameter cases: invalid number of segments */
895     status = GdipDrawCurve3(graphics, pen, points, 3, 0, -1, 1);
896     expect(InvalidParameter, status);
897 
898     status = GdipDrawCurve3(graphics, pen, points, 3, 1, 2, 1);
899     expect(InvalidParameter, status);
900 
901     status = GdipDrawCurve3(graphics, pen, points, 2, 0, 2, 1);
902     expect(InvalidParameter, status);
903 
904     /* Valid test cases */
905     status = GdipDrawCurve3(graphics, pen, points, 2, 0, 1, 1);
906     expect(Ok, status);
907 
908     status = GdipDrawCurve3(graphics, pen, points, 3, 0, 2, 2);
909     expect(Ok, status);
910 
911     status = GdipDrawCurve3(graphics, pen, points, 2, 0, 1, -2);
912     expect(Ok, status);
913 
914     status = GdipDrawCurve3(graphics, pen, points, 3, 1, 1, 0);
915     expect(Ok, status);
916 
917     GdipDeletePen(pen);
918     GdipDeleteGraphics(graphics);
919 
920     ReleaseDC(hwnd, hdc);
921 }
922 
923 static void test_GdipDrawCurve3I(void)
924 {
925     GpStatus status;
926     GpGraphics *graphics = NULL;
927     GpPen *pen = NULL;
928     HDC hdc = GetDC( hwnd );
929     GpPoint points[3];
930 
931     points[0].X = 0;
932     points[0].Y = 0;
933 
934     points[1].X = 40;
935     points[1].Y = 20;
936 
937     points[2].X = 10;
938     points[2].Y = 40;
939 
940     /* make a graphics object and pen object */
941     ok(hdc != NULL, "Expected HDC to be initialized\n");
942 
943     status = GdipCreateFromHDC(hdc, &graphics);
944     expect(Ok, status);
945     ok(graphics != NULL, "Expected graphics to be initialized\n");
946 
947     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
948     expect(Ok, status);
949     ok(pen != NULL, "Expected pen to be initialized\n");
950 
951     /* InvalidParameter cases: null graphics, null pen */
952     status = GdipDrawCurve3I(NULL, NULL, points, 3, 0, 2, 1);
953     expect(InvalidParameter, status);
954 
955     status = GdipDrawCurve3I(graphics, NULL, points, 3, 0, 2, 1);
956     expect(InvalidParameter, status);
957 
958     status = GdipDrawCurve3I(NULL, pen, points, 3, 0, 2, 1);
959     expect(InvalidParameter, status);
960 
961     /* InvalidParameter cases: invalid count */
962     status = GdipDrawCurve3I(graphics, pen, points, -1, -1, -1, 1);
963     expect(OutOfMemory, status);
964 
965     status = GdipDrawCurve3I(graphics, pen, points, 0, 0, 2, 1);
966     expect(InvalidParameter, status);
967 
968     status = GdipDrawCurve3I(graphics, pen, points, 1, 0, 0, 1);
969     expect(InvalidParameter, status);
970 
971     status = GdipDrawCurve3I(graphics, pen, points, 3, 4, 2, 1);
972     expect(InvalidParameter, status);
973 
974     /* InvalidParameter cases: invalid number of segments */
975     status = GdipDrawCurve3I(graphics, pen, points, 3, 0, -1, 1);
976     expect(InvalidParameter, status);
977 
978     status = GdipDrawCurve3I(graphics, pen, points, 3, 1, 2, 1);
979     expect(InvalidParameter, status);
980 
981     status = GdipDrawCurve3I(graphics, pen, points, 2, 0, 2, 1);
982     expect(InvalidParameter, status);
983 
984     /* Valid test cases */
985     status = GdipDrawCurve3I(graphics, pen, points, 2, 0, 1, 1);
986     expect(Ok, status);
987 
988     status = GdipDrawCurve3I(graphics, pen, points, 3, 0, 2, 2);
989     expect(Ok, status);
990 
991     status = GdipDrawCurve3I(graphics, pen, points, 2, 0, 1, -2);
992     expect(Ok, status);
993 
994     status = GdipDrawCurve3I(graphics, pen, points, 3, 1, 1, 0);
995     expect(Ok, status);
996 
997     GdipDeletePen(pen);
998     GdipDeleteGraphics(graphics);
999 
1000     ReleaseDC(hwnd, hdc);
1001 }
1002 
1003 static void test_GdipDrawCurve2(void)
1004 {
1005     GpStatus status;
1006     GpGraphics *graphics = NULL;
1007     GpPen *pen = NULL;
1008     HDC hdc = GetDC( hwnd );
1009     GpPointF points[3];
1010 
1011     points[0].X = 0;
1012     points[0].Y = 0;
1013 
1014     points[1].X = 40;
1015     points[1].Y = 20;
1016 
1017     points[2].X = 10;
1018     points[2].Y = 40;
1019 
1020     /* make a graphics object and pen object */
1021     ok(hdc != NULL, "Expected HDC to be initialized\n");
1022 
1023     status = GdipCreateFromHDC(hdc, &graphics);
1024     expect(Ok, status);
1025     ok(graphics != NULL, "Expected graphics to be initialized\n");
1026 
1027     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1028     expect(Ok, status);
1029     ok(pen != NULL, "Expected pen to be initialized\n");
1030 
1031     /* InvalidParameter cases: null graphics, null pen */
1032     status = GdipDrawCurve2(NULL, NULL, points, 3, 1);
1033     expect(InvalidParameter, status);
1034 
1035     status = GdipDrawCurve2(graphics, NULL, points, 3, 1);
1036     expect(InvalidParameter, status);
1037 
1038     status = GdipDrawCurve2(NULL, pen, points, 3, 1);
1039     expect(InvalidParameter, status);
1040 
1041     /* InvalidParameter cases: invalid count */
1042     status = GdipDrawCurve2(graphics, pen, points, -1, 1);
1043     expect(InvalidParameter, status);
1044 
1045     status = GdipDrawCurve2(graphics, pen, points, 0, 1);
1046     expect(InvalidParameter, status);
1047 
1048     status = GdipDrawCurve2(graphics, pen, points, 1, 1);
1049     expect(InvalidParameter, status);
1050 
1051     /* Valid test cases */
1052     status = GdipDrawCurve2(graphics, pen, points, 2, 1);
1053     expect(Ok, status);
1054 
1055     status = GdipDrawCurve2(graphics, pen, points, 3, 2);
1056     expect(Ok, status);
1057 
1058     status = GdipDrawCurve2(graphics, pen, points, 3, -2);
1059     expect(Ok, status);
1060 
1061     status = GdipDrawCurve2(graphics, pen, points, 3, 0);
1062     expect(Ok, status);
1063 
1064     GdipDeletePen(pen);
1065     GdipDeleteGraphics(graphics);
1066 
1067     ReleaseDC(hwnd, hdc);
1068 }
1069 
1070 static void test_GdipDrawCurve2I(void)
1071 {
1072     GpStatus status;
1073     GpGraphics *graphics = NULL;
1074     GpPen *pen = NULL;
1075     HDC hdc = GetDC( hwnd );
1076     GpPoint points[3];
1077 
1078     points[0].X = 0;
1079     points[0].Y = 0;
1080 
1081     points[1].X = 40;
1082     points[1].Y = 20;
1083 
1084     points[2].X = 10;
1085     points[2].Y = 40;
1086 
1087     /* make a graphics object and pen object */
1088     ok(hdc != NULL, "Expected HDC to be initialized\n");
1089 
1090     status = GdipCreateFromHDC(hdc, &graphics);
1091     expect(Ok, status);
1092     ok(graphics != NULL, "Expected graphics to be initialized\n");
1093 
1094     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1095     expect(Ok, status);
1096     ok(pen != NULL, "Expected pen to be initialized\n");
1097 
1098     /* InvalidParameter cases: null graphics, null pen */
1099     status = GdipDrawCurve2I(NULL, NULL, points, 3, 1);
1100     expect(InvalidParameter, status);
1101 
1102     status = GdipDrawCurve2I(graphics, NULL, points, 3, 1);
1103     expect(InvalidParameter, status);
1104 
1105     status = GdipDrawCurve2I(NULL, pen, points, 3, 1);
1106     expect(InvalidParameter, status);
1107 
1108     /* InvalidParameter cases: invalid count */
1109     status = GdipDrawCurve2I(graphics, pen, points, -1, 1);
1110     expect(OutOfMemory, status);
1111 
1112     status = GdipDrawCurve2I(graphics, pen, points, 0, 1);
1113     expect(InvalidParameter, status);
1114 
1115     status = GdipDrawCurve2I(graphics, pen, points, 1, 1);
1116     expect(InvalidParameter, status);
1117 
1118     /* Valid test cases */
1119     status = GdipDrawCurve2I(graphics, pen, points, 2, 1);
1120     expect(Ok, status);
1121 
1122     status = GdipDrawCurve2I(graphics, pen, points, 3, 2);
1123     expect(Ok, status);
1124 
1125     status = GdipDrawCurve2I(graphics, pen, points, 3, -2);
1126     expect(Ok, status);
1127 
1128     status = GdipDrawCurve2I(graphics, pen, points, 3, 0);
1129     expect(Ok, status);
1130 
1131     GdipDeletePen(pen);
1132     GdipDeleteGraphics(graphics);
1133 
1134     ReleaseDC(hwnd, hdc);
1135 }
1136 
1137 static void test_GdipDrawCurve(void)
1138 {
1139     GpStatus status;
1140     GpGraphics *graphics = NULL;
1141     GpPen *pen = NULL;
1142     HDC hdc = GetDC( hwnd );
1143     GpPointF points[3];
1144 
1145     points[0].X = 0;
1146     points[0].Y = 0;
1147 
1148     points[1].X = 40;
1149     points[1].Y = 20;
1150 
1151     points[2].X = 10;
1152     points[2].Y = 40;
1153 
1154     /* make a graphics object and pen object */
1155     ok(hdc != NULL, "Expected HDC to be initialized\n");
1156 
1157     status = GdipCreateFromHDC(hdc, &graphics);
1158     expect(Ok, status);
1159     ok(graphics != NULL, "Expected graphics to be initialized\n");
1160 
1161     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1162     expect(Ok, status);
1163     ok(pen != NULL, "Expected pen to be initialized\n");
1164 
1165     /* InvalidParameter cases: null graphics, null pen */
1166     status = GdipDrawCurve(NULL, NULL, points, 3);
1167     expect(InvalidParameter, status);
1168 
1169     status = GdipDrawCurve(graphics, NULL, points, 3);
1170     expect(InvalidParameter, status);
1171 
1172     status = GdipDrawCurve(NULL, pen, points, 3);
1173     expect(InvalidParameter, status);
1174 
1175     /* InvalidParameter cases: invalid count */
1176     status = GdipDrawCurve(graphics, pen, points, -1);
1177     expect(InvalidParameter, status);
1178 
1179     status = GdipDrawCurve(graphics, pen, points, 0);
1180     expect(InvalidParameter, status);
1181 
1182     status = GdipDrawCurve(graphics, pen, points, 1);
1183     expect(InvalidParameter, status);
1184 
1185     /* Valid test cases */
1186     status = GdipDrawCurve(graphics, pen, points, 2);
1187     expect(Ok, status);
1188 
1189     status = GdipDrawCurve(graphics, pen, points, 3);
1190     expect(Ok, status);
1191 
1192     GdipDeletePen(pen);
1193     GdipDeleteGraphics(graphics);
1194 
1195     ReleaseDC(hwnd, hdc);
1196 }
1197 
1198 static void test_GdipDrawCurveI(void)
1199 {
1200     GpStatus status;
1201     GpGraphics *graphics = NULL;
1202     GpPen *pen = NULL;
1203     HDC hdc = GetDC( hwnd );
1204     GpPoint points[3];
1205 
1206     points[0].X = 0;
1207     points[0].Y = 0;
1208 
1209     points[1].X = 40;
1210     points[1].Y = 20;
1211 
1212     points[2].X = 10;
1213     points[2].Y = 40;
1214 
1215     /* make a graphics object and pen object */
1216     ok(hdc != NULL, "Expected HDC to be initialized\n");
1217 
1218     status = GdipCreateFromHDC(hdc, &graphics);
1219     expect(Ok, status);
1220     ok(graphics != NULL, "Expected graphics to be initialized\n");
1221 
1222     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1223     expect(Ok, status);
1224     ok(pen != NULL, "Expected pen to be initialized\n");
1225 
1226     /* InvalidParameter cases: null graphics, null pen */
1227     status = GdipDrawCurveI(NULL, NULL, points, 3);
1228     expect(InvalidParameter, status);
1229 
1230     status = GdipDrawCurveI(graphics, NULL, points, 3);
1231     expect(InvalidParameter, status);
1232 
1233     status = GdipDrawCurveI(NULL, pen, points, 3);
1234     expect(InvalidParameter, status);
1235 
1236     /* InvalidParameter cases: invalid count */
1237     status = GdipDrawCurveI(graphics, pen, points, -1);
1238     expect(OutOfMemory, status);
1239 
1240     status = GdipDrawCurveI(graphics, pen, points, 0);
1241     expect(InvalidParameter, status);
1242 
1243     status = GdipDrawCurveI(graphics, pen, points, 1);
1244     expect(InvalidParameter, status);
1245 
1246     /* Valid test cases */
1247     status = GdipDrawCurveI(graphics, pen, points, 2);
1248     expect(Ok, status);
1249 
1250     status = GdipDrawCurveI(graphics, pen, points, 3);
1251     expect(Ok, status);
1252 
1253     GdipDeletePen(pen);
1254     GdipDeleteGraphics(graphics);
1255 
1256     ReleaseDC(hwnd, hdc);
1257 }
1258 
1259 static void test_GdipDrawLineI(void)
1260 {
1261     GpStatus status;
1262     GpGraphics *graphics = NULL;
1263     GpPen *pen = NULL;
1264     HDC hdc = GetDC( hwnd );
1265 
1266     /* make a graphics object and pen object */
1267     ok(hdc != NULL, "Expected HDC to be initialized\n");
1268 
1269     status = GdipCreateFromHDC(hdc, &graphics);
1270     expect(Ok, status);
1271     ok(graphics != NULL, "Expected graphics to be initialized\n");
1272 
1273     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1274     expect(Ok, status);
1275     ok(pen != NULL, "Expected pen to be initialized\n");
1276 
1277     /* InvalidParameter cases: null graphics, null pen */
1278     status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0);
1279     expect(InvalidParameter, status);
1280 
1281     status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0);
1282     expect(InvalidParameter, status);
1283 
1284     status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0);
1285     expect(InvalidParameter, status);
1286 
1287     /* successful case */
1288     status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0);
1289     expect(Ok, status);
1290 
1291     GdipDeletePen(pen);
1292     GdipDeleteGraphics(graphics);
1293 
1294     ReleaseDC(hwnd, hdc);
1295 }
1296 
1297 static void test_GdipDrawImagePointsRect(void)
1298 {
1299     GpStatus status;
1300     GpGraphics *graphics = NULL;
1301     GpPointF ptf[4];
1302     GpBitmap *bm = NULL;
1303     BYTE rbmi[sizeof(BITMAPINFOHEADER)];
1304     BYTE buff[400];
1305     BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
1306     HDC hdc = GetDC( hwnd );
1307     if (!hdc)
1308         return;
1309 
1310     memset(rbmi, 0, sizeof(rbmi));
1311     bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1312     bmi->bmiHeader.biWidth = 10;
1313     bmi->bmiHeader.biHeight = 10;
1314     bmi->bmiHeader.biPlanes = 1;
1315     bmi->bmiHeader.biBitCount = 32;
1316     bmi->bmiHeader.biCompression = BI_RGB;
1317     status = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
1318     expect(Ok, status);
1319     ok(NULL != bm, "Expected bitmap to be initialized\n");
1320     status = GdipCreateFromHDC(hdc, &graphics);
1321     expect(Ok, status);
1322     ptf[0].X = 0;
1323     ptf[0].Y = 0;
1324     ptf[1].X = 10;
1325     ptf[1].Y = 0;
1326     ptf[2].X = 0;
1327     ptf[2].Y = 10;
1328     ptf[3].X = 10;
1329     ptf[3].Y = 10;
1330     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, ptf, 4, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1331     expect(NotImplemented, status);
1332     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, ptf, 2, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1333     expect(InvalidParameter, status);
1334     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, ptf, 3, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1335     expect(Ok, status);
1336     status = GdipDrawImagePointsRect(graphics, NULL, ptf, 3, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1337     expect(InvalidParameter, status);
1338     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, NULL, 3, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1339     expect(InvalidParameter, status);
1340     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, ptf, 3, 0, 0, 0, 0, UnitPixel, NULL, NULL, NULL);
1341     expect(Ok, status);
1342     memset(ptf, 0, sizeof(ptf));
1343     status = GdipDrawImagePointsRect(graphics, (GpImage*)bm, ptf, 3, 0, 0, 10, 10, UnitPixel, NULL, NULL, NULL);
1344     expect(Ok, status);
1345 
1346     GdipDisposeImage((GpImage*)bm);
1347     GdipDeleteGraphics(graphics);
1348     ReleaseDC(hwnd, hdc);
1349 }
1350 
1351 static void test_GdipDrawLinesI(void)
1352 {
1353     GpStatus status;
1354     GpGraphics *graphics = NULL;
1355     GpPen *pen = NULL;
1356     GpPoint *ptf = NULL;
1357     HDC hdc = GetDC( hwnd );
1358 
1359     /* make a graphics object and pen object */
1360     ok(hdc != NULL, "Expected HDC to be initialized\n");
1361 
1362     status = GdipCreateFromHDC(hdc, &graphics);
1363     expect(Ok, status);
1364     ok(graphics != NULL, "Expected graphics to be initialized\n");
1365 
1366     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1367     expect(Ok, status);
1368     ok(pen != NULL, "Expected pen to be initialized\n");
1369 
1370     /* make some arbitrary valid points*/
1371     ptf = GdipAlloc(2 * sizeof(GpPointF));
1372 
1373     ptf[0].X = 1;
1374     ptf[0].Y = 1;
1375 
1376     ptf[1].X = 2;
1377     ptf[1].Y = 2;
1378 
1379     /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/
1380     status = GdipDrawLinesI(NULL, NULL, NULL, 0);
1381     expect(InvalidParameter, status);
1382 
1383     status = GdipDrawLinesI(graphics, pen, ptf, 0);
1384     expect(InvalidParameter, status);
1385 
1386     status = GdipDrawLinesI(graphics, NULL, ptf, 2);
1387     expect(InvalidParameter, status);
1388 
1389     status = GdipDrawLinesI(NULL, pen, ptf, 2);
1390     expect(InvalidParameter, status);
1391 
1392     /* successful case */
1393     status = GdipDrawLinesI(graphics, pen, ptf, 2);
1394     expect(Ok, status);
1395 
1396     GdipFree(ptf);
1397     GdipDeletePen(pen);
1398     GdipDeleteGraphics(graphics);
1399 
1400     ReleaseDC(hwnd, hdc);
1401 }
1402 
1403 static void test_GdipFillClosedCurve(void)
1404 {
1405     GpStatus status;
1406     GpGraphics *graphics = NULL;
1407     GpSolidFill *brush = NULL;
1408     HDC hdc = GetDC( hwnd );
1409     GpPointF points[3];
1410 
1411     points[0].X = 0;
1412     points[0].Y = 0;
1413 
1414     points[1].X = 40;
1415     points[1].Y = 20;
1416 
1417     points[2].X = 10;
1418     points[2].Y = 40;
1419 
1420     /* make a graphics object and brush object */
1421     ok(hdc != NULL, "Expected HDC to be initialized\n");
1422 
1423     status = GdipCreateFromHDC(hdc, &graphics);
1424     expect(Ok, status);
1425     ok(graphics != NULL, "Expected graphics to be initialized\n");
1426 
1427     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
1428 
1429     /* InvalidParameter cases: null graphics, null brush, null points */
1430     status = GdipFillClosedCurve(NULL, NULL, NULL, 3);
1431     expect(InvalidParameter, status);
1432 
1433     status = GdipFillClosedCurve(graphics, NULL, NULL, 3);
1434     expect(InvalidParameter, status);
1435 
1436     status = GdipFillClosedCurve(NULL, (GpBrush*)brush, NULL, 3);
1437     expect(InvalidParameter, status);
1438 
1439     status = GdipFillClosedCurve(NULL, NULL, points, 3);
1440     expect(InvalidParameter, status);
1441 
1442     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, NULL, 3);
1443     expect(InvalidParameter, status);
1444 
1445     status = GdipFillClosedCurve(graphics, NULL, points, 3);
1446     expect(InvalidParameter, status);
1447 
1448     status = GdipFillClosedCurve(NULL, (GpBrush*)brush, points, 3);
1449     expect(InvalidParameter, status);
1450 
1451     /* InvalidParameter cases: invalid count */
1452     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, points, -1);
1453     expect(InvalidParameter, status);
1454 
1455     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, points, 0);
1456     expect(InvalidParameter, status);
1457 
1458     /* Valid test cases */
1459     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, points, 1);
1460     expect(Ok, status);
1461 
1462     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, points, 2);
1463     expect(Ok, status);
1464 
1465     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, points, 3);
1466     expect(Ok, status);
1467 
1468     GdipDeleteGraphics(graphics);
1469     GdipDeleteBrush((GpBrush*)brush);
1470 
1471     ReleaseDC(hwnd, hdc);
1472 }
1473 
1474 static void test_GdipFillClosedCurveI(void)
1475 {
1476     GpStatus status;
1477     GpGraphics *graphics = NULL;
1478     GpSolidFill *brush = NULL;
1479     HDC hdc = GetDC( hwnd );
1480     GpPoint points[3];
1481 
1482     points[0].X = 0;
1483     points[0].Y = 0;
1484 
1485     points[1].X = 40;
1486     points[1].Y = 20;
1487 
1488     points[2].X = 10;
1489     points[2].Y = 40;
1490 
1491     /* make a graphics object and brush object */
1492     ok(hdc != NULL, "Expected HDC to be initialized\n");
1493 
1494     status = GdipCreateFromHDC(hdc, &graphics);
1495     expect(Ok, status);
1496     ok(graphics != NULL, "Expected graphics to be initialized\n");
1497 
1498     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
1499 
1500     /* InvalidParameter cases: null graphics, null brush */
1501     /* Note: GdipFillClosedCurveI and GdipFillClosedCurve2I hang in Windows
1502              when points == NULL, so don't test this condition */
1503     status = GdipFillClosedCurveI(NULL, NULL, points, 3);
1504     expect(InvalidParameter, status);
1505 
1506     status = GdipFillClosedCurveI(graphics, NULL, points, 3);
1507     expect(InvalidParameter, status);
1508 
1509     status = GdipFillClosedCurveI(NULL, (GpBrush*)brush, points, 3);
1510     expect(InvalidParameter, status);
1511 
1512     /* InvalidParameter cases: invalid count */
1513     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, points, 0);
1514     expect(InvalidParameter, status);
1515 
1516     /* OutOfMemory cases: large (unsigned) int */
1517     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, points, -1);
1518     expect(OutOfMemory, status);
1519 
1520     /* Valid test cases */
1521     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, points, 1);
1522     expect(Ok, status);
1523 
1524     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, points, 2);
1525     expect(Ok, status);
1526 
1527     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, points, 3);
1528     expect(Ok, status);
1529 
1530     GdipDeleteGraphics(graphics);
1531     GdipDeleteBrush((GpBrush*)brush);
1532 
1533     ReleaseDC(hwnd, hdc);
1534 }
1535 
1536 static void test_Get_Release_DC(void)
1537 {
1538     GpStatus status;
1539     GpGraphics *graphics = NULL;
1540     GpPen *pen;
1541     GpSolidFill *brush;
1542     GpPath *path;
1543     HDC hdc = GetDC( hwnd );
1544     HDC retdc;
1545     REAL r;
1546     CompositingQuality quality;
1547     CompositingMode compmode;
1548     InterpolationMode intmode;
1549     GpMatrix *m;
1550     GpRegion *region;
1551     GpUnit unit;
1552     PixelOffsetMode offsetmode;
1553     SmoothingMode smoothmode;
1554     TextRenderingHint texthint;
1555     GpPointF ptf[5];
1556     GpPoint  pt[5];
1557     GpRectF  rectf[2];
1558     GpRect   rect[2];
1559     GpRegion *clip;
1560     INT i;
1561     BOOL res;
1562     ARGB color = 0x00000000;
1563     HRGN hrgn = CreateRectRgn(0, 0, 10, 10);
1564 
1565     pt[0].X = 10;
1566     pt[0].Y = 10;
1567     pt[1].X = 20;
1568     pt[1].Y = 15;
1569     pt[2].X = 40;
1570     pt[2].Y = 80;
1571     pt[3].X = -20;
1572     pt[3].Y = 20;
1573     pt[4].X = 50;
1574     pt[4].Y = 110;
1575 
1576     for(i = 0; i < 5;i++){
1577         ptf[i].X = (REAL)pt[i].X;
1578         ptf[i].Y = (REAL)pt[i].Y;
1579     }
1580 
1581     rect[0].X = 0;
1582     rect[0].Y = 0;
1583     rect[0].Width  = 50;
1584     rect[0].Height = 70;
1585     rect[1].X = 0;
1586     rect[1].Y = 0;
1587     rect[1].Width  = 10;
1588     rect[1].Height = 20;
1589 
1590     for(i = 0; i < 2;i++){
1591         rectf[i].X = (REAL)rect[i].X;
1592         rectf[i].Y = (REAL)rect[i].Y;
1593         rectf[i].Height = (REAL)rect[i].Height;
1594         rectf[i].Width  = (REAL)rect[i].Width;
1595     }
1596 
1597     status = GdipCreateMatrix(&m);
1598     expect(Ok, status);
1599     GdipCreateRegion(&region);
1600     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
1601     GdipCreatePath(FillModeAlternate, &path);
1602     GdipCreateRegion(&clip);
1603 
1604     status = GdipCreateFromHDC(hdc, &graphics);
1605     expect(Ok, status);
1606     ok(graphics != NULL, "Expected graphics to be initialized\n");
1607     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1608     expect(Ok, status);
1609 
1610     /* NULL arguments */
1611     status = GdipGetDC(NULL, NULL);
1612     expect(InvalidParameter, status);
1613     status = GdipGetDC(graphics, NULL);
1614     expect(InvalidParameter, status);
1615     status = GdipGetDC(NULL, &retdc);
1616     expect(InvalidParameter, status);
1617 
1618     status = GdipReleaseDC(NULL, NULL);
1619     expect(InvalidParameter, status);
1620     status = GdipReleaseDC(graphics, NULL);
1621     expect(InvalidParameter, status);
1622     status = GdipReleaseDC(NULL, (HDC)0xdeadbeef);
1623     expect(InvalidParameter, status);
1624 
1625     /* Release without Get */
1626     status = GdipReleaseDC(graphics, hdc);
1627     expect(InvalidParameter, status);
1628 
1629     retdc = NULL;
1630     status = GdipGetDC(graphics, &retdc);
1631     expect(Ok, status);
1632     ok(retdc == hdc, "Invalid HDC returned\n");
1633     /* call it once more */
1634     status = GdipGetDC(graphics, &retdc);
1635     expect(ObjectBusy, status);
1636 
1637     /* try all Graphics calls here */
1638     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
1639     expect(ObjectBusy, status);
1640     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0.0, 0.0);
1641     expect(ObjectBusy, status);
1642     status = GdipDrawBezier(graphics, pen, 0.0, 10.0, 20.0, 15.0, 35.0, -10.0, 10.0, 10.0);
1643     expect(ObjectBusy, status);
1644     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
1645     expect(ObjectBusy, status);
1646     status = GdipDrawBeziers(graphics, pen, ptf, 5);
1647     expect(ObjectBusy, status);
1648     status = GdipDrawBeziersI(graphics, pen, pt, 5);
1649     expect(ObjectBusy, status);
1650     status = GdipDrawClosedCurve(graphics, pen, ptf, 5);
1651     expect(ObjectBusy, status);
1652     status = GdipDrawClosedCurveI(graphics, pen, pt, 5);
1653     expect(ObjectBusy, status);
1654     status = GdipDrawClosedCurve2(graphics, pen, ptf, 5, 1.0);
1655     expect(ObjectBusy, status);
1656     status = GdipDrawClosedCurve2I(graphics, pen, pt, 5, 1.0);
1657     expect(ObjectBusy, status);
1658     status = GdipDrawCurve(graphics, pen, ptf, 5);
1659     expect(ObjectBusy, status);
1660     status = GdipDrawCurveI(graphics, pen, pt, 5);
1661     expect(ObjectBusy, status);
1662     status = GdipDrawCurve2(graphics, pen, ptf, 5, 1.0);
1663     expect(ObjectBusy, status);
1664     status = GdipDrawCurve2I(graphics, pen, pt, 5, 1.0);
1665     expect(ObjectBusy, status);
1666     status = GdipDrawEllipse(graphics, pen, 0.0, 0.0, 100.0, 50.0);
1667     expect(ObjectBusy, status);
1668     status = GdipDrawEllipseI(graphics, pen, 0, 0, 100, 50);
1669     expect(ObjectBusy, status);
1670     /* GdipDrawImage/GdipDrawImageI */
1671     /* GdipDrawImagePointsRect/GdipDrawImagePointsRectI */
1672     /* GdipDrawImageRectRect/GdipDrawImageRectRectI */
1673     /* GdipDrawImageRect/GdipDrawImageRectI */
1674     status = GdipDrawLine(graphics, pen, 0.0, 0.0, 100.0, 200.0);
1675     expect(ObjectBusy, status);
1676     status = GdipDrawLineI(graphics, pen, 0, 0, 100, 200);
1677     expect(ObjectBusy, status);
1678     status = GdipDrawLines(graphics, pen, ptf, 5);
1679     expect(ObjectBusy, status);
1680     status = GdipDrawLinesI(graphics, pen, pt, 5);
1681     expect(ObjectBusy, status);
1682     status = GdipDrawPath(graphics, pen, path);
1683     expect(ObjectBusy, status);
1684     status = GdipDrawPie(graphics, pen, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
1685     expect(ObjectBusy, status);
1686     status = GdipDrawPieI(graphics, pen, 0, 0, 100, 100, 0.0, 90.0);
1687     expect(ObjectBusy, status);
1688     status = GdipDrawRectangle(graphics, pen, 0.0, 0.0, 100.0, 300.0);
1689     expect(ObjectBusy, status);
1690     status = GdipDrawRectangleI(graphics, pen, 0, 0, 100, 300);
1691     expect(ObjectBusy, status);
1692     status = GdipDrawRectangles(graphics, pen, rectf, 2);
1693     expect(ObjectBusy, status);
1694     status = GdipDrawRectanglesI(graphics, pen, rect, 2);
1695     expect(ObjectBusy, status);
1696     /* GdipDrawString */
1697     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, ptf, 5, 1.0, FillModeAlternate);
1698     expect(ObjectBusy, status);
1699     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, pt, 5, 1.0, FillModeAlternate);
1700     expect(ObjectBusy, status);
1701     status = GdipFillClosedCurve(graphics, (GpBrush*)brush, ptf, 5);
1702     expect(ObjectBusy, status);
1703     status = GdipFillClosedCurveI(graphics, (GpBrush*)brush, pt, 5);
1704     expect(ObjectBusy, status);
1705     status = GdipFillEllipse(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
1706     expect(ObjectBusy, status);
1707     status = GdipFillEllipseI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
1708     expect(ObjectBusy, status);
1709     status = GdipFillPath(graphics, (GpBrush*)brush, path);
1710     expect(ObjectBusy, status);
1711     status = GdipFillPie(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0, 0.0, 15.0);
1712     expect(ObjectBusy, status);
1713     status = GdipFillPieI(graphics, (GpBrush*)brush, 0, 0, 100, 100, 0.0, 15.0);
1714     expect(ObjectBusy, status);
1715     status = GdipFillPolygon(graphics, (GpBrush*)brush, ptf, 5, FillModeAlternate);
1716     expect(ObjectBusy, status);
1717     status = GdipFillPolygonI(graphics, (GpBrush*)brush, pt, 5, FillModeAlternate);
1718     expect(ObjectBusy, status);
1719     status = GdipFillPolygon2(graphics, (GpBrush*)brush, ptf, 5);
1720     expect(ObjectBusy, status);
1721     status = GdipFillPolygon2I(graphics, (GpBrush*)brush, pt, 5);
1722     expect(ObjectBusy, status);
1723     status = GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
1724     expect(ObjectBusy, status);
1725     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
1726     expect(ObjectBusy, status);
1727     status = GdipFillRectangles(graphics, (GpBrush*)brush, rectf, 2);
1728     expect(ObjectBusy, status);
1729     status = GdipFillRectanglesI(graphics, (GpBrush*)brush, rect, 2);
1730     expect(ObjectBusy, status);
1731     status = GdipFillRegion(graphics, (GpBrush*)brush, region);
1732     expect(ObjectBusy, status);
1733     status = GdipFlush(graphics, FlushIntentionFlush);
1734     expect(ObjectBusy, status);
1735     status = GdipGetClipBounds(graphics, rectf);
1736     expect(ObjectBusy, status);
1737     status = GdipGetClipBoundsI(graphics, rect);
1738     expect(ObjectBusy, status);
1739     status = GdipGetCompositingMode(graphics, &compmode);
1740     expect(ObjectBusy, status);
1741     status = GdipGetCompositingQuality(graphics, &quality);
1742     expect(ObjectBusy, status);
1743     status = GdipGetInterpolationMode(graphics, &intmode);
1744     expect(ObjectBusy, status);
1745     status = GdipGetNearestColor(graphics, &color);
1746     expect(ObjectBusy, status);
1747     status = GdipGetPageScale(graphics, &r);
1748     expect(ObjectBusy, status);
1749     status = GdipGetPageUnit(graphics, &unit);
1750     expect(ObjectBusy, status);
1751     status = GdipGetPixelOffsetMode(graphics, &offsetmode);
1752     expect(ObjectBusy, status);
1753     status = GdipGetSmoothingMode(graphics, &smoothmode);
1754     expect(ObjectBusy, status);
1755     status = GdipGetTextRenderingHint(graphics, &texthint);
1756     expect(ObjectBusy, status);
1757     status = GdipGetWorldTransform(graphics, m);
1758     expect(ObjectBusy, status);
1759     status = GdipGraphicsClear(graphics, 0xdeadbeef);
1760     expect(ObjectBusy, status);
1761     status = GdipIsVisiblePoint(graphics, 0.0, 0.0, &res);
1762     expect(ObjectBusy, status);
1763     status = GdipIsVisiblePointI(graphics, 0, 0, &res);
1764     expect(ObjectBusy, status);
1765     /* GdipMeasureCharacterRanges */
1766     /* GdipMeasureString */
1767     status = GdipResetClip(graphics);
1768     expect(ObjectBusy, status);
1769     status = GdipResetWorldTransform(graphics);
1770     expect(ObjectBusy, status);
1771     /* GdipRestoreGraphics */
1772     status = GdipRotateWorldTransform(graphics, 15.0, MatrixOrderPrepend);
1773     expect(ObjectBusy, status);
1774     /*  GdipSaveGraphics */
1775     status = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
1776     expect(ObjectBusy, status);
1777     status = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
1778     expect(ObjectBusy, status);
1779     status = GdipSetCompositingQuality(graphics, CompositingQualityDefault);
1780     expect(ObjectBusy, status);
1781     status = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
1782     expect(ObjectBusy, status);
1783     status = GdipSetPageScale(graphics, 1.0);
1784     expect(ObjectBusy, status);
1785     status = GdipSetPageUnit(graphics, UnitWorld);
1786     expect(ObjectBusy, status);
1787     status = GdipSetPixelOffsetMode(graphics, PixelOffsetModeDefault);
1788     expect(ObjectBusy, status);
1789     status = GdipSetSmoothingMode(graphics, SmoothingModeDefault);
1790     expect(ObjectBusy, status);
1791     status = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
1792     expect(ObjectBusy, status);
1793     status = GdipSetWorldTransform(graphics, m);
1794     expect(ObjectBusy, status);
1795     status = GdipTranslateWorldTransform(graphics, 0.0, 0.0, MatrixOrderPrepend);
1796     expect(ObjectBusy, status);
1797     status = GdipSetClipHrgn(graphics, hrgn, CombineModeReplace);
1798     expect(ObjectBusy, status);
1799     status = GdipSetClipPath(graphics, path, CombineModeReplace);
1800     expect(ObjectBusy, status);
1801     status = GdipSetClipRect(graphics, 0.0, 0.0, 10.0, 10.0, CombineModeReplace);
1802     expect(ObjectBusy, status);
1803     status = GdipSetClipRectI(graphics, 0, 0, 10, 10, CombineModeReplace);
1804     expect(ObjectBusy, status);
1805     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
1806     expect(ObjectBusy, status);
1807     status = GdipTranslateClip(graphics, 0.0, 0.0);
1808     expect(ObjectBusy, status);
1809     status = GdipTranslateClipI(graphics, 0, 0);
1810     expect(ObjectBusy, status);
1811     status = GdipDrawPolygon(graphics, pen, ptf, 5);
1812     expect(ObjectBusy, status);
1813     status = GdipDrawPolygonI(graphics, pen, pt, 5);
1814     expect(ObjectBusy, status);
1815     status = GdipGetDpiX(graphics, &r);
1816     expect(ObjectBusy, status);
1817     status = GdipGetDpiY(graphics, &r);
1818     expect(ObjectBusy, status);
1819     status = GdipMultiplyWorldTransform(graphics, m, MatrixOrderPrepend);
1820     expect(ObjectBusy, status);
1821     status = GdipGetClip(graphics, region);
1822     expect(ObjectBusy, status);
1823     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 5);
1824     expect(ObjectBusy, status);
1825 
1826     /* try to delete before release */
1827     status = GdipDeleteGraphics(graphics);
1828     expect(ObjectBusy, status);
1829 
1830     status = GdipReleaseDC(graphics, retdc);
1831     expect(Ok, status);
1832 
1833     GdipDeletePen(pen);
1834     GdipDeleteGraphics(graphics);
1835 
1836     GdipDeleteRegion(clip);
1837     GdipDeletePath(path);
1838     GdipDeleteBrush((GpBrush*)brush);
1839     GdipDeleteRegion(region);
1840     GdipDeleteMatrix(m);
1841     DeleteObject(hrgn);
1842 
1843     ReleaseDC(hwnd, hdc);
1844 }
1845 
1846 static void test_transformpoints(void)
1847 {
1848     GpStatus status;
1849     GpGraphics *graphics = NULL;
1850     HDC hdc = GetDC( hwnd );
1851     GpPointF ptf[2];
1852     GpPoint pt[2];
1853 
1854     status = GdipCreateFromHDC(hdc, &graphics);
1855     expect(Ok, status);
1856 
1857     /* NULL arguments */
1858     status = GdipTransformPoints(NULL, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
1859     expect(InvalidParameter, status);
1860     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
1861     expect(InvalidParameter, status);
1862     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 0);
1863     expect(InvalidParameter, status);
1864     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1);
1865     expect(InvalidParameter, status);
1866 
1867     status = GdipTransformPoints(graphics, CoordinateSpaceDevice+1, CoordinateSpaceWorld, ptf, 2);
1868     expect(InvalidParameter, status);
1869     status = GdipTransformPoints(graphics, -1, CoordinateSpaceWorld, ptf, 2);
1870     expect(InvalidParameter, status);
1871     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceDevice+1, ptf, 2);
1872     expect(InvalidParameter, status);
1873     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, -1, ptf, 2);
1874     expect(InvalidParameter, status);
1875 
1876     ptf[0].X = 1.0;
1877     ptf[0].Y = 0.0;
1878     ptf[1].X = 0.0;
1879     ptf[1].Y = 1.0;
1880     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2);
1881     expect(Ok, status);
1882     expectf(1.0, ptf[0].X);
1883     expectf(0.0, ptf[0].Y);
1884     expectf(0.0, ptf[1].X);
1885     expectf(1.0, ptf[1].Y);
1886 
1887     status = GdipTranslateWorldTransform(graphics, 5.0, 5.0, MatrixOrderAppend);
1888     expect(Ok, status);
1889     status = GdipSetPageUnit(graphics, UnitPixel);
1890     expect(Ok, status);
1891     status = GdipSetPageScale(graphics, 3.0);
1892     expect(Ok, status);
1893 
1894     ptf[0].X = 1.0;
1895     ptf[0].Y = 0.0;
1896     ptf[1].X = 0.0;
1897     ptf[1].Y = 1.0;
1898     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2);
1899     expect(Ok, status);
1900     expectf(18.0, ptf[0].X);
1901     expectf(15.0, ptf[0].Y);
1902     expectf(15.0, ptf[1].X);
1903     expectf(18.0, ptf[1].Y);
1904 
1905     ptf[0].X = 1.0;
1906     ptf[0].Y = 0.0;
1907     ptf[1].X = 0.0;
1908     ptf[1].Y = 1.0;
1909     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 2);
1910     expect(Ok, status);
1911     expectf(6.0, ptf[0].X);
1912     expectf(5.0, ptf[0].Y);
1913     expectf(5.0, ptf[1].X);
1914     expectf(6.0, ptf[1].Y);
1915 
1916     ptf[0].X = 1.0;
1917     ptf[0].Y = 0.0;
1918     ptf[1].X = 0.0;
1919     ptf[1].Y = 1.0;
1920     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpacePage, ptf, 2);
1921     expect(Ok, status);
1922     expectf(3.0, ptf[0].X);
1923     expectf(0.0, ptf[0].Y);
1924     expectf(0.0, ptf[1].X);
1925     expectf(3.0, ptf[1].Y);
1926 
1927     ptf[0].X = 18.0;
1928     ptf[0].Y = 15.0;
1929     ptf[1].X = 15.0;
1930     ptf[1].Y = 18.0;
1931     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
1932     expect(Ok, status);
1933     expectf(1.0, ptf[0].X);
1934     expectf(0.0, ptf[0].Y);
1935     expectf(0.0, ptf[1].X);
1936     expectf(1.0, ptf[1].Y);
1937 
1938     ptf[0].X = 6.0;
1939     ptf[0].Y = 5.0;
1940     ptf[1].X = 5.0;
1941     ptf[1].Y = 6.0;
1942     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpacePage, ptf, 2);
1943     expect(Ok, status);
1944     expectf(1.0, ptf[0].X);
1945     expectf(0.0, ptf[0].Y);
1946     expectf(0.0, ptf[1].X);
1947     expectf(1.0, ptf[1].Y);
1948 
1949     ptf[0].X = 3.0;
1950     ptf[0].Y = 0.0;
1951     ptf[1].X = 0.0;
1952     ptf[1].Y = 3.0;
1953     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceDevice, ptf, 2);
1954     expect(Ok, status);
1955     expectf(1.0, ptf[0].X);
1956     expectf(0.0, ptf[0].Y);
1957     expectf(0.0, ptf[1].X);
1958     expectf(1.0, ptf[1].Y);
1959 
1960     pt[0].X = 1;
1961     pt[0].Y = 0;
1962     pt[1].X = 0;
1963     pt[1].Y = 1;
1964     status = GdipTransformPointsI(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 2);
1965     expect(Ok, status);
1966     expect(18, pt[0].X);
1967     expect(15, pt[0].Y);
1968     expect(15, pt[1].X);
1969     expect(18, pt[1].Y);
1970 
1971     GdipDeleteGraphics(graphics);
1972     ReleaseDC(hwnd, hdc);
1973 }
1974 
1975 static void test_get_set_clip(void)
1976 {
1977     GpStatus status;
1978     GpGraphics *graphics = NULL;
1979     HDC hdc = GetDC( hwnd );
1980     GpRegion *clip;
1981     GpRectF rect;
1982     BOOL res;
1983 
1984     status = GdipCreateFromHDC(hdc, &graphics);
1985     expect(Ok, status);
1986 
1987     rect.X = rect.Y = 0.0;
1988     rect.Height = rect.Width = 100.0;
1989 
1990     status = GdipCreateRegionRect(&rect, &clip);
1991     expect(Ok, status);
1992 
1993     /* NULL arguments */
1994     status = GdipGetClip(NULL, NULL);
1995     expect(InvalidParameter, status);
1996     status = GdipGetClip(graphics, NULL);
1997     expect(InvalidParameter, status);
1998     status = GdipGetClip(NULL, clip);
1999     expect(InvalidParameter, status);
2000 
2001     status = GdipSetClipRegion(NULL, NULL, CombineModeReplace);
2002     expect(InvalidParameter, status);
2003     status = GdipSetClipRegion(graphics, NULL, CombineModeReplace);
2004     expect(InvalidParameter, status);
2005 
2006     status = GdipSetClipPath(NULL, NULL, CombineModeReplace);
2007     expect(InvalidParameter, status);
2008     status = GdipSetClipPath(graphics, NULL, CombineModeReplace);
2009     expect(InvalidParameter, status);
2010 
2011     res = FALSE;
2012     status = GdipGetClip(graphics, clip);
2013     expect(Ok, status);
2014     status = GdipIsInfiniteRegion(clip, graphics, &res);
2015     expect(Ok, status);
2016     expect(TRUE, res);
2017 
2018     /* remains infinite after reset */
2019     res = FALSE;
2020     status = GdipResetClip(graphics);
2021     expect(Ok, status);
2022     status = GdipGetClip(graphics, clip);
2023     expect(Ok, status);
2024     status = GdipIsInfiniteRegion(clip, graphics, &res);
2025     expect(Ok, status);
2026     expect(TRUE, res);
2027 
2028     /* set to empty and then reset to infinite */
2029     status = GdipSetEmpty(clip);
2030     expect(Ok, status);
2031     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
2032     expect(Ok, status);
2033 
2034     status = GdipGetClip(graphics, clip);
2035     expect(Ok, status);
2036     res = FALSE;
2037     status = GdipIsEmptyRegion(clip, graphics, &res);
2038     expect(Ok, status);
2039     expect(TRUE, res);
2040     status = GdipResetClip(graphics);
2041     expect(Ok, status);
2042     status = GdipGetClip(graphics, clip);
2043     expect(Ok, status);
2044     res = FALSE;
2045     status = GdipIsInfiniteRegion(clip, graphics, &res);
2046     expect(Ok, status);
2047     expect(TRUE, res);
2048 
2049     GdipDeleteRegion(clip);
2050 
2051     GdipDeleteGraphics(graphics);
2052     ReleaseDC(hwnd, hdc);
2053 }
2054 
2055 static void test_isempty(void)
2056 {
2057     GpStatus status;
2058     GpGraphics *graphics = NULL;
2059     HDC hdc = GetDC( hwnd );
2060     GpRegion *clip;
2061     BOOL res;
2062 
2063     status = GdipCreateFromHDC(hdc, &graphics);
2064     expect(Ok, status);
2065 
2066     status = GdipCreateRegion(&clip);
2067     expect(Ok, status);
2068 
2069     /* NULL */
2070     status = GdipIsClipEmpty(NULL, NULL);
2071     expect(InvalidParameter, status);
2072     status = GdipIsClipEmpty(graphics, NULL);
2073     expect(InvalidParameter, status);
2074     status = GdipIsClipEmpty(NULL, &res);
2075     expect(InvalidParameter, status);
2076 
2077     /* default is infinite */
2078     res = TRUE;
2079     status = GdipIsClipEmpty(graphics, &res);
2080     expect(Ok, status);
2081     expect(FALSE, res);
2082 
2083     GdipDeleteRegion(clip);
2084 
2085     GdipDeleteGraphics(graphics);
2086     ReleaseDC(hwnd, hdc);
2087 }
2088 
2089 static void test_clear(void)
2090 {
2091     GpStatus status;
2092 
2093     status = GdipGraphicsClear(NULL, 0xdeadbeef);
2094     expect(InvalidParameter, status);
2095 }
2096 
2097 static void test_textcontrast(void)
2098 {
2099     GpStatus status;
2100     HDC hdc = GetDC( hwnd );
2101     GpGraphics *graphics;
2102     UINT contrast;
2103 
2104     status = GdipGetTextContrast(NULL, NULL);
2105     expect(InvalidParameter, status);
2106 
2107     status = GdipCreateFromHDC(hdc, &graphics);
2108     expect(Ok, status);
2109 
2110     status = GdipGetTextContrast(graphics, NULL);
2111     expect(InvalidParameter, status);
2112     status = GdipGetTextContrast(graphics, &contrast);
2113     expect(Ok, status);
2114     expect(4, contrast);
2115 
2116     GdipDeleteGraphics(graphics);
2117     ReleaseDC(hwnd, hdc);
2118 }
2119 
2120 static void test_GdipDrawString(void)
2121 {
2122     GpStatus status;
2123     GpGraphics *graphics = NULL;
2124     GpFont *fnt = NULL;
2125     RectF  rect;
2126     GpStringFormat *format;
2127     GpBrush *brush;
2128     LOGFONTA logfont;
2129     HDC hdc = GetDC( hwnd );
2130     static const WCHAR string[] = {'T','e','s','t',0};
2131     static const PointF positions[4] = {{0,0}, {1,1}, {2,2}, {3,3}};
2132     GpMatrix *matrix;
2133 
2134     memset(&logfont,0,sizeof(logfont));
2135     strcpy(logfont.lfFaceName,"Arial");
2136     logfont.lfHeight = 12;
2137     logfont.lfCharSet = DEFAULT_CHARSET;
2138 
2139     status = GdipCreateFromHDC(hdc, &graphics);
2140     expect(Ok, status);
2141 
2142     status = GdipCreateFontFromLogfontA(hdc, &logfont, &fnt);
2143     if (status == NotTrueTypeFont || status == FileNotFound)
2144     {
2145         skip("Arial not installed.\n");
2146         return;
2147     }
2148     expect(Ok, status);
2149 
2150     status = GdipCreateSolidFill((ARGB)0xdeadbeef, (GpSolidFill**)&brush);
2151     expect(Ok, status);
2152 
2153     status = GdipCreateStringFormat(0,0,&format);
2154     expect(Ok, status);
2155 
2156     rect.X = 0;
2157     rect.Y = 0;
2158     rect.Width = 0;
2159     rect.Height = 12;
2160 
2161     status = GdipDrawString(graphics, string, 4, fnt, &rect, format, brush);
2162     expect(Ok, status);
2163 
2164     status = GdipCreateMatrix(&matrix);
2165     expect(Ok, status);
2166 
2167     status = GdipDrawDriverString(NULL, string, 4, fnt, brush, positions, DriverStringOptionsCmapLookup, matrix);
2168     expect(InvalidParameter, status);
2169 
2170     status = GdipDrawDriverString(graphics, NULL, 4, fnt, brush, positions, DriverStringOptionsCmapLookup, matrix);
2171     expect(InvalidParameter, status);
2172 
2173     status = GdipDrawDriverString(graphics, string, 4, NULL, brush, positions, DriverStringOptionsCmapLookup, matrix);
2174     expect(InvalidParameter, status);
2175 
2176     status = GdipDrawDriverString(graphics, string, 4, fnt, NULL, positions, DriverStringOptionsCmapLookup, matrix);
2177     expect(InvalidParameter, status);
2178 
2179     status = GdipDrawDriverString(graphics, string, 4, fnt, brush, NULL, DriverStringOptionsCmapLookup, matrix);
2180     expect(InvalidParameter, status);
2181 
2182     status = GdipDrawDriverString(graphics, string, 4, fnt, brush, positions, DriverStringOptionsCmapLookup|0x10, matrix);
2183     expect(Ok, status);
2184 
2185     status = GdipDrawDriverString(graphics, string, 4, fnt, brush, positions, DriverStringOptionsCmapLookup, NULL);
2186     expect(Ok, status);
2187 
2188     status = GdipDrawDriverString(graphics, string, 4, fnt, brush, positions, DriverStringOptionsCmapLookup, matrix);
2189     expect(Ok, status);
2190 
2191     GdipDeleteMatrix(matrix);
2192     GdipDeleteGraphics(graphics);
2193     GdipDeleteBrush(brush);
2194     GdipDeleteFont(fnt);
2195     GdipDeleteStringFormat(format);
2196 
2197     ReleaseDC(hwnd, hdc);
2198 }
2199 
2200 static void test_GdipGetVisibleClipBounds_screen(void)
2201 {
2202     GpStatus status;
2203     GpGraphics *graphics = NULL;
2204     HDC hdc = GetDC(0);
2205     GpRectF rectf, exp, clipr;
2206     GpRect recti;
2207 
2208     ok(hdc != NULL, "Expected HDC to be initialized\n");
2209 
2210     status = GdipCreateFromHDC(hdc, &graphics);
2211     expect(Ok, status);
2212     ok(graphics != NULL, "Expected graphics to be initialized\n");
2213 
2214     /* no clipping rect */
2215     exp.X = 0;
2216     exp.Y = 0;
2217     exp.Width = GetDeviceCaps(hdc, HORZRES);
2218     exp.Height = GetDeviceCaps(hdc, VERTRES);
2219 
2220     status = GdipGetVisibleClipBounds(graphics, &rectf);
2221     expect(Ok, status);
2222     ok(rectf.X == exp.X &&
2223         rectf.Y == exp.Y &&
2224         rectf.Width == exp.Width &&
2225         rectf.Height == exp.Height,
2226         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2227         "the screen (%0.f, %0.f, %0.f, %0.f)\n",
2228         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2229         exp.X, exp.Y, exp.Width, exp.Height);
2230 
2231     /* clipping rect entirely within window */
2232     exp.X = clipr.X = 10;
2233     exp.Y = clipr.Y = 12;
2234     exp.Width = clipr.Width = 14;
2235     exp.Height = clipr.Height = 16;
2236 
2237     status = GdipSetClipRect(graphics, clipr.X, clipr.Y, clipr.Width, clipr.Height, CombineModeReplace);
2238     expect(Ok, status);
2239 
2240     status = GdipGetVisibleClipBounds(graphics, &rectf);
2241     expect(Ok, status);
2242     ok(rectf.X == exp.X &&
2243         rectf.Y == exp.Y &&
2244         rectf.Width == exp.Width &&
2245         rectf.Height == exp.Height,
2246         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2247         "the clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2248         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2249         exp.X, exp.Y, exp.Width, exp.Height);
2250 
2251     /* clipping rect partially outside of screen */
2252     clipr.X = -10;
2253     clipr.Y = -12;
2254     clipr.Width = 20;
2255     clipr.Height = 24;
2256 
2257     status = GdipSetClipRect(graphics, clipr.X, clipr.Y, clipr.Width, clipr.Height, CombineModeReplace);
2258     expect(Ok, status);
2259 
2260     exp.X = 0;
2261     exp.Y = 0;
2262     exp.Width = 10;
2263     exp.Height = 12;
2264 
2265     status = GdipGetVisibleClipBounds(graphics, &rectf);
2266     expect(Ok, status);
2267     ok(rectf.X == exp.X &&
2268         rectf.Y == exp.Y &&
2269         rectf.Width == exp.Width &&
2270         rectf.Height == exp.Height,
2271         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2272         "the visible clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2273         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2274         exp.X, exp.Y, exp.Width, exp.Height);
2275 
2276     status = GdipGetVisibleClipBoundsI(graphics, &recti);
2277     expect(Ok, status);
2278     ok(recti.X == exp.X &&
2279         recti.Y == exp.Y &&
2280         recti.Width == exp.Width &&
2281         recti.Height == exp.Height,
2282         "Expected clip bounds (%d, %d, %d, %d) to be the size of "
2283         "the visible clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2284         recti.X, recti.Y, recti.Width, recti.Height,
2285         exp.X, exp.Y, exp.Width, exp.Height);
2286 
2287     GdipDeleteGraphics(graphics);
2288     ReleaseDC(0, hdc);
2289 }
2290 
2291 static void test_GdipGetVisibleClipBounds_window(void)
2292 {
2293     GpStatus status;
2294     GpGraphics *graphics = NULL;
2295     GpRectF rectf, window, exp, clipr;
2296     GpRect recti;
2297     HDC hdc;
2298     PAINTSTRUCT ps;
2299     RECT wnd_rect;
2300 
2301     /* get client area size */
2302     ok(GetClientRect(hwnd, &wnd_rect), "GetClientRect should have succeeded\n");
2303     window.X = wnd_rect.left;
2304     window.Y = wnd_rect.top;
2305     window.Width = wnd_rect.right - wnd_rect.left;
2306     window.Height = wnd_rect.bottom - wnd_rect.top;
2307 
2308     hdc = BeginPaint(hwnd, &ps);
2309 
2310     status = GdipCreateFromHDC(hdc, &graphics);
2311     expect(Ok, status);
2312     ok(graphics != NULL, "Expected graphics to be initialized\n");
2313 
2314     status = GdipGetVisibleClipBounds(graphics, &rectf);
2315     expect(Ok, status);
2316     ok(rectf.X == window.X &&
2317         rectf.Y == window.Y &&
2318         rectf.Width == window.Width &&
2319         rectf.Height == window.Height,
2320         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2321         "the window (%0.f, %0.f, %0.f, %0.f)\n",
2322         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2323         window.X, window.Y, window.Width, window.Height);
2324 
2325     /* clipping rect entirely within window */
2326     exp.X = clipr.X = 20;
2327     exp.Y = clipr.Y = 8;
2328     exp.Width = clipr.Width = 30;
2329     exp.Height = clipr.Height = 20;
2330 
2331     status = GdipSetClipRect(graphics, clipr.X, clipr.Y, clipr.Width, clipr.Height, CombineModeReplace);
2332     expect(Ok, status);
2333 
2334     status = GdipGetVisibleClipBounds(graphics, &rectf);
2335     expect(Ok, status);
2336     ok(rectf.X == exp.X &&
2337         rectf.Y == exp.Y &&
2338         rectf.Width == exp.Width &&
2339         rectf.Height == exp.Height,
2340         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2341         "the clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2342         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2343         exp.X, exp.Y, exp.Width, exp.Height);
2344 
2345     /* clipping rect partially outside of window */
2346     clipr.X = window.Width - 10;
2347     clipr.Y = window.Height - 15;
2348     clipr.Width = 20;
2349     clipr.Height = 30;
2350 
2351     status = GdipSetClipRect(graphics, clipr.X, clipr.Y, clipr.Width, clipr.Height, CombineModeReplace);
2352     expect(Ok, status);
2353 
2354     exp.X = window.Width - 10;
2355     exp.Y = window.Height - 15;
2356     exp.Width = 10;
2357     exp.Height = 15;
2358 
2359     status = GdipGetVisibleClipBounds(graphics, &rectf);
2360     expect(Ok, status);
2361     ok(rectf.X == exp.X &&
2362         rectf.Y == exp.Y &&
2363         rectf.Width == exp.Width &&
2364         rectf.Height == exp.Height,
2365         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be the size of "
2366         "the visible clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2367         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2368         exp.X, exp.Y, exp.Width, exp.Height);
2369 
2370     status = GdipGetVisibleClipBoundsI(graphics, &recti);
2371     expect(Ok, status);
2372     ok(recti.X == exp.X &&
2373         recti.Y == exp.Y &&
2374         recti.Width == exp.Width &&
2375         recti.Height == exp.Height,
2376         "Expected clip bounds (%d, %d, %d, %d) to be the size of "
2377         "the visible clipping rect (%0.f, %0.f, %0.f, %0.f)\n",
2378         recti.X, recti.Y, recti.Width, recti.Height,
2379         exp.X, exp.Y, exp.Width, exp.Height);
2380 
2381     /* window bounds with transform applied */
2382     status = GdipResetClip(graphics);
2383     expect(Ok, status);
2384 
2385     status = GdipScaleWorldTransform(graphics, 0.5, 0.5, MatrixOrderPrepend);
2386     expect(Ok, status);
2387 
2388     exp.X = window.X * 2.0;
2389     exp.Y = window.Y * 2.0;
2390     exp.Width = window.Width * 2.0;
2391     exp.Height = window.Height * 2.0;
2392 
2393     status = GdipGetVisibleClipBounds(graphics, &rectf);
2394     expect(Ok, status);
2395     ok(rectf.X == exp.X &&
2396         rectf.Y == exp.Y &&
2397         rectf.Width == exp.Width &&
2398         rectf.Height == exp.Height,
2399         "Expected clip bounds (%0.f, %0.f, %0.f, %0.f) to be "
2400         "twice the window size (%0.f, %0.f, %0.f, %0.f)\n",
2401         rectf.X, rectf.Y, rectf.Width, rectf.Height,
2402         exp.X, exp.Y, exp.Width, exp.Height);
2403 
2404     GdipDeleteGraphics(graphics);
2405     EndPaint(hwnd, &ps);
2406 }
2407 
2408 static void test_GdipGetVisibleClipBounds(void)
2409 {
2410     GpGraphics* graphics = NULL;
2411     GpRectF rectf;
2412     GpRect rect;
2413     HDC hdc = GetDC( hwnd );
2414     GpStatus status;
2415 
2416     status = GdipCreateFromHDC(hdc, &graphics);
2417     expect(Ok, status);
2418     ok(graphics != NULL, "Expected graphics to be initialized\n");
2419 
2420     /* test null parameters */
2421     status = GdipGetVisibleClipBounds(graphics, NULL);
2422     expect(InvalidParameter, status);
2423 
2424     status = GdipGetVisibleClipBounds(NULL, &rectf);
2425     expect(InvalidParameter, status);
2426 
2427     status = GdipGetVisibleClipBoundsI(graphics, NULL);
2428     expect(InvalidParameter, status);
2429 
2430     status = GdipGetVisibleClipBoundsI(NULL, &rect);
2431     expect(InvalidParameter, status);
2432 
2433     GdipDeleteGraphics(graphics);
2434     ReleaseDC(hwnd, hdc);
2435 
2436     test_GdipGetVisibleClipBounds_screen();
2437     test_GdipGetVisibleClipBounds_window();
2438 }
2439 
2440 static void test_fromMemoryBitmap(void)
2441 {
2442     GpStatus status;
2443     GpGraphics *graphics = NULL;
2444     GpBitmap *bitmap = NULL;
2445     BYTE bits[48] = {0};
2446     HDC hdc=NULL;
2447     COLORREF color;
2448 
2449     status = GdipCreateBitmapFromScan0(4, 4, 12, PixelFormat24bppRGB, bits, &bitmap);
2450     expect(Ok, status);
2451 
2452     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2453     expect(Ok, status);
2454 
2455     status = GdipGraphicsClear(graphics, 0xff686868);
2456     expect(Ok, status);
2457 
2458     GdipDeleteGraphics(graphics);
2459 
2460     /* drawing writes to the memory provided */
2461     expect(0x68, bits[10]);
2462 
2463     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2464     expect(Ok, status);
2465 
2466     status = GdipGetDC(graphics, &hdc);
2467     expect(Ok, status);
2468     ok(hdc != NULL, "got NULL hdc\n");
2469 
2470     color = GetPixel(hdc, 0, 0);
2471     /* The HDC is write-only, and native fills with a solid color to figure out
2472      * which pixels have changed. */
2473     todo_wine expect(0x0c0b0d, color);
2474 
2475     SetPixel(hdc, 0, 0, 0x797979);
2476     SetPixel(hdc, 1, 0, 0x0c0b0d);
2477 
2478     status = GdipReleaseDC(graphics, hdc);
2479     expect(Ok, status);
2480 
2481     GdipDeleteGraphics(graphics);
2482 
2483     expect(0x79, bits[0]);
2484     todo_wine expect(0x68, bits[3]);
2485 
2486     GdipDisposeImage((GpImage*)bitmap);
2487 
2488     /* We get the same kind of write-only HDC for a "normal" bitmap */
2489     status = GdipCreateBitmapFromScan0(4, 4, 12, PixelFormat24bppRGB, NULL, &bitmap);
2490     expect(Ok, status);
2491 
2492     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2493     expect(Ok, status);
2494 
2495     status = GdipGetDC(graphics, &hdc);
2496     expect(Ok, status);
2497     ok(hdc != NULL, "got NULL hdc\n");
2498 
2499     color = GetPixel(hdc, 0, 0);
2500     todo_wine expect(0x0c0b0d, color);
2501 
2502     status = GdipReleaseDC(graphics, hdc);
2503     expect(Ok, status);
2504 
2505     GdipDeleteGraphics(graphics);
2506 
2507     GdipDisposeImage((GpImage*)bitmap);
2508 
2509     /* If we don't draw to the HDC, the bits are never accessed */
2510     status = GdipCreateBitmapFromScan0(4, 4, 12, PixelFormat24bppRGB, (BYTE*)1, &bitmap);
2511     expect(Ok, status);
2512 
2513     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2514     expect(Ok, status);
2515 
2516     status = GdipGetDC(graphics, &hdc);
2517     expect(Ok, status);
2518     ok(hdc != NULL, "got NULL hdc\n");
2519 
2520     color = GetPixel(hdc, 0, 0);
2521     todo_wine expect(0x0c0b0d, color);
2522 
2523     status = GdipReleaseDC(graphics, hdc);
2524     expect(Ok, status);
2525 
2526     GdipDeleteGraphics(graphics);
2527 
2528     GdipDisposeImage((GpImage*)bitmap);
2529 }
2530 
2531 static void test_GdipIsVisiblePoint(void)
2532 {
2533     GpStatus status;
2534     GpGraphics *graphics = NULL;
2535     HDC hdc = GetDC( hwnd );
2536     REAL x, y;
2537     BOOL val;
2538 
2539     ok(hdc != NULL, "Expected HDC to be initialized\n");
2540 
2541     status = GdipCreateFromHDC(hdc, &graphics);
2542     expect(Ok, status);
2543     ok(graphics != NULL, "Expected graphics to be initialized\n");
2544 
2545     /* null parameters */
2546     status = GdipIsVisiblePoint(NULL, 0, 0, &val);
2547     expect(InvalidParameter, status);
2548 
2549     status = GdipIsVisiblePoint(graphics, 0, 0, NULL);
2550     expect(InvalidParameter, status);
2551 
2552     status = GdipIsVisiblePointI(NULL, 0, 0, &val);
2553     expect(InvalidParameter, status);
2554 
2555     status = GdipIsVisiblePointI(graphics, 0, 0, NULL);
2556     expect(InvalidParameter, status);
2557 
2558     x = 0;
2559     y = 0;
2560     status = GdipIsVisiblePoint(graphics, x, y, &val);
2561     expect(Ok, status);
2562     ok(val == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
2563 
2564     x = -10;
2565     y = 0;
2566     status = GdipIsVisiblePoint(graphics, x, y, &val);
2567     expect(Ok, status);
2568     ok(val == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
2569 
2570     x = 0;
2571     y = -5;
2572     status = GdipIsVisiblePoint(graphics, x, y, &val);
2573     expect(Ok, status);
2574     ok(val == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
2575 
2576     x = 1;
2577     y = 1;
2578     status = GdipIsVisiblePoint(graphics, x, y, &val);
2579     expect(Ok, status);
2580     ok(val == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
2581 
2582     status = GdipSetClipRect(graphics, 10, 20, 30, 40, CombineModeReplace);
2583     expect(Ok, status);
2584 
2585     x = 1;
2586     y = 1;
2587     status = GdipIsVisiblePoint(graphics, x, y, &val);
2588     expect(Ok, status);
2589     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2590 
2591     x = 15.5;
2592     y = 40.5;
2593     status = GdipIsVisiblePoint(graphics, x, y, &val);
2594     expect(Ok, status);
2595     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2596 
2597     /* translate into the center of the rect */
2598     GdipTranslateWorldTransform(graphics, 25, 40, MatrixOrderAppend);
2599 
2600     x = 0;
2601     y = 0;
2602     status = GdipIsVisiblePoint(graphics, x, y, &val);
2603     expect(Ok, status);
2604     ok(val == TRUE, "Expected (%.2f, %.2f) to be visible\n", x, y);
2605 
2606     x = 25;
2607     y = 40;
2608     status = GdipIsVisiblePoint(graphics, x, y, &val);
2609     expect(Ok, status);
2610     ok(val == FALSE, "Expected (%.2f, %.2f) not to be visible\n", x, y);
2611 
2612     GdipTranslateWorldTransform(graphics, -25, -40, MatrixOrderAppend);
2613 
2614     /* corner cases */
2615     x = 9;
2616     y = 19;
2617     status = GdipIsVisiblePoint(graphics, x, y, &val);
2618     expect(Ok, status);
2619     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2620 
2621     x = 9.25;
2622     y = 19.25;
2623     status = GdipIsVisiblePoint(graphics, x, y, &val);
2624     expect(Ok, status);
2625     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2626 
2627     x = 9.5;
2628     y = 19.5;
2629     status = GdipIsVisiblePoint(graphics, x, y, &val);
2630     expect(Ok, status);
2631     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2632 
2633     x = 9.75;
2634     y = 19.75;
2635     status = GdipIsVisiblePoint(graphics, x, y, &val);
2636     expect(Ok, status);
2637     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2638 
2639     x = 10;
2640     y = 20;
2641     status = GdipIsVisiblePoint(graphics, x, y, &val);
2642     expect(Ok, status);
2643     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2644 
2645     x = 40;
2646     y = 20;
2647     status = GdipIsVisiblePoint(graphics, x, y, &val);
2648     expect(Ok, status);
2649     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2650 
2651     x = 39;
2652     y = 59;
2653     status = GdipIsVisiblePoint(graphics, x, y, &val);
2654     expect(Ok, status);
2655     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2656 
2657     x = 39.25;
2658     y = 59.25;
2659     status = GdipIsVisiblePoint(graphics, x, y, &val);
2660     expect(Ok, status);
2661     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2662 
2663     x = 39.5;
2664     y = 39.5;
2665     status = GdipIsVisiblePoint(graphics, x, y, &val);
2666     expect(Ok, status);
2667     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2668 
2669     x = 39.75;
2670     y = 59.75;
2671     status = GdipIsVisiblePoint(graphics, x, y, &val);
2672     expect(Ok, status);
2673     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2674 
2675     x = 40;
2676     y = 60;
2677     status = GdipIsVisiblePoint(graphics, x, y, &val);
2678     expect(Ok, status);
2679     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2680 
2681     x = 40.15;
2682     y = 60.15;
2683     status = GdipIsVisiblePoint(graphics, x, y, &val);
2684     expect(Ok, status);
2685     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2686 
2687     x = 10;
2688     y = 60;
2689     status = GdipIsVisiblePoint(graphics, x, y, &val);
2690     expect(Ok, status);
2691     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2692 
2693     /* integer version */
2694     x = 25;
2695     y = 30;
2696     status = GdipIsVisiblePointI(graphics, (INT)x, (INT)y, &val);
2697     expect(Ok, status);
2698     ok(val == TRUE, "After clipping, expected (%.2f, %.2f) to be visible\n", x, y);
2699 
2700     x = 50;
2701     y = 100;
2702     status = GdipIsVisiblePointI(graphics, (INT)x, (INT)y, &val);
2703     expect(Ok, status);
2704     ok(val == FALSE, "After clipping, expected (%.2f, %.2f) not to be visible\n", x, y);
2705 
2706     GdipDeleteGraphics(graphics);
2707     ReleaseDC(hwnd, hdc);
2708 }
2709 
2710 static void test_GdipIsVisibleRect(void)
2711 {
2712     GpStatus status;
2713     GpGraphics *graphics = NULL;
2714     HDC hdc = GetDC( hwnd );
2715     REAL x, y, width, height;
2716     BOOL val;
2717 
2718     ok(hdc != NULL, "Expected HDC to be initialized\n");
2719 
2720     status = GdipCreateFromHDC(hdc, &graphics);
2721     expect(Ok, status);
2722     ok(graphics != NULL, "Expected graphics to be initialized\n");
2723 
2724     status = GdipIsVisibleRect(NULL, 0, 0, 0, 0, &val);
2725     expect(InvalidParameter, status);
2726 
2727     status = GdipIsVisibleRect(graphics, 0, 0, 0, 0, NULL);
2728     expect(InvalidParameter, status);
2729 
2730     status = GdipIsVisibleRectI(NULL, 0, 0, 0, 0, &val);
2731     expect(InvalidParameter, status);
2732 
2733     status = GdipIsVisibleRectI(graphics, 0, 0, 0, 0, NULL);
2734     expect(InvalidParameter, status);
2735 
2736     /* entirely within the visible region */
2737     x = 0; width = 10;
2738     y = 0; height = 10;
2739     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2740     expect(Ok, status);
2741     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2742 
2743     /* partially outside */
2744     x = -10; width = 20;
2745     y = -10; height = 20;
2746     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2747     expect(Ok, status);
2748     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2749 
2750     /* entirely outside */
2751     x = -10; width = 5;
2752     y = -10; height = 5;
2753     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2754     expect(Ok, status);
2755     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2756 
2757     status = GdipSetClipRect(graphics, 10, 20, 30, 40, CombineModeReplace);
2758     expect(Ok, status);
2759 
2760     /* entirely within the visible region */
2761     x = 12; width = 10;
2762     y = 22; height = 10;
2763     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2764     expect(Ok, status);
2765     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2766 
2767     /* partially outside */
2768     x = 35; width = 10;
2769     y = 55; height = 10;
2770     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2771     expect(Ok, status);
2772     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2773 
2774     /* entirely outside */
2775     x = 45; width = 5;
2776     y = 65; height = 5;
2777     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2778     expect(Ok, status);
2779     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2780 
2781     /* translate into center of clipping rect */
2782     GdipTranslateWorldTransform(graphics, 25, 40, MatrixOrderAppend);
2783 
2784     x = 0; width = 10;
2785     y = 0; height = 10;
2786     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2787     expect(Ok, status);
2788     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2789 
2790     x = 25; width = 5;
2791     y = 40; height = 5;
2792     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2793     expect(Ok, status);
2794     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2795 
2796     GdipTranslateWorldTransform(graphics, -25, -40, MatrixOrderAppend);
2797 
2798     /* corners entirely outside, but some intersections */
2799     x = 0; width = 70;
2800     y = 0; height = 90;
2801     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2802     expect(Ok, status);
2803     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2804 
2805     x = 0; width = 70;
2806     y = 0; height = 30;
2807     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2808     expect(Ok, status);
2809     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2810 
2811     x = 0; width = 30;
2812     y = 0; height = 90;
2813     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2814     expect(Ok, status);
2815     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2816 
2817     /* edge cases */
2818     x = 0; width = 10;
2819     y = 20; height = 40;
2820     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2821     expect(Ok, status);
2822     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2823 
2824     x = 10; width = 30;
2825     y = 0; height = 20;
2826     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2827     expect(Ok, status);
2828     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2829 
2830     x = 40; width = 10;
2831     y = 20; height = 40;
2832     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2833     expect(Ok, status);
2834     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2835 
2836     x = 10; width = 30;
2837     y = 60; height = 10;
2838     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2839     expect(Ok, status);
2840     ok(val == FALSE, "Expected (%.2f, %.2f, %.2f, %.2f) not to be visible\n", x, y, width, height);
2841 
2842     /* rounding tests */
2843     x = 0.4; width = 10.4;
2844     y = 20; height = 40;
2845     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2846     expect(Ok, status);
2847     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2848 
2849     x = 10; width = 30;
2850     y = 0.4; height = 20.4;
2851     status = GdipIsVisibleRect(graphics, x, y, width, height, &val);
2852     expect(Ok, status);
2853     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2854 
2855     /* integer version */
2856     x = 0; width = 30;
2857     y = 0; height = 90;
2858     status = GdipIsVisibleRectI(graphics, (INT)x, (INT)y, (INT)width, (INT)height, &val);
2859     expect(Ok, status);
2860     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2861 
2862     x = 12; width = 10;
2863     y = 22; height = 10;
2864     status = GdipIsVisibleRectI(graphics, (INT)x, (INT)y, (INT)width, (INT)height, &val);
2865     expect(Ok, status);
2866     ok(val == TRUE, "Expected (%.2f, %.2f, %.2f, %.2f) to be visible\n", x, y, width, height);
2867 
2868     GdipDeleteGraphics(graphics);
2869     ReleaseDC(hwnd, hdc);
2870 }
2871 
2872 static void test_GdipGetNearestColor(void)
2873 {
2874     GpStatus status;
2875     GpGraphics *graphics;
2876     GpBitmap *bitmap;
2877     ARGB color = 0xdeadbeef;
2878     HDC hdc = GetDC( hwnd );
2879 
2880     /* create a graphics object */
2881     ok(hdc != NULL, "Expected HDC to be initialized\n");
2882 
2883     status = GdipCreateFromHDC(hdc, &graphics);
2884     expect(Ok, status);
2885     ok(graphics != NULL, "Expected graphics to be initialized\n");
2886 
2887     status = GdipGetNearestColor(graphics, NULL);
2888     expect(InvalidParameter, status);
2889 
2890     status = GdipGetNearestColor(NULL, &color);
2891     expect(InvalidParameter, status);
2892     GdipDeleteGraphics(graphics);
2893 
2894     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, &bitmap);
2895     expect(Ok, status);
2896     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2897     ok(broken(status == OutOfMemory) /* winver < Win7 */ || status == Ok, "status=%u\n", status);
2898     if (status == Ok)
2899     {
2900         status = GdipGetNearestColor(graphics, &color);
2901         expect(Ok, status);
2902         expect(0xdeadbeef, color);
2903         GdipDeleteGraphics(graphics);
2904     }
2905     GdipDisposeImage((GpImage*)bitmap);
2906 
2907     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, &bitmap);
2908     expect(Ok, status);
2909     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2910     ok(broken(status == OutOfMemory) /* winver < Win7 */ || status == Ok, "status=%u\n", status);
2911     if (status == Ok)
2912     {
2913         status = GdipGetNearestColor(graphics, &color);
2914         expect(Ok, status);
2915         expect(0xdeadbeef, color);
2916         GdipDeleteGraphics(graphics);
2917     }
2918     GdipDisposeImage((GpImage*)bitmap);
2919 
2920     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, &bitmap);
2921     expect(Ok, status);
2922     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2923     ok(broken(status == OutOfMemory) /* winver < Win7 */ || status == Ok, "status=%u\n", status);
2924     if (status == Ok)
2925     {
2926         status = GdipGetNearestColor(graphics, &color);
2927         expect(Ok, status);
2928         expect(0xdeadbeef, color);
2929         GdipDeleteGraphics(graphics);
2930     }
2931     GdipDisposeImage((GpImage*)bitmap);
2932 
2933     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, &bitmap);
2934     expect(Ok, status);
2935     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2936     todo_wine expect(OutOfMemory, status);
2937     if (status == Ok)
2938         GdipDeleteGraphics(graphics);
2939     GdipDisposeImage((GpImage*)bitmap);
2940 
2941     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bitmap);
2942     expect(Ok, status);
2943     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2944     expect(Ok, status);
2945     status = GdipGetNearestColor(graphics, &color);
2946     expect(Ok, status);
2947     expect(0xdeadbeef, color);
2948     GdipDeleteGraphics(graphics);
2949     GdipDisposeImage((GpImage*)bitmap);
2950 
2951     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, &bitmap);
2952     expect(Ok, status);
2953     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2954     expect(Ok, status);
2955     status = GdipGetNearestColor(graphics, &color);
2956     expect(Ok, status);
2957     expect(0xdeadbeef, color);
2958     GdipDeleteGraphics(graphics);
2959     GdipDisposeImage((GpImage*)bitmap);
2960 
2961     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, &bitmap);
2962     expect(Ok, status);
2963     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2964     expect(Ok, status);
2965     status = GdipGetNearestColor(graphics, &color);
2966     expect(Ok, status);
2967     expect(0xdeadbeef, color);
2968     GdipDeleteGraphics(graphics);
2969     GdipDisposeImage((GpImage*)bitmap);
2970 
2971     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, &bitmap);
2972     expect(Ok, status);
2973     if (status == Ok)
2974     {
2975         status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2976         expect(Ok, status);
2977         status = GdipGetNearestColor(graphics, &color);
2978         expect(Ok, status);
2979         expect(0xdeadbeef, color);
2980         GdipDeleteGraphics(graphics);
2981         GdipDisposeImage((GpImage*)bitmap);
2982     }
2983 
2984     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, &bitmap);
2985     expect(Ok, status);
2986     if (status == Ok)
2987     {
2988         status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2989         expect(Ok, status);
2990         status = GdipGetNearestColor(graphics, &color);
2991         expect(Ok, status);
2992         expect(0xdeadbeef, color);
2993         GdipDeleteGraphics(graphics);
2994         GdipDisposeImage((GpImage*)bitmap);
2995     }
2996 
2997     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, &bitmap);
2998     expect(Ok, status);
2999     if (status == Ok)
3000     {
3001         status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
3002         expect(Ok, status);
3003         status = GdipGetNearestColor(graphics, &color);
3004         expect(Ok, status);
3005         expect(0xdeadbeef, color);
3006         GdipDeleteGraphics(graphics);
3007         GdipDisposeImage((GpImage*)bitmap);
3008     }
3009 
3010     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, &bitmap);
3011     expect(Ok, status);
3012     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
3013     expect(Ok, status);
3014     status = GdipGetNearestColor(graphics, &color);
3015     expect(Ok, status);
3016     todo_wine expect(0xffa8bce8, color);
3017     GdipDeleteGraphics(graphics);
3018     GdipDisposeImage((GpImage*)bitmap);
3019 
3020     status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, &bitmap);
3021     expect(Ok, status);
3022     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
3023     expect(Ok, status);
3024     status = GdipGetNearestColor(graphics, &color);
3025     expect(Ok, status);
3026     todo_wine
3027     ok(color == 0xffa8b8e8 ||
3028        broken(color == 0xffa0b8e0), /* Win98/WinMe */
3029        "Expected ffa8b8e8, got %.8x\n", color);
3030     GdipDeleteGraphics(graphics);
3031     GdipDisposeImage((GpImage*)bitmap);
3032 
3033     ReleaseDC(hwnd, hdc);
3034 }
3035 
3036 static void test_string_functions(void)
3037 {
3038     GpStatus status;
3039     GpGraphics *graphics;
3040     GpFontFamily *family;
3041     GpFont *font;
3042     RectF rc, char_bounds, bounds;
3043     GpBrush *brush;
3044     ARGB color = 0xff000000;
3045     HDC hdc = GetDC( hwnd );
3046     const WCHAR fontname[] = {'T','a','h','o','m','a',0};
3047     const WCHAR teststring[] = {'M','M',' ','M','\n','M',0};
3048     const WCHAR teststring2[] = {'j',0};
3049     REAL char_width, char_height;
3050     INT codepointsfitted, linesfilled;
3051     GpStringFormat *format;
3052     CharacterRange ranges[3] = {{0, 1}, {1, 3}, {5, 1}};
3053     GpRegion *regions[4];
3054     BOOL region_isempty[4];
3055     int i;
3056     PointF positions[8];
3057     GpMatrix *identity;
3058 
3059     ok(hdc != NULL, "Expected HDC to be initialized\n");
3060     status = GdipCreateFromHDC(hdc, &graphics);
3061     expect(Ok, status);
3062     ok(graphics != NULL, "Expected graphics to be initialized\n");
3063 
3064     status = GdipCreateFontFamilyFromName(fontname, NULL, &family);
3065     expect(Ok, status);
3066 
3067     status = GdipCreateFont(family, 10.0, FontStyleRegular, UnitPixel, &font);
3068     expect(Ok, status);
3069 
3070     status = GdipCreateSolidFill(color, (GpSolidFill**)&brush);
3071     expect(Ok, status);
3072 
3073     status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
3074     expect(Ok, status);
3075 
3076     rc.X = 0;
3077     rc.Y = 0;
3078     rc.Width = 100.0;
3079     rc.Height = 100.0;
3080 
3081     status = GdipDrawString(NULL, teststring, 6, font, &rc, NULL, brush);
3082     expect(InvalidParameter, status);
3083 
3084     status = GdipDrawString(graphics, NULL, 6, font, &rc, NULL, brush);
3085     expect(InvalidParameter, status);
3086 
3087     status = GdipDrawString(graphics, teststring, 6, NULL, &rc, NULL, brush);
3088     expect(InvalidParameter, status);
3089 
3090     status = GdipDrawString(graphics, teststring, 6, font, NULL, NULL, brush);
3091     expect(InvalidParameter, status);
3092 
3093     status = GdipDrawString(graphics, teststring, 6, font, &rc, NULL, NULL);
3094     expect(InvalidParameter, status);
3095 
3096     status = GdipDrawString(graphics, teststring, 6, font, &rc, NULL, brush);
3097     expect(Ok, status);
3098 
3099     status = GdipMeasureString(NULL, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3100     expect(InvalidParameter, status);
3101 
3102     status = GdipMeasureString(graphics, NULL, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3103     expect(InvalidParameter, status);
3104 
3105     status = GdipMeasureString(graphics, teststring, 6, NULL, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3106     expect(InvalidParameter, status);
3107 
3108     status = GdipMeasureString(graphics, teststring, 6, font, NULL, NULL, &bounds, &codepointsfitted, &linesfilled);
3109     expect(InvalidParameter, status);
3110 
3111     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, NULL, &codepointsfitted, &linesfilled);
3112     expect(InvalidParameter, status);
3113 
3114     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, NULL, &linesfilled);
3115     expect(Ok, status);
3116 
3117     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, NULL);
3118     expect(Ok, status);
3119 
3120     status = GdipMeasureString(graphics, teststring, 1, font, &rc, NULL, &char_bounds, &codepointsfitted, &linesfilled);
3121     expect(Ok, status);
3122     expectf(0.0, char_bounds.X);
3123     expectf(0.0, char_bounds.Y);
3124     ok(char_bounds.Width > 0, "got %0.2f\n", bounds.Width);
3125     ok(char_bounds.Height > 0, "got %0.2f\n", bounds.Height);
3126     expect(1, codepointsfitted);
3127     expect(1, linesfilled);
3128 
3129     status = GdipMeasureString(graphics, teststring, 2, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3130     expect(Ok, status);
3131     expectf(0.0, bounds.X);
3132     expectf(0.0, bounds.Y);
3133     ok(bounds.Width > char_bounds.Width, "got %0.2f, expected at least %0.2f\n", bounds.Width, char_bounds.Width);
3134     expectf(char_bounds.Height, bounds.Height);
3135     expect(2, codepointsfitted);
3136     expect(1, linesfilled);
3137     char_width = bounds.Width - char_bounds.Width;
3138 
3139     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3140     expect(Ok, status);
3141     expectf(0.0, bounds.X);
3142     expectf(0.0, bounds.Y);
3143     ok(bounds.Width > char_bounds.Width + char_width * 2, "got %0.2f, expected at least %0.2f\n",
3144        bounds.Width, char_bounds.Width + char_width * 2);
3145     ok(bounds.Height > char_bounds.Height, "got %0.2f, expected at least %0.2f\n", bounds.Height, char_bounds.Height);
3146     expect(6, codepointsfitted);
3147     expect(2, linesfilled);
3148     char_height = bounds.Height - char_bounds.Height;
3149 
3150     /* Measure the first line. */
3151     status = GdipMeasureString(graphics, teststring, 4, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3152     expect(Ok, status);
3153     expectf(0.0, bounds.X);
3154     expectf(0.0, bounds.Y);
3155     expect(4, codepointsfitted);
3156     expect(1, linesfilled);
3157 
3158     /* Give just enough space to fit the first line. */
3159     rc.Width = bounds.Width;
3160     status = GdipMeasureString(graphics, teststring, 5, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3161     expect(Ok, status);
3162     expectf(0.0, bounds.X);
3163     expectf(0.0, bounds.Y);
3164     todo_wine expect(5, codepointsfitted);
3165     todo_wine expect(1, linesfilled);
3166 
3167     /* Cut off everything after the first space. */
3168     rc.Width = char_bounds.Width + char_width * 2.1;
3169 
3170     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3171     expect(Ok, status);
3172     expectf(0.0, bounds.X);
3173     expectf(0.0, bounds.Y);
3174     expectf_(char_bounds.Width + char_width, bounds.Width, 0.01);
3175     expectf_(char_bounds.Height + char_height * 2, bounds.Height, 0.01);
3176     expect(6, codepointsfitted);
3177     expect(3, linesfilled);
3178 
3179     /* Cut off everything including the first space. */
3180     rc.Width = char_bounds.Width + char_width * 1.7;
3181 
3182     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3183     expect(Ok, status);
3184     expectf(0.0, bounds.X);
3185     expectf(0.0, bounds.Y);
3186     expectf_(char_bounds.Width + char_width, bounds.Width, 0.01);
3187     expectf_(char_bounds.Height + char_height * 2, bounds.Height, 0.01);
3188     expect(6, codepointsfitted);
3189     expect(3, linesfilled);
3190 
3191     /* Cut off everything after the first character. */
3192     rc.Width = char_bounds.Width + char_width * 0.8;
3193 
3194     status = GdipMeasureString(graphics, teststring, 6, font, &rc, NULL, &bounds, &codepointsfitted, &linesfilled);
3195     expect(Ok, status);
3196     expectf(0.0, bounds.X);
3197     expectf(0.0, bounds.Y);
3198     expectf_(char_bounds.Width, bounds.Width, 0.01);
3199     expectf_(char_bounds.Height + char_height * 3, bounds.Height, 0.05);
3200     expect(6, codepointsfitted);
3201     todo_wine expect(4, linesfilled);
3202 
3203     for (i = 0; i < 4; i++)
3204         regions[i] = (GpRegion *)0xdeadbeef;
3205 
3206     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 0, regions);
3207     expect(Ok, status);
3208 
3209     for (i = 0; i < 4; i++)
3210         ok(regions[i] == (GpRegion *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", regions[i]);
3211 
3212     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 3, regions);
3213     expect(Ok, status);
3214 
3215     for (i = 0; i < 4; i++)
3216         ok(regions[i] == (GpRegion *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", regions[i]);
3217 
3218     status = GdipSetStringFormatMeasurableCharacterRanges(format, 3, ranges);
3219     expect(Ok, status);
3220 
3221     set_rect_empty(&rc);
3222 
3223     for (i=0; i<4; i++)
3224     {
3225         status = GdipCreateRegion(&regions[i]);
3226         expect(Ok, status);
3227         status = GdipSetEmpty(regions[i]);
3228         expect(Ok, status);
3229     }
3230 
3231     status = GdipMeasureCharacterRanges(NULL, teststring, 6, font, &rc, format, 3, regions);
3232     expect(InvalidParameter, status);
3233 
3234     status = GdipMeasureCharacterRanges(graphics, NULL, 6, font, &rc, format, 3, regions);
3235     expect(InvalidParameter, status);
3236 
3237     status = GdipMeasureCharacterRanges(graphics, teststring, 6, NULL, &rc, format, 3, regions);
3238     expect(InvalidParameter, status);
3239 
3240     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, NULL, format, 3, regions);
3241     expect(InvalidParameter, status);
3242 
3243     if (0)
3244     {
3245         /* Crashes on Windows XP */
3246         status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, NULL, 3, regions);
3247         expect(InvalidParameter, status);
3248     }
3249 
3250     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 3, NULL);
3251     expect(InvalidParameter, status);
3252 
3253     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 2, regions);
3254     expect(InvalidParameter, status);
3255 
3256     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 3, regions);
3257     expect(Ok, status);
3258 
3259     for (i = 0; i < 4; i++)
3260     {
3261         status = GdipIsEmptyRegion(regions[i], graphics, &region_isempty[i]);
3262         expect(Ok, status);
3263     }
3264 
3265     ok(region_isempty[0], "region should be empty\n");
3266     ok(region_isempty[1], "region should be empty\n");
3267     ok(region_isempty[2], "region should be empty\n");
3268     ok(region_isempty[3], "region should be empty\n");
3269 
3270     rc.Width = 100.0;
3271     rc.Height = 100.0;
3272 
3273     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 4, regions);
3274     expect(Ok, status);
3275 
3276     for (i=0; i<4; i++)
3277     {
3278         status = GdipIsEmptyRegion(regions[i], graphics, &region_isempty[i]);
3279         expect(Ok, status);
3280     }
3281 
3282     ok(!region_isempty[0], "region shouldn't be empty\n");
3283     ok(!region_isempty[1], "region shouldn't be empty\n");
3284     ok(!region_isempty[2], "region shouldn't be empty\n");
3285     ok(region_isempty[3], "region should be empty\n");
3286 
3287     /* Cut off everything after the first space, and the second line. */
3288     rc.Width = char_bounds.Width + char_width * 2.1;
3289     rc.Height = char_bounds.Height + char_height * 0.5;
3290 
3291     status = GdipMeasureCharacterRanges(graphics, teststring, 6, font, &rc, format, 3, regions);
3292     expect(Ok, status);
3293 
3294     for (i=0; i<4; i++)
3295     {
3296         status = GdipIsEmptyRegion(regions[i], graphics, &region_isempty[i]);
3297         expect(Ok, status);
3298     }
3299 
3300     ok(!region_isempty[0], "region shouldn't be empty\n");
3301     ok(!region_isempty[1], "region shouldn't be empty\n");
3302     ok(region_isempty[2], "region should be empty\n");
3303     ok(region_isempty[3], "region should be empty\n");
3304 
3305     for (i=0; i<4; i++)
3306         GdipDeleteRegion(regions[i]);
3307 
3308     status = GdipCreateMatrix(&identity);
3309     expect(Ok, status);
3310 
3311     rc.X = 0;
3312     rc.Y = 0;
3313     rc.Width = 0;
3314     rc.Height = 0;
3315     memset(positions, 0, sizeof(positions));
3316     status = GdipMeasureDriverString(NULL, teststring, 6, font, positions,
3317         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3318         identity, &rc);
3319     expect(InvalidParameter, status);
3320 
3321     status = GdipMeasureDriverString(graphics, NULL, 6, font, positions,
3322         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3323         identity, &rc);
3324     expect(InvalidParameter, status);
3325 
3326     status = GdipMeasureDriverString(graphics, teststring, 6, NULL, positions,
3327         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3328         identity, &rc);
3329     expect(InvalidParameter, status);
3330 
3331     status = GdipMeasureDriverString(graphics, teststring, 6, font, NULL,
3332         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3333         identity, &rc);
3334     expect(InvalidParameter, status);
3335 
3336     status = GdipMeasureDriverString(graphics, teststring, 6, font, positions,
3337         0x100, identity, &rc);
3338     expect(Ok, status);
3339 
3340     status = GdipMeasureDriverString(graphics, teststring, 6, font, positions,
3341         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3342         NULL, &rc);
3343     expect(Ok, status);
3344 
3345     status = GdipMeasureDriverString(graphics, teststring, 6, font, positions,
3346         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3347         identity, NULL);
3348     expect(InvalidParameter, status);
3349 
3350     rc.X = 0;
3351     rc.Y = 0;
3352     rc.Width = 0;
3353     rc.Height = 0;
3354     status = GdipMeasureDriverString(graphics, teststring, 6, font, positions,
3355         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3356         identity, &rc);
3357     expect(Ok, status);
3358 
3359     expectf(0.0, rc.X);
3360     ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
3361     ok(rc.Width > 0.0, "unexpected Width %0.2f\n", rc.Width);
3362     ok(rc.Height > 0.0, "unexpected Y %0.2f\n", rc.Y);
3363 
3364     char_width = rc.Width;
3365     char_height = rc.Height;
3366 
3367     rc.X = 0;
3368     rc.Y = 0;
3369     rc.Width = 0;
3370     rc.Height = 0;
3371     status = GdipMeasureDriverString(graphics, teststring, 4, font, positions,
3372         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3373         identity, &rc);
3374     expect(Ok, status);
3375 
3376     expectf(0.0, rc.X);
3377     ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
3378     ok(rc.Width < char_width, "got Width %0.2f, expecting less than %0.2f\n", rc.Width, char_width);
3379     expectf(char_height, rc.Height);
3380 
3381     rc.X = 0;
3382     rc.Y = 0;
3383     rc.Width = 0;
3384     rc.Height = 0;
3385     status = GdipMeasureDriverString(graphics, teststring2, 1, font, positions,
3386         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
3387         identity, &rc);
3388     expect(Ok, status);
3389 
3390     expectf(rc.X, 0.0);
3391     ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
3392     ok(rc.Width > 0, "unexpected Width %0.2f\n", rc.Width);
3393     expectf(rc.Height, char_height);
3394 
3395     GdipDeleteMatrix(identity);
3396     GdipDeleteStringFormat(format);
3397     GdipDeleteBrush(brush);
3398     GdipDeleteFont(font);
3399     GdipDeleteFontFamily(family);
3400     GdipDeleteGraphics(graphics);
3401 
3402     ReleaseDC(hwnd, hdc);
3403 }
3404 
3405 static void test_get_set_interpolation(void)
3406 {
3407     GpGraphics *graphics;
3408     HDC hdc = GetDC( hwnd );
3409     GpStatus status;
3410     InterpolationMode mode;
3411 
3412     ok(hdc != NULL, "Expected HDC to be initialized\n");
3413     status = GdipCreateFromHDC(hdc, &graphics);
3414     expect(Ok, status);
3415     ok(graphics != NULL, "Expected graphics to be initialized\n");
3416 
3417     status = GdipGetInterpolationMode(NULL, &mode);
3418     expect(InvalidParameter, status);
3419 
3420     if (0)
3421     {
3422         /* Crashes on Windows XP */
3423         status = GdipGetInterpolationMode(graphics, NULL);
3424         expect(InvalidParameter, status);
3425     }
3426 
3427     status = GdipSetInterpolationMode(NULL, InterpolationModeNearestNeighbor);
3428     expect(InvalidParameter, status);
3429 
3430     /* out of range */
3431     status = GdipSetInterpolationMode(graphics, InterpolationModeHighQualityBicubic+1);
3432     expect(InvalidParameter, status);
3433 
3434     status = GdipSetInterpolationMode(graphics, InterpolationModeInvalid);
3435     expect(InvalidParameter, status);
3436 
3437     status = GdipGetInterpolationMode(graphics, &mode);
3438     expect(Ok, status);
3439     expect(InterpolationModeBilinear, mode);
3440 
3441     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3442     expect(Ok, status);
3443 
3444     status = GdipGetInterpolationMode(graphics, &mode);
3445     expect(Ok, status);
3446     expect(InterpolationModeNearestNeighbor, mode);
3447 
3448     status = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
3449     expect(Ok, status);
3450 
3451     status = GdipGetInterpolationMode(graphics, &mode);
3452     expect(Ok, status);
3453     expect(InterpolationModeBilinear, mode);
3454 
3455     status = GdipSetInterpolationMode(graphics, InterpolationModeLowQuality);
3456     expect(Ok, status);
3457 
3458     status = GdipGetInterpolationMode(graphics, &mode);
3459     expect(Ok, status);
3460     expect(InterpolationModeBilinear, mode);
3461 
3462     status = GdipSetInterpolationMode(graphics, InterpolationModeHighQuality);
3463     expect(Ok, status);
3464 
3465     status = GdipGetInterpolationMode(graphics, &mode);
3466     expect(Ok, status);
3467     expect(InterpolationModeHighQualityBicubic, mode);
3468 
3469     GdipDeleteGraphics(graphics);
3470 
3471     ReleaseDC(hwnd, hdc);
3472 }
3473 
3474 static void test_get_set_textrenderinghint(void)
3475 {
3476     GpGraphics *graphics;
3477     HDC hdc = GetDC( hwnd );
3478     GpStatus status;
3479     TextRenderingHint hint;
3480 
3481     ok(hdc != NULL, "Expected HDC to be initialized\n");
3482     status = GdipCreateFromHDC(hdc, &graphics);
3483     expect(Ok, status);
3484     ok(graphics != NULL, "Expected graphics to be initialized\n");
3485 
3486     status = GdipGetTextRenderingHint(NULL, &hint);
3487     expect(InvalidParameter, status);
3488 
3489     status = GdipGetTextRenderingHint(graphics, NULL);
3490     expect(InvalidParameter, status);
3491 
3492     status = GdipSetTextRenderingHint(NULL, TextRenderingHintAntiAlias);
3493     expect(InvalidParameter, status);
3494 
3495     /* out of range */
3496     status = GdipSetTextRenderingHint(graphics, TextRenderingHintClearTypeGridFit+1);
3497     expect(InvalidParameter, status);
3498 
3499     status = GdipGetTextRenderingHint(graphics, &hint);
3500     expect(Ok, status);
3501     expect(TextRenderingHintSystemDefault, hint);
3502 
3503     status = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
3504     expect(Ok, status);
3505 
3506     status = GdipGetTextRenderingHint(graphics, &hint);
3507     expect(Ok, status);
3508     expect(TextRenderingHintSystemDefault, hint);
3509 
3510     status = GdipSetTextRenderingHint(graphics, TextRenderingHintAntiAliasGridFit);
3511     expect(Ok, status);
3512 
3513     status = GdipGetTextRenderingHint(graphics, &hint);
3514     expect(Ok, status);
3515     expect(TextRenderingHintAntiAliasGridFit, hint);
3516 
3517     GdipDeleteGraphics(graphics);
3518 
3519     ReleaseDC(hwnd, hdc);
3520 }
3521 
3522 static void test_getdc_scaled(void)
3523 {
3524     GpStatus status;
3525     GpGraphics *graphics = NULL;
3526     GpBitmap *bitmap = NULL;
3527     HDC hdc=NULL;
3528     HBRUSH hbrush, holdbrush;
3529     ARGB color;
3530 
3531     status = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, NULL, &bitmap);
3532     expect(Ok, status);
3533 
3534     status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
3535     expect(Ok, status);
3536 
3537     status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
3538     expect(Ok, status);
3539 
3540     status = GdipGetDC(graphics, &hdc);
3541     expect(Ok, status);
3542     ok(hdc != NULL, "got NULL hdc\n");
3543 
3544     hbrush = CreateSolidBrush(RGB(255, 0, 0));
3545 
3546     holdbrush = SelectObject(hdc, hbrush);
3547 
3548     Rectangle(hdc, 2, 2, 6, 6);
3549 
3550     SelectObject(hdc, holdbrush);
3551 
3552     DeleteObject(hbrush);
3553 
3554     status = GdipReleaseDC(graphics, hdc);
3555     expect(Ok, status);
3556 
3557     GdipDeleteGraphics(graphics);
3558 
3559     status = GdipBitmapGetPixel(bitmap, 3, 3, &color);
3560     expect(Ok, status);
3561     expect(0xffff0000, color);
3562 
3563     status = GdipBitmapGetPixel(bitmap, 8, 8, &color);
3564     expect(Ok, status);
3565     expect(0xff000000, color);
3566 
3567     GdipDisposeImage((GpImage*)bitmap);
3568 }
3569 
3570 static void test_GdipMeasureString(void)
3571 {
3572     static const struct test_data
3573     {
3574         REAL res_x, res_y, page_scale;
3575         GpUnit unit;
3576     } td[] =
3577     {
3578         { 200.0, 200.0, 1.0, UnitPixel }, /* base */
3579         { 200.0, 200.0, 2.0, UnitPixel },
3580         { 200.0, 200.0, 1.0, UnitDisplay },
3581         { 200.0, 200.0, 2.0, UnitDisplay },
3582         { 200.0, 200.0, 1.0, UnitInch },
3583         { 200.0, 200.0, 2.0, UnitInch },
3584         { 200.0, 600.0, 1.0, UnitPoint },
3585         { 200.0, 600.0, 2.0, UnitPoint },
3586         { 200.0, 600.0, 1.0, UnitDocument },
3587         { 200.0, 600.0, 2.0, UnitDocument },
3588         { 200.0, 600.0, 1.0, UnitMillimeter },
3589         { 200.0, 600.0, 2.0, UnitMillimeter },
3590         { 200.0, 600.0, 1.0, UnitDisplay },
3591         { 200.0, 600.0, 2.0, UnitDisplay },
3592         { 200.0, 600.0, 1.0, UnitPixel },
3593         { 200.0, 600.0, 2.0, UnitPixel },
3594     };
3595     static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
3596     static const WCHAR string[] = { '1','2','3','4','5','6','7',0 };
3597     GpStatus status;
3598     GpGraphics *graphics;
3599     GpFontFamily *family;
3600     GpFont *font;
3601     GpStringFormat *format;
3602     RectF bounds, rc;
3603     REAL base_cx = 0, base_cy = 0, height;
3604     INT chars, lines;
3605     LOGFONTW lf;
3606     UINT i;
3607     REAL font_size;
3608     GpUnit font_unit, unit;
3609 
3610     status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
3611     expect(Ok, status);
3612     status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
3613     expect(Ok, status);
3614 
3615     /* font size in pixels */
3616     status = GdipCreateFont(family, 100.0, FontStyleRegular, UnitPixel, &font);
3617     expect(Ok, status);
3618     status = GdipGetFontSize(font, &font_size);
3619     expect(Ok, status);
3620     expectf(100.0, font_size);
3621     status = GdipGetFontUnit(font, &font_unit);
3622     expect(Ok, status);
3623     expect(UnitPixel, font_unit);
3624 
3625     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3626     {
3627         GpImage *image;
3628 
3629         graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].page_scale, &image);
3630 
3631         lf.lfHeight = 0xdeadbeef;
3632         status = GdipGetLogFontW(font, graphics, &lf);
3633         expect(Ok, status);
3634         height = units_to_pixels(font_size, td[i].unit, td[i].res_y);
3635         if (td[i].unit != UnitDisplay)
3636             height *= td[i].page_scale;
3637         ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
3638            i, (LONG)(height + 0.5), height, lf.lfHeight);
3639 
3640         height = font_size + 2.0 * font_size / 6.0;
3641 
3642         set_rect_empty(&rc);
3643         set_rect_empty(&bounds);
3644         status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
3645         expect(Ok, status);
3646 
3647         if (i == 0)
3648         {
3649             base_cx = bounds.Width;
3650             base_cy = bounds.Height;
3651         }
3652 
3653         expectf(0.0, bounds.X);
3654         expectf(0.0, bounds.Y);
3655 todo_wine
3656         expectf_(height, bounds.Height, height / 100.0);
3657         expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
3658         expect(7, chars);
3659         expect(1, lines);
3660 
3661         /* make sure it really fits */
3662         bounds.Width += 1.0;
3663         bounds.Height += 1.0;
3664         rc = bounds;
3665         rc.X = 50.0;
3666         rc.Y = 50.0;
3667         set_rect_empty(&bounds);
3668         status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
3669         expect(Ok, status);
3670         expectf(50.0, bounds.X);
3671         expectf(50.0, bounds.Y);
3672 todo_wine
3673         expectf_(height, bounds.Height, height / 100.0);
3674         expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
3675         expect(7, chars);
3676         expect(1, lines);
3677 
3678         status = GdipDeleteGraphics(graphics);
3679         expect(Ok, status);
3680 
3681         status = GdipDisposeImage(image);
3682         expect(Ok, status);
3683     }
3684 
3685     GdipDeleteFont(font);
3686 
3687     /* font size in logical units */
3688     /* UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
3689     for (unit = 3; unit <= 6; unit++)
3690     {
3691         /* create a font which final height is 100.0 pixels with 200 dpi device */
3692         /* height + 2 * (height/6) = 100 => height = 100 * 3 / 4 => 75 */
3693         height = pixels_to_units(75.0, unit, 200.0);
3694         status = GdipCreateFont(family, height, FontStyleRegular, unit, &font);
3695         expect(Ok, status);
3696         status = GdipGetFontSize(font, &font_size);
3697         expect(Ok, status);
3698         expectf(height, font_size);
3699         status = GdipGetFontUnit(font, &font_unit);
3700         expect(Ok, status);
3701         expect(unit, font_unit);
3702 
3703         for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3704         {
3705             REAL unit_scale;
3706             GpImage *image;
3707 
3708             graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].page_scale, &image);
3709 
3710             lf.lfHeight = 0xdeadbeef;
3711             status = GdipGetLogFontW(font, graphics, &lf);
3712             expect(Ok, status);
3713             if (td[i].unit == UnitDisplay || td[i].unit == UnitPixel)
3714                 height = units_to_pixels(font_size, font_unit, td[i].res_x);
3715             else
3716                 height = units_to_pixels(font_size, font_unit, td[i].res_y);
3717             /*trace("%.1f font units = %f pixels with %.1f dpi, page_scale %.1f\n", font_size, height, td[i].res_y, td[i].page_scale);*/
3718             ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
3719                i, (LONG)(height + 0.5), height, lf.lfHeight);
3720 
3721             if (td[i].unit == UnitDisplay || td[i].unit == UnitPixel)
3722                 unit_scale = units_scale(font_unit, td[i].unit, td[i].res_x);
3723             else
3724                 unit_scale = units_scale(font_unit, td[i].unit, td[i].res_y);
3725             /*trace("%u: %d to %d, %.1f dpi => unit_scale %f\n", i, font_unit, td[i].unit, td[i].res_y, unit_scale);*/
3726             height = (font_size + 2.0 * font_size / 6.0) * unit_scale;
3727             if (td[i].unit != UnitDisplay)
3728                 height /= td[i].page_scale;
3729             /*trace("%u: %.1f font units = %f units with %.1f dpi, page_scale %.1f\n", i, font_size, height, td[i].res_y, td[i].page_scale);*/
3730 
3731             set_rect_empty(&rc);
3732             set_rect_empty(&bounds);
3733             status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
3734             expect(Ok, status);
3735 
3736             if (i == 0)
3737             {
3738                 base_cx = bounds.Width;
3739                 base_cy = bounds.Height;
3740             }
3741 
3742             expectf(0.0, bounds.X);
3743             expectf(0.0, bounds.Y);
3744 todo_wine
3745             expectf_(height, bounds.Height, height / 85.0);
3746             expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
3747             expect(7, chars);
3748             expect(1, lines);
3749 
3750             /* make sure it really fits */
3751             bounds.Width += 1.0;
3752             bounds.Height += 1.0;
3753             rc = bounds;
3754             rc.X = 50.0;
3755             rc.Y = 50.0;
3756             set_rect_empty(&bounds);
3757             status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
3758             expect(Ok, status);
3759             expectf(50.0, bounds.X);
3760             expectf(50.0, bounds.Y);
3761 todo_wine
3762             expectf_(height, bounds.Height, height / 85.0);
3763             expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
3764             expect(7, chars);
3765             expect(1, lines);
3766 
3767             /* verify the result */
3768             height = units_to_pixels(bounds.Height, td[i].unit, td[i].res_x);
3769             if (td[i].unit != UnitDisplay)
3770                 height *= td[i].page_scale;
3771             /*trace("%u: unit %u, %.1fx%.1f dpi, scale %.1f, height %f, pixels %f\n",
3772                   i, td[i].unit, td[i].res_x, td[i].res_y, td[i].page_scale, bounds.Height, height);*/
3773 todo_wine
3774             expectf_(100.0, height, 1.1);
3775 
3776             status = GdipDeleteGraphics(graphics);
3777             expect(Ok, status);
3778 
3779             status = GdipDisposeImage(image);
3780             expect(Ok, status);
3781         }
3782 
3783         GdipDeleteFont(font);
3784     }
3785 
3786     /* Font with units = UnitWorld */
3787     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3788     {
3789         GpPointF pt = {0.0, 100.0};
3790         GpImage* image;
3791         REAL expected_width, expected_height;
3792 
3793         graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].page_scale, &image);
3794 
3795         status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &pt, 1);
3796         expect(Ok, status);
3797 
3798         status = GdipCreateFont(family, pt.Y, FontStyleRegular, UnitWorld, &font);
3799         expect(Ok, status);
3800 
3801         status = GdipGetFontUnit(font, &font_unit);
3802         expect(Ok, status);
3803         expect(UnitWorld, font_unit);
3804 
3805         lf.lfHeight = 0xdeadbeef;
3806         status = GdipGetLogFontW(font, graphics, &lf);
3807         expect(Ok, status);
3808         ok(lf.lfHeight == -100, "%u: expected -100, got %d\n", i, lf.lfHeight);
3809 
3810         set_rect_empty(&rc);
3811         set_rect_empty(&bounds);
3812         status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
3813         expect(Ok, status);
3814 
3815         if (i == 0)
3816         {
3817             base_cx = bounds.Width;
3818             base_cy = bounds.Height;
3819         }
3820 
3821         pt.X = 1.0;
3822         pt.Y = 1.0;
3823 
3824         status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &pt, 1);
3825         expect(Ok, status);
3826 
3827         /* height is constant in device space, width is proportional to height in world space */
3828         expected_width = base_cx * pt.Y;
3829         expected_height = base_cy * pt.Y;
3830 
3831         todo_wine_if(td[i].unit != UnitDisplay && td[i].unit != UnitPixel)
3832             ok(fabs(expected_width - bounds.Width) <= 0.001, "%u: expected %f, got %f\n", i, expected_width, bounds.Width);
3833         ok(fabs(expected_height - bounds.Height) <= 0.001, "%u: expected %f, got %f\n", i, expected_height, bounds.Height);
3834 
3835         GdipDeleteGraphics(graphics);
3836         GdipDisposeImage(image);
3837         GdipDeleteFont(font);
3838     }
3839 
3840     GdipDeleteFontFamily(family);
3841     GdipDeleteStringFormat(format);
3842 }
3843 
3844 static void test_transform(void)
3845 {
3846     static const struct test_data
3847     {
3848         REAL res_x, res_y, scale;
3849         GpUnit unit;
3850         GpPointF in[2], out[2];
3851     } td[] =
3852     {
3853         { 96.0, 96.0, 1.0, UnitPixel,
3854           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 100.0, 0.0 }, { 0.0, 100.0 } } },
3855         { 96.0, 96.0, 1.0, UnitDisplay,
3856           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 100.0, 0.0 }, { 0.0, 100.0 } } },
3857         { 96.0, 96.0, 1.0, UnitInch,
3858           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 9600.0, 0.0 }, { 0.0, 9600.0 } } },
3859         { 123.0, 456.0, 1.0, UnitPoint,
3860           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 170.833313, 0.0 }, { 0.0, 633.333252 } } },
3861         { 123.0, 456.0, 1.0, UnitDocument,
3862           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 40.999996, 0.0 }, { 0.0, 151.999985 } } },
3863         { 123.0, 456.0, 2.0, UnitMillimeter,
3864           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 968.503845, 0.0 }, { 0.0, 3590.550781 } } },
3865         { 196.0, 296.0, 1.0, UnitDisplay,
3866           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 100.0, 0.0 }, { 0.0, 100.0 } } },
3867         { 196.0, 296.0, 1.0, UnitPixel,
3868           { { 100.0, 0.0 }, { 0.0, 100.0 } }, { { 100.0, 0.0 }, { 0.0, 100.0 } } },
3869     };
3870     GpStatus status;
3871     GpGraphics *graphics;
3872     GpImage *image;
3873     GpPointF ptf[2];
3874     UINT i;
3875 
3876     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3877     {
3878         graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].scale, &image);
3879         ptf[0].X = td[i].in[0].X;
3880         ptf[0].Y = td[i].in[0].Y;
3881         ptf[1].X = td[i].in[1].X;
3882         ptf[1].Y = td[i].in[1].Y;
3883         status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2);
3884         expect(Ok, status);
3885         expectf(td[i].out[0].X, ptf[0].X);
3886         expectf(td[i].out[0].Y, ptf[0].Y);
3887         expectf(td[i].out[1].X, ptf[1].X);
3888         expectf(td[i].out[1].Y, ptf[1].Y);
3889         status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
3890         expect(Ok, status);
3891         expectf(td[i].in[0].X, ptf[0].X);
3892         expectf(td[i].in[0].Y, ptf[0].Y);
3893         expectf(td[i].in[1].X, ptf[1].X);
3894         expectf(td[i].in[1].Y, ptf[1].Y);
3895         status = GdipDeleteGraphics(graphics);
3896         expect(Ok, status);
3897         status = GdipDisposeImage(image);
3898         expect(Ok, status);
3899     }
3900 }
3901 
3902 static void test_pen_thickness(void)
3903 {
3904     static const struct test_data
3905     {
3906         REAL res_x, res_y, scale;
3907         GpUnit pen_unit, page_unit;
3908         REAL pen_width;
3909         INT cx, cy, path_cx, path_cy;
3910     } td[] =
3911     {
3912         { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 1.0, 1, 1, 1, 1 },
3913         { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 0.0, 0, 0, 1, 1 },
3914         { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 0.1, 1, 1, 1, 1 },
3915         { 10.0, 10.0, 3.0, UnitPixel, UnitPixel, 2.0, 2, 2, 2, 2 },
3916         { 10.0, 10.0, 30.0, UnitPixel, UnitInch, 1.0, 1, 1, 1, 1 },
3917         { 10.0, 10.0, 1.0, UnitWorld, UnitPixel, 1.0, 1, 1, 1, 1 },
3918         { 10.0, 10.0, 1.0, UnitWorld, UnitPixel, 0.0, 1, 1, 1, 1 },
3919         { 10.0, 10.0, 3.0, UnitWorld, UnitPixel, 2.0, 6, 6, 6, 6 },
3920         { 10.0, 10.0, 2.0, UnitWorld, UnitInch, 1.0, 20, 20, 20, 20 },
3921     };
3922     GpStatus status;
3923     int i, j;
3924     GpGraphics *graphics;
3925     union
3926     {
3927         GpBitmap *bitmap;
3928         GpImage *image;
3929     } u;
3930     GpPen *pen;
3931     GpPointF corner;
3932     GpPath *path;
3933     BitmapData bd;
3934     INT min, max, size;
3935 
3936     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3937     {
3938         status = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat24bppRGB, NULL, &u.bitmap);
3939         expect(Ok, status);
3940 
3941         status = GdipBitmapSetResolution(u.bitmap, td[i].res_x, td[i].res_y);
3942         expect(Ok, status);
3943 
3944         status = GdipGetImageGraphicsContext(u.image, &graphics);
3945         expect(Ok, status);
3946 
3947         status = GdipSetPageUnit(graphics, td[i].page_unit);
3948         expect(Ok, status);
3949 
3950         status = GdipSetPageScale(graphics, td[i].scale);
3951         expect(Ok, status);
3952 
3953         status = GdipCreatePen1(0xffffffff, td[i].pen_width, td[i].pen_unit, &pen);
3954         expect(Ok, status);
3955 
3956         corner.X = corner.Y = 100.0;
3957         status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &corner, 1);
3958         expect(Ok, status);
3959 
3960         status = GdipDrawLine(graphics, pen, corner.X/2, 0, corner.X/2, corner.Y);
3961         expect(Ok, status);
3962 
3963         status = GdipDrawLine(graphics, pen, 0, corner.Y/2, corner.X, corner.Y/2);
3964         expect(Ok, status);
3965 
3966         status = GdipBitmapLockBits(u.bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
3967         expect(Ok, status);
3968 
3969         min = -1;
3970         max = -2;
3971 
3972         for (j=0; j<100; j++)
3973         {
3974             if (((BYTE*)bd.Scan0)[j*3] == 0xff)
3975             {
3976                 min = j;
3977                 break;
3978             }
3979         }
3980 
3981         for (j=99; j>=0; j--)
3982         {
3983             if (((BYTE*)bd.Scan0)[j*3] == 0xff)
3984             {
3985                 max = j;
3986                 break;
3987             }
3988         }
3989 
3990         size = max-min+1;
3991 
3992         ok(size == td[i].cx, "%u: expected %d, got %d\n", i, td[i].cx, size);
3993 
3994         min = -1;
3995         max = -2;
3996 
3997         for (j=0; j<100; j++)
3998         {
3999             if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
4000             {
4001                 min = j;
4002                 break;
4003             }
4004         }
4005 
4006         for (j=99; j>=0; j--)
4007         {
4008             if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
4009             {
4010                 max = j;
4011                 break;
4012             }
4013         }
4014 
4015         size = max-min+1;
4016 
4017         ok(size == td[i].cy, "%u: expected %d, got %d\n", i, td[i].cy, size);
4018 
4019         status = GdipBitmapUnlockBits(u.bitmap, &bd);
4020         expect(Ok, status);
4021 
4022         status = GdipGraphicsClear(graphics, 0xff000000);
4023         expect(Ok, status);
4024 
4025         status = GdipCreatePath(FillModeAlternate, &path);
4026         expect(Ok, status);
4027 
4028         status = GdipAddPathLine(path, corner.X/2, 0, corner.X/2, corner.Y);
4029         expect(Ok, status);
4030 
4031         status = GdipClosePathFigure(path);
4032         expect(Ok, status);
4033 
4034         status = GdipAddPathLine(path, 0, corner.Y/2, corner.X, corner.Y/2);
4035         expect(Ok, status);
4036 
4037         status = GdipDrawPath(graphics, pen, path);
4038         expect(Ok, status);
4039 
4040         GdipDeletePath(path);
4041 
4042         status = GdipBitmapLockBits(u.bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
4043         expect(Ok, status);
4044 
4045         min = -1;
4046         max = -2;
4047 
4048         for (j=0; j<100; j++)
4049         {
4050             if (((BYTE*)bd.Scan0)[j*3] == 0xff)
4051             {
4052                 min = j;
4053                 break;
4054             }
4055         }
4056 
4057         for (j=99; j>=0; j--)
4058         {
4059             if (((BYTE*)bd.Scan0)[j*3] == 0xff)
4060             {
4061                 max = j;
4062                 break;
4063             }
4064         }
4065 
4066         size = max-min+1;
4067 
4068         ok(size == td[i].path_cx, "%u: expected %d, got %d\n", i, td[i].path_cx, size);
4069 
4070         min = -1;
4071         max = -2;
4072 
4073         for (j=0; j<100; j++)
4074         {
4075             if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
4076             {
4077                 min = j;
4078                 break;
4079             }
4080         }
4081 
4082         for (j=99; j>=0; j--)
4083         {
4084             if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
4085             {
4086                 max = j;
4087                 break;
4088             }
4089         }
4090 
4091         size = max-min+1;
4092 
4093         ok(size == td[i].path_cy, "%u: expected %d, got %d\n", i, td[i].path_cy, size);
4094 
4095         status = GdipBitmapUnlockBits(u.bitmap, &bd);
4096         expect(Ok, status);
4097 
4098         GdipDeletePen(pen);
4099         GdipDeleteGraphics(graphics);
4100         GdipDisposeImage(u.image);
4101     }
4102 }
4103 
4104 /* Many people on the net ask why there is so much difference in rendered
4105  * text height between gdiplus and gdi32, this test suggests an answer to
4106  * that question. Important: this test assumes that font dpi == device dpi.
4107  */
4108 static void test_font_height_scaling(void)
4109 {
4110     static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
4111     static const WCHAR string[] = { '1','2','3','4','5','6','7',0 };
4112     HDC hdc;
4113     GpStringFormat *format;
4114     CharacterRange range = { 0, 7 };
4115     GpRegion *region;
4116     GpGraphics *graphics;
4117     GpFontFamily *family;
4118     GpFont *font;
4119     GpStatus status;
4120     RectF bounds, rect;
4121     REAL height, dpi, scale;
4122     PointF ptf;
4123     GpUnit gfx_unit, font_unit;
4124 
4125     status = GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &format);
4126     expect(Ok, status);
4127     status = GdipSetStringFormatMeasurableCharacterRanges(format, 1, &range);
4128     expect(Ok, status);
4129     status = GdipCreateRegion(&region);
4130     expect(Ok, status);
4131 
4132     status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
4133     expect(Ok, status);
4134 
4135     hdc = CreateCompatibleDC(0);
4136     status = GdipCreateFromHDC(hdc, &graphics);
4137     expect(Ok, status);
4138 
4139     status = GdipGetDpiY(graphics, &dpi);
4140     expect(Ok, status);
4141 
4142     /* First check if tested functionality works:
4143      * under XP if font and graphics units differ then GdipTransformPoints
4144      * followed by GdipSetPageUnit to change the graphics units breaks region
4145      * scaling in GdipMeasureCharacterRanges called later.
4146      */
4147     status = GdipSetPageUnit(graphics, UnitDocument);
4148     expect(Ok, status);
4149 
4150     ptf.X = 0.0;
4151     ptf.Y = 0.0;
4152     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &ptf, 1);
4153     expect(Ok, status);
4154 
4155     status = GdipSetPageUnit(graphics, UnitInch);
4156     expect(Ok, status);
4157 
4158     status = GdipCreateFont(family, 720.0, FontStyleRegular, UnitPoint, &font);
4159     expect(Ok, status);
4160 
4161     set_rect_empty(&rect);
4162     set_rect_empty(&bounds);
4163     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
4164     expect(Ok, status);
4165     trace("test bounds: %f,%f,%f,%f\n", bounds.X, bounds.Y, bounds.Width, bounds.Height);
4166 
4167     set_rect_empty(&rect);
4168     rect.Width = 32000.0;
4169     rect.Height = 32000.0;
4170     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4171     expect(Ok, status);
4172 
4173     set_rect_empty(&rect);
4174     status = GdipGetRegionBounds(region, graphics, &rect);
4175     expect(Ok, status);
4176     trace("test region: %f,%f,%f,%f\n", rect.X, rect.Y, rect.Width, rect.Height);
4177 
4178     GdipDeleteFont(font);
4179 
4180     scale = rect.Height / bounds.Height;
4181     if (fabs(scale - 1.0) > 0.1)
4182     {
4183         win_skip("GdipGetRegionBounds is broken, scale %f (should be near 1.0)\n", scale);
4184         goto cleanup;
4185     }
4186 
4187     status = GdipScaleWorldTransform(graphics, 0.01, 0.01, MatrixOrderAppend);
4188     expect(Ok, status);
4189 
4190     /* UnitPixel = 2, UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
4191     /* UnitPixel as a font base unit is not tested because it drastically
4192        differs in behaviour */
4193     for (font_unit = 3; font_unit <= 6; font_unit++)
4194     {
4195         /* create a font for the final text height of 100 pixels */
4196         /* height + 2 * (height/6) = 100 => height = 100 * 3 / 4 => 75 */
4197         status = GdipSetPageUnit(graphics, font_unit);
4198         expect(Ok, status);
4199         ptf.X = 0;
4200         ptf.Y = 75.0;
4201         status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &ptf, 1);
4202         expect(Ok, status);
4203         height = ptf.Y;
4204         /*trace("height %f units\n", height);*/
4205         status = GdipCreateFont(family, height, FontStyleRegular, font_unit, &font);
4206         expect(Ok, status);
4207 
4208         /* UnitPixel = 2, UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
4209         for (gfx_unit = 2; gfx_unit <= 6; gfx_unit++)
4210         {
4211             static const WCHAR doubleW[2] = { 'W','W' };
4212             RectF bounds_1, bounds_2;
4213             REAL margin, margin_y, font_height;
4214             int match;
4215 
4216             status = GdipSetPageUnit(graphics, gfx_unit);
4217             expect(Ok, status);
4218 
4219             margin_y = units_to_pixels(height / 8.0, font_unit, dpi);
4220             margin_y = pixels_to_units(margin_y, gfx_unit, dpi);
4221 
4222             status = GdipGetFontHeight(font, graphics, &font_height);
4223             expect(Ok, status);
4224 
4225             set_rect_empty(&rect);
4226             set_rect_empty(&bounds);
4227             status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
4228             expect(Ok, status);
4229             /*trace("bounds: %f,%f,%f,%f\n", bounds.X, bounds.Y, bounds.Width, bounds.Height);*/
4230 todo_wine
4231             expectf_(font_height + margin_y, bounds.Height, 0.005);
4232 
4233             ptf.X = 0;
4234             ptf.Y = bounds.Height;
4235             status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &ptf, 1);
4236             expect(Ok, status);
4237             match = fabs(100.0 - ptf.Y) <= 1.0;
4238 todo_wine
4239             ok(match, "Expected 100.0, got %f\n", ptf.Y);
4240 
4241             /* verify the result */
4242             ptf.Y = units_to_pixels(bounds.Height, gfx_unit, dpi);
4243             ptf.Y /= 100.0;
4244             match = fabs(100.0 - ptf.Y) <= 1.0;
4245 todo_wine
4246             ok(match, "Expected 100.0, got %f\n", ptf.Y);
4247 
4248             /* bounds.width of 1 glyph: [margin]+[width]+[margin] */
4249             set_rect_empty(&rect);
4250             set_rect_empty(&bounds_1);
4251             status = GdipMeasureString(graphics, doubleW, 1, font, &rect, format, &bounds_1, NULL, NULL);
4252             expect(Ok, status);
4253             /* bounds.width of 2 identical glyphs: [margin]+[width]+[width]+[margin] */
4254             set_rect_empty(&rect);
4255             set_rect_empty(&bounds_2);
4256             status = GdipMeasureString(graphics, doubleW, 2, font, &rect, format, &bounds_2, NULL, NULL);
4257             expect(Ok, status);
4258 
4259             /* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
4260             margin = bounds_1.Width - bounds_2.Width / 2.0;
4261             /*trace("margin %f\n", margin);*/
4262             ok(margin > 0.0, "wrong margin %f\n", margin);
4263 
4264             set_rect_empty(&rect);
4265             rect.Width = 320000.0;
4266             rect.Height = 320000.0;
4267             status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4268             expect(Ok, status);
4269             set_rect_empty(&rect);
4270             status = GdipGetRegionBounds(region, graphics, &rect);
4271             expect(Ok, status);
4272             /*trace("region: %f,%f,%f,%f\n", rect.X, rect.Y, rect.Width, rect.Height);*/
4273             ok(rect.X > 0.0, "wrong rect.X %f\n", rect.X);
4274             expectf(0.0, rect.Y);
4275             match = fabs(1.0 - margin / rect.X) <= 0.05;
4276             ok(match, "Expected %f, got %f\n", margin, rect.X);
4277             match = fabs(1.0 - font_height / rect.Height) <= 0.1;
4278             ok(match, "Expected %f, got %f\n", font_height, rect.Height);
4279             match = fabs(1.0 - bounds.Width / (rect.Width + margin * 2.0)) <= 0.05;
4280             ok(match, "Expected %f, got %f\n", bounds.Width, rect.Width + margin * 2.0);
4281         }
4282 
4283         GdipDeleteFont(font);
4284     }
4285 
4286 cleanup:
4287     status = GdipDeleteGraphics(graphics);
4288     expect(Ok, status);
4289     DeleteDC(hdc);
4290 
4291     GdipDeleteFontFamily(family);
4292     GdipDeleteRegion(region);
4293     GdipDeleteStringFormat(format);
4294 }
4295 
4296 static void test_measure_string(void)
4297 {
4298     static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
4299     static const WCHAR string[] = { 'A','0','1',0 };
4300     HDC hdc;
4301     GpStringFormat *format;
4302     CharacterRange range;
4303     GpRegion *region;
4304     GpGraphics *graphics;
4305     GpFontFamily *family;
4306     GpFont *font;
4307     GpStatus status;
4308     RectF bounds, rect;
4309     REAL width, height, width_1, width_2;
4310     REAL margin_x, margin_y, width_rgn, height_rgn;
4311     int lines, glyphs;
4312 
4313     status = GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &format);
4314     expect(Ok, status);
4315     expect(Ok, status);
4316 
4317     status = GdipCreateRegion(&region);
4318     expect(Ok, status);
4319 
4320     status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
4321     expect(Ok, status);
4322 
4323     hdc = CreateCompatibleDC(0);
4324     status = GdipCreateFromHDC(hdc, &graphics);
4325 
4326     status = GdipCreateFont(family, 20, FontStyleRegular, UnitPixel, &font);
4327     expect(Ok, status);
4328 
4329     margin_x = 20.0 / 6.0;
4330     margin_y = 20.0 / 8.0;
4331 
4332     set_rect_empty(&rect);
4333     set_rect_empty(&bounds);
4334     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4335     expect(Ok, status);
4336     expect(3, glyphs);
4337     expect(1, lines);
4338     expectf(0.0, bounds.X);
4339     expectf(0.0, bounds.Y);
4340     width = bounds.Width;
4341     height = bounds.Height;
4342 
4343     set_rect_empty(&rect);
4344     rect.Height = height / 2.0;
4345     set_rect_empty(&bounds);
4346     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4347     expect(Ok, status);
4348     expect(3, glyphs);
4349     expect(1, lines);
4350     expectf(0.0, bounds.X);
4351     expectf(0.0, bounds.Y);
4352     expectf(width, bounds.Width);
4353 todo_wine
4354     expectf(height / 2.0, bounds.Height);
4355 
4356     range.First = 0;
4357     range.Length = lstrlenW(string);
4358     status = GdipSetStringFormatMeasurableCharacterRanges(format, 1, &range);
4359     expect(Ok, status);
4360 
4361     rect.X = 5.0;
4362     rect.Y = 5.0;
4363     rect.Width = 32000.0;
4364     rect.Height = 32000.0;
4365     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4366     expect(Ok, status);
4367     set_rect_empty(&bounds);
4368     status = GdipGetRegionBounds(region, graphics, &bounds);
4369     expect(Ok, status);
4370     expectf_(5.0 + margin_x, bounds.X, 1.0);
4371     expectf(5.0, bounds.Y);
4372     expectf_(width - margin_x*2.0, bounds.Width, 1.0);
4373 todo_wine
4374     expectf_(height - margin_y, bounds.Height, 1.0);
4375 
4376     width_rgn = bounds.Width;
4377     height_rgn = bounds.Height;
4378 
4379     range.First = 0;
4380     range.Length = 1;
4381     status = GdipSetStringFormatMeasurableCharacterRanges(format, 1, &range);
4382     expect(Ok, status);
4383 
4384     set_rect_empty(&rect);
4385     rect.Width = 32000.0;
4386     rect.Height = 32000.0;
4387     status = GdipMeasureCharacterRanges(graphics, string, 1, font, &rect, format, 1, &region);
4388     expect(Ok, status);
4389     set_rect_empty(&bounds);
4390     status = GdipGetRegionBounds(region, graphics, &bounds);
4391     expect(Ok, status);
4392     expectf_(margin_x, bounds.X, 1.0);
4393     expectf(0.0, bounds.Y);
4394     ok(bounds.Width < width_rgn / 2.0, "width of 1 glyph is wrong\n");
4395     expectf(height_rgn, bounds.Height);
4396     width_1 = bounds.Width;
4397 
4398     range.First = 0;
4399     range.Length = lstrlenW(string);
4400     status = GdipSetStringFormatMeasurableCharacterRanges(format, 1, &range);
4401     expect(Ok, status);
4402 
4403     rect.X = 5.0;
4404     rect.Y = 5.0;
4405     rect.Width = 0.0;
4406     rect.Height = 0.0;
4407     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4408     expect(Ok, status);
4409     set_rect_empty(&bounds);
4410     status = GdipGetRegionBounds(region, graphics, &bounds);
4411     expect(Ok, status);
4412     expectf(0.0, bounds.X);
4413     expectf(0.0, bounds.Y);
4414     expectf(0.0, bounds.Width);
4415     expectf(0.0, bounds.Height);
4416 
4417     rect.X = 5.0;
4418     rect.Y = 5.0;
4419     rect.Width = width_rgn / 2.0;
4420     rect.Height = 32000.0;
4421     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4422     expect(Ok, status);
4423     set_rect_empty(&bounds);
4424     status = GdipGetRegionBounds(region, graphics, &bounds);
4425     expect(Ok, status);
4426     expectf_(5.0 + margin_x, bounds.X, 1.0);
4427     expectf(5.0, bounds.Y);
4428     expectf_(width_1, bounds.Width, 1.0);
4429 todo_wine
4430     expectf_(height - margin_y, bounds.Height, 1.0);
4431 
4432     status = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap | StringFormatFlagsNoClip);
4433 
4434     rect.X = 5.0;
4435     rect.Y = 5.0;
4436     rect.Width = 0.0;
4437     rect.Height = 0.0;
4438     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4439     expect(Ok, status);
4440     set_rect_empty(&bounds);
4441     status = GdipGetRegionBounds(region, graphics, &bounds);
4442     expect(Ok, status);
4443     expectf_(5.0 + margin_x, bounds.X, 1.0);
4444     expectf(5.0, bounds.Y);
4445     expectf(width_rgn, bounds.Width);
4446     expectf(height_rgn, bounds.Height);
4447 
4448     rect.X = 5.0;
4449     rect.Y = 5.0;
4450     rect.Width = width_rgn / 2.0;
4451     rect.Height = 32000.0;
4452     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4453     expect(Ok, status);
4454     set_rect_empty(&bounds);
4455     status = GdipGetRegionBounds(region, graphics, &bounds);
4456     expect(Ok, status);
4457     expectf_(5.0 + margin_x, bounds.X, 1.0);
4458     expectf(5.0, bounds.Y);
4459     expectf_(width_1, bounds.Width, 1.0);
4460     expectf(height_rgn, bounds.Height);
4461 
4462     set_rect_empty(&rect);
4463     rect.Height = height / 2.0;
4464     set_rect_empty(&bounds);
4465     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4466     expect(Ok, status);
4467     expect(3, glyphs);
4468     expect(1, lines);
4469     expectf(0.0, bounds.X);
4470     expectf(0.0, bounds.Y);
4471     expectf_(width, bounds.Width, 0.01);
4472 todo_wine
4473     expectf(height, bounds.Height);
4474 
4475     set_rect_empty(&rect);
4476     set_rect_empty(&bounds);
4477     status = GdipMeasureString(graphics, string, 1, font, &rect, format, &bounds, &glyphs, &lines);
4478     expect(Ok, status);
4479     expect(1, glyphs);
4480     expect(1, lines);
4481     expectf(0.0, bounds.X);
4482     expectf(0.0, bounds.Y);
4483     ok(bounds.Width < width / 2.0, "width of 1 glyph is wrong\n");
4484     expectf(height, bounds.Height);
4485     width_1 = bounds.Width;
4486 
4487     set_rect_empty(&rect);
4488     set_rect_empty(&bounds);
4489     status = GdipMeasureString(graphics, string, 2, font, &rect, format, &bounds, &glyphs, &lines);
4490     expect(Ok, status);
4491     expect(2, glyphs);
4492     expect(1, lines);
4493     expectf(0.0, bounds.X);
4494     expectf(0.0, bounds.Y);
4495     ok(bounds.Width < width, "width of 2 glyphs is wrong\n");
4496     ok(bounds.Width > width_1, "width of 2 glyphs is wrong\n");
4497     expectf(height, bounds.Height);
4498     width_2 = bounds.Width;
4499 
4500     set_rect_empty(&rect);
4501     rect.Width = width / 2.0;
4502     set_rect_empty(&bounds);
4503     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4504     expect(Ok, status);
4505     expect(1, glyphs);
4506     expect(1, lines);
4507     expectf(0.0, bounds.X);
4508     expectf(0.0, bounds.Y);
4509     expectf_(width_1, bounds.Width, 0.01);
4510     expectf(height, bounds.Height);
4511 
4512     set_rect_empty(&rect);
4513     rect.Height = height;
4514     rect.Width = width - 0.05;
4515     set_rect_empty(&bounds);
4516     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4517     expect(Ok, status);
4518     expect(2, glyphs);
4519     expect(1, lines);
4520     expectf(0.0, bounds.X);
4521     expectf(0.0, bounds.Y);
4522     expectf_(width_2, bounds.Width, 0.01);
4523     expectf(height, bounds.Height);
4524 
4525     set_rect_empty(&rect);
4526     rect.Height = height;
4527     rect.Width = width_2 - 0.05;
4528     set_rect_empty(&bounds);
4529     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4530     expect(Ok, status);
4531     expect(1, glyphs);
4532     expect(1, lines);
4533     expectf(0.0, bounds.X);
4534     expectf(0.0, bounds.Y);
4535     expectf_(width_1, bounds.Width, 0.01);
4536     expectf(height, bounds.Height);
4537 
4538     /* Default (Near) alignment */
4539     rect.X = 5.0;
4540     rect.Y = 5.0;
4541     rect.Width = width * 2.0;
4542     rect.Height = height * 2.0;
4543     set_rect_empty(&bounds);
4544     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4545     expect(Ok, status);
4546     expect(3, glyphs);
4547     expect(1, lines);
4548     expectf(5.0, bounds.X);
4549     expectf(5.0, bounds.Y);
4550     expectf_(width, bounds.Width, 0.01);
4551     expectf(height, bounds.Height);
4552 
4553     rect.X = 5.0;
4554     rect.Y = 5.0;
4555     rect.Width = 32000.0;
4556     rect.Height = 32000.0;
4557     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4558     expect(Ok, status);
4559     set_rect_empty(&bounds);
4560     status = GdipGetRegionBounds(region, graphics, &bounds);
4561     expect(Ok, status);
4562     expectf_(5.0 + margin_x, bounds.X, 1.0);
4563     expectf(5.0, bounds.Y);
4564     expectf_(width - margin_x*2.0, bounds.Width, 1.0);
4565 todo_wine
4566     expectf_(height - margin_y, bounds.Height, 1.0);
4567 
4568     width_rgn = bounds.Width;
4569     height_rgn = bounds.Height;
4570 
4571     /* Center alignment */
4572     GdipSetStringFormatAlign(format, StringAlignmentCenter);
4573     GdipSetStringFormatLineAlign(format, StringAlignmentCenter);
4574 
4575     rect.X = 5.0;
4576     rect.Y = 5.0;
4577     rect.Width = width * 2.0;
4578     rect.Height = height * 2.0;
4579     set_rect_empty(&bounds);
4580     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4581     expect(Ok, status);
4582     expect(3, glyphs);
4583     expect(1, lines);
4584 todo_wine
4585     expectf_(5.0 + width/2.0, bounds.X, 0.01);
4586 todo_wine
4587     expectf(5.0 + height/2.0, bounds.Y);
4588     expectf_(width, bounds.Width, 0.01);
4589     expectf(height, bounds.Height);
4590 
4591     rect.X = 5.0;
4592     rect.Y = 5.0;
4593     rect.Width = 0.0;
4594     rect.Height = 0.0;
4595     set_rect_empty(&bounds);
4596     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4597     expect(Ok, status);
4598     expect(3, glyphs);
4599     expect(1, lines);
4600 todo_wine
4601     expectf_(5.0 - width/2.0, bounds.X, 0.01);
4602 todo_wine
4603     expectf(5.0 - height/2.0, bounds.Y);
4604     expectf_(width, bounds.Width, 0.01);
4605     expectf(height, bounds.Height);
4606 
4607     rect.X = 5.0;
4608     rect.Y = 5.0;
4609     rect.Width = width_rgn * 2.0;
4610     rect.Height = height_rgn * 2.0;
4611     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4612     expect(Ok, status);
4613     set_rect_empty(&bounds);
4614     status = GdipGetRegionBounds(region, graphics, &bounds);
4615     expect(Ok, status);
4616 todo_wine
4617     expectf_(5.0 + width_rgn/2.0, bounds.X, 1.0);
4618 todo_wine
4619     expectf_(5.0 + height_rgn/2.0, bounds.Y, 1.0);
4620     expectf_(width_rgn, bounds.Width, 1.0);
4621     expectf_(height_rgn, bounds.Height, 1.0);
4622 
4623     rect.X = 5.0;
4624     rect.Y = 5.0;
4625     rect.Width = 0.0;
4626     rect.Height = 0.0;
4627     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4628     expect(Ok, status);
4629     set_rect_empty(&bounds);
4630     status = GdipGetRegionBounds(region, graphics, &bounds);
4631     expect(Ok, status);
4632 todo_wine
4633     expectf_(5.0 - width_rgn/2.0, bounds.X, 1.0);
4634 todo_wine
4635     expectf_(5.0 - height_rgn/2.0, bounds.Y, 1.0);
4636     expectf_(width_rgn, bounds.Width, 1.0);
4637     expectf_(height_rgn, bounds.Height, 1.0);
4638 
4639     /* Far alignment */
4640     GdipSetStringFormatAlign(format, StringAlignmentFar);
4641     GdipSetStringFormatLineAlign(format, StringAlignmentFar);
4642 
4643     rect.X = 5.0;
4644     rect.Y = 5.0;
4645     rect.Width = width * 2.0;
4646     rect.Height = height * 2.0;
4647     set_rect_empty(&bounds);
4648     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4649     expect(Ok, status);
4650     expect(3, glyphs);
4651     expect(1, lines);
4652 todo_wine
4653     expectf_(5.0 + width, bounds.X, 0.01);
4654 todo_wine
4655     expectf(5.0 + height, bounds.Y);
4656     expectf_(width, bounds.Width, 0.01);
4657     expectf(height, bounds.Height);
4658 
4659     rect.X = 5.0;
4660     rect.Y = 5.0;
4661     rect.Width = 0.0;
4662     rect.Height = 0.0;
4663     set_rect_empty(&bounds);
4664     status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, &glyphs, &lines);
4665     expect(Ok, status);
4666     expect(3, glyphs);
4667     expect(1, lines);
4668 todo_wine
4669     expectf_(5.0 - width, bounds.X, 0.01);
4670 todo_wine
4671     expectf(5.0 - height, bounds.Y);
4672     expectf_(width, bounds.Width, 0.01);
4673     expectf(height, bounds.Height);
4674 
4675     rect.X = 5.0;
4676     rect.Y = 5.0;
4677     rect.Width = width_rgn * 2.0;
4678     rect.Height = height_rgn * 2.0;
4679     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4680     expect(Ok, status);
4681     set_rect_empty(&bounds);
4682     status = GdipGetRegionBounds(region, graphics, &bounds);
4683     expect(Ok, status);
4684 todo_wine
4685     expectf_(5.0 + width_rgn, bounds.X, 2.0);
4686 todo_wine
4687     expectf_(5.0 + height_rgn, bounds.Y, 1.0);
4688     expectf_(width_rgn, bounds.Width, 1.0);
4689     expectf_(height_rgn, bounds.Height, 1.0);
4690 
4691     rect.X = 5.0;
4692     rect.Y = 5.0;
4693     rect.Width = 0.0;
4694     rect.Height = 0.0;
4695     status = GdipMeasureCharacterRanges(graphics, string, -1, font, &rect, format, 1, &region);
4696     expect(Ok, status);
4697     set_rect_empty(&bounds);
4698     status = GdipGetRegionBounds(region, graphics, &bounds);
4699     expect(Ok, status);
4700 todo_wine
4701     expectf_(5.0 - width_rgn, bounds.X, 2.0);
4702 todo_wine
4703     expectf_(5.0 - height_rgn, bounds.Y, 1.0);
4704     expectf_(width_rgn, bounds.Width, 1.0);
4705     expectf_(height_rgn, bounds.Height, 1.0);
4706 
4707     status = GdipDeleteFont(font);
4708     expect(Ok, status);
4709 
4710     status = GdipDeleteGraphics(graphics);
4711     expect(Ok, status);
4712     DeleteDC(hdc);
4713 
4714     GdipDeleteFontFamily(family);
4715     GdipDeleteRegion(region);
4716     GdipDeleteStringFormat(format);
4717 }
4718 
4719 static void test_measured_extra_space(void)
4720 {
4721     static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
4722     static const WCHAR string[2] = { 'W','W' };
4723     GpStringFormat *format;
4724     HDC hdc;
4725     GpGraphics *graphics;
4726     GpFontFamily *family;
4727     GpFont *font;
4728     GpStatus status;
4729     GpUnit gfx_unit, font_unit;
4730     RectF bounds_1, bounds_2, rect;
4731     REAL margin, font_size, dpi;
4732 
4733     status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
4734     expect(Ok, status);
4735 
4736     status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
4737     expect(Ok, status);
4738     hdc = CreateCompatibleDC(0);
4739     status = GdipCreateFromHDC(hdc, &graphics);
4740     expect(Ok, status);
4741 
4742     status = GdipGetDpiX(graphics, &dpi);
4743     expect(Ok, status);
4744 
4745     /* UnitPixel = 2, UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
4746     /* UnitPixel as a font base unit is not tested because it differs in behaviour */
4747     for (font_unit = 3; font_unit <= 6; font_unit++)
4748     {
4749         status = GdipCreateFont(family, 1234.0, FontStyleRegular, font_unit, &font);
4750         expect(Ok, status);
4751 
4752         status = GdipGetFontSize(font, &font_size);
4753         expect(Ok, status);
4754         font_size = units_to_pixels(font_size, font_unit, dpi);
4755         /*trace("font size/6 = %f pixels\n", font_size / 6.0);*/
4756 
4757         /* UnitPixel = 2, UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
4758         for (gfx_unit = 2; gfx_unit <= 6; gfx_unit++)
4759         {
4760             status = GdipSetPageUnit(graphics, gfx_unit);
4761             expect(Ok, status);
4762 
4763             /* bounds.width of 1 glyph: [margin]+[width]+[margin] */
4764             set_rect_empty(&rect);
4765             set_rect_empty(&bounds_1);
4766             status = GdipMeasureString(graphics, string, 1, font, &rect, format, &bounds_1, NULL, NULL);
4767             expect(Ok, status);
4768             /* bounds.width of 2 identical glyphs: [margin]+[width]+[width]+[margin] */
4769             set_rect_empty(&rect);
4770             set_rect_empty(&bounds_2);
4771             status = GdipMeasureString(graphics, string, 2, font, &rect, format, &bounds_2, NULL, NULL);
4772             expect(Ok, status);
4773 
4774             /* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
4775             margin = units_to_pixels(bounds_1.Width - bounds_2.Width / 2.0, gfx_unit, dpi);
4776             /*trace("margin %f pixels\n", margin);*/
4777             expectf_(font_size / 6.0, margin, font_size / 100.0);
4778         }
4779 
4780         GdipDeleteFont(font);
4781     }
4782 
4783     GdipDeleteGraphics(graphics);
4784     DeleteDC(hdc);
4785     GdipDeleteFontFamily(family);
4786     GdipDeleteStringFormat(format);
4787 }
4788 
4789 static void test_alpha_hdc(void)
4790 {
4791     GpStatus status;
4792     HDC hdc, gp_hdc;
4793     HBITMAP hbm, old_hbm;
4794     GpGraphics *graphics;
4795     ULONG *bits;
4796     BITMAPINFO bmi;
4797     GpRectF bounds;
4798     COLORREF colorref;
4799 
4800     hdc = CreateCompatibleDC(0);
4801     ok(hdc != NULL, "CreateCompatibleDC failed\n");
4802     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
4803     bmi.bmiHeader.biHeight = 5;
4804     bmi.bmiHeader.biWidth = 5;
4805     bmi.bmiHeader.biBitCount = 32;
4806     bmi.bmiHeader.biPlanes = 1;
4807     bmi.bmiHeader.biCompression = BI_RGB;
4808     bmi.bmiHeader.biClrUsed = 0;
4809 
4810     hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
4811     ok(hbm != NULL, "CreateDIBSection failed\n");
4812 
4813     old_hbm = SelectObject(hdc, hbm);
4814 
4815     status = GdipCreateFromHDC(hdc, &graphics);
4816     expect(Ok, status);
4817 
4818     status = GdipGetVisibleClipBounds(graphics, &bounds);
4819     expect(Ok, status);
4820     expectf(0.0, bounds.X);
4821     expectf(0.0, bounds.Y);
4822     expectf(5.0, bounds.Width);
4823     expectf(5.0, bounds.Height);
4824 
4825     bits[0] = 0xdeadbeef;
4826 
4827     status = GdipGraphicsClear(graphics, 0xffaaaaaa);
4828     expect(Ok, status);
4829 
4830     expect(0xffaaaaaa, bits[0]);
4831 
4832     bits[0] = 0xdeadbeef;
4833 
4834     status = GdipGetDC(graphics, &gp_hdc);
4835     expect(Ok, status);
4836 
4837     colorref = GetPixel(gp_hdc, 0, 4);
4838     expect(0xefbead, colorref);
4839 
4840     SetPixel(gp_hdc, 0, 4, 0xffffff);
4841 
4842     expect(0xffffff, bits[0]);
4843 
4844     status = GdipReleaseDC(graphics, gp_hdc);
4845     expect(Ok, status);
4846 
4847     SelectObject(hdc, old_hbm);
4848 
4849     bits[0] = 0xdeadbeef;
4850 
4851     status = GdipGraphicsClear(graphics, 0xffbbbbbb);
4852     expect(Ok, status);
4853 
4854     todo_wine expect(0xffbbbbbb, bits[0]);
4855 
4856     GdipDeleteGraphics(graphics);
4857 
4858     DeleteObject(hbm);
4859     DeleteDC(hdc);
4860 }
4861 
4862 static void test_bitmapfromgraphics(void)
4863 {
4864     GpStatus stat;
4865     GpGraphics *graphics = NULL;
4866     HDC hdc = GetDC( hwnd );
4867     GpBitmap *bitmap = NULL;
4868     PixelFormat format;
4869     REAL imageres, graphicsres;
4870     UINT width, height;
4871 
4872     stat = GdipCreateFromHDC(hdc, &graphics);
4873     expect(Ok, stat);
4874 
4875     stat = GdipCreateBitmapFromGraphics(12, 13, NULL, &bitmap);
4876     expect(InvalidParameter, stat);
4877 
4878     stat = GdipCreateBitmapFromGraphics(12, 13, graphics, NULL);
4879     expect(InvalidParameter, stat);
4880 
4881     stat = GdipCreateBitmapFromGraphics(12, 13, graphics, &bitmap);
4882     expect(Ok, stat);
4883 
4884     stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
4885     expect(Ok, stat);
4886     expect(PixelFormat32bppPARGB, format);
4887 
4888     stat = GdipGetDpiX(graphics, &graphicsres);
4889     expect(Ok, stat);
4890 
4891     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &imageres);
4892     expect(Ok, stat);
4893     expectf(graphicsres, imageres);
4894 
4895     stat = GdipGetDpiY(graphics, &graphicsres);
4896     expect(Ok, stat);
4897 
4898     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &imageres);
4899     expect(Ok, stat);
4900     expectf(graphicsres, imageres);
4901 
4902     stat = GdipGetImageWidth((GpImage*)bitmap, &width);
4903     expect(Ok, stat);
4904     expect(12, width);
4905 
4906     stat = GdipGetImageHeight((GpImage*)bitmap, &height);
4907     expect(Ok, stat);
4908     expect(13, height);
4909 
4910     GdipDeleteGraphics(graphics);
4911     GdipDisposeImage((GpImage*)bitmap);
4912 }
4913 
4914 static void test_clipping(void)
4915 {
4916     HDC hdc;
4917     GpStatus status;
4918     GpGraphics *graphics;
4919     GpRegion *region, *region100x100;
4920     GpMatrix *matrix;
4921     GpRectF rect;
4922     GpPointF ptf[4];
4923     GpUnit unit;
4924     HRGN hrgn;
4925     int ret;
4926     RECT rc;
4927 
4928     hdc = CreateCompatibleDC(0);
4929     status = GdipCreateFromHDC(hdc, &graphics);
4930     expect(Ok, status);
4931 
4932     status = GdipGetPageUnit(graphics, &unit);
4933     expect(Ok, status);
4934     expect(UnitDisplay, unit);
4935 
4936     status = GdipCreateRegion(&region);
4937     expect(Ok, status);
4938     status = GdipSetEmpty(region);
4939     expect(Ok, status);
4940 
4941     status = GdipCreateRegion(&region100x100);
4942     expect(Ok, status);
4943     status = GdipSetEmpty(region100x100);
4944     expect(Ok, status);
4945 
4946     rect.X = rect.Y = 100.0;
4947     rect.Width = rect.Height = 100.0;
4948     status = GdipCombineRegionRect(region100x100, &rect, CombineModeUnion);
4949     expect(Ok, status);
4950     status = GdipSetClipRegion(graphics, region100x100, CombineModeReplace);
4951     expect(Ok, status);
4952 
4953     status = GdipGetClipBounds(graphics, &rect);
4954     expect(Ok, status);
4955     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
4956        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
4957 
4958     /* Clip region does not account for changes to gdi32 transform */
4959     SetViewportOrgEx(hdc, 10, 10, NULL);
4960 
4961     status = GdipGetClipBounds(graphics, &rect);
4962     expect(Ok, status);
4963     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
4964        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
4965 
4966     SetViewportOrgEx(hdc, 0, 0, NULL);
4967 
4968     status = GdipSetEmpty(region);
4969     expect(Ok, status);
4970     status = GdipGetClip(graphics, region);
4971     expect(Ok, status);
4972     status = GdipGetRegionBounds(region, graphics, &rect);
4973     expect(Ok, status);
4974     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
4975        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
4976 
4977     ptf[0].X = 100.0;
4978     ptf[0].Y = 100.0;
4979     ptf[1].X = 200.0;
4980     ptf[1].Y = 200.0;
4981     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
4982     expect(Ok, status);
4983     ok(ptf[0].X == 100.0 && ptf[0].Y == 100.0 && ptf[1].X == 200.0 && ptf[1].Y == 200.0,
4984        "expected 100.0,100.0-200.0,200.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
4985 
4986     status = GdipCreateMatrix(&matrix);
4987     expect(Ok, status);
4988     status = GdipScaleMatrix(matrix, 2.0, 4.0, MatrixOrderAppend);
4989     expect(Ok, status);
4990     status = GdipTranslateMatrix(matrix, 10.0, 20.0, MatrixOrderAppend);
4991     expect(Ok, status);
4992     status = GdipSetWorldTransform(graphics, matrix);
4993     expect(Ok, status);
4994 
4995     status = GdipGetClipBounds(graphics, &rect);
4996     expect(Ok, status);
4997     ok(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0,
4998        "expected 45.0,20.0-50.0,25.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
4999 
5000     status = GdipSetEmpty(region);
5001     expect(Ok, status);
5002     status = GdipGetClip(graphics, region);
5003     expect(Ok, status);
5004     status = GdipGetRegionBounds(region, graphics, &rect);
5005     expect(Ok, status);
5006     ok(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0,
5007        "expected 45.0,20.0-50.0,25.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5008 
5009     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5010     expect(Ok, status);
5011     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
5012        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5013 
5014     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5015     expect(Ok, status);
5016     ret = GetRgnBox(hrgn, &rc);
5017     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5018     ok(rc.left == 45 && rc.top == 20 && rc.right == 95 && rc.bottom == 45,
5019        "expected 45,20-95,45, got %s\n", wine_dbgstr_rect(&rc));
5020     DeleteObject(hrgn);
5021 
5022     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5023     expect(Ok, status);
5024     ret = GetRgnBox(hrgn, &rc);
5025     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5026     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5027        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5028     DeleteObject(hrgn);
5029 
5030     ptf[0].X = 100.0;
5031     ptf[0].Y = 100.0;
5032     ptf[1].X = 200.0;
5033     ptf[1].Y = 200.0;
5034     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5035     expect(Ok, status);
5036     ok(ptf[0].X == 45.0 && ptf[0].Y == 20.0 && ptf[1].X == 95.0 && ptf[1].Y == 45.0,
5037        "expected 45.0,20.0-95.0,45.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5038 
5039     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5040     expect(Ok, status);
5041     ret = GetRgnBox(hrgn, &rc);
5042     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5043     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5044        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5045     DeleteObject(hrgn);
5046 
5047     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5048     expect(Ok, status);
5049     ret = GetRgnBox(hrgn, &rc);
5050     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5051     ok(rc.left == 210 && rc.top == 420 && rc.right == 410 && rc.bottom == 820,
5052        "expected 210,420-410,820, got %s\n", wine_dbgstr_rect(&rc));
5053     DeleteObject(hrgn);
5054 
5055     ptf[0].X = 210.0;
5056     ptf[0].Y = 420.0;
5057     ptf[1].X = 410.0;
5058     ptf[1].Y = 820.0;
5059     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5060     expect(Ok, status);
5061     ok(ptf[0].X == 100.0 && ptf[0].Y == 100.0 && ptf[1].X == 200.0 && ptf[1].Y == 200.0,
5062        "expected 100.0,100.0-200.0,200.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5063 
5064     status = GdipSetPageScale(graphics, 2.0);
5065     expect(Ok, status);
5066 
5067     status = GdipGetClipBounds(graphics, &rect);
5068     expect(Ok, status);
5069     ok(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0,
5070        "expected 45.0,20.0-50.0,25.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5071 
5072     status = GdipSetEmpty(region);
5073     expect(Ok, status);
5074     status = GdipGetClip(graphics, region);
5075     expect(Ok, status);
5076     status = GdipGetRegionBounds(region, graphics, &rect);
5077     expect(Ok, status);
5078     ok(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0,
5079        "expected 45.0,20.0-50.0,25.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5080 
5081     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5082     expect(Ok, status);
5083     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
5084        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5085 
5086     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5087     expect(Ok, status);
5088     ret = GetRgnBox(hrgn, &rc);
5089     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5090     ok(rc.left == 45 && rc.top == 20 && rc.right == 95 && rc.bottom == 45,
5091        "expected 45,20-95,45, got %s\n", wine_dbgstr_rect(&rc));
5092     DeleteObject(hrgn);
5093 
5094     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5095     expect(Ok, status);
5096     ret = GetRgnBox(hrgn, &rc);
5097     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5098     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5099        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5100     DeleteObject(hrgn);
5101 
5102     ptf[0].X = 100.0;
5103     ptf[0].Y = 100.0;
5104     ptf[1].X = 200.0;
5105     ptf[1].Y = 200.0;
5106     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5107     expect(Ok, status);
5108     ok(ptf[0].X == 45.0 && ptf[0].Y == 20.0 && ptf[1].X == 95.0 && ptf[1].Y == 45.0,
5109        "expected 45.0,20.0-95.0,45.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5110 
5111     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5112     expect(Ok, status);
5113     ret = GetRgnBox(hrgn, &rc);
5114     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5115     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5116        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5117     DeleteObject(hrgn);
5118 
5119     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5120     expect(Ok, status);
5121     ret = GetRgnBox(hrgn, &rc);
5122     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5123     ok(rc.left == 210 && rc.top == 420 && rc.right == 410 && rc.bottom == 820,
5124        "expected 210,420-410,820, got %s\n", wine_dbgstr_rect(&rc));
5125     DeleteObject(hrgn);
5126 
5127     ptf[0].X = 210.0;
5128     ptf[0].Y = 420.0;
5129     ptf[1].X = 410.0;
5130     ptf[1].Y = 820.0;
5131     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5132     expect(Ok, status);
5133     ok(ptf[0].X == 100.0 && ptf[0].Y == 100.0 && ptf[1].X == 200.0 && ptf[1].Y == 200.0,
5134        "expected 100.0,100.0-200.0,200.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5135 
5136     GdipSetPageUnit(graphics, UnitPoint);
5137     expect(Ok, status);
5138 
5139     status = GdipGetClipBounds(graphics, &rect);
5140     expect(Ok, status);
5141     ok((rect.X == 13.75 && rect.Y == 4.375 && rect.Width == 18.75 && rect.Height == 9.375) ||
5142        /* rounding under Wine is slightly different */
5143        (rect.X == 14.0 && rect.Y == 4.0 && rect.Width == 19.0 && rect.Height == 10.0) /* Wine */ ||
5144        broken(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0) /* before Win7 */,
5145        "expected 13.75,4.375-18.75,9.375, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5146 
5147     status = GdipSetEmpty(region);
5148     expect(Ok, status);
5149     status = GdipGetClip(graphics, region);
5150     expect(Ok, status);
5151     status = GdipGetRegionBounds(region, graphics, &rect);
5152     expect(Ok, status);
5153     ok((rect.X == 13.75 && rect.Y == 4.375 && rect.Width == 18.75 && rect.Height == 9.375) ||
5154        /* rounding under Wine is slightly different */
5155        (rect.X == 14.0 && rect.Y == 4.0 && rect.Width == 19.0 && rect.Height == 10.0) /* Wine */ ||
5156        broken(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0) /* before Win7 */,
5157        "expected 13.75,4.375-18.75,9.375, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5158 
5159     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5160     expect(Ok, status);
5161     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
5162        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5163 
5164     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5165     expect(Ok, status);
5166     ret = GetRgnBox(hrgn, &rc);
5167     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5168     ok((rc.left == 14 && rc.top == 5 && rc.right == 33 && rc.bottom == 14) ||
5169        /* rounding under Wine is slightly different */
5170        (rc.left == 14 && rc.top == 4 && rc.right == 33 && rc.bottom == 14) /* Wine */ ||
5171        broken(rc.left == 45 && rc.top == 20 && rc.right == 95 && rc.bottom == 45) /* before Win7 */,
5172        "expected 14,5-33,14, got %s\n", wine_dbgstr_rect(&rc));
5173     DeleteObject(hrgn);
5174 
5175     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5176     expect(Ok, status);
5177     ret = GetRgnBox(hrgn, &rc);
5178     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5179     ok((rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) ||
5180       broken(rc.left == 267 && rc.top == 267 && rc.right == 534 && rc.bottom == 534) /* before Win7 */,
5181        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5182     DeleteObject(hrgn);
5183 
5184     ptf[0].X = 100.0;
5185     ptf[0].Y = 100.0;
5186     ptf[1].X = 200.0;
5187     ptf[1].Y = 200.0;
5188     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5189     expect(Ok, status);
5190     ok((ptf[0].X == 13.75 && ptf[0].Y == 4.375 && ptf[1].X == 32.5 && ptf[1].Y == 13.75) ||
5191        broken(ptf[0].X == 45.0 && ptf[0].Y == 20.0 && ptf[1].X == 95.0 && ptf[1].Y == 45.0) /* before Win7 */,
5192        "expected 13.75,4.375-32.5,13.75, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5193 
5194     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5195     expect(Ok, status);
5196     ret = GetRgnBox(hrgn, &rc);
5197     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5198     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5199        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5200     DeleteObject(hrgn);
5201 
5202     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5203     expect(Ok, status);
5204     ret = GetRgnBox(hrgn, &rc);
5205     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5206     ok((rc.left == 560 && rc.top == 1120 && rc.right == 1094 && rc.bottom == 2187) ||
5207        /* rounding under Wine is slightly different */
5208        (rc.left == 560 && rc.top == 1120 && rc.right == 1093 && rc.bottom == 2187) /* Wine */,
5209        "expected 560,1120-1094,2187, got %s\n", wine_dbgstr_rect(&rc));
5210     DeleteObject(hrgn);
5211 
5212     ptf[0].X = 560.0;
5213     ptf[0].Y = 1120.0;
5214     ptf[1].X = 1094.0;
5215     ptf[1].Y = 2187.0;
5216     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5217     expect(Ok, status);
5218     if (fabs(ptf[0].X - 100.0) < 0.001)
5219     {
5220         expectf(100.0, ptf[0].X);
5221         expectf(100.0, ptf[0].Y);
5222         expectf(200.125, ptf[1].X);
5223         expectf(200.03125, ptf[1].Y);
5224     }
5225     else /* before Win7 */
5226     {
5227         ok(broken(fabs(ptf[0].X - 275.0) < 0.001), "expected 275.0, got %f\n", ptf[0].X);
5228         ok(broken(fabs(ptf[0].Y - 275.0) < 0.001), "expected 275.0, got %f\n", ptf[0].Y);
5229         ok(broken(fabs(ptf[1].X - 542.0) < 0.001), "expected 542.0, got %f\n", ptf[1].X);
5230         ok(broken(fabs(ptf[1].Y - 541.75) < 0.001), "expected 541.75, got %f\n", ptf[1].Y);
5231     }
5232 
5233     status = GdipTransformRegion(region100x100, matrix);
5234     expect(Ok, status);
5235 
5236     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5237     expect(Ok, status);
5238     ok(rect.X == 210.0 && rect.Y == 420.0 && rect.Width == 200.0 && rect.Height == 400.0,
5239        "expected 210.0,420.0-200.0,400.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
5240 
5241     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5242     expect(Ok, status);
5243     ret = GetRgnBox(hrgn, &rc);
5244     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5245     ok(rc.left == 210 && rc.top == 420 && rc.right == 410 && rc.bottom == 820,
5246        "expected 210,420-410,820, got %s\n", wine_dbgstr_rect(&rc));
5247     DeleteObject(hrgn);
5248 
5249     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5250     expect(Ok, status);
5251     ret = GetRgnBox(hrgn, &rc);
5252     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5253     ok((rc.left == 1147 && rc.top == 4534 && rc.right == 2214 && rc.bottom == 8800) ||
5254        /* rounding under Wine is slightly different */
5255        (rc.left == 1147 && rc.top == 4533 && rc.right == 2213 && rc.bottom == 8800) /* Wine */,
5256        "expected 1147,4534-2214,8800, got %s\n", wine_dbgstr_rect(&rc));
5257     DeleteObject(hrgn);
5258 
5259     ptf[0].X = 1147.0;
5260     ptf[0].Y = 4534.0;
5261     ptf[1].X = 2214.0;
5262     ptf[1].Y = 8800.0;
5263     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5264     expect(Ok, status);
5265     if (fabs(ptf[0].X - 210.0625) < 0.001)
5266     {
5267         expectf(210.0625, ptf[0].X);
5268         expectf(420.0625, ptf[0].Y);
5269         expectf(410.125, ptf[1].X);
5270         expectf(820.0, ptf[1].Y);
5271     }
5272     else /* before Win7 */
5273     {
5274         ok(broken(fabs(ptf[0].X - 568.5) < 0.001), "expected 568.5, got %f\n", ptf[0].X);
5275         ok(broken(fabs(ptf[0].Y - 1128.5) < 0.001), "expected 1128.5, got %f\n", ptf[0].Y);
5276         ok(broken(fabs(ptf[1].X - 1102.0) < 0.001), "expected 1102.0, got %f\n", ptf[1].X);
5277         ok(broken(fabs(ptf[1].Y - 2195.0) < 0.001), "expected 2195.0, got %f\n", ptf[1].Y);
5278     }
5279 
5280     status = GdipRotateMatrix(matrix, 30.0, MatrixOrderAppend);
5281     expect(Ok, status);
5282     status = GdipSetWorldTransform(graphics, matrix);
5283     expect(Ok, status);
5284 
5285     status = GdipGetClipBounds(graphics, &rect);
5286     expect(Ok, status);
5287     expectf_(20.612978, rect.X, 1.0);
5288     expectf_(-6.256012, rect.Y, 1.5);
5289     expectf_(25.612978, rect.Width, 1.0);
5290     expectf_(12.806489, rect.Height, 1.0);
5291 
5292     status = GdipSetEmpty(region);
5293     expect(Ok, status);
5294     status = GdipGetClip(graphics, region);
5295     expect(Ok, status);
5296     status = GdipGetRegionBounds(region, graphics, &rect);
5297     expect(Ok, status);
5298    /* rounding under Wine is slightly different */
5299     expectf_(20.612978, rect.X, 1.0);
5300     expectf_(-6.256012, rect.Y, 1.5);
5301     expectf_(25.612978, rect.Width, 1.0);
5302     expectf_(12.806489, rect.Height, 1.0);
5303 
5304     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5305     expect(Ok, status);
5306     ok(rect.X == 210.0 && rect.Y == 420.0 && rect.Width == 200.0 && rect.Height == 400.0,
5307        "expected 210.0,420.0-200.0,400.0, got %f,%f-%f,%f\n", rect.X, rect.Y, rect.Width, rect.Height);
5308 
5309     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5310     expect(Ok, status);
5311     ret = GetRgnBox(hrgn, &rc);
5312     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5313     ok((rc.left == 22 && rc.top == -6 && rc.right == 46 && rc.bottom == 7) ||
5314        /* rounding under Wine is slightly different */
5315        (rc.left == 21 && rc.top == -5 && rc.right == 46 && rc.bottom == 7) /* Wine */,
5316        "expected (22,-6)-(46,7), got %s\n", wine_dbgstr_rect(&rc));
5317     DeleteObject(hrgn);
5318 
5319     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5320     expect(Ok, status);
5321     ret = GetRgnBox(hrgn, &rc);
5322     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5323     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5324        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5325     DeleteObject(hrgn);
5326 
5327     ptf[0].X = 100.0;
5328     ptf[0].Y = 100.0;
5329     ptf[1].X = 200.0;
5330     ptf[1].Y = 200.0;
5331     ptf[2].X = 200.0;
5332     ptf[2].Y = 100.0;
5333     ptf[3].X = 100.0;
5334     ptf[3].Y = 200.0;
5335     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5336     expect(Ok, status);
5337     expectf(20.612978, ptf[0].X);
5338     expectf(-1.568512, ptf[0].Y);
5339     expectf(46.225956, ptf[1].X);
5340     expectf(1.862977, ptf[1].Y);
5341     expectf(36.850956, ptf[2].X);
5342     expectf(-6.256012, ptf[2].Y);
5343     expectf(29.987980, ptf[3].X);
5344     expectf(6.550478, ptf[3].Y);
5345 
5346     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5347     expect(Ok, status);
5348     ret = GetRgnBox(hrgn, &rc);
5349     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5350     ok(rc.left == 210 && rc.top == 420 && rc.right == 410 && rc.bottom == 820,
5351        "expected 210,420-410,820, got %s\n", wine_dbgstr_rect(&rc));
5352     DeleteObject(hrgn);
5353 
5354     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5355     expect(Ok, status);
5356     ret = GetRgnBox(hrgn, &rc);
5357     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5358     ok((rc.left == -3406 && rc.top == 4500 && rc.right == -350 && rc.bottom == 8728) ||
5359        /* rounding under Wine is slightly different */
5360        (rc.left == -3407 && rc.top == 4500 && rc.right == -350 && rc.bottom == 8728) /* Wine */,
5361        "expected (-3406,4500)-(-350,8728), got %s\n", wine_dbgstr_rect(&rc));
5362     DeleteObject(hrgn);
5363 
5364     ptf[0].X = -3406.0;
5365     ptf[0].Y = 4500.0;
5366     ptf[1].X = -350.0;
5367     ptf[1].Y = 8728.0;
5368     ptf[2].X = -350.0;
5369     ptf[2].Y = 4500.0;
5370     ptf[3].X = -3406.0;
5371     ptf[3].Y = 8728.0;
5372     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5373     expect(Ok, status);
5374     expectf(-136.190491, ptf[0].X);
5375     expectf(520.010742, ptf[0].Y);
5376     expectf(756.417175, ptf[1].X);
5377     expectf(720.031616, ptf[1].Y);
5378     expectf(360.042114, ptf[2].X);
5379     expectf(376.760742, ptf[2].Y);
5380     expectf(260.184570, ptf[3].X);
5381     expectf(863.281616, ptf[3].Y);
5382 
5383     status = GdipRotateMatrix(matrix, -90.0, MatrixOrderAppend);
5384     expect(Ok, status);
5385     status = GdipSetWorldTransform(graphics, matrix);
5386     expect(Ok, status);
5387 
5388     status = GdipGetClipBounds(graphics, &rect);
5389     expect(Ok, status);
5390     expectf_(-28.100956, rect.X, 1.0);
5391     expectf_(7.806488, rect.Y, 1.5);
5392     expectf_(25.612978, rect.Width, 1.0);
5393     expectf_(12.806489, rect.Height, 1.0);
5394 
5395     status = GdipSetEmpty(region);
5396     expect(Ok, status);
5397     status = GdipGetClip(graphics, region);
5398     expect(Ok, status);
5399     status = GdipGetRegionBounds(region, graphics, &rect);
5400     expect(Ok, status);
5401    /* rounding under Wine is slightly different */
5402     expectf_(-28.100956, rect.X, 1.0);
5403     expectf_(7.806488, rect.Y, 1.5);
5404     expectf_(25.612978, rect.Width, 1.0);
5405     expectf_(12.806489, rect.Height, 1.0);
5406 
5407     status = GdipGetRegionBounds(region100x100, graphics, &rect);
5408     expect(Ok, status);
5409     ok(rect.X == 210.0 && rect.Y == 420.0 && rect.Width == 200.0 && rect.Height == 400.0,
5410        "expected 210.0,420.0-200.0,400.0, got %f,%f-%f,%f\n", rect.X, rect.Y, rect.Width, rect.Height);
5411 
5412     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5413     expect(Ok, status);
5414     ret = GetRgnBox(hrgn, &rc);
5415     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5416     ok((rc.left == -27 && rc.top == 8 && rc.right == -2 && rc.bottom == 21) ||
5417        /* rounding under Wine is slightly different */
5418        (rc.left == -28 && rc.top == 9 && rc.right == -2 && rc.bottom == 21) /* Wine */,
5419        "expected (-27,8)-(-2,21), got %s\n", wine_dbgstr_rect(&rc));
5420     DeleteObject(hrgn);
5421 
5422     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5423     expect(Ok, status);
5424     ret = GetRgnBox(hrgn, &rc);
5425     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5426     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5427        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5428     DeleteObject(hrgn);
5429 
5430     ptf[0].X = 100.0;
5431     ptf[0].Y = 100.0;
5432     ptf[1].X = 200.0;
5433     ptf[1].Y = 200.0;
5434     ptf[2].X = 200.0;
5435     ptf[2].Y = 100.0;
5436     ptf[3].X = 100.0;
5437     ptf[3].Y = 200.0;
5438     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5439     expect(Ok, status);
5440     expectf(-11.862979, ptf[0].X);
5441     expectf(7.806488, ptf[0].Y);
5442     expectf(-18.725958, ptf[1].X);
5443     expectf(20.612976, ptf[1].Y);
5444     expectf(-2.487981, ptf[2].X);
5445     expectf(15.925477, ptf[2].Y);
5446     expectf(-28.100956, ptf[3].X);
5447     expectf(12.493987, ptf[3].Y);
5448 
5449     status = GdipGetRegionHRgn(region100x100, NULL, &hrgn);
5450     expect(Ok, status);
5451     ret = GetRgnBox(hrgn, &rc);
5452     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5453     ok(rc.left == 210 && rc.top == 420 && rc.right == 410 && rc.bottom == 820,
5454        "expected 210,420-410,820, got %s\n", wine_dbgstr_rect(&rc));
5455     DeleteObject(hrgn);
5456 
5457     status = GdipGetRegionHRgn(region100x100, graphics, &hrgn);
5458     expect(Ok, status);
5459     ret = GetRgnBox(hrgn, &rc);
5460     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5461     ok((rc.left == 4500 && rc.top == 351 && rc.right == 8728 && rc.bottom == 3407) ||
5462        /* rounding under Wine is slightly different */
5463        (rc.left == 4499 && rc.top == 351 && rc.right == 8728 && rc.bottom == 3407) /* Wine */,
5464        "expected (4500,351)-(8728,3407), got %s\n", wine_dbgstr_rect(&rc));
5465     DeleteObject(hrgn);
5466 
5467     ptf[0].X = -3406.0;
5468     ptf[0].Y = 4500.0;
5469     ptf[1].X = -350.0;
5470     ptf[1].Y = 8728.0;
5471     ptf[2].X = -350.0;
5472     ptf[2].Y = 4500.0;
5473     ptf[3].X = -3406.0;
5474     ptf[3].Y = 8728.0;
5475     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5476     expect(Ok, status);
5477     expectf(-1055.021484, ptf[0].X);
5478     expectf(-70.595329, ptf[0].Y);
5479     expectf(-1455.063232, ptf[1].X);
5480     expectf(375.708435, ptf[1].Y);
5481     expectf(-768.521484, ptf[2].X);
5482     expectf(177.520981, ptf[2].Y);
5483     expectf(-1741.563110, ptf[3].X);
5484     expectf(127.592125, ptf[3].Y);
5485 
5486     GdipDeleteMatrix(matrix);
5487     GdipDeleteRegion(region);
5488     GdipDeleteRegion(region100x100);
5489     GdipDeleteGraphics(graphics);
5490     DeleteDC(hdc);
5491 }
5492 
5493 static void test_clipping_2(void)
5494 {
5495 
5496     HDC hdc;
5497     GpStatus status;
5498     GpGraphics *graphics;
5499     GpRegion *region;
5500     GpMatrix *matrix;
5501     GpRectF rect;
5502     GpPointF ptf[4];
5503     GpUnit unit;
5504     HRGN hrgn;
5505     int ret;
5506     RECT rc;
5507 
5508     hdc = CreateCompatibleDC(0);
5509     status = GdipCreateFromHDC(hdc, &graphics);
5510     expect(Ok, status);
5511 
5512     status = GdipGetPageUnit(graphics, &unit);
5513     expect(Ok, status);
5514     expect(UnitDisplay, unit);
5515 
5516     GdipSetPageUnit(graphics, UnitInch);
5517 
5518     status = GdipCreateRegion(&region);
5519     expect(Ok, status);
5520     status = GdipSetEmpty(region);
5521     expect(Ok, status);
5522     rect.X = rect.Y = 100.0;
5523     rect.Width = rect.Height = 100.0;
5524     status = GdipCombineRegionRect(region, &rect, CombineModeUnion);
5525     expect(Ok, status);
5526     status = GdipSetClipRegion(graphics, region, CombineModeReplace);
5527     expect(Ok, status);
5528 
5529     status = GdipGetClip(graphics, region);
5530     expect(Ok, status);
5531     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5532     expect(Ok, status);
5533     ret = GetRgnBox(hrgn, &rc);
5534     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5535     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5536        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5537     DeleteObject(hrgn);
5538     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5539     expect(Ok, status);
5540     ret = GetRgnBox(hrgn, &rc);
5541     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5542     ok(rc.left == 9600 && rc.top == 9600 && rc.right == 19200 && rc.bottom == 19200,
5543        "expected 9600,9600-19200,19200, got %s\n", wine_dbgstr_rect(&rc));
5544     DeleteObject(hrgn);
5545 
5546     ptf[0].X = 9600.0;
5547     ptf[0].Y = 9600.0;
5548     ptf[1].X = 19200.0;
5549     ptf[1].Y = 19200.0;
5550     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5551     expect(Ok, status);
5552     expectf(100.0, ptf[0].X);
5553     expectf(100.0, ptf[0].Y);
5554     expectf(200.0, ptf[1].X);
5555     expectf(200.0, ptf[1].X);
5556 
5557     GdipSetPageUnit(graphics, UnitPoint);
5558 
5559     status = GdipGetClip(graphics, region);
5560     expect(Ok, status);
5561     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5562     expect(Ok, status);
5563     ret = GetRgnBox(hrgn, &rc);
5564     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5565     ok((rc.left == 7200 && rc.top == 7200 && rc.right == 14400 && rc.bottom == 14400) ||
5566        broken(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) /* before Win7 */,
5567        "expected 7200,7200-14400,14400, got %s\n", wine_dbgstr_rect(&rc));
5568     DeleteObject(hrgn);
5569     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5570     expect(Ok, status);
5571     ret = GetRgnBox(hrgn, &rc);
5572     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5573     ok((rc.left == 9600 && rc.top == 9600 && rc.right == 19200 && rc.bottom == 19200) ||
5574        broken(rc.left == 134 && rc.top == 134 && rc.right == 267 && rc.bottom == 267) /* before Win7 */,
5575        "expected 9600,9600-19200,19200, got %s\n", wine_dbgstr_rect(&rc));
5576     DeleteObject(hrgn);
5577 
5578     ptf[0].X = 9600.0;
5579     ptf[0].Y = 9600.0;
5580     ptf[1].X = 19200.0;
5581     ptf[1].Y = 19200.0;
5582     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5583     expect(Ok, status);
5584     if (fabs(ptf[0].X - 7200.0) < 0.001)
5585         ok(ptf[0].X == 7200.0 && ptf[0].Y == 7200.0 && ptf[1].X == 14400.0 && ptf[1].Y == 14400.0,
5586            "expected 7200.0,7200.0-14400.0,14400.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5587     else /* before Win7 */
5588     {
5589         ok(broken(fabs(ptf[0].X - 100.0) < 0.001), "expected 100.0, got %f\n", ptf[0].X);
5590         ok(broken(fabs(ptf[0].Y - 100.0) < 0.001), "expected 100.0, got %f\n", ptf[0].Y);
5591         ok(broken(fabs(ptf[1].X - 200.0) < 0.001), "expected 200.0, got %f\n", ptf[1].X);
5592         ok(broken(fabs(ptf[1].Y - 200.0) < 0.001), "expected 200.0, got %f\n", ptf[1].Y);
5593     }
5594 
5595     GdipDeleteRegion(region);
5596 
5597     GdipSetPageUnit(graphics, UnitPixel);
5598 
5599     status = GdipCreateRegion(&region);
5600     expect(Ok, status);
5601     status = GdipSetEmpty(region);
5602     expect(Ok, status);
5603     rect.X = rect.Y = 100.0;
5604     rect.Width = rect.Height = 100.0;
5605     status = GdipCombineRegionRect(region, &rect, CombineModeUnion);
5606     expect(Ok, status);
5607     status = GdipSetClipRegion(graphics, region, CombineModeReplace);
5608     expect(Ok, status);
5609 
5610     status = GdipGetClip(graphics, region);
5611     expect(Ok, status);
5612     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5613     expect(Ok, status);
5614     ret = GetRgnBox(hrgn, &rc);
5615     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5616     ok((rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) ||
5617        broken(rc.left == 2 && rc.top == 2 && rc.right == 3 && rc.bottom == 3) /* before Win7 */,
5618        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5619     DeleteObject(hrgn);
5620     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5621     expect(Ok, status);
5622     ret = GetRgnBox(hrgn, &rc);
5623     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5624     ok((rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) ||
5625        broken(rc.left == 2 && rc.top == 2 && rc.right == 3 && rc.bottom == 3) /* before Win7 */,
5626        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5627     DeleteObject(hrgn);
5628 
5629     ptf[0].X = 100.0;
5630     ptf[0].Y = 100.0;
5631     ptf[1].X = 200.0;
5632     ptf[1].Y = 200.0;
5633     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5634     expect(Ok, status);
5635     if (fabs(ptf[0].X - 100.0) < 0.001)
5636         ok(ptf[0].X == 100.0 && ptf[0].Y == 100.0 && ptf[1].X == 200.0 && ptf[1].Y == 200.0,
5637            "expected 100.0,100.0-200.0,200.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5638     else /* before Win7 */
5639     {
5640         ok(broken(fabs(ptf[0].X - 1.041667) < 0.001), "expected 1.041667, got %f\n", ptf[0].X);
5641         ok(broken(fabs(ptf[0].Y - 1.041667) < 0.001), "expected 1.041667, got %f\n", ptf[0].Y);
5642         ok(broken(fabs(ptf[1].X - 2.083333) < 0.001), "expected 2.083333, got %f\n", ptf[1].X);
5643         ok(broken(fabs(ptf[1].Y - 2.083333) < 0.001), "expected 2.083333, got %f\n", ptf[1].Y);
5644     }
5645 
5646     GdipSetPageUnit(graphics, UnitPoint);
5647 
5648     status = GdipGetClip(graphics, region);
5649     expect(Ok, status);
5650     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5651     expect(Ok, status);
5652     ret = GetRgnBox(hrgn, &rc);
5653     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5654     ok((rc.left == 75 && rc.top == 75 && rc.right == 150 && rc.bottom == 150) ||
5655        broken(rc.left == 2 && rc.top == 2 && rc.right == 3 && rc.bottom == 3) /* before Win7 */,
5656        "expected 75,75-150,150, got %s\n", wine_dbgstr_rect(&rc));
5657     DeleteObject(hrgn);
5658     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5659     expect(Ok, status);
5660     ret = GetRgnBox(hrgn, &rc);
5661     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5662     ok((rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) ||
5663        broken(rc.left == 2 && rc.top == 2 && rc.right == 3 && rc.bottom == 3) /* before Win7 */,
5664        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5665     DeleteObject(hrgn);
5666 
5667     ptf[0].X = 100.0;
5668     ptf[0].Y = 100.0;
5669     ptf[1].X = 200.0;
5670     ptf[1].Y = 200.0;
5671     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5672     expect(Ok, status);
5673     if (fabs(ptf[0].X - 75.0) < 0.001)
5674         ok(ptf[0].X == 75.0 && ptf[0].Y == 75.0 && ptf[1].X == 150.0 && ptf[1].Y == 150.0,
5675            "expected 75.0,75.0-150.0,150.0, got %f,%f-%f,%f\n", ptf[0].X, ptf[0].Y, ptf[1].X, ptf[1].Y);
5676     else /* before Win7 */
5677     {
5678         ok(broken(fabs(ptf[0].X - 1.041667) < 0.001), "expected 1.041667, got %f\n", ptf[0].X);
5679         ok(broken(fabs(ptf[0].Y - 1.041667) < 0.001), "expected 1.041667, got %f\n", ptf[0].Y);
5680         ok(broken(fabs(ptf[1].X - 2.083333) < 0.001), "expected 2.083333, got %f\n", ptf[1].X);
5681         ok(broken(fabs(ptf[1].Y - 2.083333) < 0.001), "expected 2.083333, got %f\n", ptf[1].Y);
5682     }
5683 
5684     status = GdipCreateMatrix(&matrix);
5685     expect(Ok, status);
5686     status = GdipTranslateMatrix(matrix, 10.0, 10.0, MatrixOrderAppend);
5687     expect(Ok, status);
5688     status = GdipSetWorldTransform(graphics, matrix);
5689     expect(Ok, status);
5690     GdipDeleteMatrix(matrix);
5691 
5692     status = GdipGetClip(graphics, region);
5693     expect(Ok, status);
5694     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5695     expect(Ok, status);
5696     ret = GetRgnBox(hrgn, &rc);
5697     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5698     ok(rc.left == 65 && rc.top == 65 && rc.right == 140 && rc.bottom == 140,
5699        "expected 65,65-140,140, got %s\n", wine_dbgstr_rect(&rc));
5700     DeleteObject(hrgn);
5701     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5702     expect(Ok, status);
5703     ret = GetRgnBox(hrgn, &rc);
5704     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5705     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5706        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5707     DeleteObject(hrgn);
5708 
5709     ptf[0].X = 100.0;
5710     ptf[0].Y = 100.0;
5711     ptf[1].X = 200.0;
5712     ptf[1].Y = 200.0;
5713     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5714     expect(Ok, status);
5715     expectf(65.0, ptf[0].X);
5716     expectf(65.0, ptf[0].Y);
5717     expectf(140.0, ptf[1].X);
5718     expectf(140.0, ptf[1].X);
5719 
5720     status = GdipCreateMatrix(&matrix);
5721     expect(Ok, status);
5722     status = GdipScaleMatrix(matrix, 0.25, 0.5, MatrixOrderAppend);
5723     expect(Ok, status);
5724     status = GdipSetWorldTransform(graphics, matrix);
5725     expect(Ok, status);
5726     GdipDeleteMatrix(matrix);
5727 
5728     status = GdipGetClip(graphics, region);
5729     expect(Ok, status);
5730     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5731     expect(Ok, status);
5732     ret = GetRgnBox(hrgn, &rc);
5733     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5734     ok(rc.left == 300 && rc.top == 150 && rc.right == 600 && rc.bottom == 300,
5735        "expected 300,150-600,300, got %s\n", wine_dbgstr_rect(&rc));
5736     DeleteObject(hrgn);
5737     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5738     expect(Ok, status);
5739     ret = GetRgnBox(hrgn, &rc);
5740     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5741     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5742        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5743     DeleteObject(hrgn);
5744 
5745     ptf[0].X = 100.0;
5746     ptf[0].Y = 100.0;
5747     ptf[1].X = 200.0;
5748     ptf[1].Y = 200.0;
5749     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5750     expect(Ok, status);
5751     expectf(300.0, ptf[0].X);
5752     expectf(150.0, ptf[0].Y);
5753     expectf(600.0, ptf[1].X);
5754     expectf(300.0, ptf[1].Y);
5755 
5756     status = GdipSetPageScale(graphics, 2.0);
5757     expect(Ok, status);
5758 
5759     status = GdipGetClip(graphics, region);
5760     expect(Ok, status);
5761     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5762     expect(Ok, status);
5763     ret = GetRgnBox(hrgn, &rc);
5764     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5765     ok((rc.left == 150 && rc.top == 75 && rc.right == 300 && rc.bottom == 150) ||
5766        broken(rc.left == 300 && rc.top == 150 && rc.right == 600 && rc.bottom == 300) /* before Win7 */,
5767        "expected 150,75-300,150, got %s\n", wine_dbgstr_rect(&rc));
5768     DeleteObject(hrgn);
5769     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5770     expect(Ok, status);
5771     ret = GetRgnBox(hrgn, &rc);
5772     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5773     ok((rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200) ||
5774        broken(rc.left == 200 && rc.top == 200 && rc.right == 400 && rc.bottom == 400) /* before Win7 */,
5775        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5776     DeleteObject(hrgn);
5777 
5778     ptf[0].X = 100.0;
5779     ptf[0].Y = 100.0;
5780     ptf[1].X = 200.0;
5781     ptf[1].Y = 200.0;
5782     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
5783     expect(Ok, status);
5784     if (fabs(ptf[0].X - 150.0) < 0.001)
5785     {
5786         expectf(150.0, ptf[0].X);
5787         expectf(75.0, ptf[0].Y);
5788         expectf(300.0, ptf[1].X);
5789         expectf(150.0, ptf[1].Y);
5790     }
5791     else /* before Win7 */
5792     {
5793         ok(broken(fabs(ptf[0].X - 300.0) < 0.001), "expected 300.0, got %f\n", ptf[0].X);
5794         ok(broken(fabs(ptf[0].Y - 150.0) < 0.001), "expected 150.0, got %f\n", ptf[0].Y);
5795         ok(broken(fabs(ptf[1].X - 600.0) < 0.001), "expected 600.0, got %f\n", ptf[1].X);
5796         ok(broken(fabs(ptf[1].Y - 300.0) < 0.001), "expected 300.0, got %f\n", ptf[1].Y);
5797     }
5798 
5799     status = GdipCreateMatrix(&matrix);
5800     expect(Ok, status);
5801     status = GdipRotateMatrix(matrix, 45.0, MatrixOrderAppend);
5802     expect(Ok, status);
5803     status = GdipSetWorldTransform(graphics, matrix);
5804     expect(Ok, status);
5805     GdipDeleteMatrix(matrix);
5806 
5807     status = GdipGetClip(graphics, region);
5808     expect(Ok, status);
5809     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5810     expect(Ok, status);
5811     ret = GetRgnBox(hrgn, &rc);
5812     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5813     ok((rc.left == 54 && rc.top == -26 && rc.right == 107 && rc.bottom == 27) ||
5814        /* rounding under Wine is slightly different */
5815        (rc.left == 53 && rc.top == -26 && rc.right == 106 && rc.bottom == 27) /* Wine */,
5816        "expected 54,-26-107,27, got %s\n", wine_dbgstr_rect(&rc));
5817     DeleteObject(hrgn);
5818     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5819     expect(Ok, status);
5820     ret = GetRgnBox(hrgn, &rc);
5821     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5822     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5823        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5824     DeleteObject(hrgn);
5825 
5826     ptf[0].X = 100.0;
5827     ptf[0].Y = 100.0;
5828     ptf[1].X = 200.0;
5829     ptf[1].Y = 200.0;
5830     ptf[2].X = 200.0;
5831     ptf[2].Y = 100.0;
5832     ptf[3].X = 100.0;
5833     ptf[3].Y = 200.0;
5834     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5835     expect(Ok, status);
5836     expectf(53.033016, ptf[0].X);
5837     expectf(0.0, ptf[0].Y);
5838     expectf(106.066032, ptf[1].X);
5839     expectf(0.0, ptf[1].Y);
5840     expectf(79.549522, ptf[2].X);
5841     expectf(-26.516510, ptf[2].Y);
5842     expectf(79.549522, ptf[3].X);
5843     expectf(26.516508, ptf[3].Y);
5844 
5845     status = GdipCreateMatrix(&matrix);
5846     expect(Ok, status);
5847     status = GdipRotateMatrix(matrix, -45.0, MatrixOrderAppend);
5848     expect(Ok, status);
5849     status = GdipSetWorldTransform(graphics, matrix);
5850     expect(Ok, status);
5851     GdipDeleteMatrix(matrix);
5852 
5853     status = GdipGetClip(graphics, region);
5854     expect(Ok, status);
5855     status = GdipGetRegionHRgn(region, NULL, &hrgn);
5856     expect(Ok, status);
5857     ret = GetRgnBox(hrgn, &rc);
5858     ok(ret == COMPLEXREGION, "expected COMPLEXREGION, got %d\n", ret);
5859     ok((rc.left == -26 && rc.top == 54 && rc.right == 27 && rc.bottom == 107) ||
5860        /* rounding under Wine is slightly different */
5861        (rc.left == -27 && rc.top == 54 && rc.right == 27 && rc.bottom == 106) /* Wine */,
5862        "expected -26,54-27,107, got %s\n", wine_dbgstr_rect(&rc));
5863     DeleteObject(hrgn);
5864     status = GdipGetRegionHRgn(region, graphics, &hrgn);
5865     expect(Ok, status);
5866     ret = GetRgnBox(hrgn, &rc);
5867     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
5868     ok(rc.left == 100 && rc.top == 100 && rc.right == 200 && rc.bottom == 200,
5869        "expected 100,100-200,200, got %s\n", wine_dbgstr_rect(&rc));
5870     DeleteObject(hrgn);
5871 
5872     ptf[0].X = 100.0;
5873     ptf[0].Y = 100.0;
5874     ptf[1].X = 200.0;
5875     ptf[1].Y = 200.0;
5876     ptf[2].X = 200.0;
5877     ptf[2].Y = 100.0;
5878     ptf[3].X = 100.0;
5879     ptf[3].Y = 200.0;
5880     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 4);
5881     expect(Ok, status);
5882     expectf(0.0, ptf[0].X);
5883     expectf(53.033005, ptf[0].Y);
5884     expectf(0.0, ptf[1].X);
5885     expectf(106.066010, ptf[1].Y);
5886     expectf(26.516491, ptf[2].X);
5887     expectf(79.549507, ptf[2].Y);
5888     expectf(-26.516520, ptf[3].X);
5889     expectf(79.549500, ptf[3].Y);
5890 
5891     GdipDeleteRegion(region);
5892     GdipDeleteGraphics(graphics);
5893     DeleteDC(hdc);
5894 }
5895 
5896 
5897 static void test_GdipFillRectangles(void)
5898 {
5899     GpStatus status;
5900     GpGraphics *graphics = NULL;
5901     GpBrush *brush = NULL;
5902     HDC hdc = GetDC( hwnd );
5903     GpRectF rects[2] = {{0,0,10,10}, {10,10,10,10}};
5904 
5905     ok(hdc != NULL, "Expected HDC to be initialized\n");
5906 
5907     status = GdipCreateFromHDC(hdc, &graphics);
5908     expect(Ok, status);
5909     ok(graphics != NULL, "Expected graphics to be initialized\n");
5910 
5911     status = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
5912     expect(Ok, status);
5913     ok(brush != NULL, "Expected brush to be initialized\n");
5914 
5915     status = GdipFillRectangles(NULL, brush, rects, 2);
5916     expect(InvalidParameter, status);
5917 
5918     status = GdipFillRectangles(graphics, NULL, rects, 2);
5919     expect(InvalidParameter, status);
5920 
5921     status = GdipFillRectangles(graphics, brush, NULL, 2);
5922     expect(InvalidParameter, status);
5923 
5924     status = GdipFillRectangles(graphics, brush, rects, 0);
5925     expect(InvalidParameter, status);
5926 
5927     status = GdipFillRectangles(graphics, brush, rects, -1);
5928     expect(InvalidParameter, status);
5929 
5930     status = GdipFillRectangles(graphics, brush, rects, 1);
5931     expect(Ok, status);
5932 
5933     status = GdipFillRectangles(graphics, brush, rects, 2);
5934     expect(Ok, status);
5935 
5936     GdipDeleteBrush(brush);
5937     GdipDeleteGraphics(graphics);
5938 
5939     ReleaseDC(hwnd, hdc);
5940 }
5941 
5942 static void test_GdipGetVisibleClipBounds_memoryDC(void)
5943 {
5944     HDC hdc,dc;
5945     HBITMAP bmp;
5946     HGDIOBJ old;
5947     RECT rect;
5948     POINT pt;
5949     int width = 0;
5950     int height = 0;
5951     GpGraphics* graphics = NULL;
5952     GpRect boundRect;
5953     GpStatus status;
5954 
5955     ok(GetClientRect(hwnd, &rect), "GetClientRect should have succeeded\n");
5956     width = rect.right - rect.left;
5957     height = rect.bottom - rect.top;
5958 
5959     dc = GetDC(hwnd);
5960     hdc = CreateCompatibleDC ( dc );
5961     bmp = CreateCompatibleBitmap ( dc, width, height );
5962     old = SelectObject (hdc, bmp);
5963 
5964     /*change the window origin is the key test point*/
5965     SetWindowOrgEx (hdc, rect.left+10, rect.top+10, &pt);
5966 
5967     status = GdipCreateFromHDC(hdc, &graphics);
5968     expect(Ok, status);
5969 
5970     status = GdipGetVisibleClipBoundsI(graphics, &boundRect);
5971     expect(Ok, status);
5972 
5973     ok(boundRect.X==rect.left+10 &&
5974        boundRect.Y==rect.top+10 &&
5975        boundRect.Width==width &&
5976        boundRect.Height==height, "Expected GdipGetVisibleClipBoundsI ok\n");
5977 
5978     status = GdipSetClipRectI(graphics, 0, 0, width, height, CombineModeReplace);
5979     expect(Ok, status);
5980 
5981     status = GdipGetVisibleClipBoundsI(graphics, &boundRect);
5982     expect(Ok, status);
5983 
5984     ok(boundRect.X==rect.left+10 &&
5985        boundRect.Y==rect.top+10 &&
5986        boundRect.Width==width-10 &&
5987        boundRect.Height==height-10, "Expected GdipGetVisibleClipBoundsI ok\n");
5988 
5989     GdipDeleteGraphics(graphics);
5990 
5991     SelectObject (hdc, old);
5992     DeleteObject (bmp);
5993     DeleteDC (hdc);
5994     ReleaseDC(hwnd, dc);
5995 }
5996 
5997 static void test_container_rects(void)
5998 {
5999     GpStatus status;
6000     GpGraphics *graphics;
6001     HDC hdc = GetDC( hwnd );
6002     GpRectF dstrect, srcrect;
6003     GraphicsContainer state;
6004     static const GpPointF test_points[3] = {{0.0,0.0}, {1.0,0.0}, {0.0,1.0}};
6005     GpPointF points[3];
6006     REAL dpix, dpiy;
6007 
6008     status = GdipCreateFromHDC(hdc, &graphics);
6009     expect(Ok, status);
6010 
6011     dstrect.X = 0.0;
6012     dstrect.Y = 0.0;
6013     dstrect.Width = 1.0;
6014     dstrect.Height = 1.0;
6015     srcrect = dstrect;
6016 
6017     status = GdipGetDpiX(graphics, &dpix);
6018     expect(Ok, status);
6019 
6020     status = GdipGetDpiY(graphics, &dpiy);
6021     expect(Ok, status);
6022 
6023     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitWorld, &state);
6024     expect(InvalidParameter, status);
6025 
6026     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitDisplay, &state);
6027     expect(InvalidParameter, status);
6028 
6029     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitMillimeter+1, &state);
6030     expect(InvalidParameter, status);
6031 
6032     status = GdipBeginContainer(NULL, &dstrect, &srcrect, UnitPixel, &state);
6033     expect(InvalidParameter, status);
6034 
6035     status = GdipBeginContainer(graphics, NULL, &srcrect, UnitPixel, &state);
6036     expect(InvalidParameter, status);
6037 
6038     status = GdipBeginContainer(graphics, &dstrect, NULL, UnitPixel, &state);
6039     expect(InvalidParameter, status);
6040 
6041     status = GdipBeginContainer(graphics, &dstrect, &srcrect, -1, &state);
6042     expect(InvalidParameter, status);
6043 
6044     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, NULL);
6045     expect(InvalidParameter, status);
6046 
6047     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
6048     expect(Ok, status);
6049 
6050     memcpy(points, test_points, sizeof(points));
6051     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6052     expect(Ok, status);
6053     expectf(0.0, points[0].X);
6054     expectf(0.0, points[0].Y);
6055     expectf(1.0, points[1].X);
6056     expectf(0.0, points[1].Y);
6057     expectf(0.0, points[2].X);
6058     expectf(1.0, points[2].Y);
6059 
6060     status = GdipEndContainer(graphics, state);
6061     expect(Ok, status);
6062 
6063     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
6064     expect(Ok, status);
6065 
6066     memcpy(points, test_points, sizeof(points));
6067     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6068     expect(Ok, status);
6069     expectf(0.0, points[0].X);
6070     expectf(0.0, points[0].Y);
6071     expectf(1.0/dpix, points[1].X);
6072     expectf(0.0, points[1].Y);
6073     expectf(0.0, points[2].X);
6074     expectf(1.0/dpiy, points[2].Y);
6075 
6076     status = GdipEndContainer(graphics, state);
6077     expect(Ok, status);
6078 
6079     status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
6080     expect(Ok, status);
6081 
6082     dstrect.X = 1.0;
6083     dstrect.Height = 3.0;
6084     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
6085     expect(Ok, status);
6086 
6087     memcpy(points, test_points, sizeof(points));
6088     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6089     expect(Ok, status);
6090     expectf(2.0, points[0].X);
6091     expectf(0.0, points[0].Y);
6092     expectf(4.0, points[1].X);
6093     expectf(0.0, points[1].Y);
6094     expectf(2.0, points[2].X);
6095     expectf(6.0, points[2].Y);
6096 
6097     status = GdipEndContainer(graphics, state);
6098     expect(Ok, status);
6099 
6100     memcpy(points, test_points, sizeof(points));
6101     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6102     expect(Ok, status);
6103     expectf(0.0, points[0].X);
6104     expectf(0.0, points[0].Y);
6105     expectf(2.0, points[1].X);
6106     expectf(0.0, points[1].Y);
6107     expectf(0.0, points[2].X);
6108     expectf(2.0, points[2].Y);
6109 
6110     status = GdipResetWorldTransform(graphics);
6111     expect(Ok, status);
6112 
6113     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
6114     expect(Ok, status);
6115 
6116     memcpy(points, test_points, sizeof(points));
6117     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6118     expect(Ok, status);
6119     expectf(1.0, points[0].X);
6120     expectf(0.0, points[0].Y);
6121     expectf((dpix+1.0)/dpix, points[1].X);
6122     expectf(0.0, points[1].Y);
6123     expectf(1.0, points[2].X);
6124     expectf(3.0/dpiy, points[2].Y);
6125 
6126     status = GdipEndContainer(graphics, state);
6127     expect(Ok, status);
6128 
6129     status = GdipSetPageUnit(graphics, UnitInch);
6130     expect(Ok, status);
6131 
6132     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
6133     expect(Ok, status);
6134 
6135     memcpy(points, test_points, sizeof(points));
6136     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6137     expect(Ok, status);
6138     expectf(dpix, points[0].X);
6139     expectf(0.0, points[0].Y);
6140     expectf(dpix*2, points[1].X);
6141     expectf(0.0, points[1].Y);
6142     expectf(dpix, points[2].X);
6143     expectf(dpiy*3, points[2].Y);
6144 
6145     status = GdipEndContainer(graphics, state);
6146     expect(Ok, status);
6147 
6148     status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
6149     expect(Ok, status);
6150 
6151     memcpy(points, test_points, sizeof(points));
6152     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
6153     expect(Ok, status);
6154     expectf(dpix, points[0].X);
6155     expectf(0.0, points[0].Y);
6156     expectf(dpix+1.0, points[1].X);
6157     expectf(0.0, points[1].Y);
6158     expectf(dpix, points[2].X);
6159     expectf(3.0, points[2].Y);
6160 
6161     status = GdipEndContainer(graphics, state);
6162     expect(Ok, status);
6163 
6164     GdipDeleteGraphics(graphics);
6165 
6166     ReleaseDC(hwnd, hdc);
6167 }
6168 
6169 static void test_GdipGraphicsSetAbort(void)
6170 {
6171     HDC hdc;
6172     GpStatus status;
6173     GpGraphics *graphics;
6174 
6175     if (!pGdipGraphicsSetAbort)
6176     {
6177         win_skip("GdipGraphicsSetAbort() is not supported.\n");
6178         return;
6179     }
6180 
6181     hdc = GetDC(hwnd);
6182 
6183     status = GdipCreateFromHDC(hdc, &graphics);
6184     expect(Ok, status);
6185 
6186     status = pGdipGraphicsSetAbort(NULL, NULL);
6187     expect(InvalidParameter, status);
6188 
6189     status = pGdipGraphicsSetAbort(graphics, NULL);
6190     expect(Ok, status);
6191 
6192     GdipDeleteGraphics(graphics);
6193 
6194     ReleaseDC(hwnd, hdc);
6195 }
6196 
6197 #define BLUE_COLOR (0xff0000ff)
6198 #define is_blue_color(color) ( ((color) & 0x00ffffff) == 0xff )
6199 #define get_bitmap_pixel(x,y) pixel[(y)*(width) + (x)]
6200 static DWORD* GetBitmapPixelBuffer(HDC hdc, HBITMAP hbmp, int width, int height)
6201 {
6202     BITMAPINFOHEADER bi;
6203     UINT lines = 0;
6204     DWORD *buffer = (DWORD *)GdipAlloc(width*height*4);
6205 
6206     bi.biSize = sizeof(BITMAPINFOHEADER);
6207     bi.biWidth = width;
6208     bi.biHeight = -height; /*very Important, set negative, indicating a top-down DIB*/
6209     bi.biPlanes = 1;
6210     bi.biBitCount = 32;
6211     bi.biCompression = BI_RGB;
6212     bi.biSizeImage = 0;
6213     bi.biXPelsPerMeter = 0;
6214     bi.biYPelsPerMeter = 0;
6215     bi.biClrUsed = 0;
6216     bi.biClrImportant = 0;
6217 
6218     lines = GetDIBits(hdc, hbmp, 0, height, buffer, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
6219     ok(lines == height, "Expected GetDIBits:%p,%d->%d,%d\n", buffer, height, lines, GetLastError());
6220 
6221     return buffer;
6222 }
6223 
6224 static void ReleaseBitmapPixelBuffer(DWORD* buffer)
6225 {
6226     if (buffer) GdipFree(buffer);
6227 }
6228 
6229 static void test_GdipFillRectanglesOnMemoryDCSolidBrush(void)
6230 {
6231     ARGB color[6] = {0,0,0,0,0,0};
6232     POINT pt = {0,0};
6233     RECT rect = {100, 100, 180, 180};
6234     UINT width = rect.right - rect.left;
6235     UINT height = rect.bottom - rect.top;
6236     GpStatus status = 0;
6237     GpSolidFill *brush = NULL;
6238     GpGraphics *graphics = NULL;
6239     HDC dc = GetDC( hwnd);
6240     HDC hdc = CreateCompatibleDC(dc);
6241     HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
6242     HGDIOBJ old = SelectObject(hdc, bmp);
6243     DWORD* pixel = NULL;
6244 
6245     /*Change the window origin is the key test point*/
6246     SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
6247 
6248     status = GdipCreateSolidFill(BLUE_COLOR, &brush);
6249     expect(Ok, status);
6250 
6251     status = GdipCreateFromHDC(hdc, &graphics);
6252     expect(Ok, status);
6253 
6254     status = GdipSetClipRectI(graphics, rect.left+width/2, rect.top+height/2,
6255             width, height, CombineModeReplace);
6256     expect(Ok, status);
6257 
6258     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, rect.right, rect.bottom);
6259     expect(Ok, status);
6260 
6261     GdipDeleteBrush((GpBrush*)brush);
6262     GdipDeleteGraphics(graphics);
6263 
6264     pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
6265     if (pixel)
6266     {
6267        color[0] = get_bitmap_pixel(width/2, height/2);
6268        color[1] = get_bitmap_pixel(width/2+1, height/2);
6269        color[2] = get_bitmap_pixel(width/2, height/2+1);
6270        color[3] = get_bitmap_pixel(width/2-1, height/2-1);
6271        color[4] = get_bitmap_pixel(width/2-1, height-1);
6272        color[5] = get_bitmap_pixel(width-1, height/2-1);
6273     }
6274 
6275     ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
6276        color[3] == 0 && color[4] == 0 && color[5] == 0,
6277        "Expected GdipFillRectangleI take effect!\n" );
6278     ReleaseBitmapPixelBuffer(pixel);
6279 
6280     SelectObject(hdc, old);
6281     DeleteObject(bmp);
6282     DeleteDC(hdc);
6283     ReleaseDC(hwnd, dc);
6284 }
6285 
6286 static void test_GdipFillRectanglesOnMemoryDCTextureBrush(void)
6287 {
6288     ARGB color[6] = {0,0,0,0,0,0};
6289     POINT pt = {0,0};
6290     RECT rect = {100, 100, 180, 180};
6291     UINT width = rect.right - rect.left;
6292     UINT height = rect.bottom - rect.top;
6293     GpStatus status = 0;
6294     union
6295     {
6296         GpBitmap *bitmap;
6297         GpImage *image;
6298     } src_img;
6299     GpTexture *brush = NULL;
6300     GpGraphics *graphics = NULL;
6301     HDC dc = GetDC( hwnd);
6302     HDC hdc = CreateCompatibleDC(dc);
6303     HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
6304     HGDIOBJ old = SelectObject(hdc, bmp);
6305 
6306     UINT x = 0;
6307     UINT y = 0;
6308     UINT src_img_width = width/2;
6309     UINT src_img_height = height/2;
6310     BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
6311     DWORD *pixel = (DWORD *)src_img_data;
6312     ok(pixel != NULL, "Expected src_img_data is valid\n");
6313 
6314     /*Change the window origin is the key test point*/
6315     SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
6316 
6317     /*build a blue solid image!*/
6318     for(y = 0; y < src_img_height; ++y)
6319     {
6320         for(x = 0; x < src_img_width; ++x)
6321         {
6322             pixel[x] = BLUE_COLOR;
6323         }
6324 
6325         pixel += src_img_width;
6326     }
6327 
6328     status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
6329             PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
6330     expect(Ok, status);
6331 
6332     status = GdipCreateTexture(src_img.image, 0, &brush);
6333     expect(Ok, status);
6334 
6335     status = GdipCreateFromHDC(hdc, &graphics);
6336     expect(Ok, status);
6337 
6338     status = GdipSetClipRectI(graphics, rect.left+width/2, rect.top+height/2,
6339             width, height, CombineModeReplace);
6340     expect(Ok, status);
6341 
6342     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, rect.right, rect.bottom);
6343     expect(Ok, status);
6344 
6345     GdipDisposeImage(src_img.image);
6346     GdipDeleteBrush((GpBrush*)brush);
6347     GdipDeleteGraphics(graphics);
6348     GdipFree(src_img_data);
6349 
6350     pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
6351     if (pixel)
6352     {
6353        color[0] = get_bitmap_pixel(width/2, height/2);
6354        color[1] = get_bitmap_pixel(width/2+1, height/2);
6355        color[2] = get_bitmap_pixel(width/2, height/2+1);
6356        color[3] = get_bitmap_pixel(width/2-1, height/2-1);
6357        color[4] = get_bitmap_pixel(width/2-1, height-1);
6358        color[5] = get_bitmap_pixel(width-1, height/2-1);
6359     }
6360     ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
6361        color[3] == 0 && color[4] == 0 && color[5] == 0,
6362       "Expected GdipFillRectangleI take effect!\n" );
6363     ReleaseBitmapPixelBuffer(pixel);
6364 
6365     SelectObject(hdc, old);
6366     DeleteObject(bmp);
6367     DeleteDC(hdc);
6368     ReleaseDC(hwnd, dc);
6369 }
6370 
6371 static void test_GdipFillRectanglesOnBitmapTextureBrush(void)
6372 {
6373     ARGB color[6] = {0,0,0,0,0,0};
6374     UINT x = 0;
6375     UINT y = 0;
6376     RECT rect = {100, 100, 180, 180};
6377     UINT width = rect.right - rect.left;
6378     UINT height = rect.bottom - rect.top;
6379     UINT src_img_width = width/2;
6380     UINT src_img_height = height/2;
6381 
6382     GpStatus status = 0;
6383     union
6384     {
6385         GpBitmap *bitmap;
6386         GpImage *image;
6387     } src_img;
6388     union
6389     {
6390         GpBitmap *bitmap;
6391         GpImage *image;
6392     } dst_img;
6393 
6394     GpTexture *brush = NULL;
6395     GpGraphics *graphics = NULL;
6396     BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
6397     DWORD *pixel = (DWORD *)src_img_data;
6398     ok(pixel != NULL, "Expected src_img_data is valid\n");
6399 
6400     status = GdipCreateBitmapFromScan0(width, height, width*4,
6401             PixelFormat32bppARGB, NULL, &dst_img.bitmap);
6402     expect(Ok, status);
6403 
6404     /*build a blue solid image!*/
6405     for(y = 0; y < src_img_height; ++y)
6406     {
6407         for(x = 0; x < src_img_width; ++x)
6408         {
6409             pixel[x] = BLUE_COLOR;
6410         }
6411 
6412         pixel += src_img_width;
6413     }
6414 
6415     status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
6416             PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
6417     expect(Ok, status);
6418 
6419     status = GdipCreateTexture(src_img.image, 0, &brush);
6420     expect(Ok, status);
6421 
6422     status = GdipGetImageGraphicsContext(dst_img.image, &graphics);
6423     expect(Ok, status);
6424 
6425     status = GdipSetClipRectI(graphics, 0, 0, width, height, CombineModeReplace);
6426     expect(Ok, status);
6427 
6428     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, width/2, height/2);
6429     expect(Ok, status);
6430 
6431     GdipDeleteBrush((GpBrush*)brush);
6432     GdipDeleteGraphics(graphics);
6433 
6434     GdipBitmapGetPixel(dst_img.bitmap, 0, 0, &color[0]);
6435     GdipBitmapGetPixel(dst_img.bitmap, 0, 1, &color[1]);
6436     GdipBitmapGetPixel(dst_img.bitmap, 1, 0, &color[2]);
6437     GdipBitmapGetPixel(dst_img.bitmap, width/2, 0, &color[3]);
6438     GdipBitmapGetPixel(dst_img.bitmap, width/2, height/2, &color[4]);
6439     GdipBitmapGetPixel(dst_img.bitmap, 0, height/2, &color[5]);
6440 
6441     ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
6442        color[3] == 0 && color[4] == 0 && color[5] == 0,
6443        "Expected GdipFillRectangleI take effect!\n" );
6444 
6445     GdipDisposeImage(src_img.image);
6446     GdipDisposeImage(dst_img.image);
6447     GdipFree(src_img_data);
6448 }
6449 
6450 static void test_GdipDrawImagePointsRectOnMemoryDC(void)
6451 {
6452     ARGB color[6] = {0,0,0,0,0,0};
6453     POINT pt = {0,0};
6454     RECT rect = {100, 100, 180, 180};
6455     UINT width = rect.right - rect.left;
6456     UINT height = rect.bottom - rect.top;
6457     GpStatus status = 0;
6458     union
6459     {
6460         GpBitmap *bitmap;
6461         GpImage *image;
6462     } src_img;
6463     GpGraphics *graphics = NULL;
6464     HDC dc = GetDC( hwnd);
6465     HDC hdc = CreateCompatibleDC(dc);
6466     HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
6467     HGDIOBJ old = SelectObject(hdc, bmp);
6468 
6469     UINT x = 0;
6470     UINT y = 0;
6471     UINT src_img_width = width/2;
6472     UINT src_img_height = height/2;
6473     BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
6474     DWORD *pixel = (DWORD *)src_img_data;
6475     ok(pixel != NULL, "Expected src_img_data is valid\n");
6476 
6477     /*Change the window origin is the key test point*/
6478     SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
6479 
6480     /*build a blue solid image!*/
6481     for(y = 0; y < src_img_height; ++y)
6482     {
6483         for(x = 0; x < src_img_width; ++x)
6484         {
6485             pixel[x] = BLUE_COLOR;
6486         }
6487 
6488         pixel += src_img_width;
6489     }
6490 
6491     status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
6492             PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
6493     expect(Ok, status);
6494 
6495     status = GdipCreateFromHDC(hdc, &graphics);
6496     expect(Ok, status);
6497 
6498     status = GdipDrawImageRectRectI(graphics, src_img.image,
6499             rect.left+width/2, rect.top+height/2, width/2, height/2,
6500             0, 0, src_img_width, src_img_height, UnitPixel, NULL, NULL, NULL);
6501     expect(Ok, status);
6502 
6503     GdipDisposeImage(src_img.image);
6504     GdipDeleteGraphics(graphics);
6505     GdipFree(src_img_data);
6506 
6507     pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
6508     if (pixel)
6509     {
6510        color[0] = get_bitmap_pixel(width/2, height/2);
6511        color[1] = get_bitmap_pixel(width/2+1, height/2);
6512        color[2] = get_bitmap_pixel(width/2, height/2+1);
6513        color[3] = get_bitmap_pixel(width/2-1, height/2-1);
6514        color[4] = get_bitmap_pixel(width/2-1, height-1);
6515        color[5] = get_bitmap_pixel(width-1, height/2-1);
6516     }
6517     ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
6518        color[3] == 0 && color[4] == 0 && color[5] == 0,
6519        "Expected GdipDrawImageRectRectI take effect!\n" );
6520     ReleaseBitmapPixelBuffer(pixel);
6521 
6522     SelectObject(hdc, old);
6523     DeleteObject(bmp);
6524     DeleteDC(hdc);
6525     ReleaseDC(hwnd, dc);
6526 }
6527 
6528 START_TEST(graphics)
6529 {
6530     struct GdiplusStartupInput gdiplusStartupInput;
6531     ULONG_PTR gdiplusToken;
6532     WNDCLASSA class;
6533     HMODULE gdiplus_mod = GetModuleHandleA("gdiplus.dll");
6534     HMODULE hmsvcrt;
6535     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
6536 
6537     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
6538     hmsvcrt = LoadLibraryA("msvcrt");
6539     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
6540     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
6541 
6542     pGdipGraphicsSetAbort = (void*)GetProcAddress(gdiplus_mod, "GdipGraphicsSetAbort");
6543 
6544     memset( &class, 0, sizeof(class) );
6545     class.lpszClassName = "gdiplus_test";
6546     class.style = CS_HREDRAW | CS_VREDRAW;
6547     class.lpfnWndProc = DefWindowProcA;
6548     class.hInstance = GetModuleHandleA(0);
6549     class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
6550     class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6551     class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
6552     RegisterClassA( &class );
6553     hwnd = CreateWindowA( "gdiplus_test", "graphics test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6554                           CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, 0, 0, GetModuleHandleA(0), 0 );
6555     ok(hwnd != NULL, "Expected window to be created\n");
6556 
6557     gdiplusStartupInput.GdiplusVersion              = 1;
6558     gdiplusStartupInput.DebugEventCallback          = NULL;
6559     gdiplusStartupInput.SuppressBackgroundThread    = 0;
6560     gdiplusStartupInput.SuppressExternalCodecs      = 0;
6561 
6562     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
6563 
6564     test_clipping();
6565     test_clipping_2();
6566     test_measured_extra_space();
6567     test_measure_string();
6568     test_font_height_scaling();
6569     test_transform();
6570     test_pen_thickness();
6571     test_GdipMeasureString();
6572     test_constructor_destructor();
6573     test_save_restore();
6574     test_GdipFillClosedCurve2();
6575     test_GdipFillClosedCurve2I();
6576     test_GdipDrawBezierI();
6577     test_GdipDrawArc();
6578     test_GdipDrawArcI();
6579     test_GdipDrawCurve();
6580     test_GdipDrawCurveI();
6581     test_GdipDrawCurve2();
6582     test_GdipDrawCurve2I();
6583     test_GdipDrawCurve3();
6584     test_GdipDrawCurve3I();
6585     test_GdipDrawLineI();
6586     test_GdipDrawLinesI();
6587     test_GdipDrawImagePointsRect();
6588     test_GdipFillClosedCurve();
6589     test_GdipFillClosedCurveI();
6590     test_GdipDrawString();
6591     test_GdipGetNearestColor();
6592     test_GdipGetVisibleClipBounds();
6593     test_GdipIsVisiblePoint();
6594     test_GdipIsVisibleRect();
6595     test_Get_Release_DC();
6596     test_BeginContainer2();
6597     test_transformpoints();
6598     test_get_set_clip();
6599     test_isempty();
6600     test_clear();
6601     test_textcontrast();
6602     test_fromMemoryBitmap();
6603     test_string_functions();
6604     test_get_set_interpolation();
6605     test_get_set_textrenderinghint();
6606     test_getdc_scaled();
6607     test_alpha_hdc();
6608     test_bitmapfromgraphics();
6609     test_GdipFillRectangles();
6610     test_GdipGetVisibleClipBounds_memoryDC();
6611     test_GdipFillRectanglesOnMemoryDCSolidBrush();
6612     test_GdipFillRectanglesOnMemoryDCTextureBrush();
6613     test_GdipFillRectanglesOnBitmapTextureBrush();
6614     test_GdipDrawImagePointsRectOnMemoryDC();
6615     test_container_rects();
6616     test_GdipGraphicsSetAbort();
6617 
6618     GdiplusShutdown(gdiplusToken);
6619     DestroyWindow( hwnd );
6620 }
6621