[GDIPLUS_WINETEST] Sync with Wine Staging 2.16. CORE-13762
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 17 Sep 2017 12:34:24 +0000 (12:34 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 17 Sep 2017 12:34:24 +0000 (12:34 +0000)
svn path=/trunk/; revision=75873

12 files changed:
rostests/winetests/gdiplus/brush.c
rostests/winetests/gdiplus/customlinecap.c
rostests/winetests/gdiplus/font.c
rostests/winetests/gdiplus/graphics.c
rostests/winetests/gdiplus/graphicspath.c
rostests/winetests/gdiplus/image.c
rostests/winetests/gdiplus/matrix.c
rostests/winetests/gdiplus/metafile.c
rostests/winetests/gdiplus/pathiterator.c
rostests/winetests/gdiplus/pen.c
rostests/winetests/gdiplus/region.c
rostests/winetests/gdiplus/stringformat.c

index 939c327..759090b 100644 (file)
@@ -32,6 +32,8 @@
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
 
+static HWND hwnd;
+
 static void test_constructor_destructor(void)
 {
     GpStatus status;
@@ -179,12 +181,17 @@ static void test_transform(void)
 {
     GpStatus status;
     GpTexture *texture;
+    GpLineGradient *line;
     GpGraphics *graphics = NULL;
     GpBitmap *bitmap;
     HDC hdc = GetDC(0);
     GpMatrix *m, *m1;
     BOOL res;
+    GpPointF start, end;
+    GpRectF rectf;
+    REAL elements[6];
 
+    /* GpTexture */
     status = GdipCreateMatrix2(2.0, 0.0, 0.0, 0.0, 0.0, 0.0, &m);
     expect(Ok, status);
 
@@ -238,6 +245,245 @@ static void test_transform(void)
     expect(Ok, status);
     status = GdipDeleteGraphics(graphics);
     expect(Ok, status);
+
+
+
+    status = GdipCreateFromHWND(hwnd, &graphics);
+    expect(Ok, status);
+
+    /* GpLineGradient */
+    /* create with vertical gradient line */
+    start.X = start.Y = end.X = 0.0;
+    end.Y = 100.0;
+
+    status = GdipCreateLineBrush(&start, &end, (ARGB)0xffff0000, 0xff00ff00, WrapModeTile, &line);
+    expect(Ok, status);
+
+    status = GdipCreateMatrix2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, &m);
+    expect(Ok, status);
+
+    /* NULL arguments */
+    status = GdipResetLineTransform(NULL);
+    expect(InvalidParameter, status);
+    status = GdipSetLineTransform(NULL, m);
+    expect(InvalidParameter, status);
+    status = GdipSetLineTransform(line, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetLineTransform(NULL, m);
+    expect(InvalidParameter, status);
+    status = GdipGetLineTransform(line, NULL);
+    expect(InvalidParameter, status);
+    status = GdipScaleLineTransform(NULL, 1, 1, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+    status = GdipMultiplyLineTransform(NULL, m, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+    status = GdipTranslateLineTransform(NULL, 0, 0, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+
+    /* initial transform */
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(0.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(0.0, elements[3]);
+    expectf(50.0, elements[4]);
+    expectf(50.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 0, 200, 200);
+    expect(Ok, status);
+
+    /* manually set transform */
+    GdipSetMatrixElements(m, 2.0, 0.0, 0.0, 4.0, 0.0, 0.0);
+
+    status = GdipSetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(2.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(4.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 0, 200, 200);
+    expect(Ok, status);
+
+    /* scale transform */
+    status = GdipScaleLineTransform(line, 4.0, 0.5, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(8.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(2.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 0, 200, 200);
+    expect(Ok, status);
+
+    /* translate transform */
+    status = GdipTranslateLineTransform(line, 10.0, -20.0, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(8.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(2.0, elements[3]);
+    expectf(10.0, elements[4]);
+    expectf(-20.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 200, 200, 200);
+    expect(Ok, status);
+
+    /* multiply transform */
+    GdipSetMatrixElements(m, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
+    GdipRotateMatrix(m, 45.0, MatrixOrderAppend);
+    GdipScaleMatrix(m, 0.25, 0.5, MatrixOrderAppend);
+
+    status = GdipMultiplyLineTransform(line, m, MatrixOrderAppend);
+    expect(Ok, status);
+
+    /* NULL transform does nothing */
+    status = GdipMultiplyLineTransform(line, NULL, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(1.414214, elements[0]);
+    expectf(2.828427, elements[1]);
+    expectf(-0.353553, elements[2]);
+    expectf(0.707107, elements[3]);
+    expectf(5.303300, elements[4]);
+    expectf(-3.535534, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 200, 200, 200);
+    expect(Ok, status);
+
+    /* reset transform sets to identity */
+    status = GdipResetLineTransform(line);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 200, 200, 200);
+    expect(Ok, status);
+
+    GdipDeleteBrush((GpBrush*)line);
+
+    /* passing negative Width/Height to LinearGradientModeHorizontal */
+    rectf.X = rectf.Y = 10.0;
+    rectf.Width = rectf.Height = -100.0;
+    status = GdipCreateLineBrushFromRect(&rectf, (ARGB)0xffff0000, 0xff00ff00,
+            LinearGradientModeHorizontal, WrapModeTile, &line);
+    expect(Ok, status);
+    memset(&rectf, 0, sizeof(GpRectF));
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(10.0, rectf.X);
+    expectf(10.0, rectf.Y);
+    expectf(-100.0, rectf.Width);
+    expectf(-100.0, rectf.Height);
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 400, 200, 200);
+    expect(Ok, status);
+    status = GdipDeleteBrush((GpBrush*)line);
+    expect(Ok,status);
+
+    if(0){
+        /* enable to visually compare with Windows */
+        MSG msg;
+        while(GetMessageW(&msg, hwnd, 0, 0) > 0){
+            TranslateMessage(&msg);
+            DispatchMessageW(&msg);
+        }
+    }
+
+    GdipDeleteMatrix(m);
+    GdipDeleteGraphics(graphics);
     ReleaseDC(0, hdc);
 }
 
@@ -313,20 +559,18 @@ static void test_gradientgetrect(void)
     expectf(99.0, rectf.Width);
     expectf(99.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(1.0, elements[1]);
-        expectf(-1.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(50.50, elements[4]);
-        expectf(-50.50, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(50.50, elements[4]);
+    expectf(-50.50, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* vertical gradient */
     pt1.X = pt1.Y = pt2.X = 0.0;
     pt2.Y = 10.0;
@@ -340,20 +584,18 @@ static void test_gradientgetrect(void)
     expectf(10.0, rectf.Width);
     expectf(10.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(0.0, elements[0]);
-        expectf(1.0, elements[1]);
-        expectf(-1.0, elements[2]);
-        expectf(0.0, elements[3]);
-        expectf(5.0, elements[4]);
-        expectf(5.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(0.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(0.0, elements[3]);
+    expectf(5.0, elements[4]);
+    expectf(5.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* horizontal gradient */
     pt1.X = pt1.Y = pt2.Y = 0.0;
     pt2.X = 10.0;
@@ -367,20 +609,18 @@ static void test_gradientgetrect(void)
     expectf(10.0, rectf.Width);
     expectf(10.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* slope = -1 */
     pt1.X = pt1.Y = 0.0;
     pt2.X = 20.0;
@@ -395,20 +635,18 @@ static void test_gradientgetrect(void)
     expectf(20.0, rectf.Width);
     expectf(20.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(-1.0, elements[1]);
-        expectf(1.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(10.0, elements[4]);
-        expectf(10.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(-1.0, elements[1]);
+    expectf(1.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(10.0, elements[4]);
+    expectf(10.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* slope = 1/100 */
     pt1.X = pt1.Y = 0.0;
     pt2.X = 100.0;
@@ -423,20 +661,18 @@ static void test_gradientgetrect(void)
     expectf(100.0, rectf.Width);
     expectf(1.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.01, elements[1]);
-        expectf(-0.02, elements[2]);
-        /* expectf(2.0, elements[3]); */
-        expectf(0.01, elements[4]);
-        /* expectf(-1.0, elements[5]); */
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.01, elements[1]);
+    expectf(-0.02, elements[2]);
+    /* expectf(2.0, elements[3]); */
+    expectf(0.01, elements[4]);
+    /* expectf(-1.0, elements[5]); */
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
+
     /* zero height rect */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = 100.0;
@@ -444,6 +680,7 @@ static void test_gradientgetrect(void)
     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeVertical,
         WrapModeTile, &brush);
     expect(OutOfMemory, status);
+
     /* zero width rect */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = 0.0;
@@ -451,6 +688,7 @@ static void test_gradientgetrect(void)
     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
         WrapModeTile, &brush);
     expect(OutOfMemory, status);
+
     /* from rect with LinearGradientModeHorizontal */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = rectf.Height = 100.0;
@@ -465,20 +703,18 @@ static void test_gradientgetrect(void)
     expectf(100.0, rectf.Width);
     expectf(100.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
+
     /* passing negative Width/Height to LinearGradientModeHorizontal */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = rectf.Height = -100.0;
@@ -493,21 +729,45 @@ static void test_gradientgetrect(void)
     expectf(-100.0, rectf.Width);
     expectf(-100.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
 
+    /* reverse gradient line as immediately previous */
+    pt1.X = 10.0;
+    pt1.Y = 10.0;
+    pt2.X = -90.0;
+    pt2.Y = 10.0;
+    status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
+    expect(Ok, status);
+    memset(&rectf, 0, sizeof(GpRectF));
+    status = GdipGetLineRect(brush, &rectf);
+    expect(Ok, status);
+    expectf(-90.0, rectf.X);
+    expectf(-40.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+    status = GdipGetLineTransform(brush, transform);
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(-1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(-1.0, elements[3]);
+    expectf(-80.0, elements[4]);
+    expectf(20.0, elements[5]);
+    status = GdipDeleteBrush((GpBrush*)brush);
+    expect(Ok, status);
+
     GdipDeleteMatrix(transform);
 }
 
@@ -1278,6 +1538,27 @@ START_TEST(brush)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+    WNDCLASSA class;
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
+
+    memset( &class, 0, sizeof(class) );
+    class.lpszClassName = "gdiplus_test";
+    class.style = CS_HREDRAW | CS_VREDRAW;
+    class.lpfnWndProc = DefWindowProcA;
+    class.hInstance = GetModuleHandleA(0);
+    class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
+    class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+    class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    RegisterClassA( &class );
+    hwnd = CreateWindowA( "gdiplus_test", "graphics test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                          CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, GetModuleHandleA(0), 0 );
+    ok(hwnd != NULL, "Expected window to be created\n");
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
@@ -1304,4 +1585,5 @@ START_TEST(brush)
     test_pathgradientblend();
 
     GdiplusShutdown(gdiplusToken);
+    DestroyWindow(hwnd);
 }
index c5dad1f..b406ecc 100644 (file)
@@ -321,6 +321,13 @@ START_TEST(customlinecap)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index 19405f7..f31a5ee 100644 (file)
@@ -1121,6 +1121,13 @@ START_TEST(font)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index 1ba522e..33fee40 100644 (file)
@@ -35,6 +35,8 @@
 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
 #define expectf(expected, got) expectf_((expected), (got), 0.001)
 
+static GpStatus (WINAPI *pGdipGraphicsSetAbort)(GpGraphics*,GdiplusAbort*);
+
 static const REAL mm_per_inch = 25.4;
 static const REAL point_per_inch = 72.0;
 static HWND hwnd;
@@ -1872,6 +1874,15 @@ static void test_transformpoints(void)
     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1);
     expect(InvalidParameter, status);
 
+    status = GdipTransformPoints(graphics, CoordinateSpaceDevice+1, CoordinateSpaceWorld, ptf, 2);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, -1, CoordinateSpaceWorld, ptf, 2);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceDevice+1, ptf, 2);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, CoordinateSpaceDevice, -1, ptf, 2);
+    expect(InvalidParameter, status);
+
     ptf[0].X = 1.0;
     ptf[0].Y = 0.0;
     ptf[1].X = 0.0;
@@ -4954,6 +4965,16 @@ static void test_clipping(void)
     ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
        "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
 
+    /* Clip region does not account for changes to gdi32 transform */
+    SetViewportOrgEx(hdc, 10, 10, NULL);
+
+    status = GdipGetClipBounds(graphics, &rect);
+    expect(Ok, status);
+    ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
+       "expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
+
+    SetViewportOrgEx(hdc, 0, 0, NULL);
+
     status = GdipSetEmpty(region);
     expect(Ok, status);
     status = GdipGetClip(graphics, region);
@@ -6155,11 +6176,380 @@ static void test_container_rects(void)
     ReleaseDC(hwnd, hdc);
 }
 
+static void test_GdipGraphicsSetAbort(void)
+{
+    HDC hdc;
+    GpStatus status;
+    GpGraphics *graphics;
+
+    if (!pGdipGraphicsSetAbort)
+    {
+        win_skip("GdipGraphicsSetAbort() is not supported.\n");
+        return;
+    }
+
+    hdc = GetDC(hwnd);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = pGdipGraphicsSetAbort(NULL, NULL);
+    expect(InvalidParameter, status);
+
+    status = pGdipGraphicsSetAbort(graphics, NULL);
+    expect(Ok, status);
+
+    GdipDeleteGraphics(graphics);
+
+    ReleaseDC(hwnd, hdc);
+}
+
+#define BLUE_COLOR (0xff0000ff)
+#define is_blue_color(color) ( ((color) & 0x00ffffff) == 0xff )
+#define get_bitmap_pixel(x,y) pixel[(y)*(width) + (x)]
+static DWORD* GetBitmapPixelBuffer(HDC hdc, HBITMAP hbmp, int width, int height)
+{
+    BITMAPINFOHEADER bi;
+    UINT lines = 0;
+    DWORD *buffer = (DWORD *)GdipAlloc(width*height*4);
+
+    bi.biSize = sizeof(BITMAPINFOHEADER);
+    bi.biWidth = width;
+    bi.biHeight = -height; /*very Important, set negative, indicating a top-down DIB*/
+    bi.biPlanes = 1;
+    bi.biBitCount = 32;
+    bi.biCompression = BI_RGB;
+    bi.biSizeImage = 0;
+    bi.biXPelsPerMeter = 0;
+    bi.biYPelsPerMeter = 0;
+    bi.biClrUsed = 0;
+    bi.biClrImportant = 0;
+
+    lines = GetDIBits(hdc, hbmp, 0, height, buffer, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
+    ok(lines == height, "Expected GetDIBits:%p,%d->%d,%d\n", buffer, height, lines, GetLastError());
+
+    return buffer;
+}
+
+static void ReleaseBitmapPixelBuffer(DWORD* buffer)
+{
+    if (buffer) GdipFree(buffer);
+}
+
+static void test_GdipFillRectanglesOnMemoryDCSolidBrush(void)
+{
+    ARGB color[6] = {0,0,0,0,0,0};
+    POINT pt = {0,0};
+    RECT rect = {100, 100, 180, 180};
+    UINT width = rect.right - rect.left;
+    UINT height = rect.bottom - rect.top;
+    GpStatus status = 0;
+    GpSolidFill *brush = NULL;
+    GpGraphics *graphics = NULL;
+    HDC dc = GetDC( hwnd);
+    HDC hdc = CreateCompatibleDC(dc);
+    HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
+    HGDIOBJ old = SelectObject(hdc, bmp);
+    DWORD* pixel = NULL;
+
+    /*Change the window origin is the key test point*/
+    SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
+
+    status = GdipCreateSolidFill(BLUE_COLOR, &brush);
+    expect(Ok, status);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipSetClipRectI(graphics, rect.left+width/2, rect.top+height/2,
+            width, height, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, rect.right, rect.bottom);
+    expect(Ok, status);
+
+    GdipDeleteBrush((GpBrush*)brush);
+    GdipDeleteGraphics(graphics);
+
+    pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
+    if (pixel)
+    {
+       color[0] = get_bitmap_pixel(width/2, height/2);
+       color[1] = get_bitmap_pixel(width/2+1, height/2);
+       color[2] = get_bitmap_pixel(width/2, height/2+1);
+       color[3] = get_bitmap_pixel(width/2-1, height/2-1);
+       color[4] = get_bitmap_pixel(width/2-1, height-1);
+       color[5] = get_bitmap_pixel(width-1, height/2-1);
+    }
+
+    ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
+       color[3] == 0 && color[4] == 0 && color[5] == 0,
+       "Expected GdipFillRectangleI take effect!\n" );
+    ReleaseBitmapPixelBuffer(pixel);
+
+    SelectObject(hdc, old);
+    DeleteObject(bmp);
+    DeleteDC(hdc);
+    ReleaseDC(hwnd, dc);
+}
+
+static void test_GdipFillRectanglesOnMemoryDCTextureBrush(void)
+{
+    ARGB color[6] = {0,0,0,0,0,0};
+    POINT pt = {0,0};
+    RECT rect = {100, 100, 180, 180};
+    UINT width = rect.right - rect.left;
+    UINT height = rect.bottom - rect.top;
+    GpStatus status = 0;
+    union
+    {
+        GpBitmap *bitmap;
+        GpImage *image;
+    } src_img;
+    GpTexture *brush = NULL;
+    GpGraphics *graphics = NULL;
+    HDC dc = GetDC( hwnd);
+    HDC hdc = CreateCompatibleDC(dc);
+    HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
+    HGDIOBJ old = SelectObject(hdc, bmp);
+
+    UINT x = 0;
+    UINT y = 0;
+    UINT src_img_width = width/2;
+    UINT src_img_height = height/2;
+    BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
+    DWORD *pixel = (DWORD *)src_img_data;
+    ok(pixel != NULL, "Expected src_img_data is valid\n");
+
+    /*Change the window origin is the key test point*/
+    SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
+
+    /*build a blue solid image!*/
+    for(y = 0; y < src_img_height; ++y)
+    {
+        for(x = 0; x < src_img_width; ++x)
+        {
+            pixel[x] = BLUE_COLOR;
+        }
+
+        pixel += src_img_width;
+    }
+
+    status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
+            PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
+    expect(Ok, status);
+
+    status = GdipCreateTexture(src_img.image, 0, &brush);
+    expect(Ok, status);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipSetClipRectI(graphics, rect.left+width/2, rect.top+height/2,
+            width, height, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, rect.right, rect.bottom);
+    expect(Ok, status);
+
+    GdipDisposeImage(src_img.image);
+    GdipDeleteBrush((GpBrush*)brush);
+    GdipDeleteGraphics(graphics);
+    GdipFree(src_img_data);
+
+    pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
+    if (pixel)
+    {
+       color[0] = get_bitmap_pixel(width/2, height/2);
+       color[1] = get_bitmap_pixel(width/2+1, height/2);
+       color[2] = get_bitmap_pixel(width/2, height/2+1);
+       color[3] = get_bitmap_pixel(width/2-1, height/2-1);
+       color[4] = get_bitmap_pixel(width/2-1, height-1);
+       color[5] = get_bitmap_pixel(width-1, height/2-1);
+    }
+    ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
+       color[3] == 0 && color[4] == 0 && color[5] == 0,
+      "Expected GdipFillRectangleI take effect!\n" );
+    ReleaseBitmapPixelBuffer(pixel);
+
+    SelectObject(hdc, old);
+    DeleteObject(bmp);
+    DeleteDC(hdc);
+    ReleaseDC(hwnd, dc);
+}
+
+static void test_GdipFillRectanglesOnBitmapTextureBrush(void)
+{
+    ARGB color[6] = {0,0,0,0,0,0};
+    UINT x = 0;
+    UINT y = 0;
+    RECT rect = {100, 100, 180, 180};
+    UINT width = rect.right - rect.left;
+    UINT height = rect.bottom - rect.top;
+    UINT src_img_width = width/2;
+    UINT src_img_height = height/2;
+
+    GpStatus status = 0;
+    union
+    {
+        GpBitmap *bitmap;
+        GpImage *image;
+    } src_img;
+    union
+    {
+        GpBitmap *bitmap;
+        GpImage *image;
+    } dst_img;
+
+    GpTexture *brush = NULL;
+    GpGraphics *graphics = NULL;
+    BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
+    DWORD *pixel = (DWORD *)src_img_data;
+    ok(pixel != NULL, "Expected src_img_data is valid\n");
+
+    status = GdipCreateBitmapFromScan0(width, height, width*4,
+            PixelFormat32bppARGB, NULL, &dst_img.bitmap);
+    expect(Ok, status);
+
+    /*build a blue solid image!*/
+    for(y = 0; y < src_img_height; ++y)
+    {
+        for(x = 0; x < src_img_width; ++x)
+        {
+            pixel[x] = BLUE_COLOR;
+        }
+
+        pixel += src_img_width;
+    }
+
+    status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
+            PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
+    expect(Ok, status);
+
+    status = GdipCreateTexture(src_img.image, 0, &brush);
+    expect(Ok, status);
+
+    status = GdipGetImageGraphicsContext(dst_img.image, &graphics);
+    expect(Ok, status);
+
+    status = GdipSetClipRectI(graphics, 0, 0, width, height, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, width/2, height/2);
+    expect(Ok, status);
+
+    GdipDeleteBrush((GpBrush*)brush);
+    GdipDeleteGraphics(graphics);
+
+    GdipBitmapGetPixel(dst_img.bitmap, 0, 0, &color[0]);
+    GdipBitmapGetPixel(dst_img.bitmap, 0, 1, &color[1]);
+    GdipBitmapGetPixel(dst_img.bitmap, 1, 0, &color[2]);
+    GdipBitmapGetPixel(dst_img.bitmap, width/2, 0, &color[3]);
+    GdipBitmapGetPixel(dst_img.bitmap, width/2, height/2, &color[4]);
+    GdipBitmapGetPixel(dst_img.bitmap, 0, height/2, &color[5]);
+
+    ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
+       color[3] == 0 && color[4] == 0 && color[5] == 0,
+       "Expected GdipFillRectangleI take effect!\n" );
+
+    GdipDisposeImage(src_img.image);
+    GdipDisposeImage(dst_img.image);
+    GdipFree(src_img_data);
+}
+
+static void test_GdipDrawImagePointsRectOnMemoryDC(void)
+{
+    ARGB color[6] = {0,0,0,0,0,0};
+    POINT pt = {0,0};
+    RECT rect = {100, 100, 180, 180};
+    UINT width = rect.right - rect.left;
+    UINT height = rect.bottom - rect.top;
+    GpStatus status = 0;
+    union
+    {
+        GpBitmap *bitmap;
+        GpImage *image;
+    } src_img;
+    GpGraphics *graphics = NULL;
+    HDC dc = GetDC( hwnd);
+    HDC hdc = CreateCompatibleDC(dc);
+    HBITMAP bmp = CreateCompatibleBitmap(dc, width, height);
+    HGDIOBJ old = SelectObject(hdc, bmp);
+
+    UINT x = 0;
+    UINT y = 0;
+    UINT src_img_width = width/2;
+    UINT src_img_height = height/2;
+    BYTE *src_img_data = GdipAlloc(src_img_width*src_img_height*4);
+    DWORD *pixel = (DWORD *)src_img_data;
+    ok(pixel != NULL, "Expected src_img_data is valid\n");
+
+    /*Change the window origin is the key test point*/
+    SetWindowOrgEx(hdc, rect.left, rect.top, &pt);
+
+    /*build a blue solid image!*/
+    for(y = 0; y < src_img_height; ++y)
+    {
+        for(x = 0; x < src_img_width; ++x)
+        {
+            pixel[x] = BLUE_COLOR;
+        }
+
+        pixel += src_img_width;
+    }
+
+    status = GdipCreateBitmapFromScan0(src_img_width, src_img_height, src_img_width*4,
+            PixelFormat32bppARGB, src_img_data, &src_img.bitmap);
+    expect(Ok, status);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipDrawImageRectRectI(graphics, src_img.image,
+            rect.left+width/2, rect.top+height/2, width/2, height/2,
+            0, 0, src_img_width, src_img_height, UnitPixel, NULL, NULL, NULL);
+    expect(Ok, status);
+
+    GdipDisposeImage(src_img.image);
+    GdipDeleteGraphics(graphics);
+    GdipFree(src_img_data);
+
+    pixel = GetBitmapPixelBuffer(hdc, bmp, width, height);
+    if (pixel)
+    {
+       color[0] = get_bitmap_pixel(width/2, height/2);
+       color[1] = get_bitmap_pixel(width/2+1, height/2);
+       color[2] = get_bitmap_pixel(width/2, height/2+1);
+       color[3] = get_bitmap_pixel(width/2-1, height/2-1);
+       color[4] = get_bitmap_pixel(width/2-1, height-1);
+       color[5] = get_bitmap_pixel(width-1, height/2-1);
+    }
+    ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
+       color[3] == 0 && color[4] == 0 && color[5] == 0,
+       "Expected GdipDrawImageRectRectI take effect!\n" );
+    ReleaseBitmapPixelBuffer(pixel);
+
+    SelectObject(hdc, old);
+    DeleteObject(bmp);
+    DeleteDC(hdc);
+    ReleaseDC(hwnd, dc);
+}
+
 START_TEST(graphics)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
     WNDCLASSA class;
+    HMODULE gdiplus_mod = GetModuleHandleA("gdiplus.dll");
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
+
+    pGdipGraphicsSetAbort = (void*)GetProcAddress(gdiplus_mod, "GdipGraphicsSetAbort");
 
     memset( &class, 0, sizeof(class) );
     class.lpszClassName = "gdiplus_test";
@@ -6228,7 +6618,12 @@ START_TEST(graphics)
     test_bitmapfromgraphics();
     test_GdipFillRectangles();
     test_GdipGetVisibleClipBounds_memoryDC();
+    test_GdipFillRectanglesOnMemoryDCSolidBrush();
+    test_GdipFillRectanglesOnMemoryDCTextureBrush();
+    test_GdipFillRectanglesOnBitmapTextureBrush();
+    test_GdipDrawImagePointsRectOnMemoryDC();
     test_container_rects();
+    test_GdipGraphicsSetAbort();
 
     GdiplusShutdown(gdiplusToken);
     DestroyWindow( hwnd );
index 25aea41..6206096 100644 (file)
@@ -1071,6 +1071,17 @@ static path_test_t widenline_wide_path[] = {
     {5.0, 20.0,  PathPointTypeLine|PathPointTypeCloseSubpath,  0, 0} /*3*/
     };
 
+static path_test_t widenline_dash_path[] = {
+    {5.0, 0.0,   PathPointTypeStart, 0, 0}, /*0*/
+    {35.0, 0.0,  PathPointTypeLine,  0, 0}, /*1*/
+    {35.0, 10.0, PathPointTypeLine,  0, 0}, /*2*/
+    {5.0, 10.0,  PathPointTypeLine|PathPointTypeCloseSubpath,  0, 0}, /*3*/
+    {45.0, 0.0,   PathPointTypeStart, 0, 0}, /*4*/
+    {50.0, 0.0,  PathPointTypeLine,  0, 0}, /*5*/
+    {50.0, 10.0, PathPointTypeLine,  0, 0}, /*6*/
+    {45.0, 10.0,  PathPointTypeLine|PathPointTypeCloseSubpath,  0, 0}, /*7*/
+    };
+
 static void test_widen(void)
 {
     GpStatus status;
@@ -1145,6 +1156,22 @@ static void test_widen(void)
     status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
     expect(Ok, status);
 
+    /* dashed line */
+    status = GdipResetPath(path);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
+    expect(Ok, status);
+
+    status = GdipSetPenDashStyle(pen, DashStyleDash);
+    expect(Ok, status);
+
+    status = GdipWidenPath(path, pen, m, 1.0);
+    expect(Ok, status);
+    ok_path(path, widenline_dash_path, sizeof(widenline_dash_path)/sizeof(path_test_t), FALSE);
+
+    status = GdipSetPenDashStyle(pen, DashStyleSolid);
+    expect(Ok, status);
+
     /* pen width in UnitWorld */
     GdipDeletePen(pen);
     status = GdipCreatePen1(0xffffffff, 10.0, UnitWorld, &pen);
@@ -1308,6 +1335,13 @@ START_TEST(graphicspath)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index 268cdea..a332ddf 100644 (file)
@@ -5376,6 +5376,13 @@ START_TEST(image)
     HMODULE mod = GetModuleHandleA("gdiplus.dll");
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index be82f18..e1e61aa 100644 (file)
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
 
+static BOOL compare_float(float f, float g, unsigned int ulps)
+{
+    int x = *(int *)&f;
+    int y = *(int *)&g;
+
+    if (x < 0)
+        x = INT_MIN - x;
+    if (y < 0)
+        y = INT_MIN - y;
+
+    if (abs(x - y) > ulps)
+        return FALSE;
+
+    return TRUE;
+}
+
 static void test_constructor_destructor(void)
 {
     GpStatus status;
@@ -135,6 +151,7 @@ static void test_invert(void)
     GpMatrix *matrix = NULL;
     GpMatrix *inverted = NULL;
     BOOL equal = FALSE;
+    REAL elems[6];
 
     /* NULL */
     status = GdipInvertMatrix(NULL);
@@ -154,6 +171,18 @@ static void test_invert(void)
     GdipIsMatrixEqual(matrix, inverted, &equal);
     expect(TRUE, equal);
 
+    GdipCreateMatrix2(0.0006, 0, 0, 0.0006, 400, 400, &matrix);
+    status = GdipInvertMatrix(matrix);
+    expect(Ok, status);
+    status = GdipGetMatrixElements(matrix, elems);
+    expect(Ok, status);
+    ok(compare_float(elems[0], 1666.666504, 1), "elems[0] = %.10g\n", elems[0]);
+    ok(compare_float(elems[1], 0, 0), "elems[1] = %.10g\n", elems[1]);
+    ok(compare_float(elems[2], 0, 0), "elems[2] = %.10g\n", elems[2]);
+    ok(compare_float(elems[3], 1666.666504, 1), "elems[3] = %.10g\n", elems[3]);
+    ok(compare_float(elems[4], -666666.6875, 1), "elems[4] = %.10g\n", elems[4]);
+    ok(compare_float(elems[5], -666666.6875, 1), "elems[5] = %.10g\n", elems[5]);
+
     GdipDeleteMatrix(inverted);
     GdipDeleteMatrix(matrix);
 }
@@ -350,6 +379,13 @@ START_TEST(matrix)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index b5351ef..1235767 100644 (file)
@@ -69,6 +69,39 @@ typedef struct EmfPlusRecordHeader
     DWORD DataSize;
 } EmfPlusRecordHeader;
 
+typedef enum
+{
+    ObjectTypeInvalid,
+    ObjectTypeBrush,
+    ObjectTypePen,
+    ObjectTypePath,
+    ObjectTypeRegion,
+    ObjectTypeImage,
+    ObjectTypeFont,
+    ObjectTypeStringFormat,
+    ObjectTypeImageAttributes,
+    ObjectTypeCustomLineCap,
+} ObjectType;
+
+typedef enum
+{
+    ImageDataTypeUnknown,
+    ImageDataTypeBitmap,
+    ImageDataTypeMetafile,
+} ImageDataType;
+
+typedef struct
+{
+    EmfPlusRecordHeader Header;
+    /* EmfPlusImage */
+    DWORD Version;
+    ImageDataType Type;
+    /* EmfPlusMetafile */
+    DWORD MetafileType;
+    DWORD MetafileDataSize;
+    BYTE MetafileData[1];
+} MetafileImageObject;
+
 static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
     int nObj, LPARAM lpData)
 {
@@ -102,14 +135,30 @@ static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETAR
                     actual.record_type = record->Type;
 
                     check_record(state->count, state->desc, &state->expected[state->count], &actual);
-
                     state->count++;
+
+                    if (state->expected[state->count-1].todo && state->expected[state->count-1].record_type != actual.record_type)
+                        continue;
                 }
                 else
                 {
                     ok(0, "%s: Unexpected EMF+ 0x%x record\n", state->desc, record->Type);
                 }
 
+                if ((record->Flags >> 8) == ObjectTypeImage && record->Type == EmfPlusRecordTypeObject)
+                {
+                    const MetafileImageObject *image = (const MetafileImageObject*)record;
+
+                    if (image->Type == ImageDataTypeMetafile)
+                    {
+                        HENHMETAFILE hemf = SetEnhMetaFileBits(image->MetafileDataSize, image->MetafileData);
+                        ok(hemf != NULL, "%s: SetEnhMetaFileBits failed\n", state->desc);
+
+                        EnumEnhMetaFile(0, hemf, enum_emf_proc, state, NULL);
+                        DeleteEnhMetaFile(hemf);
+                    }
+                }
+
                 offset += record->Size;
             }
 
@@ -645,6 +694,26 @@ static const emfplus_record emfonly_records[] = {
     {0}
 };
 
+static const emfplus_record emfonly_draw_records[] = {
+    {0, EMR_HEADER},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_SETMITERLIMIT},
+    {1, EMR_MODIFYWORLDTRANSFORM},
+    {1, EMR_EXTCREATEPEN},
+    {1, EMR_SELECTOBJECT},
+    {1, EMR_SELECTOBJECT},
+    {1, EMR_POLYLINE16},
+    {1, EMR_SELECTOBJECT},
+    {1, EMR_SELECTOBJECT},
+    {1, EMR_MODIFYWORLDTRANSFORM},
+    {1, EMR_DELETEOBJECT},
+    {1, EMR_SETMITERLIMIT},
+    {1, EMR_RESTOREDC},
+    {0, EMR_EOF},
+    {1}
+};
+
 static void test_emfonly(void)
 {
     GpStatus stat;
@@ -663,6 +732,7 @@ static void test_emfonly(void)
     HBRUSH hbrush, holdbrush;
     GpBitmap *bitmap;
     ARGB color;
+    GpPen *pen;
 
     hdc = CreateCompatibleDC(0);
 
@@ -905,6 +975,35 @@ static void test_emfonly(void)
 
     stat = GdipDisposeImage((GpImage*)metafile);
     expect(Ok, stat);
+
+    /* test drawing to metafile with gdi+ functions */
+    hdc = CreateCompatibleDC(0);
+
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+
+    DeleteDC(hdc);
+
+    if (stat != Ok)
+        return;
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, stat);
+    stat = GdipDrawLineI(graphics, pen, 0, 0, 10, 10);
+    todo_wine expect(Ok, stat);
+    GdipDeletePen(pen);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+
+    check_metafile(metafile, emfonly_draw_records, "emfonly draw metafile", dst_points, &frame, UnitPixel);
+    sync_metafile(&metafile, "emfonly_draw.emf");
+
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
 }
 
 static const emfplus_record fillrect_records[] = {
@@ -2060,6 +2159,8 @@ static const emfplus_record clipping_records[] = {
     {0, EmfPlusRecordTypeRestore},
     {0, EmfPlusRecordTypeSetClipRect},
     {0, EmfPlusRecordTypeFillRects},
+    {0, EmfPlusRecordTypeObject, 1},
+    {0, EmfPlusRecordTypeSetClipRegion, 1},
     {0, EmfPlusRecordTypeEndOfFile},
     {0, EMR_EOF},
     {0}
@@ -2071,7 +2172,9 @@ static void test_clipping(void)
     GpMetafile *metafile;
     GpGraphics *graphics;
     GpBitmap *bitmap;
+    GpRegion *region;
     GpBrush *brush;
+    GpRectF rect;
     ARGB color;
     HDC hdc;
     static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
@@ -2095,9 +2198,23 @@ static void test_clipping(void)
     stat = GdipSaveGraphics(graphics, &state);
     expect(Ok, stat);
 
+    stat = GdipGetVisibleClipBounds(graphics, &rect);
+    expect(Ok, stat);
+    ok(rect.X == -0x400000, "rect.X = %f\n", rect.X);
+    ok(rect.Y == -0x400000, "rect.Y = %f\n", rect.Y);
+    ok(rect.Width == 0x800000, "rect.Width = %f\n", rect.Width);
+    ok(rect.Height == 0x800000, "rect.Height = %f\n", rect.Height);
+
     stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeReplace);
     expect(Ok, stat);
 
+    stat = GdipGetVisibleClipBounds(graphics, &rect);
+    expect(Ok, stat);
+    ok(rect.X == 30, "rect.X = %f\n", rect.X);
+    ok(rect.Y == 30, "rect.Y = %f\n", rect.Y);
+    ok(rect.Width == 10, "rect.Width = %f\n", rect.Width);
+    ok(rect.Height == 10, "rect.Height = %f\n", rect.Height);
+
     stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
     expect(Ok, stat);
 
@@ -2122,6 +2239,15 @@ static void test_clipping(void)
     stat = GdipDeleteBrush(brush);
     expect(Ok, stat);
 
+    stat = GdipCreateRegionRect(&rect, &region);
+    expect(Ok, stat);
+
+    stat = GdipSetClipRegion(graphics, region, CombineModeIntersect);
+    expect(Ok, stat);
+
+    stat = GdipDeleteRegion(region);
+    expect(Ok, stat);
+
     stat = GdipDeleteGraphics(graphics);
     expect(Ok, stat);
 
@@ -2277,12 +2403,389 @@ static void test_gditransform(void)
     expect(Ok, stat);
 }
 
+static const emfplus_record draw_image_bitmap_records[] = {
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeDrawImagePoints},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_BITBLT},
+    {1, EMR_RESTOREDC},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    {0}
+};
+
+static const emfplus_record draw_image_metafile_records[] = {
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeObject},
+    /* metafile object */
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeDrawImagePoints},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_BITBLT},
+    {1, EMR_RESTOREDC},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    /* end of metafile object */
+    {0, EmfPlusRecordTypeDrawImagePoints},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_BITBLT},
+    {1, EMR_RESTOREDC},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    {0}
+};
+
+static void test_drawimage(void)
+{
+    static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+    static const GpPointF dst_points[3] = {{10.0,10.0},{85.0,15.0},{10.0,80.0}};
+    static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+    const ColorMatrix double_red = {{
+        {2.0,0.0,0.0,0.0,0.0},
+        {0.0,1.0,0.0,0.0,0.0},
+        {0.0,0.0,1.0,0.0,0.0},
+        {0.0,0.0,0.0,1.0,0.0},
+        {0.0,0.0,0.0,0.0,1.0}}};
+
+    GpImageAttributes *imageattr;
+    GpMetafile *metafile;
+    GpGraphics *graphics;
+    HENHMETAFILE hemf;
+    GpStatus stat;
+    BITMAPINFO info;
+    BYTE buff[400];
+    GpImage *image;
+    HDC hdc;
+
+    hdc = CreateCompatibleDC(0);
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    memset(&info, 0, sizeof(info));
+    info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    info.bmiHeader.biWidth = 10;
+    info.bmiHeader.biHeight = 10;
+    info.bmiHeader.biPlanes = 1;
+    info.bmiHeader.biBitCount = 32;
+    info.bmiHeader.biCompression = BI_RGB;
+    memset(buff, 0x80, sizeof(buff));
+    stat = GdipCreateBitmapFromGdiDib(&info, buff, (GpBitmap**)&image);
+    expect(Ok, stat);
+
+    stat = GdipCreateImageAttributes(&imageattr);
+    expect(Ok, stat);
+
+    stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
+            TRUE, &double_red, NULL, ColorMatrixFlagsDefault);
+    expect(Ok, stat);
+
+    stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
+            0.0, 0.0, 10.0, 10.0, UnitPixel, imageattr, NULL, NULL);
+    GdipDisposeImageAttributes(imageattr);
+    expect(Ok, stat);
+
+    GdipDisposeImage(image);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+    sync_metafile(&metafile, "draw_image_bitmap.emf");
+
+    stat = GdipGetHemfFromMetafile(metafile, &hemf);
+    expect(Ok, stat);
+
+    check_emfplus(hemf, draw_image_bitmap_records, "draw image bitmap");
+
+    /* test drawing metafile */
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    stat = GdipCreateMetafileFromEmf(hemf, TRUE, (GpMetafile**)&image);
+    expect(Ok, stat);
+
+    stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
+            0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
+    expect(Ok, stat);
+
+    GdipDisposeImage(image);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+    sync_metafile(&metafile, "draw_image_metafile.emf");
+
+    stat = GdipGetHemfFromMetafile(metafile, &hemf);
+    expect(Ok, stat);
+
+    if (GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipConvertToEmfPlus"))
+    {
+        check_emfplus(hemf, draw_image_metafile_records, "draw image metafile");
+    }
+    else
+    {
+        win_skip("draw image metafile records tests skipped\n");
+    }
+    DeleteEnhMetaFile(hemf);
+
+    DeleteDC(hdc);
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
+}
+
+static const emfplus_record properties_records[] = {
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeSetTextRenderingHint},
+    {0, EmfPlusRecordTypeSetPixelOffsetMode},
+    {0, EmfPlusRecordTypeSetAntiAliasMode},
+    {0, EmfPlusRecordTypeSetCompositingMode},
+    {0, EmfPlusRecordTypeSetCompositingQuality},
+    {0, EmfPlusRecordTypeSetInterpolationMode},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    {0}
+};
+
+static void test_properties(void)
+{
+    static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+    static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+
+    GpMetafile *metafile;
+    GpGraphics *graphics;
+    HENHMETAFILE hemf;
+    GpStatus stat;
+    HDC hdc;
+
+    hdc = CreateCompatibleDC(0);
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+    DeleteDC(hdc);
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    stat = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
+    expect(Ok, stat);
+    stat = GdipSetTextRenderingHint(graphics, TextRenderingHintAntiAlias);
+    expect(Ok, stat);
+
+    stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
+    expect(Ok, stat);
+    stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
+    expect(Ok, stat);
+
+    stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
+    expect(Ok, stat);
+    stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
+    expect(Ok, stat);
+
+    stat = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
+    expect(Ok, stat);
+    stat = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
+    expect(Ok, stat);
+
+    stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
+    expect(Ok, stat);
+    stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
+    expect(Ok, stat);
+
+    stat = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
+    expect(Ok, stat);
+    stat = GdipSetInterpolationMode(graphics, InterpolationModeHighQuality);
+    expect(Ok, stat);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+    sync_metafile(&metafile, "properties.emf");
+
+    stat = GdipGetHemfFromMetafile(metafile, &hemf);
+    expect(Ok, stat);
+
+    check_emfplus(hemf, properties_records, "properties");
+    DeleteEnhMetaFile(hemf);
+
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
+}
+
+static const emfplus_record draw_path_records[] = {
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeDrawPath},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_BITBLT},
+    {1, EMR_RESTOREDC},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    {0}
+};
+
+static void test_drawpath(void)
+{
+    static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+    static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+
+    GpMetafile *metafile;
+    GpGraphics *graphics;
+    HENHMETAFILE hemf;
+    GpStatus stat;
+    GpPath *path;
+    GpPen *pen;
+    HDC hdc;
+
+    hdc = CreateCompatibleDC(0);
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+    DeleteDC(hdc);
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathLine(path, 5, 5, 30, 30);
+    expect(Ok, stat);
+
+    stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, stat);
+
+    stat = GdipDrawPath(graphics, pen, path);
+    expect(Ok, stat);
+
+    stat = GdipDeletePen(pen);
+    expect(Ok, stat);
+    stat = GdipDeletePath(path);
+    expect(Ok, stat);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+    sync_metafile(&metafile, "draw_path.emf");
+
+    stat = GdipGetHemfFromMetafile(metafile, &hemf);
+    expect(Ok, stat);
+
+    check_emfplus(hemf, draw_path_records, "draw path");
+    DeleteEnhMetaFile(hemf);
+
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
+}
+
+static const emfplus_record fill_path_records[] = {
+    {0, EMR_HEADER},
+    {0, EmfPlusRecordTypeHeader},
+    {0, EmfPlusRecordTypeObject},
+    {0, EmfPlusRecordTypeFillPath},
+    {1, EMR_SAVEDC},
+    {1, EMR_SETICMMODE},
+    {1, EMR_BITBLT},
+    {1, EMR_RESTOREDC},
+    {0, EmfPlusRecordTypeEndOfFile},
+    {0, EMR_EOF},
+    {0}
+};
+
+static void test_fillpath(void)
+{
+    static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+    static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+    static const WCHAR winetestemfW[] = {'w','i','n','e','t','e','s','t','.','e','m','f',0};
+
+    GpMetafile *metafile;
+    GpGraphics *graphics;
+    GpSolidFill *brush;
+    HENHMETAFILE hemf;
+    GpStatus stat;
+    GpPath *path;
+    HDC hdc;
+
+    hdc = CreateCompatibleDC(0);
+    stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+    expect(Ok, stat);
+    DeleteDC(hdc);
+
+    stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+    expect(Ok, stat);
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathLine(path, 5, 5, 30, 30);
+    expect(Ok, stat);
+    stat = GdipAddPathLine(path, 30, 30, 5, 30);
+    expect(Ok, stat);
+
+    stat = GdipCreateSolidFill(0xffaabbcc, &brush);
+    expect(Ok, stat);
+
+    stat = GdipFillPath(graphics, (GpBrush*)brush, path);
+    expect(Ok, stat);
+
+    stat = GdipDeleteBrush((GpBrush*)brush);
+    expect(Ok, stat);
+    stat = GdipDeletePath(path);
+    expect(Ok, stat);
+
+    stat = GdipDeleteGraphics(graphics);
+    expect(Ok, stat);
+    sync_metafile(&metafile, "fill_path.emf");
+
+    stat = GdipGetHemfFromMetafile(metafile, &hemf);
+    expect(Ok, stat);
+
+    check_emfplus(hemf, fill_path_records, "fill path");
+
+    /* write to disk */
+    DeleteEnhMetaFile(CopyEnhMetaFileW(hemf, winetestemfW));
+
+    DeleteEnhMetaFile(hemf);
+
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
+
+    /* should succeed when given path to an EMF */
+    stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
+    expect(Ok, stat);
+
+    stat = GdipDisposeImage((GpImage*)metafile);
+    expect(Ok, stat);
+
+    DeleteFileW(winetestemfW);
+
+    stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
+    expect(GenericError, stat);
+}
+
 START_TEST(metafile)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
     int myARGC;
     char **myARGV;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
@@ -2314,6 +2817,10 @@ START_TEST(metafile)
     test_containers();
     test_clipping();
     test_gditransform();
+    test_drawimage();
+    test_properties();
+    test_drawpath();
+    test_fillpath();
 
     GdiplusShutdown(gdiplusToken);
 }
index 137f332..cf6d100 100644 (file)
@@ -565,6 +565,13 @@ START_TEST(pathiterator)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index a8ee9da..39833ca 100644 (file)
@@ -461,6 +461,13 @@ START_TEST(pen)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     test_startup();
 
index b09c55c..878c000 100644 (file)
@@ -42,7 +42,7 @@
 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) < (precision), "Expected %f, got %f\n", (expected), (got))
 #define expectf(expected, got) expectf_((expected), (got), 0.001)
 
