[PATCH] gdiplus: Implement transform matrix for line gradient brushes

Andrew Eikum aeikum at codeweavers.com
Mon Aug 14 11:10:34 CDT 2017


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 dlls/gdiplus/brush.c           |  99 +++++++----
 dlls/gdiplus/gdiplus_private.h |   1 +
 dlls/gdiplus/graphics.c        |  22 +--
 dlls/gdiplus/tests/brush.c     | 386 ++++++++++++++++++++++++++++++++---------
 include/gdiplusflat.h          |   1 +
 5 files changed, 377 insertions(+), 132 deletions(-)

diff --git a/dlls/gdiplus/brush.c b/dlls/gdiplus/brush.c
index a184276804..90df36b9fc 100644
--- a/dlls/gdiplus/brush.c
+++ b/dlls/gdiplus/brush.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007 Google (Evan Stade)
+ * Copyright (C) 2003-2004,2007 Novell, Inc. http://www.novell.com (Ravindra (rkumar at novell.com))
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -149,6 +150,8 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
                 return OutOfMemory;
             }
 
+            dest->transform = src->transform;
+
             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
 
@@ -259,6 +262,41 @@ GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, AR
     return Ok;
 }
 
+static void linegradient_init_transform(GpLineGradient *line)
+{
+    float dx = line->rect.X + (line->rect.Width / 2.f);
+    float dy = line->rect.Y + (line->rect.Height / 2.f);
+    float t, t_cos, t_sin, w_ratio, h_ratio;
+    GpMatrix rot;
+
+    if (line->startpoint.X == line->endpoint.X)
+        t = line->startpoint.Y > line->endpoint.Y ? 3.f * M_PI / 2.f : M_PI / 2.f;
+    else
+        t = atanf((line->endpoint.Y - line->startpoint.Y) / (line->endpoint.X - line->startpoint.X));
+
+    t_cos = cosf(t);
+    t_sin = sinf(t);
+
+    w_ratio = (fabs(t_cos) * line->rect.Width + fabs(t_sin) * line->rect.Height) / line->rect.Width;
+    h_ratio = (fabs(t_sin) * line->rect.Width + fabs(t_cos) * line->rect.Height) / line->rect.Height;
+
+    GdipSetMatrixElements(&line->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
+
+    GdipSetMatrixElements(&rot, t_cos, t_sin, -1.f * t_sin, t_cos, 0, 0);
+
+    /* center about the origin */
+    GdipTranslateMatrix(&line->transform, -dx, -dy, MatrixOrderAppend);
+
+    /* scale to normalize gradient along gradient line (?) */
+    GdipScaleMatrix(&line->transform, w_ratio, h_ratio, MatrixOrderAppend);
+
+    /* rotate so the gradient is horizontal */
+    GdipMultiplyMatrix(&line->transform, &rot, MatrixOrderAppend);
+
+    /* restore original offset in new coords */
+    GdipTranslateMatrix(&line->transform, dx, dy, MatrixOrderAppend);
+}
+
 /******************************************************************************
  * GdipCreateLineBrush [GDIPLUS.@]
  */
@@ -325,6 +363,8 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
     (*line)->pblendpos = NULL;
     (*line)->pblendcount = 0;
 
+    linegradient_init_transform(*line);
+
     TRACE("<-- %p\n", *line);
 
     return Ok;
@@ -497,6 +537,8 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect
             (*line)->startpoint.X = rect->X + exofs;
             (*line)->startpoint.Y = rect->Y + eyofs;
         }
+
+        linegradient_init_transform(*line);
     }
 
     return stat;
