[5/5] gdiplus: Account for gdi transform in SOFTWARE_GdipFillRegion.

Vincent Povirk vincent at codeweavers.com
Wed Aug 30 12:32:17 CDT 2017


Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
 dlls/gdiplus/gdiplus_private.h |  4 +++
 dlls/gdiplus/graphics.c        | 57 +++++++++++++++++++++++++++++++++++++++---
 dlls/gdiplus/tests/graphics.c  |  2 +-
 3 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 9980afc..6bb7f88 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -81,6 +81,8 @@ extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
 
 #define WineCoordinateSpaceGdiDevice ((GpCoordinateSpace)4)
 
+extern GpStatus gdi_transform_acquire(GpGraphics *graphics);
+extern GpStatus gdi_transform_release(GpGraphics *graphics);
 extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
         GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN;
 extern GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace dst_space,
@@ -258,6 +260,8 @@ struct GpGraphics{
     struct list containers;
     GraphicsContainer contid; /* last-issued container ID */
     INT origin_x, origin_y;
+    INT gdi_transform_acquire_count, gdi_transform_save;
+    GpMatrix gdi_transform;
     /* For giving the caller an HDC when we technically can't: */
     HBITMAP temp_hbitmap;
     int temp_hbitmap_width;
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 3dbb457..7aa1dac 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -2039,7 +2039,7 @@ static GpStatus restore_container(GpGraphics* graphics,
     return Ok;
 }
 
-static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect)
+static GpStatus get_graphics_device_bounds(GpGraphics* graphics, GpRectF* rect)
 {
     RECT wnd_rect;
     GpStatus stat=Ok;
@@ -2083,7 +2083,14 @@ static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect)
         rect->Height = GetDeviceCaps(graphics->hdc, VERTRES);
     }
 
-    if (graphics->hdc)
+    return stat;
+}
+
+static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect)
+{
+    GpStatus stat = get_graphics_device_bounds(graphics, rect);
+
+    if (stat == Ok && graphics->hdc)
     {
         GpPointF points[4], min_point, max_point;
         int i;
@@ -4457,14 +4464,17 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
     if (!brush_can_fill_pixels(brush))
         return NotImplemented;
 
-    stat = get_graphics_bounds(graphics, &graphics_bounds);
+    stat = gdi_transform_acquire(graphics);
+
+    if (stat == Ok)
+        stat = get_graphics_device_bounds(graphics, &graphics_bounds);
 
     if (stat == Ok)
         stat = GdipCloneRegion(region, &temp_region);
 
     if (stat == Ok)
     {
-        stat = get_graphics_transform(graphics, CoordinateSpaceDevice,
+        stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice,
             CoordinateSpaceWorld, &world_to_device);
 
         if (stat == Ok)
@@ -4482,6 +4492,7 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
     if (stat == Ok && GetRgnBox(hregion, &bound_rect) == NULLREGION)
     {
         DeleteObject(hregion);
+        gdi_transform_release(graphics);
         return Ok;
     }
 
@@ -4513,6 +4524,8 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
         DeleteObject(hregion);
     }
 
+    gdi_transform_release(graphics);
+
     return stat;
 }
 
@@ -6586,10 +6599,46 @@ static void get_gdi_transform(GpGraphics *graphics, GpMatrix *matrix)
         return;
     }
 
+    if (graphics->gdi_transform_acquire_count)
+    {
+        *matrix = graphics->gdi_transform;
+        return;
+    }
+
     GetTransform(graphics->hdc, 0x204, &xform);
     GdipSetMatrixElements(matrix, xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
 }
 
+GpStatus gdi_transform_acquire(GpGraphics *graphics)
+{
+    if (graphics->gdi_transform_acquire_count == 0 && graphics->hdc)
+    {
+        get_gdi_transform(graphics, &graphics->gdi_transform);
+        graphics->gdi_transform_save = SaveDC(graphics->hdc);
+        SetGraphicsMode(graphics->hdc, GM_COMPATIBLE);
+        SetMapMode(graphics->hdc, MM_TEXT);
+        SetWindowOrgEx(graphics->hdc, 0, 0, NULL);
+        SetViewportOrgEx(graphics->hdc, 0, 0, NULL);
+    }
+    graphics->gdi_transform_acquire_count++;
+    return Ok;
+}
+
+GpStatus gdi_transform_release(GpGraphics *graphics)
+{
+    if (graphics->gdi_transform_acquire_count <= 0)
+    {
+        ERR("called without matching gdi_transform_acquire");
+        return GenericError;
+    }
+    if (graphics->gdi_transform_acquire_count == 1 && graphics->hdc)
+    {
+        RestoreDC(graphics->hdc, graphics->gdi_transform_save);
+    }
+    graphics->gdi_transform_acquire_count--;
+    return Ok;
+}
+
 GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
         GpCoordinateSpace src_space, GpMatrix *matrix)
 {
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 5f45cc2..5416ebc 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -6361,7 +6361,7 @@ static void test_GdipFillRectanglesOnMemoryDCTextureBrush(void)
        color[4] = get_bitmap_pixel(width/2-1, height-1);
        color[5] = get_bitmap_pixel(width-1, height/2-1);
     }
-    todo_wine ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
+    ok(is_blue_color(color[0]) && is_blue_color(color[1]) && is_blue_color(color[2]) &&
        color[3] == 0 && color[4] == 0 && color[5] == 0,
       "Expected GdipFillRectangleI take effect!\n" );
     ReleaseBitmapPixelBuffer(pixel);
-- 
2.7.4




More information about the wine-patches mailing list