-#define expect_magic(value) ok(*(value) == RGNDATA_MAGIC || *(value) == RGNDATA_MAGIC2, "Expected a known magic value, got %8x\n", *(value))
+#define expect_magic(value) ok(broken(*(value) == RGNDATA_MAGIC) || *(value) == RGNDATA_MAGIC2, "Expected a known magic value, got %8x\n", *(value))
 #define expect_dword(value, expected) expect((expected), *(value))
 #define expect_float(value, expected) expectf((expected), *(FLOAT *)(value))
 
@@ -1123,6 +1123,8 @@ static void test_gethrgn(void)
     GpGraphics *graphics;
     HRGN hrgn;
     HDC hdc=GetDC(0);
+    INT rgntype;
+    RECT rgnbox;
     static const RECT empty_rect = {0,0,0,0};
     static const RECT test_rect = {10, 11, 20, 21};
     static const GpRectF test_rectF = {10.0, 11.0, 10.0, 10.0};
@@ -1243,6 +1245,35 @@ static void test_gethrgn(void)
     ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteGraphics(graphics);
     ok(status == Ok, "status %08x\n", status);
+
+    /* test with gdi32 transform */
+    SetViewportOrgEx(hdc, 10, 10, NULL);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipCreateRegionRect(&test_rectF, &region);
+    expect(Ok, status);
+
+    status = GdipGetRegionHRgn(region, graphics, &hrgn);
+    expect(Ok, status);
+
+    rgntype = GetRgnBox(hrgn, &rgnbox);
+    DeleteObject(hrgn);
+
+    expect(SIMPLEREGION, rgntype);
+    expect(20, rgnbox.left);
+    expect(21, rgnbox.top);
+    expect(30, rgnbox.right);
+    expect(31, rgnbox.bottom);
+
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+    status = GdipDeleteGraphics(graphics);
+    expect(Ok, status);
+
+    SetViewportOrgEx(hdc, 0, 0, NULL);
+
     ReleaseDC(0, hdc);
 }
 
@@ -2267,6 +2298,13 @@ START_TEST(region)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
index 0135d6e..b06726f 100644 (file)
@@ -444,6 +444,13 @@ START_TEST(stringformat)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
     ULONG_PTR gdiplusToken;
+    HMODULE hmsvcrt;
+    int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+
+    /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
+    hmsvcrt = LoadLibraryA("msvcrt");
+    _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
+    if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;