@@ -2005,78 +2047,73 @@ GpStatus WINGDIPAPI GdipGetLinePresetBlendCount(GpLineGradient *brush,
 
 GpStatus WINGDIPAPI GdipResetLineTransform(GpLineGradient *brush)
 {
-    static int calls;
-
     TRACE("(%p)\n", brush);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush)
+        return InvalidParameter;
 
-    return NotImplemented;
+    return GdipSetMatrixElements(&brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
 }
 
 GpStatus WINGDIPAPI GdipSetLineTransform(GpLineGradient *brush,
     GDIPCONST GpMatrix *matrix)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", brush,  matrix);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush || !matrix)
+        return InvalidParameter;
 
-    return NotImplemented;
+    brush->transform = *matrix;
+
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetLineTransform(GpLineGradient *brush, GpMatrix *matrix)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", brush, matrix);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush || !matrix)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *matrix = brush->transform;
+
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipScaleLineTransform(GpLineGradient *brush, REAL sx, REAL sy,
     GpMatrixOrder order)
 {
-    static int calls;
-
     TRACE("(%p,%0.2f,%0.2f,%u)\n", brush, sx, sy, order);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush)
+        return InvalidParameter;
 
-    return NotImplemented;
+    return GdipScaleMatrix(&brush->transform, sx, sy, order);
 }
 
 GpStatus WINGDIPAPI GdipMultiplyLineTransform(GpLineGradient *brush,
     GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
 {
-    static int calls;
-
     TRACE("(%p,%p,%u)\n", brush, matrix, order);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush)
+        return InvalidParameter;
 
-    return NotImplemented;
+    if(!matrix)
+        return Ok;
+
+    return GdipMultiplyMatrix(&brush->transform, matrix, order);
 }
 
-GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient* brush,
+GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient *brush,
         REAL dx, REAL dy, GpMatrixOrder order)
 {
-    static int calls;
-
     TRACE("(%p,%f,%f,%d)\n", brush, dx, dy, order);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if(!brush)
+        return InvalidParameter;
 
-    return Ok;
+    return GdipTranslateMatrix(&brush->transform, dx, dy, order);
 }
 
 /******************************************************************************
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 33966767cc..e1169c6cdf 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -312,6 +312,7 @@ struct GpLineGradient{
     ARGB* pblendcolor; /* preset blend colors */
     REAL* pblendpos; /* preset blend positions */
     INT pblendcount;
