- Sync gdiplus wine tests
authorDmitry Chapyshev <dmitry@reactos.org>
Sat, 6 Dec 2008 09:26:52 +0000 (09:26 +0000)
committerDmitry Chapyshev <dmitry@reactos.org>
Sat, 6 Dec 2008 09:26:52 +0000 (09:26 +0000)
svn path=/trunk/; revision=37883

13 files changed:
rostests/winetests/gdiplus/brush.c
rostests/winetests/gdiplus/customlinecap.c [new file with mode: 0644]
rostests/winetests/gdiplus/font.c
rostests/winetests/gdiplus/gdiplus.rbuild
rostests/winetests/gdiplus/graphics.c
rostests/winetests/gdiplus/graphicspath.c
rostests/winetests/gdiplus/image.c
rostests/winetests/gdiplus/matrix.c
rostests/winetests/gdiplus/pathiterator.c
rostests/winetests/gdiplus/pen.c
rostests/winetests/gdiplus/region.c
rostests/winetests/gdiplus/stringformat.c
rostests/winetests/gdiplus/testlist.c

index 70eac03..ae83184 100644 (file)
 #include "windows.h"
 #include "gdiplus.h"
 #include "wine/test.h"
+#include <math.h>
 
 #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 void test_constructor_destructor(void)
 {
@@ -49,12 +51,238 @@ static void test_type(void)
     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
 
     status = GdipGetBrushType((GpBrush*)brush, &bt);
-    expect(status, Ok);
-    expect(bt, BrushTypeSolidColor);
+    expect(Ok, status);
+    expect(BrushTypeSolidColor, bt);
+
+    GdipDeleteBrush((GpBrush*) brush);
+}
+static GpPointF blendcount_ptf[] = {{0.0, 0.0},
+                                    {50.0, 50.0}};
+static void test_gradientblendcount(void)
+{
+    GpStatus status;
+    GpPathGradient *brush;
+    INT count;
+
+    status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &brush);
+    expect(Ok, status);
+
+    status = GdipGetPathGradientBlendCount(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlendCount(NULL, &count);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlendCount(brush, NULL);
+    expect(InvalidParameter, status);
+
+    status = GdipGetPathGradientBlendCount(brush, &count);
+    expect(Ok, status);
+    expect(1, count);
+
+    GdipDeleteBrush((GpBrush*) brush);
+}
+
+static GpPointF getblend_ptf[] = {{0.0, 0.0},
+                                  {50.0, 50.0}};
+static void test_getblend(void)
+{
+    GpStatus status;
+    GpPathGradient *brush;
+    REAL blends[4];
+    REAL pos[4];
+
+    status = GdipCreatePathGradient(getblend_ptf, 2, WrapModeClamp, &brush);
+    expect(Ok, status);
+
+    /* check some invalid parameters combinations */
+    status = GdipGetPathGradientBlend(NULL, NULL,  NULL, -1);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlend(brush,NULL,  NULL, -1);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlend(NULL, blends,NULL, -1);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlend(NULL, NULL,  pos,  -1);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientBlend(NULL, NULL,  NULL,  1);
+    expect(InvalidParameter, status);
+
+    blends[0] = (REAL)0xdeadbeef;
+    pos[0]    = (REAL)0xdeadbeef;
+    status = GdipGetPathGradientBlend(brush, blends, pos, 1);
+    expect(Ok, status);
+    expectf(1.0, blends[0]);
+    expectf((REAL)0xdeadbeef, pos[0]);
 
     GdipDeleteBrush((GpBrush*) brush);
 }
 
