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