+    GpMatrix transform;
 };
 
 struct GpTexture{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index e45618eefe..3024b4496a 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -547,6 +547,7 @@ static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
     REAL blendfac;
 
     /* clamp to between 0.0 and 1.0, using the wrap mode */
+    position = (position + brush->rect.X) / brush->rect.Width;
     if (brush->wrap == WrapModeTile)
     {
         position = fmodf(position, 1.0f);
@@ -1138,10 +1139,8 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
     case BrushTypeLinearGradient:
     {
         GpLineGradient *fill = (GpLineGradient*)brush;
-        GpPointF draw_points[3], line_points[3];
+        GpPointF draw_points[3];
         GpStatus stat;
-        static const GpRectF box_1 = { 0.0, 0.0, 1.0, 1.0 };
-        GpMatrix *world_to_gradient; /* FIXME: Store this in the brush? */
         int x, y;
 
         draw_points[0].X = fill_area->X;
@@ -1159,22 +1158,11 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
 
         if (stat == Ok)
         {
-            line_points[0] = fill->startpoint;
-            line_points[1] = fill->endpoint;
-            line_points[2].X = fill->startpoint.X + (fill->startpoint.Y - fill->endpoint.Y);
-            line_points[2].Y = fill->startpoint.Y + (fill->endpoint.X - fill->startpoint.X);
-
-            stat = GdipCreateMatrix3(&box_1, line_points, &world_to_gradient);
-        }
-
-        if (stat == Ok)
-        {
-            stat = GdipInvertMatrix(world_to_gradient);
+            GpMatrix world_to_gradient = fill->transform;
 
+            stat = GdipInvertMatrix(&world_to_gradient);
             if (stat == Ok)
-                stat = GdipTransformMatrixPoints(world_to_gradient, draw_points, 3);
-
-            GdipDeleteMatrix(world_to_gradient);
+                stat = GdipTransformMatrixPoints(&world_to_gradient, draw_points, 3);
         }
 
         if (stat == Ok)
diff --git a/dlls/gdiplus/tests/brush.c b/dlls/gdiplus/tests/brush.c
index 9fd80d2305..6d35073a67 100644
--- a/dlls/gdiplus/tests/brush.c
+++ b/dlls/gdiplus/tests/brush.c
@@ -27,6 +27,8 @@
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
 
+static HWND hwnd;
+
 static void test_constructor_destructor(void)
 {
     GpStatus status;
@@ -174,12 +176,17 @@ static void test_transform(void)
 {
     GpStatus status;
     GpTexture *texture;
+    GpLineGradient *line;
     GpGraphics *graphics = NULL;
     GpBitmap *bitmap;
     HDC hdc = GetDC(0);
     GpMatrix *m, *m1;
     BOOL res;
+    GpPointF start, end;
+    GpRectF rectf;
+    REAL elements[6];
 
+    /* GpTexture */
     status = GdipCreateMatrix2(2.0, 0.0, 0.0, 0.0, 0.0, 0.0, &m);
     expect(Ok, status);
 
@@ -233,6 +240,216 @@ static void test_transform(void)
     expect(Ok, status);
     status = GdipDeleteGraphics(graphics);
     expect(Ok, status);
+
+
+
+    status = GdipCreateFromHWND(hwnd, &graphics);
+    expect(Ok, status);
+
+    /* GpLineGradient */
+    /* create with vertical gradient line */
+    start.X = start.Y = end.X = 0.0;
+    end.Y = 100.0;
+
+    status = GdipCreateLineBrush(&start, &end, (ARGB)0xffff0000, 0xff00ff00, WrapModeTile, &line);
+    expect(Ok, status);
+
+    status = GdipCreateMatrix2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, &m);
+    expect(Ok, status);
+
+    /* NULL arguments */
+    status = GdipResetLineTransform(NULL);
+    expect(InvalidParameter, status);
+    status = GdipSetLineTransform(NULL, m);
+    expect(InvalidParameter, status);
+    status = GdipSetLineTransform(line, NULL);
+    expect(InvalidParameter, status);
+    status = GdipGetLineTransform(NULL, m);
+    expect(InvalidParameter, status);
+    status = GdipGetLineTransform(line, NULL);
+    expect(InvalidParameter, status);
+    status = GdipScaleLineTransform(NULL, 1, 1, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+    status = GdipMultiplyLineTransform(NULL, m, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+    status = GdipTranslateLineTransform(NULL, 0, 0, MatrixOrderPrepend);
+    expect(InvalidParameter, status);
+
+    /* initial transform */
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(0.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(0.0, elements[3]);
+    expectf(50.0, elements[4]);
+    expectf(50.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 0, 200, 200);
+    expect(Ok, status);
+
+    /* manually set transform */
+    GdipSetMatrixElements(m, 2.0, 0.0, 0.0, 4.0, 0.0, 0.0);
+
+    status = GdipSetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(2.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(4.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 0, 200, 200);
+    expect(Ok, status);
+
+    /* scale transform */
+    status = GdipScaleLineTransform(line, 4.0, 0.5, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(8.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(2.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 0, 200, 200);
+    expect(Ok, status);
+
+    /* translate transform */
+    status = GdipTranslateLineTransform(line, 10.0, -20.0, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(8.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(2.0, elements[3]);
+    expectf(10.0, elements[4]);
+    expectf(-20.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 200, 200, 200);
+    expect(Ok, status);
+
+    /* multiply transform */
+    GdipSetMatrixElements(m, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
+    GdipRotateMatrix(m, 45.0, MatrixOrderAppend);
+    GdipScaleMatrix(m, 0.25, 0.5, MatrixOrderAppend);
+
+    status = GdipMultiplyLineTransform(line, m, MatrixOrderAppend);
+    expect(Ok, status);
+
+    /* NULL transform does nothing */
+    status = GdipMultiplyLineTransform(line, NULL, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(1.414214, elements[0]);
+    expectf(2.828427, elements[1]);
+    expectf(-0.353553, elements[2]);
+    expectf(0.707107, elements[3]);
+    expectf(5.303300, elements[4]);
+    expectf(-3.535534, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 200, 200, 200);
+    expect(Ok, status);
+
+    /* reset transform sets to identity */
+    status = GdipResetLineTransform(line);
+    expect(Ok, status);
+
+    status = GdipGetLineTransform(line, m);
+    expect(Ok, status);
+
+    status = GdipGetMatrixElements(m, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    status = GdipGetLineRect(line, &rectf);
+    expect(Ok, status);
+    expectf(-50.0, rectf.X);
+    expectf(0.0, rectf.Y);
+    expectf(100.0, rectf.Width);
+    expectf(100.0, rectf.Height);
+
+    status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 200, 200, 200);
+    expect(Ok, status);
+
+    if(0){
+        /* enable to visually compare with Windows */
+        MSG msg;
+        while(GetMessageW(&msg, hwnd, 0, 0) > 0){
+            TranslateMessage(&msg);
+            DispatchMessageW(&msg);
+        }
+    }
+
+    GdipDeleteBrush((GpBrush*)line);
+    GdipDeleteMatrix(m);
+    GdipDeleteGraphics(graphics);
     ReleaseDC(0, hdc);
 }
 
@@ -308,20 +525,18 @@ static void test_gradientgetrect(void)
     expectf(99.0, rectf.Width);
     expectf(99.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(1.0, elements[1]);
-        expectf(-1.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(50.50, elements[4]);
-        expectf(-50.50, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(50.50, elements[4]);
+    expectf(-50.50, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* vertical gradient */
     pt1.X = pt1.Y = pt2.X = 0.0;
     pt2.Y = 10.0;
@@ -335,20 +550,18 @@ static void test_gradientgetrect(void)
     expectf(10.0, rectf.Width);
     expectf(10.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(0.0, elements[0]);
-        expectf(1.0, elements[1]);
-        expectf(-1.0, elements[2]);
-        expectf(0.0, elements[3]);
-        expectf(5.0, elements[4]);
-        expectf(5.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(0.0, elements[0]);
+    expectf(1.0, elements[1]);
+    expectf(-1.0, elements[2]);
+    expectf(0.0, elements[3]);
+    expectf(5.0, elements[4]);
+    expectf(5.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* horizontal gradient */
     pt1.X = pt1.Y = pt2.Y = 0.0;
     pt2.X = 10.0;
@@ -362,20 +575,18 @@ static void test_gradientgetrect(void)
     expectf(10.0, rectf.Width);
     expectf(10.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* slope = -1 */
     pt1.X = pt1.Y = 0.0;
     pt2.X = 20.0;
@@ -390,20 +601,18 @@ static void test_gradientgetrect(void)
     expectf(20.0, rectf.Width);
     expectf(20.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok, status);
-        expectf(1.0, elements[0]);
-        expectf(-1.0, elements[1]);
-        expectf(1.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(10.0, elements[4]);
-        expectf(10.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok, status);
+    expectf(1.0, elements[0]);
+    expectf(-1.0, elements[1]);
+    expectf(1.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(10.0, elements[4]);
+    expectf(10.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok, status);
+
     /* slope = 1/100 */
     pt1.X = pt1.Y = 0.0;
     pt2.X = 100.0;
@@ -418,20 +627,18 @@ static void test_gradientgetrect(void)
     expectf(100.0, rectf.Width);
     expectf(1.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.01, elements[1]);
-        expectf(-0.02, elements[2]);
-        /* expectf(2.0, elements[3]); */
-        expectf(0.01, elements[4]);
-        /* expectf(-1.0, elements[5]); */
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.01, elements[1]);
+    expectf(-0.02, elements[2]);
+    /* expectf(2.0, elements[3]); */
+    expectf(0.01, elements[4]);
+    /* expectf(-1.0, elements[5]); */
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
+
     /* zero height rect */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = 100.0;
@@ -439,6 +646,7 @@ static void test_gradientgetrect(void)
     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeVertical,
         WrapModeTile, &brush);
     expect(OutOfMemory, status);
+
     /* zero width rect */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = 0.0;
@@ -446,6 +654,7 @@ static void test_gradientgetrect(void)
     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
         WrapModeTile, &brush);
     expect(OutOfMemory, status);
+
     /* from rect with LinearGradientModeHorizontal */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = rectf.Height = 100.0;
@@ -460,20 +669,18 @@ static void test_gradientgetrect(void)
     expectf(100.0, rectf.Width);
     expectf(100.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
+
     /* passing negative Width/Height to LinearGradientModeHorizontal */
     rectf.X = rectf.Y = 10.0;
     rectf.Width = rectf.Height = -100.0;
@@ -488,18 +695,15 @@ static void test_gradientgetrect(void)
     expectf(-100.0, rectf.Width);
     expectf(-100.0, rectf.Height);
     status = GdipGetLineTransform(brush, transform);
-    todo_wine expect(Ok, status);
-    if (status == Ok)
-    {
-        status = GdipGetMatrixElements(transform, elements);
-        expect(Ok,status);
-        expectf(1.0, elements[0]);
-        expectf(0.0, elements[1]);
-        expectf(0.0, elements[2]);
-        expectf(1.0, elements[3]);
-        expectf(0.0, elements[4]);
-        expectf(0.0, elements[5]);
-    }
+    expect(Ok, status);
+    status = GdipGetMatrixElements(transform, elements);
+    expect(Ok,status);
+    expectf(1.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
     status = GdipDeleteBrush((GpBrush*)brush);
     expect(Ok,status);
 
@@ -1275,12 +1479,26 @@ START_TEST(brush)
     ULONG_PTR gdiplusToken;
     HMODULE hmsvcrt;
     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
+    WNDCLASSA class;
 
     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
     hmsvcrt = LoadLibraryA("msvcrt");
     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
 
+    memset( &class, 0, sizeof(class) );
+    class.lpszClassName = "gdiplus_test";
+    class.style = CS_HREDRAW | CS_VREDRAW;
+    class.lpfnWndProc = DefWindowProcA;
+    class.hInstance = GetModuleHandleA(0);
+    class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
+    class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+    class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    RegisterClassA( &class );
+    hwnd = CreateWindowA( "gdiplus_test", "graphics test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                          CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, GetModuleHandleA(0), 0 );
+    ok(hwnd != NULL, "Expected window to be created\n");
+
     gdiplusStartupInput.GdiplusVersion              = 1;
     gdiplusStartupInput.DebugEventCallback          = NULL;
     gdiplusStartupInput.SuppressBackgroundThread    = 0;
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 10d537a017..f2ac91e83d 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -495,6 +495,7 @@ GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient*,GDIPCONST ARGB*,
 GpStatus WINGDIPAPI GdipGetLinePresetBlend(GpLineGradient*,ARGB*,REAL*,INT);
 GpStatus WINGDIPAPI GdipGetLinePresetBlendCount(GpLineGradient*,INT*);
 GpStatus WINGDIPAPI GdipGetLineTransform(GpLineGradient*,GpMatrix*);
+GpStatus WINGDIPAPI GdipMultiplyLineTransform(GpLineGradient*,GDIPCONST GpMatrix*,GpMatrixOrder);
 GpStatus WINGDIPAPI GdipResetLineTransform(GpLineGradient*);
 GpStatus WINGDIPAPI GdipRotateLineTransform(GpLineGradient*,REAL,GpMatrixOrder);
 GpStatus WINGDIPAPI GdipScaleLineTransform(GpLineGradient*,REAL,REAL,
-- 
2.14.0




More information about the wine-patches mailing list