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