+static GpPointF getbounds_ptf[] = {{0.0, 20.0},
+                                   {50.0, 50.0},
+                                   {21.0, 25.0},
+                                   {25.0, 46.0}};
+static void test_getbounds(void)
+{
+    GpStatus status;
+    GpPathGradient *brush;
+    GpRectF bounds;
+
+    status = GdipCreatePathGradient(getbounds_ptf, 4, WrapModeClamp, &brush);
+    expect(Ok, status);
+
+    status = GdipGetPathGradientRect(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientRect(brush, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPathGradientRect(NULL, &bounds);
+    expect(InvalidParameter, status);
+
+    status = GdipGetPathGradientRect(brush, &bounds);
+    expect(Ok, status);
+    expectf(0.0, bounds.X);
+    expectf(20.0, bounds.Y);
+    expectf(50.0, bounds.Width);
+    expectf(30.0, bounds.Height);
+
+    GdipDeleteBrush((GpBrush*) brush);
+}
+
+static void test_getgamma(void)
+{
+    GpStatus status;
+    GpLineGradient *line;
+    GpPointF start, end;
+    BOOL gamma;
+
+    start.X = start.Y = 0.0;
+    end.X = end.Y = 100.0;
+
+    status = GdipCreateLineBrush(&start, &end, (ARGB)0xdeadbeef, 0xdeadbeef, WrapModeTile, &line);
+    expect(Ok, status);
+
+    /* NULL arguments */
+    status = GdipGetLineGammaCorrection(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetLineGammaCorrection(line, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetLineGammaCorrection(NULL, &gamma);
+    expect(InvalidParameter, status);
+
+    GdipDeleteBrush((GpBrush*)line);
+}
+
+static void test_transform(void)
+{
+    GpStatus status;
+    GpTexture *texture;
+    GpGraphics *graphics = NULL;
+    GpBitmap *bitmap;
+    HDC hdc = GetDC(0);
+    GpMatrix *m, *m1;
+    BOOL res;
+
+    status = GdipCreateMatrix2(2.0, 0.0, 0.0, 0.0, 0.0, 0.0, &m);
+    expect(Ok, status);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    status = GdipCreateBitmapFromGraphics(1, 1, graphics, &bitmap);
+    expect(Ok, status);
+
+    status = GdipCreateTexture((GpImage*)bitmap, WrapModeTile, &texture);
+    expect(Ok, status);
+
+    /* NULL */
+    status = GdipGetTextureTransform(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetTextureTransform(texture, NULL);
+    expect(InvalidParameter, status);
+
+    /* get default value - identity matrix */
+    status = GdipGetTextureTransform(texture, m);
+    expect(Ok, status);
+    status = GdipIsMatrixIdentity(m, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+    /* set and get then */
+    status = GdipCreateMatrix2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, &m1);
+    expect(Ok, status);
+    status = GdipSetTextureTransform(texture, m1);
+    expect(Ok, status);
+    status = GdipGetTextureTransform(texture, m);
+    expect(Ok, status);
+    status = GdipIsMatrixEqual(m, m1, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+    /* reset */
+    status = GdipResetTextureTransform(texture);
+    expect(Ok, status);
+    status = GdipGetTextureTransform(texture, m);
+    expect(Ok, status);
+    status = GdipIsMatrixIdentity(m, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    status = GdipDeleteBrush((GpBrush*)texture);
+    expect(Ok, status);
+
+    status = GdipDeleteMatrix(m1);
+    expect(Ok, status);
+    status = GdipDeleteMatrix(m);
+    expect(Ok, status);
+    status = GdipDisposeImage((GpImage*)bitmap);
+    expect(Ok, status);
+    status = GdipDeleteGraphics(graphics);
+    expect(Ok, status);
+    ReleaseDC(0, hdc);
+}
+
+static void test_texturewrap(void)
+{
+    GpStatus status;
+    GpTexture *texture;
+    GpGraphics *graphics = NULL;
+    GpBitmap *bitmap;
+    HDC hdc = GetDC(0);
+    GpWrapMode wrap;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    status = GdipCreateBitmapFromGraphics(1, 1, graphics, &bitmap);
+    expect(Ok, status);
+
+    status = GdipCreateTexture((GpImage*)bitmap, WrapModeTile, &texture);
+    expect(Ok, status);
+
+    /* NULL */
+    status = GdipGetTextureWrapMode(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetTextureWrapMode(texture, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetTextureWrapMode(NULL, &wrap);
+    expect(InvalidParameter, status);
+
+    /* get */
+    wrap = WrapModeClamp;
+    status = GdipGetTextureWrapMode(texture, &wrap);
+    expect(Ok, status);
+    expect(WrapModeTile, wrap);
+    /* set, then get */
+    wrap = WrapModeClamp;
+    status = GdipSetTextureWrapMode(texture, wrap);
+    expect(Ok, status);
+    wrap = WrapModeTile;
+    status = GdipGetTextureWrapMode(texture, &wrap);
+    expect(Ok, status);
+    expect(WrapModeClamp, wrap);
+
+    status = GdipDeleteBrush((GpBrush*)texture);
+    expect(Ok, status);
+    status = GdipDisposeImage((GpImage*)bitmap);
+    expect(Ok, status);
+    status = GdipDeleteGraphics(graphics);
+    expect(Ok, status);
+    ReleaseDC(0, hdc);
+}
+
 START_TEST(brush)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -69,6 +297,12 @@ START_TEST(brush)
 
     test_constructor_destructor();
     test_type();
+    test_gradientblendcount();
+    test_getblend();
+    test_getbounds();
+    test_getgamma();
+    test_transform();
+    test_texturewrap();
 
     GdiplusShutdown(gdiplusToken);
 }
diff --git a/rostests/winetests/gdiplus/customlinecap.c b/rostests/winetests/gdiplus/customlinecap.c
new file mode 100644 (file)
index 0000000..78a8c70
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Unit test suite for customlinecap
+ *
+ * Copyright (C) 2008 Nikolay Sivov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "windows.h"
+#include "gdiplus.h"
+#include "wine/test.h"
+
+#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
+#define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got)
+
+static void test_constructor_destructor(void)
+{
+    GpCustomLineCap *custom;
+    GpPath *path, *path2;
+    GpStatus stat;
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
+    expect(Ok, stat);
+
+    stat = GdipCreatePath(FillModeAlternate, &path2);
+    expect(Ok, stat);
+    stat = GdipAddPathRectangle(path2, 5.0, 5.0, 10.0, 10.0);
+    expect(Ok, stat);
+
+    /* NULL args */
+    stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 0.0, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, &custom);
+    expect(InvalidParameter, stat);
+    stat = GdipDeleteCustomLineCap(NULL);
+    expect(InvalidParameter, stat);
+
+    /* valid args */
+    stat = GdipCreateCustomLineCap(NULL, path2, LineCapFlat, 0.0, &custom);
+    expect(Ok, stat);
+    stat = GdipDeleteCustomLineCap(custom);
+    expect(Ok, stat);
+    /* it's strange but native returns NotImplemented on stroke == NULL */
+    stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 10.0, &custom);
+    todo_wine expect(NotImplemented, stat);
+
+    GdipDeletePath(path2);
+    GdipDeletePath(path);
+}
+
+static void test_linejoin(void)
+{
+    GpCustomLineCap *custom;
+    GpPath *path;
+    GpLineJoin join;
+    GpStatus stat;
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
+    expect(Ok, stat);
+
+    stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
+    expect(Ok, stat);
+
+    /* NULL args */
+    stat = GdipGetCustomLineCapStrokeJoin(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapStrokeJoin(custom, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapStrokeJoin(NULL, &join);
+    expect(InvalidParameter, stat);
+    stat = GdipSetCustomLineCapStrokeJoin(NULL, LineJoinBevel);
+    expect(InvalidParameter, stat);
+
+    /* LineJoinMiter is default */
+    stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
+    expect(Ok, stat);
+    expect(LineJoinMiter, join);
+
+    /* set/get */
+    stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinBevel);
+    expect(Ok, stat);
+    stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
+    expect(Ok, stat);
+    expect(LineJoinBevel, join);
+    stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinRound);
+    expect(Ok, stat);
+    stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
+    expect(Ok, stat);
+    expect(LineJoinRound, join);
+    stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinMiterClipped);
+    expect(Ok, stat);
+    stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
+    expect(Ok, stat);
+    expect(LineJoinMiterClipped, join);
+
+    GdipDeleteCustomLineCap(custom);
+    GdipDeletePath(path);
+}
+
+static void test_inset(void)
+{
+    GpCustomLineCap *custom;
+    GpPath *path;
+    REAL inset;
+    GpStatus stat;
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
+    expect(Ok, stat);
+
+    stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
+    expect(Ok, stat);
+
+    /* NULL args */
+    stat = GdipGetCustomLineCapBaseInset(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapBaseInset(NULL, &inset);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapBaseInset(custom, NULL);
+    expect(InvalidParameter, stat);
+    /* valid args */
+    inset = (REAL)0xdeadbeef;
+    stat = GdipGetCustomLineCapBaseInset(custom, &inset);
+    expect(Ok, stat);
+    expectf(0.0, inset);
+
+    GdipDeleteCustomLineCap(custom);
+    GdipDeletePath(path);
+}
+
+static void test_scale(void)
+{
+    GpCustomLineCap *custom;
+    GpPath *path;
+    REAL scale;
+    GpStatus stat;
+
+    stat = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, stat);
+    stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
+    expect(Ok, stat);
+
+    stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
+    expect(Ok, stat);
+
+    /* NULL args */
+    stat = GdipGetCustomLineCapWidthScale(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapWidthScale(NULL, &scale);
+    expect(InvalidParameter, stat);
+    stat = GdipGetCustomLineCapWidthScale(custom, NULL);
+    expect(InvalidParameter, stat);
+    /* valid args */
+    scale = (REAL)0xdeadbeef;
+    stat = GdipGetCustomLineCapWidthScale(custom, &scale);
+    expect(Ok, stat);
+    expectf(1.0, scale);
+
+    GdipDeleteCustomLineCap(custom);
+    GdipDeletePath(path);
+}
+
+START_TEST(customlinecap)
+{
+    struct GdiplusStartupInput gdiplusStartupInput;
+    ULONG_PTR gdiplusToken;
+
+    gdiplusStartupInput.GdiplusVersion              = 1;
+    gdiplusStartupInput.DebugEventCallback          = NULL;
+    gdiplusStartupInput.SuppressBackgroundThread    = 0;
+    gdiplusStartupInput.SuppressExternalCodecs      = 0;
+
+    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
+
+    test_constructor_destructor();
+    test_linejoin();
+    test_inset();
+    test_scale();
+
+    GdiplusShutdown(gdiplusToken);
+}
index 59a8d53..7ff5afc 100644 (file)
@@ -25,7 +25,7 @@
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 
 static const WCHAR arial[] = {'A','r','i','a','l','\0'};
-static const WCHAR nonexistant[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
+static const WCHAR nonexistent[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
 static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
 static const WCHAR MicrosoftSansSerif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
 static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
@@ -41,18 +41,24 @@ static const char *debugstr_w(LPCWSTR str)
 
 static void test_createfont(void)
 {
-    GpFontFamily* fontfamily = NULL;
+    GpFontFamily* fontfamily = NULL, *fontfamily2;
     GpFont* font = NULL;
     GpStatus stat;
     Unit unit;
     UINT i;
     REAL size;
+    WCHAR familyname[LF_FACESIZE];
 
-    stat = GdipCreateFontFamilyFromName(nonexistant, NULL, &fontfamily);
+    stat = GdipCreateFontFamilyFromName(nonexistent, NULL, &fontfamily);
     expect (FontFamilyNotFound, stat);
     stat = GdipDeleteFont(font);
     expect (InvalidParameter, stat);
     stat = GdipCreateFontFamilyFromName(arial, NULL, &fontfamily);
+    if(stat == FontFamilyNotFound)
+    {
+        skip("Arial not installed\n");
+        return;
+    }
     expect (Ok, stat);
     stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font);
     expect (Ok, stat);
@@ -60,6 +66,15 @@ static void test_createfont(void)
     expect (Ok, stat);
     expect (UnitPoint, unit);
 
+    stat = GdipGetFamily(font, &fontfamily2);
+    expect(Ok, stat);
+    stat = GdipGetFamilyName(fontfamily2, familyname, 0);
+    expect(Ok, stat);
+    ok (lstrcmpiW(arial, familyname) == 0, "Expected arial, got %s\n",
+            debugstr_w(familyname));
+    stat = GdipDeleteFontFamily(fontfamily2);
+    expect(Ok, stat);
+
     /* Test to see if returned size is based on unit (its not) */
     GdipGetFontSize(font, &size);
     ok (size == 12, "Expected 12, got %f\n", size);
@@ -76,6 +91,8 @@ static void test_createfont(void)
         expect (i, unit);
         GdipDeleteFont(font);
     }
+
+    GdipDeleteFontFamily(fontfamily);
 }
 
 static void test_logfont(void)
@@ -85,13 +102,26 @@ static void test_logfont(void)
     GpStatus stat;
     GpGraphics *graphics;
     HDC hdc = GetDC(0);
+    INT style;
 
     GdipCreateFromHDC(hdc, &graphics);
     memset(&lfw, 0, sizeof(LOGFONTW));
     memset(&lfw2, 0xff, sizeof(LOGFONTW));
+
+    /* empty FaceName */
+    lfw.lfFaceName[0] = 0;
+    stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font);
+
+    expect(NotTrueTypeFont, stat);
+
     memcpy(&lfw.lfFaceName, arial, 6 * sizeof(WCHAR));
 
     stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font);
+    if (stat == FileNotFound)
+    {
+        skip("Arial not installed.\n");
+        return;
+    }
     expect(Ok, stat);
     stat = GdipGetLogFontW(font, graphics, &lfw2);
     expect(Ok, stat);
@@ -140,6 +170,11 @@ static void test_logfont(void)
     expect(0, lfw2.lfQuality);
     expect(0, lfw2.lfPitchAndFamily);
 
+    stat = GdipGetFontStyle(font, &style);
+    expect(Ok, stat);
+    ok (style == (FontStyleItalic | FontStyleUnderline | FontStyleStrikeout),
+            "Expected , got %d\n", style);
+
     GdipDeleteFont(font);
 
     GdipDeleteGraphics(graphics);
@@ -148,91 +183,162 @@ static void test_logfont(void)
 
 static void test_fontfamily (void)
 {
-    GpFontFamily** family = NULL;
+    GpFontFamily *family, *clonedFontFamily;
     WCHAR itsName[LF_FACESIZE];
     GpStatus stat;
 
-    /* FontFamily can not be NULL */
-    stat = GdipCreateFontFamilyFromName (arial , NULL, family);
+    /* FontFamily cannot be NULL */
+    stat = GdipCreateFontFamilyFromName (arial , NULL, NULL);
     expect (InvalidParameter, stat);
 
-    family = GdipAlloc (sizeof (GpFontFamily*));
-
     /* FontFamily must be able to actually find the family.
-     * If it can't, any subsequent calls should fail
-     *
-     * We currently fail (meaning we don't) because we don't actually
-     * test to see if we can successfully get a family
+     * If it can't, any subsequent calls should fail.
      */
-    stat = GdipCreateFontFamilyFromName (nonexistant, NULL, family);
+    stat = GdipCreateFontFamilyFromName (nonexistent, NULL, &family);
     expect (FontFamilyNotFound, stat);
-    stat = GdipGetFamilyName (*family,itsName, LANG_NEUTRAL);
-    expect (InvalidParameter, stat);
-    ok ((lstrcmpiW(itsName,nonexistant) != 0),
-        "Expected a non-zero value for nonexistant font!\n");
-    stat = GdipDeleteFontFamily(*family);
-    expect (InvalidParameter, stat);
 
-    stat = GdipCreateFontFamilyFromName (arial, NULL, family);
+    /* Bitmap fonts are not found */
+todo_wine
+{
+    stat = GdipCreateFontFamilyFromName (MSSansSerif, NULL, &family);
+    expect (FontFamilyNotFound, stat);
+}
+
+    stat = GdipCreateFontFamilyFromName (arial, NULL, &family);
+    if(stat == FontFamilyNotFound)
+    {
+        skip("Arial not installed\n");
+        return;
+    }
     expect (Ok, stat);
 
-    stat = GdipGetFamilyName (*family, itsName, LANG_NEUTRAL);
+    stat = GdipGetFamilyName (family, itsName, LANG_NEUTRAL);
     expect (Ok, stat);
-    expect (0, lstrcmpiW(itsName,arial));
+    expect (0, lstrcmpiW(itsName, arial));
 
     if (0)
     {
         /* Crashes on Windows XP SP2, Vista, and so Wine as well */
-        stat = GdipGetFamilyName (*family, NULL, LANG_NEUTRAL);
+        stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
         expect (Ok, stat);
     }
 
-    stat = GdipDeleteFontFamily(*family);
+    /* Make sure we don't read old data */
+    ZeroMemory (itsName, sizeof(itsName));
+    stat = GdipCloneFontFamily(family, &clonedFontFamily);
     expect (Ok, stat);
+    GdipDeleteFontFamily(family);
+    stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
+    expect(Ok, stat);
+    expect(0, lstrcmpiW(itsName, arial));
 
-    GdipFree (family);
+    GdipDeleteFontFamily(clonedFontFamily);
 }
 
+static void test_fontfamily_properties (void)
+{
+    GpFontFamily* FontFamily = NULL;
+    GpStatus stat;
+    UINT16 result = 0;
+
+    stat = GdipCreateFontFamilyFromName(arial, NULL, &FontFamily);
+    if(stat == FontFamilyNotFound)
+        skip("Arial not installed\n");
+    else
+    {
+        stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok (result == 2355, "Expected 2355, got %d\n", result);
+        result = 0;
+        stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok(result == 2048, "Expected 2048, got %d\n", result);
+        result = 0;
+        stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok(result == 1854, "Expected 1854, got %d\n", result);
+        result = 0;
+        stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
+        ok(result == 434, "Expected 434, got %d\n", result);
+        GdipDeleteFontFamily(FontFamily);
+    }
+
+    stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, &FontFamily);
+    if(stat == FontFamilyNotFound)
+        skip("Times New Roman not installed\n");
+    else
+    {
+        result = 0;
+        stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok(result == 2355, "Expected 2355, got %d\n", result);
+        result = 0;
+        stat = GdipGetEmHeight(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok(result == 2048, "Expected 2048, got %d\n", result);
+        result = 0;
+        stat = GdipGetCellAscent(FontFamily, FontStyleRegular, &result);
+        expect(Ok, stat);
+        ok(result == 1825, "Expected 1825, got %d\n", result);
+        result = 0;
+        stat = GdipGetCellDescent(FontFamily, FontStyleRegular, &result);
+        ok(result == 443, "Expected 443 got %d\n", result);
+        GdipDeleteFontFamily(FontFamily);
+    }
+}
 
 static void test_getgenerics (void)
 {
     GpStatus stat;
-    GpFontFamily** family;
+    GpFontFamily* family;
     WCHAR familyName[LF_FACESIZE];
     ZeroMemory(familyName, sizeof(familyName)/sizeof(WCHAR));
 
-    family = GdipAlloc (sizeof (GpFontFamily*));
-
-    stat = GdipGetGenericFontFamilySansSerif (family);
+    stat = GdipGetGenericFontFamilySansSerif (&family);
+    if (stat == FontFamilyNotFound)
+    {
+        skip("Microsoft Sans Serif not installed\n");
+        goto serif;
+    }
     expect (Ok, stat);
-    stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL);
+    stat = GdipGetFamilyName (family, familyName, LANG_NEUTRAL);
     expect (Ok, stat);
     ok ((lstrcmpiW(familyName, MicrosoftSansSerif) == 0) ||
         (lstrcmpiW(familyName,MSSansSerif) == 0),
         "Expected Microsoft Sans Serif or MS Sans Serif, got %s\n",
         debugstr_w(familyName));
-    stat = GdipDeleteFontFamily (*family);
+    stat = GdipDeleteFontFamily (family);
     expect (Ok, stat);
 
-    stat = GdipGetGenericFontFamilySerif (family);
+serif:
+    stat = GdipGetGenericFontFamilySerif (&family);
+    if (stat == FontFamilyNotFound)
+    {
+        skip("Times New Roman not installed\n");
+        goto monospace;
+    }
     expect (Ok, stat);
-    stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL);
+    stat = GdipGetFamilyName (family, familyName, LANG_NEUTRAL);
     expect (Ok, stat);
     ok (lstrcmpiW(familyName, TimesNewRoman) == 0,
         "Expected Times New Roman, got %s\n", debugstr_w(familyName));
-    stat = GdipDeleteFontFamily (*family);
+    stat = GdipDeleteFontFamily (family);
     expect (Ok, stat);
 
-    stat = GdipGetGenericFontFamilyMonospace (family);
+monospace:
+    stat = GdipGetGenericFontFamilyMonospace (&family);
+    if (stat == FontFamilyNotFound)
+    {
+        skip("Courier New not installed\n");
+        return;
+    }
     expect (Ok, stat);
-    stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL);
+    stat = GdipGetFamilyName (family, familyName, LANG_NEUTRAL);
     expect (Ok, stat);
     ok (lstrcmpiW(familyName, CourierNew) == 0,
         "Expected Courier New, got %s\n", debugstr_w(familyName));
-    stat = GdipDeleteFontFamily (*family);
+    stat = GdipDeleteFontFamily (family);
     expect (Ok, stat);
-
-    GdipFree (family);
 }
 
 START_TEST(font)
@@ -250,6 +356,7 @@ START_TEST(font)
     test_createfont();
     test_logfont();
     test_fontfamily();
+    test_fontfamily_properties();
     test_getgenerics();
 
     GdiplusShutdown(gdiplusToken);
index 2067c9f..4caec7d 100644 (file)
@@ -4,6 +4,7 @@
 <module name="gdiplus_winetest" type="win32cui" installbase="bin" installname="gdiplus_winetest.exe" allowwarnings="true">
        <include base="gdiplus_winetest">.</include>
        <file>brush.c</file>
+       <file>customlinecap.c</file>
        <file>font.c</file>
        <file>graphics.c</file>
        <file>graphicspath.c</file>
index 168eae3..5db3ca9 100644 (file)
@@ -130,12 +130,10 @@ static void test_save_restore(void)
     GdipCreateFromHDC(hdc, &graphics1);
     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
     stat = GdipSaveGraphics(graphics1, &state_a);
-    todo_wine
-        expect(Ok, stat);
+    expect(Ok, stat);
     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
     stat = GdipRestoreGraphics(graphics1, state_a);
-    todo_wine
-        expect(Ok, stat);
+    expect(Ok, stat);
     GdipGetInterpolationMode(graphics1, &mode);
     todo_wine
         expect(InterpolationModeBilinear, mode);
@@ -151,8 +149,7 @@ static void test_save_restore(void)
     GdipSaveGraphics(graphics1, &state_b);
     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
     stat = GdipRestoreGraphics(graphics1, 0xdeadbeef);
-    todo_wine
-        expect(Ok, stat);
+    expect(Ok, stat);
     GdipRestoreGraphics(graphics1, state_b);
     GdipGetInterpolationMode(graphics1, &mode);
     todo_wine
@@ -277,6 +274,8 @@ static void test_GdipDrawArc(void)
     expect(Ok, status);
 
     GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
     ReleaseDC(0, hdc);
 }
 
@@ -321,6 +320,8 @@ static void test_GdipDrawArcI(void)
     expect(Ok, status);
 
     GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
     ReleaseDC(0, hdc);
 }
 
@@ -359,6 +360,8 @@ static void test_GdipDrawBezierI(void)
     expect(Ok, status);
 
     GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
     ReleaseDC(0, hdc);
 }
 
@@ -397,6 +400,8 @@ static void test_GdipDrawLineI(void)
     expect(Ok, status);
 
     GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
     ReleaseDC(0, hdc);
 }
 
@@ -449,6 +454,470 @@ static void test_GdipDrawLinesI(void)
 
     GdipFree(ptf);
     GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
