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