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