+    ReleaseDC(0, hdc);
+}
+
+static void test_Get_Release_DC(void)
+{
+    GpStatus status;
+    GpGraphics *graphics = NULL;
+    GpPen *pen;
+    GpSolidFill *brush;
+    GpPath *path;
+    HDC hdc = GetDC(0);
+    HDC retdc;
+    REAL r;
+    CompositingQuality quality;
+    CompositingMode compmode;
+    InterpolationMode intmode;
+    GpMatrix *m;
+    GpRegion *region;
+    GpUnit unit;
+    PixelOffsetMode offsetmode;
+    SmoothingMode smoothmode;
+    TextRenderingHint texthint;
+    GpPointF ptf[5];
+    GpPoint  pt[5];
+    GpRectF  rectf[2];
+    GpRect   rect[2];
+    GpRegion *clip;
+    INT i;
+    BOOL res;
+
+    pt[0].X = 10;
+    pt[0].Y = 10;
+    pt[1].X = 20;
+    pt[1].Y = 15;
+    pt[2].X = 40;
+    pt[2].Y = 80;
+    pt[3].X = -20;
+    pt[3].Y = 20;
+    pt[4].X = 50;
+    pt[4].Y = 110;
+
+    for(i = 0; i < 5;i++){
+        ptf[i].X = (REAL)pt[i].X;
+        ptf[i].Y = (REAL)pt[i].Y;
+    }
+
+    rect[0].X = 0;
+    rect[0].Y = 0;
+    rect[0].Width  = 50;
+    rect[0].Height = 70;
+    rect[1].X = 0;
+    rect[1].Y = 0;
+    rect[1].Width  = 10;
+    rect[1].Height = 20;
+
+    for(i = 0; i < 2;i++){
+        rectf[i].X = (REAL)rect[i].X;
+        rectf[i].Y = (REAL)rect[i].Y;
+        rectf[i].Height = (REAL)rect[i].Height;
+        rectf[i].Width  = (REAL)rect[i].Width;
+    }
+
+    GdipCreateMatrix(&m);
+    GdipCreateRegion(&region);
+    GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
+    GdipCreatePath(FillModeAlternate, &path);
+    GdipCreateRegion(&clip);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    ok(graphics != NULL, "Expected graphics to be initialized\n");
+    status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+
+    /* NULL arguments */
+    status = GdipGetDC(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetDC(graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetDC(NULL, &retdc);
+    expect(InvalidParameter, status);
+
+    status = GdipReleaseDC(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipReleaseDC(graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipReleaseDC(NULL, (HDC)0xdeadbeef);
+    expect(InvalidParameter, status);
+
+    /* Release without Get */
+    status = GdipReleaseDC(graphics, hdc);
+    expect(InvalidParameter, status);
+
+    retdc = NULL;
+    status = GdipGetDC(graphics, &retdc);
+    expect(Ok, status);
+    ok(retdc == hdc, "Invalid HDC returned\n");
+    /* call it once more */
+    status = GdipGetDC(graphics, &retdc);
+    expect(ObjectBusy, status);
+
+    /* try all Graphics calls here */
+    status = Ok;
+    status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0.0, 0.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawBezier(graphics, pen, 0.0, 10.0, 20.0, 15.0, 35.0, -10.0, 10.0, 10.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawBeziers(graphics, pen, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawBeziersI(graphics, pen, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawClosedCurve(graphics, pen, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawClosedCurveI(graphics, pen, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawClosedCurve2(graphics, pen, ptf, 5, 1.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawClosedCurve2I(graphics, pen, pt, 5, 1.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawCurve(graphics, pen, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawCurveI(graphics, pen, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawCurve2(graphics, pen, ptf, 5, 1.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawCurve2I(graphics, pen, pt, 5, 1.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawEllipse(graphics, pen, 0.0, 0.0, 100.0, 50.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawEllipseI(graphics, pen, 0, 0, 100, 50);
+    expect(ObjectBusy, status); status = Ok;
+    /* GdipDrawImage/GdipDrawImageI */
+    /* GdipDrawImagePointsRect/GdipDrawImagePointsRectI */
+    /* GdipDrawImageRectRect/GdipDrawImageRectRectI */
+    /* GdipDrawImageRect/GdipDrawImageRectI */
+    status = GdipDrawLine(graphics, pen, 0.0, 0.0, 100.0, 200.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawLineI(graphics, pen, 0, 0, 100, 200);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawLines(graphics, pen, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawLinesI(graphics, pen, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawPath(graphics, pen, path);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawPie(graphics, pen, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawPieI(graphics, pen, 0, 0, 100, 100, 0.0, 90.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawRectangle(graphics, pen, 0.0, 0.0, 100.0, 300.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawRectangleI(graphics, pen, 0, 0, 100, 300);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawRectangles(graphics, pen, rectf, 2);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawRectanglesI(graphics, pen, rect, 2);
+    expect(ObjectBusy, status); status = Ok;
+    /* GdipDrawString */
+    status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, ptf, 5, 1.0, FillModeAlternate);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, pt, 5, 1.0, FillModeAlternate);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillEllipse(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillEllipseI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPath(graphics, (GpBrush*)brush, path);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPie(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0, 0.0, 15.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPieI(graphics, (GpBrush*)brush, 0, 0, 100, 100, 0.0, 15.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPolygon(graphics, (GpBrush*)brush, ptf, 5, FillModeAlternate);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPolygonI(graphics, (GpBrush*)brush, pt, 5, FillModeAlternate);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPolygon2(graphics, (GpBrush*)brush, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillPolygon2I(graphics, (GpBrush*)brush, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillRectangles(graphics, (GpBrush*)brush, rectf, 2);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillRectanglesI(graphics, (GpBrush*)brush, rect, 2);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFillRegion(graphics, (GpBrush*)brush, region);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipFlush(graphics, FlushIntentionFlush);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetCompositingMode(graphics, &compmode);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetCompositingQuality(graphics, &quality);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetInterpolationMode(graphics, &intmode);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetPageScale(graphics, &r);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetPageUnit(graphics, &unit);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetPixelOffsetMode(graphics, &offsetmode);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetSmoothingMode(graphics, &smoothmode);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetTextRenderingHint(graphics, &texthint);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetWorldTransform(graphics, m);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGraphicsClear(graphics, 0xdeadbeef);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipIsVisiblePoint(graphics, 0.0, 0.0, &res);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipIsVisiblePointI(graphics, 0, 0, &res);
+    expect(ObjectBusy, status); status = Ok;
+    /* GdipMeasureCharacterRanges */
+    /* GdipMeasureString */
+    status = GdipResetClip(graphics);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipResetWorldTransform(graphics);
+    expect(ObjectBusy, status); status = Ok;
+    /* GdipRestoreGraphics */
+    status = GdipRotateWorldTransform(graphics, 15.0, MatrixOrderPrepend);
+    expect(ObjectBusy, status); status = Ok;
+    /*  GdipSaveGraphics */
+    status = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetCompositingQuality(graphics, CompositingQualityDefault);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetPageScale(graphics, 1.0);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetPageUnit(graphics, UnitWorld);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetPixelOffsetMode(graphics, PixelOffsetModeDefault);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetSmoothingMode(graphics, SmoothingModeDefault);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetWorldTransform(graphics, m);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipTranslateWorldTransform(graphics, 0.0, 0.0, MatrixOrderPrepend);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetClipPath(graphics, path, CombineModeReplace);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetClipRect(graphics, 0.0, 0.0, 10.0, 10.0, CombineModeReplace);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetClipRectI(graphics, 0, 0, 10, 10, CombineModeReplace);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
+    expect(ObjectBusy, status);
+    status = GdipDrawPolygon(graphics, pen, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipDrawPolygonI(graphics, pen, pt, 5);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetDpiX(graphics, &r);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipGetDpiY(graphics, &r);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipMultiplyWorldTransform(graphics, m, MatrixOrderPrepend);
+    status = GdipGetClip(graphics, region);
+    expect(ObjectBusy, status); status = Ok;
+    status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 5);
+    expect(ObjectBusy, status); status = Ok;
+    /* try to delete before release */
+    status = GdipDeleteGraphics(graphics);
+    expect(ObjectBusy, status);
+
+    status = GdipReleaseDC(graphics, retdc);
+    expect(Ok, status);
+
+    GdipDeletePen(pen);
+    GdipDeleteGraphics(graphics);
+
+    GdipDeletePath(path);
+    GdipDeleteBrush((GpBrush*)brush);
+    GdipDeleteRegion(region);
+    GdipDeleteMatrix(m);
+    GdipDeleteRegion(region);
+
+    ReleaseDC(0, hdc);
+}
+
+static void test_transformpoints(void)
+{
+    GpStatus status;
+    GpGraphics *graphics = NULL;
+    HDC hdc = GetDC(0);
+    GpPointF ptf[5];
+    INT i;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    for(i = 0; i < 5; i++){
+        ptf[i].X = 200.0 + i * 50.0 * (i % 2);
+        ptf[i].Y = 200.0 + i * 50.0 * !(i % 2);
+    }
+
+    /* NULL arguments */
+    status = GdipTransformPoints(NULL, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 0);
+    expect(InvalidParameter, status);
+    status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1);
+    expect(InvalidParameter, status);
+
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(0, hdc);
+}
+
+static void test_get_set_clip(void)
+{
+    GpStatus status;
+    GpGraphics *graphics = NULL;
+    HDC hdc = GetDC(0);
+    GpRegion *clip;
+    GpRectF rect;
+    BOOL res;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    rect.X = rect.Y = 0.0;
+    rect.Height = rect.Width = 100.0;
+
+    status = GdipCreateRegionRect(&rect, &clip);
+
+    /* NULL arguments */
+    status = GdipGetClip(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetClip(graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetClip(NULL, clip);
+    expect(InvalidParameter, status);
+
+    status = GdipSetClipRegion(NULL, NULL, CombineModeReplace);
+    expect(InvalidParameter, status);
+    status = GdipSetClipRegion(graphics, NULL, CombineModeReplace);
+    expect(InvalidParameter, status);
+
+    status = GdipSetClipPath(NULL, NULL, CombineModeReplace);
+    expect(InvalidParameter, status);
+    status = GdipSetClipPath(graphics, NULL, CombineModeReplace);
+    expect(InvalidParameter, status);
+
+    res = FALSE;
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    status = GdipIsInfiniteRegion(clip, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    /* remains infinite after reset */
+    res = FALSE;
+    status = GdipResetClip(graphics);
+    expect(Ok, status);
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    status = GdipIsInfiniteRegion(clip, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    /* set to empty and then reset to infinite */
+    status = GdipSetEmpty(clip);
+    expect(Ok, status);
+    status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    res = FALSE;
+    status = GdipIsEmptyRegion(clip, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+    status = GdipResetClip(graphics);
+    expect(Ok, status);
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    res = FALSE;
+    status = GdipIsInfiniteRegion(clip, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    GdipDeleteRegion(clip);
+
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(0, hdc);
+}
+
+static void test_isempty(void)
+{
+    GpStatus status;
+    GpGraphics *graphics = NULL;
+    HDC hdc = GetDC(0);
+    GpRegion *clip;
+    BOOL res;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipCreateRegion(&clip);
+    expect(Ok, status);
+
+    /* NULL */
+    status = GdipIsClipEmpty(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsClipEmpty(graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsClipEmpty(NULL, &res);
+    expect(InvalidParameter, status);
+
+    /* default is infinite */
+    res = TRUE;
+    status = GdipIsClipEmpty(graphics, &res);
+    expect(Ok, status);
+    expect(FALSE, res);
+
+    GdipDeleteRegion(clip);
+
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(0, hdc);
+}
+
+static void test_clear(void)
+{
+    GpStatus status;
+
+    status = GdipGraphicsClear(NULL, 0xdeadbeef);
+    expect(InvalidParameter, status);
+}
+
+static void test_textcontrast(void)
+{
+    GpStatus status;
+    HDC hdc = GetDC(0);
+    GpGraphics *graphics;
+    UINT contrast;
+
+    status = GdipGetTextContrast(NULL, NULL);
+    expect(InvalidParameter, status);
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipGetTextContrast(graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetTextContrast(graphics, &contrast);
+    expect(4, contrast);
+
+    GdipDeleteGraphics(graphics);
     ReleaseDC(0, hdc);
 }
 
@@ -471,6 +940,12 @@ START_TEST(graphics)
     test_GdipDrawArcI();
     test_GdipDrawLineI();
     test_GdipDrawLinesI();
+    test_Get_Release_DC();
+    test_transformpoints();
+    test_get_set_clip();
+    test_isempty();
+    test_clear();
+    test_textcontrast();
 
     GdiplusShutdown(gdiplusToken);
 }
index 9f9af9c..168c4b5 100644 (file)
@@ -214,6 +214,8 @@ static void test_line2(void)
     expect(Ok, status);
 
     ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE);
+
+    GdipDeletePath(path);
 }
 
 static path_test_t arc_path[] = {
@@ -283,6 +285,8 @@ static void test_arc(void)
     expect(Ok, status);
 
     ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE);
+
+    GdipDeletePath(path);
 }
 
 static void test_worldbounds(void)
@@ -696,6 +700,304 @@ static void test_lastpoint(void)
     GdipDeletePath(path);
 }
 
+static path_test_t addcurve_path[] = {
+    {0.0, 0.0,   PathPointTypeStart,  0, 0}, /*0*/
+    {3.3, 3.3,   PathPointTypeBezier, 0, 0}, /*1*/
+    {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*2*/
+    {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
+    {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
+    {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*5*/
+    {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
+    {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
+    {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
+    {30.0, 10.0, PathPointTypeBezier, 0, 0}  /*9*/
+    };
+static path_test_t addcurve_path2[] = {
+    {100.0,120.0,PathPointTypeStart,  0, 0}, /*0*/
+    {123.0,10.0, PathPointTypeLine,   0, 0}, /*1*/
+    {0.0, 0.0,   PathPointTypeLine,   0, 0}, /*2*/
+    {3.3, 3.3,   PathPointTypeBezier, 0, 0}, /*3*/
+    {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*4*/
+    {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
+    {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
+    {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*7*/
+    {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
+    {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
+    {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
+    {30.0, 10.0, PathPointTypeBezier, 0, 0}  /*11*/
+    };
+static void test_addcurve(void)
+{
+    GpStatus status;
+    GpPath *path;
+    GpPointF points[4];
+
+    points[0].X = 0.0;
+    points[0].Y = 0.0;
+    points[1].X = 10.0;
+    points[1].Y = 10.0;
+    points[2].X = 10.0;
+    points[2].Y = 20.0;
+    points[3].X = 30.0;
+    points[3].Y = 10.0;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL args */
+    status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathCurve2(path, NULL, 0, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathCurve2(path, points, -1, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathCurve2(path, points, 1, 1.0);
+    expect(InvalidParameter, status);
+
+    /* add to empty path */
+    status = GdipAddPathCurve2(path, points, 4, 1.0);
+    expect(Ok, status);
+    ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
+    GdipDeletePath(path);
+
+    /* add to notempty path and opened figure */
+    GdipCreatePath(FillModeAlternate, &path);
+    GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
+    status = GdipAddPathCurve2(path, points, 4, 1.0);
+    expect(Ok, status);
+    ok_path(path, addcurve_path2, sizeof(addcurve_path2)/sizeof(path_test_t), FALSE);
+    GdipDeletePath(path);
+}
+
+static path_test_t addclosedcurve_path[] = {
+    {0.0, 0.0,   PathPointTypeStart,  0, 0}, /*0*/
+    {-6.7, 0.0,  PathPointTypeBezier, 0, 0}, /*1*/
+    {6.7, 3.3,   PathPointTypeBezier, 0, 0}, /*2*/
+    {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
+    {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
+    {3.3,  20.0, PathPointTypeBezier, 0, 0}, /*5*/
+    {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
+    {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
+    {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
+    {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
+    {26.7, 3.3,  PathPointTypeBezier, 0, 0}, /*10*/
+    {6.7,  0.0,  PathPointTypeBezier, 0, 0}, /*11*/
+    {0.0,  0.0,  PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}  /*12*/
+    };
+static void test_addclosedcurve(void)
+{
+    GpStatus status;
+    GpPath *path;
+    GpPointF points[4];
+
+    points[0].X = 0.0;
+    points[0].Y = 0.0;
+    points[1].X = 10.0;
+    points[1].Y = 10.0;
+    points[2].X = 10.0;
+    points[2].Y = 20.0;
+    points[3].X = 30.0;
+    points[3].Y = 10.0;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL args */
+    status = GdipAddPathClosedCurve2(NULL, NULL, 0, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathClosedCurve2(path, NULL, 0, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathClosedCurve2(path, points, -1, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipAddPathClosedCurve2(path, points, 1, 1.0);
+    expect(InvalidParameter, status);
+
+    /* add to empty path */
+    status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
+    expect(Ok, status);
+    ok_path(path, addclosedcurve_path, sizeof(addclosedcurve_path)/sizeof(path_test_t), FALSE);
+    GdipDeletePath(path);
+}
+
+static path_test_t reverse_path[] = {
+    {0.0,  20.0, PathPointTypeStart, 0, 0}, /*0*/
+    {25.0, 25.0, PathPointTypeLine,  0, 0}, /*1*/
+    {0.0,  30.0, PathPointTypeLine,  0, 0}, /*2*/
+    {15.0, 35.0, PathPointTypeStart, 0, 0}, /*3*/
+    {0.0,  40.0, PathPointTypeLine,  0, 0}, /*4*/
+    {5.0,  45.0, PathPointTypeLine,  0, 0}, /*5*/
+    {0.0,  50.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}  /*6*/
+    };
+
+static void test_reverse(void)
+{
+    GpStatus status;
+    GpPath *path;
+    GpPointF pts[7];
+    INT i;
+
+    for(i = 0; i < 7; i++){
+        pts[i].X = i * 5.0 * (REAL)(i % 2);
+        pts[i].Y = 50.0 - i * 5.0;
+    }
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL argument */
+    status = GdipReversePath(NULL);
+    expect(InvalidParameter, status);
+
+    /* empty path */
+    status = GdipReversePath(path);
+    expect(Ok, status);
+
+    GdipAddPathLine2(path, pts, 4);
+    GdipClosePathFigure(path);
+    GdipAddPathLine2(path, &(pts[4]), 3);
+
+    status = GdipReversePath(path);
+    expect(Ok, status);
+    ok_path(path, reverse_path, sizeof(reverse_path)/sizeof(path_test_t), FALSE);
+
+    GdipDeletePath(path);
+}
+
+static path_test_t addpie_path[] = {
+    {50.0, 25.0, PathPointTypeStart, 0, 0}, /*0*/
+    {97.2, 33.3, PathPointTypeLine,  0, 0}, /*1*/
+    {91.8, 40.9, PathPointTypeBezier,0, 0}, /*2*/
+    {79.4, 46.8, PathPointTypeBezier,0, 0}, /*3*/
+    {63.9, 49.0, PathPointTypeBezier | PathPointTypeCloseSubpath,  0, 0} /*4*/
+    };
+
+static void test_addpie(void)
+{
+    GpStatus status;
+    GpPath *path;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL argument */
+    status = GdipAddPathPie(NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    expect(InvalidParameter, status);
+
+    status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
+    expect(Ok, status);
+    ok_path(path, addpie_path, sizeof(addpie_path)/sizeof(path_test_t), FALSE);
+
+    GdipDeletePath(path);
+}
+
+static path_test_t flattenellipse_path[] = {
+    {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
+    {99.0, 30.0, PathPointTypeLine,  0, 0}, /*1*/
+    {96.0, 34.8, PathPointTypeLine,  0, 0}, /*2*/
+    {91.5, 39.0, PathPointTypeLine,  0, 0}, /*3*/
+    {85.5, 42.8, PathPointTypeLine,  0, 0}, /*4*/
+    {69.5, 48.0, PathPointTypeLine,  0, 1}, /*5*/
+    {50.0, 50.0, PathPointTypeLine,  0, 1}, /*6*/
+    {30.5, 48.0, PathPointTypeLine,  0, 1}, /*7*/
+    {14.8, 42.8, PathPointTypeLine,  0, 1}, /*8*/
+    {8.5,  39.0, PathPointTypeLine,  0, 1}, /*9*/
+    {4.0,  34.8, PathPointTypeLine,  0, 1}, /*10*/
+    {1.0,  30.0, PathPointTypeLine,  0, 1}, /*11*/
+    {0.0,  25.0, PathPointTypeLine,  0, 1}, /*12*/
+    {1.0,  20.0, PathPointTypeLine,  0, 1}, /*13*/
+    {4.0,  15.3, PathPointTypeLine,  0, 1}, /*14*/
+    {8.5,  11.0, PathPointTypeLine,  0, 1}, /*15*/
+    {14.8, 7.3,  PathPointTypeLine,  0, 1}, /*16*/
+    {30.5, 2.0,  PathPointTypeLine,  0, 1}, /*17*/
+    {50.0, 0.0,  PathPointTypeLine,  0, 1}, /*18*/
+    {69.5, 2.0,  PathPointTypeLine,  0, 1}, /*19*/
+    {85.5, 7.3,  PathPointTypeLine,  0, 1}, /*20*/
+    {91.5, 11.0, PathPointTypeLine,  0, 1}, /*21*/
+    {96.0, 15.3, PathPointTypeLine,  0, 1}, /*22*/
+    {99.0, 20.0, PathPointTypeLine,  0, 1}, /*23*/
+    {100.0,25.0, PathPointTypeLine | PathPointTypeCloseSubpath,  0, 1}  /*24*/
+    };
+
+static path_test_t flattenline_path[] = {
+    {5.0, 10.0,PathPointTypeStart, 0, 0}, /*0*/
+    {50.0, 100.0, PathPointTypeLine,  0, 0} /*1*/
+    };
+
+static path_test_t flattenarc_path[] = {
+    {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
+    {99.0, 30.0, PathPointTypeLine,  0, 0}, /*1*/
+    {96.0, 34.8, PathPointTypeLine,  0, 0}, /*2*/
+    {91.5, 39.0, PathPointTypeLine,  0, 0}, /*3*/
+    {85.5, 42.8, PathPointTypeLine,  0, 0}, /*4*/
+    {69.5, 48.0, PathPointTypeLine,  0, 1}, /*5*/
+    {50.0, 50.0, PathPointTypeLine,  0, 1}  /*6*/
+    };
+
+static path_test_t flattenquater_path[] = {
+    {100.0, 50.0,PathPointTypeStart, 0, 0}, /*0*/
+    {99.0, 60.0, PathPointTypeLine,  0, 0}, /*1*/
+    {96.0, 69.5, PathPointTypeLine,  0, 0}, /*2*/
+    {91.5, 78.0, PathPointTypeLine,  0, 0}, /*3*/
+    {85.5, 85.5, PathPointTypeLine,  0, 0}, /*4*/
+    {78.0, 91.5, PathPointTypeLine,  0, 0}, /*5*/
+    {69.5, 96.0, PathPointTypeLine,  0, 0}, /*6*/
+    {60.0, 99.0, PathPointTypeLine,  0, 0}, /*7*/
+    {50.0, 100.0,PathPointTypeLine,  0, 0}  /*8*/
+    };
+
+static void test_flatten(void)
+{
+    GpStatus status;
+    GpPath *path;
+    GpMatrix *m;
+
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+    status = GdipCreateMatrix(&m);
+    expect(Ok, status);
+
+    /* NULL arguments */
+    status = GdipFlattenPath(NULL, NULL, 0.0);
+    expect(InvalidParameter, status);
+    status = GdipFlattenPath(NULL, m, 0.0);
+    expect(InvalidParameter, status);
+
+    /* flatten empty path */
+    status = GdipFlattenPath(path, NULL, 1.0);
+    expect(Ok, status);
+
+    status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 50.0);
+    expect(Ok, status);
+
+    status = GdipFlattenPath(path, NULL, 1.0);
+    expect(Ok, status);
+    ok_path(path, flattenellipse_path, sizeof(flattenellipse_path)/sizeof(path_test_t), TRUE);
+
+    status = GdipResetPath(path);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 100.0);
+    expect(Ok, status);
+    status = GdipFlattenPath(path, NULL, 1.0);
+    expect(Ok, status);
+    ok_path(path, flattenline_path, sizeof(flattenline_path)/sizeof(path_test_t), FALSE);
+
+    status = GdipResetPath(path);
+    expect(Ok, status);
+    status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 50.0, 0.0, 90.0);
+    expect(Ok, status);
+    status = GdipFlattenPath(path, NULL, 1.0);
+    expect(Ok, status);
+    ok_path(path, flattenarc_path, sizeof(flattenarc_path)/sizeof(path_test_t), TRUE);
+
+    /* easy case - quater of a full circle */
+    status = GdipResetPath(path);
+    expect(Ok, status);
+    status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
+    expect(Ok, status);
+    status = GdipFlattenPath(path, NULL, 1.0);
+    expect(Ok, status);
+    ok_path(path, flattenquater_path, sizeof(flattenquater_path)/sizeof(path_test_t), FALSE);
+
+    GdipDeleteMatrix(m);
+    GdipDeletePath(path);
+}
+
 START_TEST(graphicspath)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -719,6 +1021,11 @@ START_TEST(graphicspath)
     test_rect();
     test_polygon();
     test_lastpoint();
+    test_addcurve();
+    test_addclosedcurve();
+    test_reverse();
+    test_addpie();
+    test_flatten();
 
     GdiplusShutdown(gdiplusToken);
 }
index 38a58b9..6000dde 100644 (file)
@@ -42,20 +42,17 @@ static void test_Scan0(void)
     bm = (GpBitmap*)0xdeadbeef;
     stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
     expect(InvalidParameter, stat);
-
-    expect(NULL, bm);
+    ok( !bm, "expected null bitmap\n" );
 
     bm = (GpBitmap*)0xdeadbeef;
     stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
     expect(InvalidParameter, stat);
-
-    expect(NULL, bm);
+    ok( !bm, "expected null bitmap\n" );
 
     bm = (GpBitmap*)0xdeadbeef;
     stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
     expect(InvalidParameter, stat);
-
-    expect(NULL, bm);
+    ok( !bm, "expected null bitmap\n" );
 
     bm = NULL;
     stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
@@ -67,12 +64,26 @@ static void test_Scan0(void)
     bm = (GpBitmap*) 0xdeadbeef;
     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
     expect(InvalidParameter, stat);
-    expect(NULL, bm);
+    ok( !bm, "expected null bitmap\n" );
 
     bm = (GpBitmap*)0xdeadbeef;
     stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
     expect(InvalidParameter, stat);
-    expect(0xdeadbeef, bm);
+    ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
+
+    bm = NULL;
+    stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
+    todo_wine{
+        expect(Ok, stat);
+        ok(NULL != bm, "Expected bitmap to be initialized\n");
+    }
+    if (stat == Ok)
+        GdipDisposeImage((GpImage*)bm);
+
+    bm = (GpBitmap*)0xdeadbeef;
+    stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
+    expect(InvalidParameter, stat);
+    ok( !bm, "expected null bitmap\n" );
 }
 
 static void test_GetImageDimension(void)
@@ -490,21 +501,33 @@ static void test_GdipCloneImage(void)
     /* Create an image, clone it, delete the original, make sure the copy works */
     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
     expect(Ok, stat);
-todo_wine
-{
+
     image_src = ((GpImage*)bm);
     stat = GdipCloneImage(image_src, &image_dest);
     expect(Ok, stat);
-}
+
     stat = GdipDisposeImage((GpImage*)bm);
     expect(Ok, stat);
-todo_wine
-{
     stat = GdipGetImageBounds(image_dest, &rectF, &unit);
     expect(Ok, stat);
+
+    /* Treat FP values carefully */
+    ok(fabsf(rectF.Width-WIDTH)<1e-5, "Expected: %d, got %.05f\n", WIDTH, rectF.Width);
+    ok(fabsf(rectF.Height-HEIGHT)<1e-5, "Expected: %d, got %.05f\n", HEIGHT, rectF.Height);
+
     stat = GdipDisposeImage(image_dest);
     expect(Ok, stat);
 }
+
+static void test_testcontrol(void)
+{
+    GpStatus stat;
+    DWORD param;
+
+    param = 0;
+    stat = GdipTestControl(TestControlGetBuildNumber, &param);
+    expect(Ok, stat);
+    ok(param != 0, "Build number expected, got %u\n", param);
 }
 
 START_TEST(image)
@@ -529,6 +552,7 @@ START_TEST(image)
     test_GdipCreateBitmapFromHBITMAP();
     test_GdipGetImageFlags();
     test_GdipCloneImage();
+    test_testcontrol();
 
     GdiplusShutdown(gdiplusToken);
 }
index cc53488..16ce85a 100644 (file)
@@ -21,6 +21,7 @@
 #include <math.h>
 
 #include "windows.h"
+#include <stdio.h>
 #include "gdiplus.h"
 #include "wine/test.h"
 
@@ -89,6 +90,136 @@ static void test_transform(void)
     GdipDeleteMatrix(matrix);
 }
 
+static void test_isinvertible(void)
+{
+    GpStatus status;
+    GpMatrix *matrix = NULL;
+    BOOL result;
+
+    /* NULL arguments */
+    status = GdipIsMatrixInvertible(NULL, &result);
+    expect(InvalidParameter, status);
+    status = GdipIsMatrixInvertible((GpMatrix*)0xdeadbeef, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsMatrixInvertible(NULL, NULL);
+    expect(InvalidParameter, status);
+
+    /* invertible */
+    GdipCreateMatrix2(1.0, 1.2, 2.3, -1.0, 2.0, 3.0, &matrix);
+    status = GdipIsMatrixInvertible(matrix, &result);
+    expect(Ok, status);
+    expect(TRUE, result);
+    GdipDeleteMatrix(matrix);
+
+    /* noninvertible */
+    GdipCreateMatrix2(2.0, -1.0, 6.0, -3.0, 2.2, 3.0, &matrix);
+    status = GdipIsMatrixInvertible(matrix, &result);
+    expect(Ok, status);
+    expect(FALSE, result);
+    GdipDeleteMatrix(matrix);
+}
+
+static void test_invert(void)
+{
+    GpStatus status;
+    GpMatrix *matrix = NULL;
+    GpMatrix *inverted = NULL;
+    BOOL equal = FALSE;
+
+    /* NULL */
+    status = GdipInvertMatrix(NULL);
+    expect(InvalidParameter, status);
+
+    /* noninvertible */
+    GdipCreateMatrix2(2.0, -1.0, 6.0, -3.0, 2.2, 3.0, &matrix);
+    status = GdipInvertMatrix(matrix);
+    expect(InvalidParameter, status);
+    GdipDeleteMatrix(matrix);
+
+    /* invertible */
+    GdipCreateMatrix2(3.0, -2.0, 5.0, 2.0, 6.0, 3.0, &matrix);
+    status = GdipInvertMatrix(matrix);
+    expect(Ok, status);
+    GdipCreateMatrix2(2.0/16.0, 2.0/16.0, -5.0/16.0, 3.0/16.0, 3.0/16.0, -21.0/16.0, &inverted);
+    GdipIsMatrixEqual(matrix, inverted, &equal);
+    expect(TRUE, equal);
+
+    GdipDeleteMatrix(inverted);
+    GdipDeleteMatrix(matrix);
+}
+
+static void test_shear(void)
+{
+    GpStatus status;
+    GpMatrix *matrix  = NULL;
+    GpMatrix *sheared = NULL;
+    BOOL equal;
+
+    /* NULL */
+    status = GdipShearMatrix(NULL, 0.0, 0.0, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+
+    /* X only shearing, MatrixOrderPrepend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderPrepend);
+    expect(Ok, status);
+    GdipCreateMatrix2(1.0, 2.0, 5.5, 2.0, 6.0, 3.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+
+    /* X only shearing, MatrixOrderAppend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderAppend);
+    expect(Ok, status);
+    GdipCreateMatrix2(4.0, 2.0, 2.5, -1.0, 10.5, 3.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+
+    /* Y only shearing, MatrixOrderPrepend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderPrepend);
+    expect(Ok, status);
+    GdipCreateMatrix2(7.0, 0.5, 4.0, -1.0, 6.0, 3.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+
+    /* Y only shearing, MatrixOrderAppend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderAppend);
+    expect(Ok, status);
+    GdipCreateMatrix2(1.0, 3.5, 4.0, 5.0, 6.0, 12.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+
+    /* X,Y shearing, MatrixOrderPrepend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderPrepend);
+    expect(Ok, status);
+    GdipCreateMatrix2(7.0, 0.5, 8.0, 7.0, 6.0, 3.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+
+    /* X,Y shearing, MatrixOrderAppend */
+    GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+    status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderAppend);
+    expect(Ok, status);
+    GdipCreateMatrix2(9.0, 3.5, 0.0, 5.0, 18.0, 12.0, &sheared);
+    GdipIsMatrixEqual(matrix, sheared, &equal);
+    expect(TRUE, equal);
+    GdipDeleteMatrix(sheared);
+    GdipDeleteMatrix(matrix);
+}
+
 START_TEST(matrix)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -103,6 +234,9 @@ START_TEST(matrix)
 
     test_constructor_destructor();
     test_transform();
+    test_isinvertible();
+    test_invert();
+    test_shear();
 
     GdiplusShutdown(gdiplusToken);
 }
index baeb22b..eddb24e 100644 (file)
@@ -37,7 +37,7 @@ static void test_constructor_destructor(void)
     stat = GdipCreatePathIter(NULL, NULL);
     expect(InvalidParameter, stat);
     stat = GdipCreatePathIter(&iter, NULL);
-    expect(InvalidParameter, stat);
+    expect(Ok, stat);
     stat = GdipCreatePathIter(NULL, path);
     expect(InvalidParameter, stat);
     stat = GdipDeletePathIter(NULL);
@@ -90,6 +90,467 @@ static void test_hascurve(void)
     GdipDeletePath(path);
 }
 
+static void test_nextmarker(void)
+{
+    GpPath *path;
+    GpPathIterator *iter;
+    GpStatus stat;
+    INT start, end;
+    INT result;
+
+    /* NULL args
+       BOOL out argument is local in wrapper class method,
+       so it always has not-NULL address */
+    stat = GdipPathIterNextMarker(NULL, &result, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextMarker(NULL, &result, &start, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextMarker(NULL, &result, NULL, &end);
+    expect(InvalidParameter, stat);
+
+    GdipCreatePath(FillModeAlternate, &path);
+    GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
+
+    /* no markers */
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect(0, start);
+    expect(3, end);
+    expect(4, result);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    /* start/end remain unchanged */
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(0, result);
+    GdipDeletePathIter(iter);
+
+    /* one marker */
+    GdipSetPathMarker(path);
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect(0, start);
+    expect(3, end);
+    expect(4, result);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(0, result);
+    GdipDeletePathIter(iter);
+
+    /* two markers */
+    GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
+    GdipSetPathMarker(path);
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect(0, start);
+    expect(3, end);
+    expect(4, result);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect(4, start);
+    expect(5, end);
+    expect(2, result);
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextMarker(iter, &result, &start, &end);
+    expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(0, result);
+    GdipDeletePathIter(iter);
+
+    GdipDeletePath(path);
+}
+
+static void test_nextmarkerpath(void)
+{
+    GpPath *path, *retpath;
+    GpPathIterator *iter;
+    GpStatus stat;
+    INT result, count;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL */
+    stat = GdipPathIterNextMarkerPath(NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextMarkerPath(NULL, &result, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextMarkerPath(NULL, &result, path);
+    expect(InvalidParameter, stat);
+
+    GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
+
+    /* no markers */
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(4, result);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(4, count);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(0, result);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(4, count);
+    GdipDeletePathIter(iter);
+    GdipDeletePath(retpath);
+
+    /* one marker */
+    GdipSetPathMarker(path);
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(4, result);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(4, count);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(0, result);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(4, count);
+    GdipDeletePathIter(iter);
+    GdipDeletePath(retpath);
+
+    /* two markers */
+    GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
+    GdipSetPathMarker(path);
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(4, result);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(2, result);
+    result = -1;
+    stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
+    expect(Ok, stat);
+    expect(0, result);
+    GdipDeletePathIter(iter);
+    GdipDeletePath(retpath);
+
+    GdipDeletePath(path);
+}
+
+static void test_getsubpathcount(void)
+{
+    GpPath *path;
+    GpPathIterator *iter;
+    GpStatus stat;
+    INT count;
+
+    /* NULL args */
+    stat = GdipPathIterGetSubpathCount(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterGetSubpathCount(NULL, &count);
+    expect(InvalidParameter, stat);
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* empty path */
+    GdipCreatePathIter(&iter, path);
+    stat = GdipPathIterGetSubpathCount(iter, &count);
+    expect(Ok, stat);
+    expect(0, count);
+    GdipDeletePathIter(iter);
+
+    GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
+
+    /* open figure */
+    GdipCreatePathIter(&iter, path);
+    stat = GdipPathIterGetSubpathCount(iter, &count);
+    expect(Ok, stat);
+    expect(1, count);
+    GdipDeletePathIter(iter);
+
+    /* manually start new figure */
+    GdipStartPathFigure(path);
+    GdipAddPathLine(path, 50.0, 50.0, 110.0, 40.0);
+    GdipCreatePathIter(&iter, path);
+    stat = GdipPathIterGetSubpathCount(iter, &count);
+    expect(Ok, stat);
+    expect(2, count);
+    GdipDeletePathIter(iter);
+
+    GdipDeletePath(path);
+}
+
+static void test_isvalid(void)
+{
+    GpPath *path;
+    GpPathIterator *iter;
+    GpStatus stat;
+    BOOL isvalid;
+    INT start, end, result;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL args */
+    GdipCreatePathIter(&iter, path);
+    stat = GdipPathIterIsValid(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterIsValid(iter, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterIsValid(NULL, &isvalid);
+    expect(InvalidParameter, stat);
+    GdipDeletePathIter(iter);
+
+    /* on empty path */
+    GdipCreatePathIter(&iter, path);
+    isvalid = FALSE;
+    stat = GdipPathIterIsValid(iter, &isvalid);
+    expect(Ok, stat);
+    expect(TRUE, isvalid);
+    GdipDeletePathIter(iter);
+
+    /* no markers */
+    GdipAddPathLine(path, 50.0, 50.0, 110.0, 40.0);
+    GdipCreatePathIter(&iter, path);
+    GdipPathIterNextMarker(iter, &result, &start, &end);
+    isvalid = FALSE;
+    stat = GdipPathIterIsValid(iter, &isvalid);
+    expect(Ok, stat);
+    expect(TRUE, isvalid);
+    GdipDeletePathIter(iter);
+
+    GdipDeletePath(path);
+}
+
+static void test_nextsubpathpath(void)
+{
+    GpPath *path, *retpath;
+    GpPathIterator *iter;
+    GpStatus stat;
+    BOOL closed;
+    INT count, result;
+
+    GdipCreatePath(FillModeAlternate, &path);
+
+    /* NULL args */
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    stat = GdipPathIterNextSubpathPath(NULL, NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextSubpathPath(NULL, &result, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextSubpathPath(iter, &result, NULL, &closed);
+    expect(Ok, stat);
+    stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, &closed);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextSubpathPath(iter, NULL, retpath, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, NULL);
+    expect(InvalidParameter, stat);
+    GdipDeletePathIter(iter);
+    GdipDeletePath(retpath);
+
+    /* empty path */
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    result = -2;
+    closed = TRUE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(0, result);
+    expect(TRUE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(0, count);
+    GdipDeletePathIter(iter);
+    GdipDeletePath(retpath);
+
+    /* open figure */
+    GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
+
+    GdipCreatePath(FillModeAlternate, &retpath);
+    GdipCreatePathIter(&iter, path);
+    result = -2;
+    closed = TRUE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(2, result);
+    expect(FALSE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(2, count);
+    /* subsequent call */
+    result = -2;
+    closed = TRUE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(0, result);
+    expect(TRUE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(2, count);
+    GdipDeletePathIter(iter);
+
+    /* closed figure, check does it extend retpath or reset it */
+    GdipAddPathLine(retpath, 50.0, 55.0, 200.0, 150.0);
+
+    GdipClosePathFigure(path);
+    GdipAddPathLine(path, 50.0, 55.0, 200.0, 150.0);
+    GdipClosePathFigure(path);
+
+    GdipCreatePathIter(&iter, path);
+    result = -2;
+    closed = FALSE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(2, result);
+    expect(TRUE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(2, count);
+    /* subsequent call */
+    result = -2;
+    closed = FALSE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(2, result);
+    expect(TRUE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(2, count);
+    result = -2;
+    closed = FALSE;
+    stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
+    expect(Ok, stat);
+    expect(0, result);
+    expect(TRUE, closed);
+    count = -1;
+    GdipGetPointCount(retpath, &count);
+    expect(2, count);
+    GdipDeletePathIter(iter);
+
+    GdipDeletePath(retpath);
+    GdipDeletePath(path);
+}
+
+static void test_nextsubpath(void)
+{
+    GpPath *path;
+    GpPathIterator *iter;
+    GpStatus stat;
+    INT start, end, result;
+    BOOL closed;
+
+    /* empty path */
+    GdipCreatePath(FillModeAlternate, &path);
+    GdipCreatePathIter(&iter, path);
+
+    result = -2;
+    closed = TRUE;
+    stat = GdipPathIterNextSubpath(iter, &result, &start, &end, &closed);
+    expect(Ok, stat);
+    expect(0, result);
+    expect(TRUE, closed);
+
+    GdipDeletePathIter(iter);
+    GdipDeletePath(path);
+}
+
+static void test_nextpathtype(void)
+{
+    GpPath *path;
+    GpPathIterator *iter;
+    GpStatus stat;
+    INT start, end, result;
+    BYTE type;
+
+    GdipCreatePath(FillModeAlternate, &path);
+    GdipCreatePathIter(&iter, path);
+
+    /* NULL arguments */
+    stat = GdipPathIterNextPathType(NULL, NULL, NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, NULL, NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, &result, NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, NULL, &type, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, NULL, NULL, &start, &end);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, NULL, &type, &start, &end);
+    expect(InvalidParameter, stat);
+    stat = GdipPathIterNextPathType(iter, &result, &type, NULL, NULL);
+    expect(InvalidParameter, stat);
+
+    /* empty path */
+    start = end = result = (INT)0xdeadbeef;
+    stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
+    todo_wine expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    todo_wine expect(0, result);
+    GdipDeletePathIter(iter);
+
+    /* single figure */
+    GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    type = 255; /* out of range */
+    stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
+    todo_wine expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(255, type);
+    todo_wine expect(0, result);
+    GdipDeletePathIter(iter);
+
+    GdipAddPathEllipse(path, 0.0, 0.0, 35.0, 70.0);
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    type = 255; /* out of range */
+    stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
+    todo_wine expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(255, type);
+    todo_wine expect(0, result);
+    GdipDeletePathIter(iter);
+
+    /* closed */
+    GdipClosePathFigure(path);
+    GdipCreatePathIter(&iter, path);
+    start = end = result = (INT)0xdeadbeef;
+    type = 255; /* out of range */
+    stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
+    todo_wine expect(Ok, stat);
+    expect((INT)0xdeadbeef, start);
+    expect((INT)0xdeadbeef, end);
+    expect(255, type);
+    todo_wine expect(0, result);
+    GdipDeletePathIter(iter);
+
+    GdipDeletePath(path);
+}
+
 START_TEST(pathiterator)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -104,6 +565,13 @@ START_TEST(pathiterator)
 
     test_constructor_destructor();
     test_hascurve();
+    test_nextmarker();
+    test_nextmarkerpath();
+    test_getsubpathcount();
+    test_isvalid();
+    test_nextsubpathpath();
+    test_nextsubpath();
+    test_nextpathtype();
 
     GdiplusShutdown(gdiplusToken);
 }
index ad484ce..d2f33f0 100644 (file)
@@ -226,6 +226,132 @@ static void test_dasharray(void)
     GdipDeletePen(pen);
 }
 
+static void test_customcap(void)
+{
+    GpPen *pen;
+    GpStatus status;
+    GpCustomLineCap *custom;
+
+    status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+
+    /* NULL args */
+    status = GdipGetPenCustomStartCap(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPenCustomStartCap(pen, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPenCustomStartCap(NULL, &custom);
+    expect(InvalidParameter, status);
+
+    status = GdipGetPenCustomEndCap(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPenCustomEndCap(pen, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetPenCustomEndCap(NULL, &custom);
+    expect(InvalidParameter, status);
+
+    /* native crashes on pen == NULL, custom != NULL */
+    status = GdipSetPenCustomStartCap(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipSetPenCustomStartCap(pen, NULL);
+    expect(InvalidParameter, status);
+
+    status = GdipSetPenCustomEndCap(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipSetPenCustomEndCap(pen, NULL);
+    expect(InvalidParameter, status);
+
+    /* get without setting previously */
+    custom = (GpCustomLineCap*)0xdeadbeef;
+    status = GdipGetPenCustomEndCap(pen, &custom);
+    expect(Ok, status);
+    ok(custom == NULL,"Expect CustomCap == NULL\n");
+
+    custom = (GpCustomLineCap*)0xdeadbeef;
+    status = GdipGetPenCustomStartCap(pen, &custom);
+    expect(Ok, status);
+    ok(custom == NULL,"Expect CustomCap == NULL\n");
+
+    GdipDeletePen(pen);
+}
+
+static void test_penfilltype(void)
+{
+    GpPen *pen;
+    GpSolidFill *solid;
+    GpLineGradient *line;
+    GpPointF a, b;
+    GpStatus status;
+    GpPenType type;
+
+    /* NULL */
+    status = GdipGetPenFillType(NULL, NULL);
+    expect(InvalidParameter, status);
+
+    status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+    status = GdipGetPenFillType(pen, NULL);
+    expect(InvalidParameter, status);
+
+    /* created with GdipCreatePen1() */
+    status = GdipGetPenFillType(pen, &type);
+    expect(Ok, status);
+    expect(PenTypeSolidColor, type);
+    GdipDeletePen(pen);
+
+    /* based on SolidBrush */
+    status = GdipCreateSolidFill((ARGB)0xffff00ff, &solid);
+    expect(Ok, status);
+    status = GdipCreatePen2((GpBrush*)solid, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+    status = GdipGetPenFillType(pen, &type);
+    expect(Ok, status);
+    expect(PenTypeSolidColor, type);
+    GdipDeletePen(pen);
+    GdipDeleteBrush((GpBrush*)solid);
+
+    /* based on LinearGradientBrush */
+    a.X = a.Y = 0.0;
+    b.X = b.Y = 10.0;
+    status = GdipCreateLineBrush(&a, &b, (ARGB)0xffff00ff, (ARGB)0xffff0000,
+                                 WrapModeTile, &line);
+    expect(Ok, status);
+    status = GdipCreatePen2((GpBrush*)line, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+    status = GdipGetPenFillType(pen, &type);
+    expect(Ok, status);
+    expect(PenTypeLinearGradient, type);
+    GdipDeletePen(pen);
+    GdipDeleteBrush((GpBrush*)line);
+}
+
+static void test_compoundarray(void)
+{
+    GpStatus status;
+    GpPen *pen;
+    static const REAL testvalues[] = {0.2, 0.4, 0.6, 0.8};
+
+    status = GdipSetPenCompoundArray(NULL, testvalues, 4);
+    expect(InvalidParameter, status);
+
+    status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
+    expect(Ok, status);
+
+    status = GdipSetPenCompoundArray(pen, NULL, 4);
+    expect(InvalidParameter, status);
+    status = GdipSetPenCompoundArray(pen, testvalues, 3);
+    expect(InvalidParameter, status);
+    status = GdipSetPenCompoundArray(pen, testvalues, 0);
+    expect(InvalidParameter, status);
+    status = GdipSetPenCompoundArray(pen, testvalues, -2);
+    expect(InvalidParameter, status);
+
+    status = GdipSetPenCompoundArray(pen, testvalues, 4);
+    todo_wine expect(Ok, status);
+
+    GdipDeletePen(pen);
+}
+
 START_TEST(pen)
 {
     struct GdiplusStartupInput gdiplusStartupInput;
@@ -244,6 +370,9 @@ START_TEST(pen)
     test_constructor_destructor2();
     test_brushfill();
     test_dasharray();
+    test_customcap();
+    test_penfilltype();
+    test_compoundarray();
 
     GdiplusShutdown(gdiplusToken);
 }
index 166df2d..1373634 100644 (file)
 #include "wingdi.h"
 #include "wine/test.h"
 
-static inline void expect_dword(DWORD *value, DWORD expected)
-{
-    ok(*value == expected, "expected %08x got %08x\n", expected, *value);
-}
+#define RGNDATA_RECT            0x10000000
+#define RGNDATA_PATH            0x10000001
+#define RGNDATA_EMPTY_RECT      0x10000002
+#define RGNDATA_INFINITE_RECT   0x10000003
+
+#define RGNDATA_MAGIC           0xdbc01001
+#define RGNDATA_MAGIC2          0xdbc01002
+
+#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
+
+#define expect_magic(value) ok(*value == RGNDATA_MAGIC || *value == RGNDATA_MAGIC2, "Expected a known magic value, got %8x\n", *value)
+
+#define expect_dword(value, expected) ok(*(value) == expected, "expected %08x got %08x\n", expected, *(value))
 
 static inline void expect_float(DWORD *value, FLOAT expected)
 {
@@ -34,59 +43,117 @@ static inline void expect_float(DWORD *value, FLOAT expected)
     ok(valuef == expected, "expected %f got %f\n", expected, valuef);
 }
 
-static void test_create_rgn(void)
+/* We get shorts back, not INTs like a GpPoint */
+typedef struct RegionDataPoint
+{
+    short X, Y;
+} RegionDataPoint;
+
+static void verify_region(HRGN hrgn, const RECT *rc)
+{
+    union
+    {
+        RGNDATA data;
+        char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
+    } rgn;
+    const RECT *rect;
+    DWORD ret;
+
+    ret = GetRegionData(hrgn, 0, NULL);
+    if (IsRectEmpty(rc))
+        ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
+    else
+        ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
+
+    if (!ret) return;
+
+    ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data);
+    if (IsRectEmpty(rc))
+        ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
+    else
+        ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
+
+    trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
+          rgn.data.rdh.dwSize, rgn.data.rdh.iType,
+          rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize,
+          rgn.data.rdh.rcBound.left, rgn.data.rdh.rcBound.top,
+          rgn.data.rdh.rcBound.right, rgn.data.rdh.rcBound.bottom);
+    if (rgn.data.rdh.nCount != 0)
+    {
+        rect = (const RECT *)rgn.data.Buffer;
+        trace("rect (%d,%d-%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
+        ok(EqualRect(rect, rc), "rects don't match\n");
+    }
+
+    ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", rgn.data.rdh.dwSize);
+    ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType);
+    if (IsRectEmpty(rc))
+    {
+        ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount);
+        ok(rgn.data.rdh.nRgnSize == 0,  "expected 0, got %u\n", rgn.data.rdh.nRgnSize);
+    }
+    else
+    {
+        ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount);
+        ok(rgn.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize);
+    }
+    ok(EqualRect(&rgn.data.rdh.rcBound, rc), "rects don't match\n");
+}
+
+static void test_getregiondata(void)
 {
     GpStatus status;
     GpRegion *region, *region2;
+    RegionDataPoint *point;
     UINT needed;
     DWORD buf[100];
     GpRect rect;
+    GpPath *path;
+
+    memset(buf, 0xee, sizeof(buf));
 
     status = GdipCreateRegion(&region);
-todo_wine
     ok(status == Ok, "status %08x\n", status);
 
-    if(status != Ok) return;
-
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
-    expect_dword(buf + 2, 0xdbc01001);
+    expect_magic((DWORD*)(buf + 2));
     expect_dword(buf + 3, 0);
-    expect_dword(buf + 4, 0x10000003);
+    expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
 
     status = GdipSetEmpty(region);
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
-    expect_dword(buf + 2, 0xdbc01001);
+    expect_magic((DWORD*)(buf + 2));
     expect_dword(buf + 3, 0);
-    expect_dword(buf + 4, 0x10000002);
+    expect_dword(buf + 4, RGNDATA_EMPTY_RECT);
 
     status = GdipSetInfinite(region);
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
-    expect_dword(buf + 2, 0xdbc01001);
+    expect_magic((DWORD*)(buf + 2));
     expect_dword(buf + 3, 0);
-    expect_dword(buf + 4, 0x10000003);
+    expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
 
     status = GdipDeleteRegion(region);
     ok(status == Ok, "status %08x\n", status);
@@ -99,15 +166,15 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     expect_dword(buf, 28);
     trace("buf[1] = %08x\n", buf[1]);
-    expect_dword(buf + 2, 0xdbc01001);
+    expect_magic((DWORD*)(buf + 2));
     expect_dword(buf + 3, 0);
-    expect_dword(buf + 4, 0x10000000);
+    expect_dword(buf + 4, RGNDATA_RECT);
     expect_float(buf + 5, 10.0);
     expect_float(buf + 6, 20.0);
     expect_float(buf + 7, 100.0);
@@ -151,56 +218,713 @@ todo_wine
 
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 156, "got %d\n", needed);
+    expect(156, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 156, "got %d\n", needed);
+    expect(156, needed);
     expect_dword(buf, 148);
     trace("buf[1] = %08x\n", buf[1]);
-    expect_dword(buf + 2, 0xdbc01001);
+    expect_magic((DWORD*)(buf + 2));
     expect_dword(buf + 3, 10);
     expect_dword(buf + 4, CombineModeExclude);
     expect_dword(buf + 5, CombineModeComplement);
     expect_dword(buf + 6, CombineModeXor);
     expect_dword(buf + 7, CombineModeIntersect);
-    expect_dword(buf + 8, 0x10000000);
+    expect_dword(buf + 8, RGNDATA_RECT);
     expect_float(buf + 9, 10.0);
     expect_float(buf + 10, 20.0);
     expect_float(buf + 11, 100.0);
     expect_float(buf + 12, 200.0);
-    expect_dword(buf + 13, 0x10000000);
+    expect_dword(buf + 13, RGNDATA_RECT);
     expect_float(buf + 14, 50.0);
     expect_float(buf + 15, 30.0);
     expect_float(buf + 16, 10.0);
     expect_float(buf + 17, 20.0);
-    expect_dword(buf + 18, 0x10000000);
+    expect_dword(buf + 18, RGNDATA_RECT);
     expect_float(buf + 19, 100.0);
     expect_float(buf + 20, 300.0);
     expect_float(buf + 21, 30.0);
     expect_float(buf + 22, 50.0);
     expect_dword(buf + 23, CombineModeUnion);
-    expect_dword(buf + 24, 0x10000000);
+    expect_dword(buf + 24, RGNDATA_RECT);
     expect_float(buf + 25, 200.0);
     expect_float(buf + 26, 100.0);
     expect_float(buf + 27, 133.0);
     expect_float(buf + 28, 266.0);
-    expect_dword(buf + 29, 0x10000000);
+    expect_dword(buf + 29, RGNDATA_RECT);
     expect_float(buf + 30, 20.0);
     expect_float(buf + 31, 10.0);
     expect_float(buf + 32, 40.0);
     expect_float(buf + 33, 66.0);
-    expect_dword(buf + 34, 0x10000000);
+    expect_dword(buf + 34, RGNDATA_RECT);
     expect_float(buf + 35, 400.0);
     expect_float(buf + 36, 500.0);
     expect_float(buf + 37, 22.0);
     expect_float(buf + 38, 55.0);
 
-
     status = GdipDeleteRegion(region2);
     ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteRegion(region);
     ok(status == Ok, "status %08x\n", status);
 
+    /* Try some paths */
+
+    status = GdipCreatePath(FillModeAlternate, &path);
+    ok(status == Ok, "status %08x\n", status);
+    GdipAddPathRectangle(path, 12.5, 13.0, 14.0, 15.0);
+
+    status = GdipCreateRegionPath(path, &region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionDataSize(region, &needed);
+    ok(status == Ok, "status %08x\n", status);
+    expect(72, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    ok(status == Ok, "status %08x\n", status);
+    expect(72, needed);
+    expect_dword(buf, 64);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+    expect_dword(buf + 5, 0x00000030);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 0x00000004);
+    expect_dword(buf + 8, 0x00000000);
+    expect_float(buf + 9, 12.5);
+    expect_float(buf + 10, 13.0);
+    expect_float(buf + 11, 26.5);
+    expect_float(buf + 12, 13.0);
+    expect_float(buf + 13, 26.5);
+    expect_float(buf + 14, 28.0);
+    expect_float(buf + 15, 12.5);
+    expect_float(buf + 16, 28.0);
+    expect_dword(buf + 17, 0x81010100);
+
+
+    rect.X = 50;
+    rect.Y = 30;
+    rect.Width = 10;
+    rect.Height = 20;
+    status = GdipCombineRegionRectI(region, &rect, CombineModeIntersect);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionDataSize(region, &needed);
+    ok(status == Ok, "status %08x\n", status);
+    expect(96, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    ok(status == Ok, "status %08x\n", status);
+    expect(96, needed);
+    expect_dword(buf, 88);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 2);
+    expect_dword(buf + 4, CombineModeIntersect);
+    expect_dword(buf + 5, RGNDATA_PATH);
+    expect_dword(buf + 6, 0x00000030);
+    expect_magic((DWORD*)(buf + 7));
+    expect_dword(buf + 8, 0x00000004);
+    expect_dword(buf + 9, 0x00000000);
+    expect_float(buf + 10, 12.5);
+    expect_float(buf + 11, 13.0);
+    expect_float(buf + 12, 26.5);
+    expect_float(buf + 13, 13.0);
+    expect_float(buf + 14, 26.5);
+    expect_float(buf + 15, 28.0);
+    expect_float(buf + 16, 12.5);
+    expect_float(buf + 17, 28.0);
+    expect_dword(buf + 18, 0x81010100);
+    expect_dword(buf + 19, RGNDATA_RECT);
+    expect_float(buf + 20, 50.0);
+    expect_float(buf + 21, 30.0);
+    expect_float(buf + 22, 10.0);
+    expect_float(buf + 23, 20.0);
+
+    status = GdipDeleteRegion(region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipDeletePath(path);
+    ok(status == Ok, "status %08x\n", status);
+
+    /* Test an empty path */
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+    status = GdipCreateRegionPath(path, &region);
+    expect(Ok, status);
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(36, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(36, needed);
+    expect_dword(buf, 28);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+
+    /* Second signature for pathdata */
+    expect_dword(buf + 5, 12);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 0);
+    expect_dword(buf + 8, 0x00004000);
+
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+
+    /* Test a simple triangle of INTs */
+    status = GdipAddPathLine(path, 5, 6, 7, 8);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 8, 1, 5, 6);
+    expect(Ok, status);
+    status = GdipClosePathFigure(path);
+    expect(Ok, status);
+    status = GdipCreateRegionPath(path, &region);
+    expect(Ok, status);
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(56, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(56, needed);
+    expect_dword(buf, 48);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3 , 0);
+    expect_dword(buf + 4 , RGNDATA_PATH);
+
+    expect_dword(buf + 5, 32);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 4);
+    expect_dword(buf + 8, 0x00004000); /* ?? */
+
+    point = (RegionDataPoint*)buf + 9;
+    expect(5, point[0].X);
+    expect(6, point[0].Y);
+    expect(7, point[1].X); /* buf + 10 */
+    expect(8, point[1].Y);
+    expect(8, point[2].X); /* buf + 11 */
+    expect(1, point[2].Y);
+    expect(5, point[3].X); /* buf + 12 */
+    expect(6, point[3].Y);
+    expect_dword(buf + 13, 0x81010100); /* 0x01010100 if we don't close the path */
+
+    status = GdipDeletePath(path);
+    expect(Ok, status);
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+
+    /* Test a floating-point triangle */
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 5.6, 6.2, 7.2, 8.9);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 8.1, 1.6, 5.6, 6.2);
+    expect(Ok, status);
+    status = GdipCreateRegionPath(path, &region);
+    expect(Ok, status);
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(72, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(72, needed);
+    expect_dword(buf, 64);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+
+    expect_dword(buf + 5, 48);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 4);
+    expect_dword(buf + 8, 0);
+    expect_float(buf + 9, 5.6);
+    expect_float(buf + 10, 6.2);
+    expect_float(buf + 11, 7.2);
+    expect_float(buf + 12, 8.9);
+    expect_float(buf + 13, 8.1);
+    expect_float(buf + 14, 1.6);
+    expect_float(buf + 15, 5.6);
+    expect_float(buf + 16, 6.2);
+
+    status = GdipDeletePath(path);
+    expect(Ok, status);
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+
+    /* Test for a path with > 4 points, and CombineRegionPath */
+    GdipCreatePath(FillModeAlternate, &path);
+    status = GdipAddPathLine(path, 50, 70.2, 60, 102.8);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 55.4, 122.4, 40.4, 60.2);
+    expect(Ok, status);
+    status = GdipAddPathLine(path, 45.6, 20.2, 50, 70.2);
+    expect(Ok, status);
+    rect.X = 20;
+    rect.Y = 25;
+    rect.Width = 60;
+    rect.Height = 120;
+    status = GdipCreateRegionRectI(&rect, &region);
+    expect(Ok, status);
+    status = GdipCombineRegionPath(region, path, CombineModeUnion);
+    expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(116, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(116, needed);
+    expect_dword(buf, 108);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 2);
+    expect_dword(buf + 4, CombineModeUnion);
+    expect_dword(buf + 5, RGNDATA_RECT);
+    expect_float(buf + 6, 20);
+    expect_float(buf + 7, 25);
+    expect_float(buf + 8, 60);
+    expect_float(buf + 9, 120);
+    expect_dword(buf + 10, RGNDATA_PATH);
+
+    expect_dword(buf + 11, 68);
+    expect_magic((DWORD*)(buf + 12));
+    expect_dword(buf + 13, 6);
+    expect_float(buf + 14, 0x0);
+
+    expect_float(buf + 15, 50);
+    expect_float(buf + 16, 70.2);
+    expect_float(buf + 17, 60);
+    expect_float(buf + 18, 102.8);
+    expect_float(buf + 19, 55.4);
+    expect_float(buf + 20, 122.4);
+    expect_float(buf + 21, 40.4);
+    expect_float(buf + 22, 60.2);
+    expect_float(buf + 23, 45.6);
+    expect_float(buf + 24, 20.2);
+    expect_float(buf + 25, 50);
+    expect_float(buf + 26, 70.2);
+    expect_dword(buf + 27, 0x01010100);
+    expect_dword(buf + 28, 0x00000101);
+
+    status = GdipDeletePath(path);
+    expect(Ok, status);
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+}
+
+static void test_isinfinite(void)
+{
+    GpStatus status;
+    GpRegion *region;
+    GpGraphics *graphics = NULL;
+    GpMatrix *m;
+    HDC hdc = GetDC(0);
+    BOOL res;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    GdipCreateRegion(&region);
+
+    GdipCreateMatrix2(3.0, 0.0, 0.0, 1.0, 20.0, 30.0, &m);
+
+    /* NULL arguments */
+    status = GdipIsInfiniteRegion(NULL, NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsInfiniteRegion(region, NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsInfiniteRegion(NULL, graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsInfiniteRegion(NULL, NULL, &res);
+    expect(InvalidParameter, status);
+    status = GdipIsInfiniteRegion(region, NULL, &res);
+    expect(InvalidParameter, status);
+
+    res = FALSE;
+    status = GdipIsInfiniteRegion(region, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    /* after world transform */
+    status = GdipSetWorldTransform(graphics, m);
+    expect(Ok, status);
+
+    res = FALSE;
+    status = GdipIsInfiniteRegion(region, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    GdipDeleteMatrix(m);
+    GdipDeleteRegion(region);
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(0, hdc);
+}
+
+static void test_isempty(void)
+{
+    GpStatus status;
+    GpRegion *region;
+    GpGraphics *graphics = NULL;
+    HDC hdc = GetDC(0);
+    BOOL res;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    GdipCreateRegion(&region);
+
+    /* NULL arguments */
+    status = GdipIsEmptyRegion(NULL, NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsEmptyRegion(region, NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsEmptyRegion(NULL, graphics, NULL);
+    expect(InvalidParameter, status);
+    status = GdipIsEmptyRegion(NULL, NULL, &res);
+    expect(InvalidParameter, status);
+    status = GdipIsEmptyRegion(region, NULL, &res);
+    expect(InvalidParameter, status);
+
+    /* default is infinite */
+    res = TRUE;
+    status = GdipIsEmptyRegion(region, graphics, &res);
+    expect(Ok, status);
+    expect(FALSE, res);
+
+    status = GdipSetEmpty(region);
+    expect(Ok, status);
+
+    res = FALSE;
+    status = GdipIsEmptyRegion(region, graphics, &res);
+    expect(Ok, status);
+    expect(TRUE, res);
+
+    GdipDeleteRegion(region);
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(0, hdc);
+}
+
+static void test_combinereplace(void)
+{
+    GpStatus status;
+    GpRegion *region, *region2;
+    GpPath *path;
+    GpRectF rectf;
+    UINT needed;
+    DWORD buf[50];
+
+    rectf.X = rectf.Y = 0.0;
+    rectf.Width = rectf.Height = 100.0;
+
+    status = GdipCreateRegionRect(&rectf, &region);
+    expect(Ok, status);
+
+    /* replace with the same rectangle */
+    status = GdipCombineRegionRect(region, &rectf,CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(36, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(36, needed);
+    expect_dword(buf, 28);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_RECT);
+
+    /* replace with path */
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+    status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
+    expect(Ok, status);
+    status = GdipCombineRegionPath(region, path, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(156, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(156, needed);
+    expect_dword(buf, 148);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+    GdipDeletePath(path);
+
+    /* replace with infinite rect */
+    status = GdipCreateRegion(&region2);
+    expect(Ok, status);
+    status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
+    expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(20, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(20, needed);
+    expect_dword(buf, 12);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
+    GdipDeletePath(path);
+    GdipDeleteRegion(region2);
+
+    /* more complex case : replace with a combined region */
+    status = GdipCreateRegionRect(&rectf, &region2);
+    expect(Ok, status);
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+    status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0);
+    expect(Ok, status);
+    status = GdipCombineRegionPath(region2, path, CombineModeUnion);
+    expect(Ok, status);
+    GdipDeletePath(path);
+    status = GdipCombineRegionRegion(region, region2, CombineModeReplace);
+    expect(Ok, status);
+    GdipDeleteRegion(region2);
+
+    status = GdipGetRegionDataSize(region, &needed);
+    expect(Ok, status);
+    expect(180, needed);
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    expect(Ok, status);
+    expect(180, needed);
+    expect_dword(buf, 172);
+    trace("buf[1] = %08x\n", buf[1]);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 2);
+    expect_dword(buf + 4, CombineModeUnion);
+
+    GdipDeleteRegion(region);
+}
+
+static void test_fromhrgn(void)
+{
+    GpStatus status;
+    GpRegion *region;
+    HRGN hrgn;
+    UINT needed;
+    DWORD buf[220];
+    RegionDataPoint *point;
+
+    /* NULL */
+    status = GdipCreateRegionHrgn(NULL, NULL);
+    expect(InvalidParameter, status);
+    status = GdipCreateRegionHrgn(NULL, &region);
+    expect(InvalidParameter, status);
+    status = GdipCreateRegionHrgn((HRGN)0xdeadbeef, &region);
+    todo_wine expect(InvalidParameter, status);
+
+    /* rectangle */
+    hrgn = CreateRectRgn(0, 0, 100, 10);
+    status = GdipCreateRegionHrgn(hrgn, &region);
+    todo_wine expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+todo_wine{
+    expect(Ok, status);
+    expect(56, needed);
+}
+
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+    todo_wine expect(Ok, status);
+
+    if(status == Ok){
+todo_wine{
+    expect(56, needed);
+    expect_dword(buf, 48);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+    expect_dword(buf + 5, 0x00000020);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 0x00000004);
+    expect_dword(buf + 8, 0x00006000); /* ?? */
+}
+    point = (RegionDataPoint*)buf + 9;
+
+    expect(0,  point[0].X);
+    expect(0,  point[0].Y);
+
+todo_wine{
+    expect(100,point[1].X); /* buf + 10 */
+    expect(0,  point[1].Y);
+    expect(100,point[2].X); /* buf + 11 */
+    expect(10, point[2].Y);
+}
+    expect(0,  point[3].X); /* buf + 12 */
+
+todo_wine{
+    expect(10, point[3].Y);
+    expect_dword(buf + 13, 0x81010100); /* closed */
+}
+    }
+
+    GdipDeleteRegion(region);
+    DeleteObject(hrgn);
+
+    /* ellipse */
+    hrgn = CreateEllipticRgn(0, 0, 100, 10);
+    status = GdipCreateRegionHrgn(hrgn, &region);
+    todo_wine expect(Ok, status);
+
+    status = GdipGetRegionDataSize(region, &needed);
+todo_wine{
+    expect(Ok, status);
+    expect(216, needed);
+}
+    status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
+todo_wine{
+    expect(Ok, status);
+    expect(216, needed);
+    expect_dword(buf, 208);
+    expect_magic((DWORD*)(buf + 2));
+    expect_dword(buf + 3, 0);
+    expect_dword(buf + 4, RGNDATA_PATH);
+    expect_dword(buf + 5, 0x000000C0);
+    expect_magic((DWORD*)(buf + 6));
+    expect_dword(buf + 7, 0x00000024);
+    expect_dword(buf + 8, 0x00006000); /* ?? */
+}
+    GdipDeleteRegion(region);
+    DeleteObject(hrgn);
+}
+
+static void test_gethrgn(void)
+{
+    GpStatus status;
+    GpRegion *region, *region2;
+    GpPath *path;
+    GpGraphics *graphics;
+    HRGN hrgn;
+    HDC hdc=GetDC(0);
+    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};
+    static const RECT scaled_rect = {20, 22, 40, 42};
+    static const RECT test_rect2 = {10, 21, 20, 31};
+    static const GpRectF test_rect2F = {10.0, 21.0, 10.0, 10.0};
+    static const RECT test_rect3 = {10, 11, 20, 31};
+    static const GpRectF test_rect3F = {10.0, 11.0, 10.0, 20.0};
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    ok(status == Ok, "status %08x\n", status);
+
+    status = GdipCreateRegion(&region);
+    ok(status == Ok, "status %08x\n", status);
+
+    status = GdipGetRegionHRgn(NULL, graphics, &hrgn);
+    ok(status == InvalidParameter, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, graphics, NULL);
+    ok(status == InvalidParameter, "status %08x\n", status);
+
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    ok(hrgn == NULL, "hrgn=%p\n", hrgn);
+    DeleteObject(hrgn);
+
+    status = GdipGetRegionHRgn(region, graphics, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    ok(hrgn == NULL, "hrgn=%p\n", hrgn);
+    DeleteObject(hrgn);
+
+    status = GdipSetEmpty(region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &empty_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCreatePath(FillModeAlternate, &path);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipAddPathRectangle(path, 10.0, 11.0, 10.0, 10.0);
+    ok(status == Ok, "status %08x\n", status);
+
+    status = GdipCreateRegionPath(path, &region2);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region2, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    /* resulting HRGN is in device coordinates */
+    status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region2, graphics, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &scaled_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region2, &test_rectF, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region2, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    status = GdipGetRegionHRgn(region2, graphics, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &scaled_rect);
+    DeleteObject(hrgn);
+
+    status = GdipSetInfinite(region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeIntersect);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect2F, CombineModeUnion);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect3);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect2F, CombineModeXor);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeExclude);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect2);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeComplement);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect2);
+    DeleteObject(hrgn);
+
+    status = GdipDeletePath(path);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipDeleteRegion(region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipDeleteRegion(region2);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipDeleteGraphics(graphics);
+    ok(status == Ok, "status %08x\n", status);
+    ReleaseDC(0, hdc);
 }
 
 START_TEST(region)
@@ -215,8 +939,12 @@ START_TEST(region)
 
     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
-    test_create_rgn();
+    test_getregiondata();
+    test_isinfinite();
+    test_isempty();
+    test_combinereplace();
+    test_fromhrgn();
+    test_gethrgn();
 
     GdiplusShutdown(gdiplusToken);
-
 }
index 9cf46a4..9331912 100644 (file)
@@ -23,6 +23,7 @@
 #include "wine/test.h"
 
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
+#define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got)
 
 static void test_constructor(void)
 {
@@ -31,19 +32,287 @@ static void test_constructor(void)
     INT n;
     StringAlignment align, valign;
     StringTrimming trimming;
+    StringDigitSubstitute digitsub;
+    LANGID digitlang;
 
-    stat = GdipCreateStringFormat(0, 0, &format);
+    stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
     expect(Ok, stat);
 
     GdipGetStringFormatAlign(format, &align);
     GdipGetStringFormatLineAlign(format, &valign);
     GdipGetStringFormatHotkeyPrefix(format, &n);
     GdipGetStringFormatTrimming(format, &trimming);
+    GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
 
     expect(HotkeyPrefixNone, n);
     expect(StringAlignmentNear, align);
     expect(StringAlignmentNear, align);
     expect(StringTrimmingCharacter, trimming);
+    expect(StringDigitSubstituteUser, digitsub);
+    expect(LANG_NEUTRAL, digitlang);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+}
+
+static void test_characterrange(void)
+{
+    CharacterRange ranges[3];
+    INT count;
+    GpStringFormat* format;
+    GpStatus stat;
+
+    stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
+    expect(Ok, stat);
+todo_wine
+{
+    stat = GdipSetStringFormatMeasurableCharacterRanges(format, 3, ranges);
+    expect(Ok, stat);
+    stat = GdipGetStringFormatMeasurableCharacterRangeCount(format, &count);
+    expect(Ok, stat);
+    if (stat == Ok) expect(3, count);
+}
+    stat= GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+}
+
+static void test_digitsubstitution(void)
+{
+    GpStringFormat *format;
+    GpStatus stat;
+    StringDigitSubstitute digitsub;
+    LANGID digitlang;
+
+    stat = GdipCreateStringFormat(0, LANG_RUSSIAN, &format);
+    expect(Ok, stat);
+
+    /* NULL arguments */
+    stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatDigitSubstitution(format, NULL, NULL);
+    expect(Ok, stat);
+    stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, &digitsub);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, &digitsub);
+    expect(InvalidParameter, stat);
+    stat = GdipSetStringFormatDigitSubstitution(NULL, LANG_NEUTRAL, StringDigitSubstituteNone);
+    expect(InvalidParameter, stat);
+
+    /* try to get both and one by one */
+    stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
+    expect(Ok, stat);
+    expect(StringDigitSubstituteUser, digitsub);
+    expect(LANG_NEUTRAL, digitlang);
+
+    digitsub  = StringDigitSubstituteNone;
+    stat = GdipGetStringFormatDigitSubstitution(format, NULL, &digitsub);
+    expect(Ok, stat);
+    expect(StringDigitSubstituteUser, digitsub);
+
+    digitlang = LANG_RUSSIAN;
+    stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, NULL);
+    expect(Ok, stat);
+    expect(LANG_NEUTRAL, digitlang);
+
+    /* set/get */
+    stat = GdipSetStringFormatDigitSubstitution(format, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL),
+                                                        StringDigitSubstituteUser);
+    expect(Ok, stat);
+    digitsub  = StringDigitSubstituteNone;
+    digitlang = LANG_RUSSIAN;
+    stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
+    expect(Ok, stat);
+    expect(StringDigitSubstituteUser, digitsub);
+    expect(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), digitlang);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+}
+
+static void test_getgenerictypographic(void)
+{
+    GpStringFormat *format;
+    GpStatus stat;
+    INT flags;
+    INT n;
+    StringAlignment align, valign;
+    StringTrimming trimming;
+    StringDigitSubstitute digitsub;
+    LANGID digitlang;
+    INT tabcount;
+
+    /* NULL arg */
+    stat = GdipStringFormatGetGenericTypographic(NULL);
+    expect(InvalidParameter, stat);
+
+    stat = GdipStringFormatGetGenericTypographic(&format);
+    expect(Ok, stat);
+
+    GdipGetStringFormatFlags(format, &flags);
+    GdipGetStringFormatAlign(format, &align);
+    GdipGetStringFormatLineAlign(format, &valign);
+    GdipGetStringFormatHotkeyPrefix(format, &n);
+    GdipGetStringFormatTrimming(format, &trimming);
+    GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
+    GdipGetStringFormatTabStopCount(format, &tabcount);
+
+    expect((StringFormatFlagsNoFitBlackBox |StringFormatFlagsLineLimit | StringFormatFlagsNoClip),
+            flags);
+    expect(HotkeyPrefixNone, n);
+    expect(StringAlignmentNear, align);
+    expect(StringAlignmentNear, align);
+    expect(StringTrimmingNone, trimming);
+    expect(StringDigitSubstituteUser, digitsub);
+    expect(LANG_NEUTRAL, digitlang);
+    expect(0, tabcount);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+}
+
+static REAL tabstops[] = {0.0, 10.0, 2.0};
+static void test_tabstops(void)
+{
+    GpStringFormat *format;
+    GpStatus stat;
+    INT count;
+    REAL tabs[3];
+    REAL firsttab;
+
+    stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
+    expect(Ok, stat);
+
+    /* NULL */
+    stat = GdipGetStringFormatTabStopCount(NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStopCount(NULL, &count);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStopCount(format, NULL);
+    expect(InvalidParameter, stat);
+
+    stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipSetStringFormatTabStops(format, 0.0, 0, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, tabstops);
+    expect(InvalidParameter, stat);
+
+    stat = GdipGetStringFormatTabStops(NULL, 0, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStops(format, 0, NULL, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStops(NULL, 0, &firsttab, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStops(NULL, 0, NULL, tabs);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStops(format, 0, &firsttab, NULL);
+    expect(InvalidParameter, stat);
+    stat = GdipGetStringFormatTabStops(format, 0, NULL, tabs);
+    expect(InvalidParameter, stat);
+
+    /* not NULL */
+    stat = GdipGetStringFormatTabStopCount(format, &count);
+    expect(Ok, stat);
+    expect(0, count);
+    /* negative tabcount */
+    stat = GdipSetStringFormatTabStops(format, 0.0, -1, tabstops);
+    expect(Ok, stat);
+    count = -1;
+    stat = GdipGetStringFormatTabStopCount(format, &count);
+    expect(Ok, stat);
+    expect(0, count);
+
+    stat = GdipSetStringFormatTabStops(format, -10.0, 0, tabstops);
+    expect(Ok, stat);
+    stat = GdipSetStringFormatTabStops(format, -10.0, 1, tabstops);
+    expect(NotImplemented, stat);
+
+    firsttab = -1.0;
+    tabs[0] = tabs[1] = tabs[2] = -1.0;
+    stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs);
+    expect(Ok, stat);
+    expectf(-1.0, tabs[0]);
+    expectf(-1.0, tabs[1]);
+    expectf(-1.0, tabs[2]);
+    expectf(0.0, firsttab);
+
+    stat = GdipSetStringFormatTabStops(format, +0.0, 3, tabstops);
+    expect(Ok, stat);
+    count = 0;
+    stat = GdipGetStringFormatTabStopCount(format, &count);
+    expect(Ok, stat);
+    expect(3, count);
+
+    firsttab = -1.0;
+    tabs[0] = tabs[1] = tabs[2] = -1.0;
+    stat = GdipGetStringFormatTabStops(format, 3, &firsttab, tabs);
+    expect(Ok, stat);
+    expectf(0.0,  tabs[0]);
+    expectf(10.0, tabs[1]);
+    expectf(2.0,  tabs[2]);
+    expectf(0.0,  firsttab);
+
+    stat = GdipSetStringFormatTabStops(format, 10.0, 3, tabstops);
+    expect(Ok, stat);
+    firsttab = -1.0;
+    tabs[0] = tabs[1] = tabs[2] = -1.0;
+    stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs);
+    expect(Ok, stat);
+    expectf(-1.0, tabs[0]);
+    expectf(-1.0, tabs[1]);
+    expectf(-1.0, tabs[2]);
+    expectf(10.0, firsttab);
+
+    /* zero tabcount, after valid setting to 3 */
+    stat = GdipSetStringFormatTabStops(format, 0.0, 0, tabstops);
+    expect(Ok, stat);
+    count = 0;
+    stat = GdipGetStringFormatTabStopCount(format, &count);
+    expect(Ok, stat);
+    expect(3, count);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+}
+
+static void test_getgenericdefault(void)
+{
+    GpStringFormat *format;
+    GpStatus stat;
+
+    INT flags;
+    INT n;
+    StringAlignment align, valign;
+    StringTrimming trimming;
+    StringDigitSubstitute digitsub;
+    LANGID digitlang;
+    INT tabcount;
+
+    /* NULL arg */
+    stat = GdipStringFormatGetGenericDefault(NULL);
+    expect(InvalidParameter, stat);
+
+    stat = GdipStringFormatGetGenericDefault(&format);
+    expect(Ok, stat);
+
+    GdipGetStringFormatFlags(format, &flags);
+    GdipGetStringFormatAlign(format, &align);
+    GdipGetStringFormatLineAlign(format, &valign);
+    GdipGetStringFormatHotkeyPrefix(format, &n);
+    GdipGetStringFormatTrimming(format, &trimming);
+    GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
+    GdipGetStringFormatTabStopCount(format, &tabcount);
+
+    expect(0, flags);
+    expect(HotkeyPrefixNone, n);
+    expect(StringAlignmentNear, align);
+    expect(StringAlignmentNear, align);
+    expect(StringTrimmingCharacter, trimming);
+    expect(StringDigitSubstituteUser, digitsub);
+    expect(LANG_NEUTRAL, digitlang);
+    expect(0, tabcount);
 
     stat = GdipDeleteStringFormat(format);
     expect(Ok, stat);
@@ -62,6 +331,11 @@ START_TEST(stringformat)
     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
     test_constructor();
+    test_characterrange();
+    test_digitsubstitution();
+    test_getgenerictypographic();
+    test_tabstops();
+    test_getgenericdefault();
 
     GdiplusShutdown(gdiplusToken);
 }
index 4504881..05456c6 100644 (file)
@@ -7,6 +7,7 @@
 #include "wine/test.h"
 
 extern void func_brush(void);
+extern void func_customlinecap(void);
 extern void func_font(void);
 extern void func_graphics(void);
 extern void func_graphicspath(void);
@@ -20,6 +21,7 @@ extern void func_stringformat(void);
 const struct test winetest_testlist[] =
 {
     { "brush", func_brush },
+       { "customlinecap", func_customlinecap },
     { "font", func_font },
     { "graphics", func_graphics },
     { "graphicspath", func_graphicspath },