https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6619d0261f266a3e7cec775a6b227daf3a352540

commit 6619d0261f266a3e7cec775a6b227daf3a352540
Author:     Amine Khaldi <[email protected]>
AuthorDate: Sun May 27 04:10:39 2018 +0100
Commit:     Amine Khaldi <[email protected]>
CommitDate: Sun May 27 04:10:39 2018 +0100

    [GDIPLUS] Sync with Wine Staging 3.9. CORE-14656
---
 dll/win32/gdiplus/brush.c           |  14 ++-
 dll/win32/gdiplus/customlinecap.c   | 231 +++++++++++++++++++++++++-----------
 dll/win32/gdiplus/font.c            |   4 +-
 dll/win32/gdiplus/gdiplus.spec      |   2 +-
 dll/win32/gdiplus/gdiplus_private.h |   5 +
 dll/win32/gdiplus/graphics.c        |  40 +++++--
 dll/win32/gdiplus/image.c           |   8 +-
 dll/win32/gdiplus/metafile.c        |   2 +-
 dll/win32/gdiplus/pen.c             |   7 +-
 dll/win32/gdiplus/region.c          |  38 +++++-
 media/doc/README.WINE               |   2 +-
 11 files changed, 253 insertions(+), 100 deletions(-)

diff --git a/dll/win32/gdiplus/brush.c b/dll/win32/gdiplus/brush.c
index 51264212ae..d06832045a 100644
--- a/dll/win32/gdiplus/brush.c
+++ b/dll/win32/gdiplus/brush.c
@@ -261,7 +261,7 @@ static const char HatchBrushes[][8] = {
 
 GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
 {
-    if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
+    if (hatchstyle < ARRAY_SIZE(HatchBrushes))
     {
         *result = HatchBrushes[hatchstyle];
         return Ok;
@@ -1715,6 +1715,18 @@ GpStatus WINGDIPAPI 
GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
     return Ok;
 }
 
+GpStatus WINGDIPAPI GdipSetPathGradientPath(GpPathGradient *grad, GDIPCONST 
GpPath *path)
+{
+    static int calls;
+
+    TRACE("(%p, %p)\n", grad, path);
+
+    if (!(calls++))
+        FIXME("not implemented\n");
+
+    return NotImplemented;
+}
+
 GpStatus WINGDIPAPI GdipSetPathGradientSigmaBlend(GpPathGradient *grad,
     REAL focus, REAL scale)
 {
diff --git a/dll/win32/gdiplus/customlinecap.c 
b/dll/win32/gdiplus/customlinecap.c
index ca81bee217..c74928eeda 100644
--- a/dll/win32/gdiplus/customlinecap.c
+++ b/dll/win32/gdiplus/customlinecap.c
@@ -17,6 +17,7 @@
  */
 
 #include <stdarg.h>
+#include <assert.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -38,11 +39,20 @@ GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap* 
from,
     if(!from || !to)
         return InvalidParameter;
 
-    *to = heap_alloc_zero(sizeof(GpCustomLineCap));
-    if(!*to)   return OutOfMemory;
+    if (from->type == CustomLineCapTypeDefault)
+        *to = heap_alloc_zero(sizeof(GpCustomLineCap));
+    else
+        *to = heap_alloc_zero(sizeof(GpAdjustableArrowCap));
 
-    memcpy(*to, from, sizeof(GpCustomLineCap));
+    if (!*to)
+        return OutOfMemory;
+
+    if (from->type == CustomLineCapTypeDefault)
+        **to = *from;
+    else
+        *(GpAdjustableArrowCap *)*to = *(GpAdjustableArrowCap *)from;
 
+    /* Duplicate path data */
     (*to)->pathdata.Points = heap_alloc_zero(from->pathdata.Count * 
sizeof(PointF));
     (*to)->pathdata.Types = heap_alloc_zero(from->pathdata.Count);
 
@@ -62,12 +72,44 @@ GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap* 
from,
     return Ok;
 }
 
+static GpStatus init_custom_linecap(GpCustomLineCap *cap, GpPathData 
*pathdata, BOOL fill, GpLineCap basecap,
+    REAL base_inset)
+{
+    cap->fill = fill;
+
+    cap->pathdata.Points = heap_alloc_zero(pathdata->Count * sizeof(PointF));
+    cap->pathdata.Types = heap_alloc_zero(pathdata->Count);
+
+    if ((!cap->pathdata.Types || !cap->pathdata.Points) && pathdata->Count)
+    {
+        heap_free(cap->pathdata.Points);
+        heap_free(cap->pathdata.Types);
+        cap->pathdata.Points = NULL;
+        cap->pathdata.Types = NULL;
+        return OutOfMemory;
+    }
+
+    if (pathdata->Points)
+        memcpy(cap->pathdata.Points, pathdata->Points, pathdata->Count * 
sizeof(PointF));
+    if (pathdata->Types)
+        memcpy(cap->pathdata.Types, pathdata->Types, pathdata->Count);
+    cap->pathdata.Count = pathdata->Count;
+
+    cap->inset = base_inset;
+    cap->cap = basecap;
+    cap->join = LineJoinMiter;
+    cap->scale = 1.0;
+
+    return Ok;
+}
+
 /* FIXME: Sometimes when fillPath is non-null and stroke path is null, the 
native
  * version of this function returns NotImplemented. I cannot figure out why. */
 GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* 
strokePath,
     GpLineCap baseCap, REAL baseInset, GpCustomLineCap **customCap)
 {
     GpPathData *pathdata;
+    GpStatus stat;
 
     TRACE("%p %p %d %f %p\n", fillPath, strokePath, baseCap, baseInset, 
customCap);
 
@@ -77,37 +119,18 @@ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* 
fillPath, GpPath* strokePath
     *customCap = heap_alloc_zero(sizeof(GpCustomLineCap));
     if(!*customCap)    return OutOfMemory;
 
-    (*customCap)->type = CustomLineCapTypeDefault;
-    if(strokePath){
-        (*customCap)->fill = FALSE;
+    if (strokePath)
         pathdata = &strokePath->pathdata;
-    }
-    else{
-        (*customCap)->fill = TRUE;
+    else
         pathdata = &fillPath->pathdata;
-    }
 
-    (*customCap)->pathdata.Points = heap_alloc_zero(pathdata->Count * 
sizeof(PointF));
-    (*customCap)->pathdata.Types = heap_alloc_zero(pathdata->Count);
-
-    if((!(*customCap)->pathdata.Types || !(*customCap)->pathdata.Points) &&
-        pathdata->Count){
-        heap_free((*customCap)->pathdata.Points);
-        heap_free((*customCap)->pathdata.Types);
+    stat = init_custom_linecap(*customCap, pathdata, fillPath != NULL, 
baseCap, baseInset);
+    if (stat != Ok)
+    {
         heap_free(*customCap);
-        return OutOfMemory;
+        return stat;
     }
 
-    memcpy((*customCap)->pathdata.Points, pathdata->Points, pathdata->Count
-           * sizeof(PointF));
-    memcpy((*customCap)->pathdata.Types, pathdata->Types, pathdata->Count);
-    (*customCap)->pathdata.Count = pathdata->Count;
-
-    (*customCap)->inset = baseInset;
-    (*customCap)->cap = baseCap;
-    (*customCap)->join = LineJoinMiter;
-    (*customCap)->scale = 1.0;
-
     TRACE("<-- %p\n", *customCap);
 
     return Ok;
@@ -257,111 +280,175 @@ GpStatus WINGDIPAPI 
GdipGetCustomLineCapType(GpCustomLineCap *customCap, CustomL
     return Ok;
 }
 
+static void arrowcap_update_path(GpAdjustableArrowCap *cap)
+{
+    static const BYTE types_filled[] =
+    {
+        PathPointTypeStart, PathPointTypeLine, PathPointTypeLine, 
PathPointTypeLine | PathPointTypeCloseSubpath
+    };
+    static const BYTE types_unfilled[] =
+    {
+        PathPointTypeStart, PathPointTypeLine, PathPointTypeLine
+    };
+    GpPointF *points;
+
+    assert(cap->cap.pathdata.Count == 3 || cap->cap.pathdata.Count == 4);
+
+    points = cap->cap.pathdata.Points;
+    if (cap->cap.fill)
+    {
+        memcpy(cap->cap.pathdata.Types, types_filled, sizeof(types_filled));
+        cap->cap.pathdata.Count = 4;
+        points[0].X = -cap->width / 2.0;
+        points[0].Y = -cap->height;
+        points[1].X = 0.0;
+        points[1].Y = 0.0;
+        points[2].X = cap->width / 2.0;
+        points[2].Y = -cap->height;
+        points[3].X = 0.0;
+        points[3].Y = -cap->height - cap->middle_inset;
+    }
+    else
+    {
+        memcpy(cap->cap.pathdata.Types, types_unfilled, 
sizeof(types_unfilled));
+        cap->cap.pathdata.Count = 3;
+        points[0].X = -cap->width / 4.0;
+        points[0].Y = -cap->height / 2.0;
+        points[1].X = 0.0;
+        points[1].Y = 0.0;
+        points[2].X = cap->width / 4.0;
+        points[2].Y = -cap->height / 2.0;
+    }
+
+    if (cap->width == 0.0)
+        cap->cap.inset = 0.0;
+    else
+        cap->cap.inset = cap->height / cap->width;
+}
+
 GpStatus WINGDIPAPI GdipCreateAdjustableArrowCap(REAL height, REAL width, BOOL 
fill,
     GpAdjustableArrowCap **cap)
 {
-    static int calls;
+    GpPathData pathdata;
+    GpStatus stat;
 
     TRACE("(%0.2f,%0.2f,%i,%p)\n", height, width, fill, cap);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *cap = heap_alloc_zero(sizeof(**cap));
+    if (!*cap)
+        return OutOfMemory;
+
+    /* We'll need 4 points at most. */
+    pathdata.Count = 4;
+    pathdata.Points = NULL;
+    pathdata.Types = NULL;
+    stat = init_custom_linecap(&(*cap)->cap, &pathdata, fill, LineCapTriangle, 
width != 0.0 ? height / width : 0.0);
+    if (stat != Ok)
+    {
+        heap_free(*cap);
+        return stat;
+    }
+
+    (*cap)->cap.type = CustomLineCapTypeAdjustableArrow;
+    (*cap)->height = height;
+    (*cap)->width = width;
+    (*cap)->middle_inset = 0.0;
+    arrowcap_update_path(*cap);
+
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetAdjustableArrowCapFillState(GpAdjustableArrowCap* 
cap, BOOL* fill)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", cap, fill);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap || !fill)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *fill = cap->cap.fill;
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, 
REAL* height)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", cap, height);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap || !height)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *height = cap->height;
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* 
cap, REAL* middle)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", cap, middle);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap || !middle)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *middle = cap->middle_inset;
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipGetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, 
REAL* width)
 {
-    static int calls;
-
     TRACE("(%p,%p)\n", cap, width);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap || !width)
+        return InvalidParameter;
 
-    return NotImplemented;
+    *width = cap->width;
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipSetAdjustableArrowCapFillState(GpAdjustableArrowCap* 
cap, BOOL fill)
 {
-    static int calls;
-
     TRACE("(%p,%i)\n", cap, fill);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap)
+        return InvalidParameter;
 
-    return NotImplemented;
+    cap->cap.fill = fill;
+    arrowcap_update_path(cap);
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipSetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, 
REAL height)
 {
-    static int calls;
-
     TRACE("(%p,%0.2f)\n", cap, height);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap)
+        return InvalidParameter;
 
-    return NotImplemented;
+    cap->height = height;
+    arrowcap_update_path(cap);
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* 
cap, REAL middle)
 {
-    static int calls;
-
     TRACE("(%p,%0.2f)\n", cap, middle);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap)
+        return InvalidParameter;
 
-    return NotImplemented;
+    cap->middle_inset = middle;
+    arrowcap_update_path(cap);
+    return Ok;
 }
 
 GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, 
REAL width)
 {
-    static int calls;
-
     TRACE("(%p,%0.2f)\n", cap, width);
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (!cap)
+        return InvalidParameter;
 
-    return NotImplemented;
+    cap->width = width;
+    arrowcap_update_path(cap);
+    return Ok;
 }
diff --git a/dll/win32/gdiplus/font.c b/dll/win32/gdiplus/font.c
index f99b026b25..64778bb226 100644
--- a/dll/win32/gdiplus/font.c
+++ b/dll/win32/gdiplus/font.c
@@ -1367,7 +1367,7 @@ static int match_name_table_language( const 
tt_name_record *name, LANGID lang )
     case TT_PLATFORM_MACINTOSH:
         if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
         name_lang = GET_BE_WORD(name->language_id);
-        if (name_lang >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) 
return 0;
+        if (name_lang >= ARRAY_SIZE(mac_langid_table)) return 0;
         name_lang = mac_langid_table[name_lang];
         break;
     case TT_PLATFORM_APPLE_UNICODE:
@@ -1377,7 +1377,7 @@ static int match_name_table_language( const 
tt_name_record *name, LANGID lang )
         case TT_APPLE_ID_ISO_10646:
         case TT_APPLE_ID_UNICODE_2_0:
             name_lang = GET_BE_WORD(name->language_id);
-            if (name_lang >= 
sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
+            if (name_lang >= ARRAY_SIZE(mac_langid_table)) return 0;
             name_lang = mac_langid_table[name_lang];
             break;
         default:
diff --git a/dll/win32/gdiplus/gdiplus.spec b/dll/win32/gdiplus/gdiplus.spec
index b29e41ebfa..ed9d50c058 100644
--- a/dll/win32/gdiplus/gdiplus.spec
+++ b/dll/win32/gdiplus/gdiplus.spec
@@ -534,7 +534,7 @@
 534 stdcall GdipSetPathGradientFocusScales(ptr float float)
 535 stdcall GdipSetPathGradientGammaCorrection(ptr long)
 536 stdcall GdipSetPathGradientLinearBlend(ptr float float)
-537 stub GdipSetPathGradientPath
+537 stdcall GdipSetPathGradientPath(ptr ptr)
 538 stdcall GdipSetPathGradientPresetBlend(ptr ptr ptr long)
 539 stdcall GdipSetPathGradientSigmaBlend(ptr float float)
 540 stdcall GdipSetPathGradientSurroundColorsWithCount(ptr ptr ptr)
diff --git a/dll/win32/gdiplus/gdiplus_private.h 
b/dll/win32/gdiplus/gdiplus_private.h
index ea79f1183c..25b269ba35 100644
--- a/dll/win32/gdiplus/gdiplus_private.h
+++ b/dll/win32/gdiplus/gdiplus_private.h
@@ -35,6 +35,8 @@
 
 #include "gdiplus.h"
 
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
 #define GP_DEFAULT_PENSTYLE (PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | 
PS_JOIN_MITER)
 #define MAX_ARC_PTS (13)
 #define MAX_DASHLEN (16) /* this is a limitation of gdi */
@@ -341,6 +343,9 @@ struct GpCustomLineCap{
 
 struct GpAdjustableArrowCap{
     GpCustomLineCap cap;
+    REAL middle_inset;
+    REAL height;
+    REAL width;
 };
 
 struct GpImage{
diff --git a/dll/win32/gdiplus/graphics.c b/dll/win32/gdiplus/graphics.c
index f42fca643d..1e2aff14f4 100644
--- a/dll/win32/gdiplus/graphics.c
+++ b/dll/win32/gdiplus/graphics.c
@@ -353,15 +353,20 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN 
*hrgn)
     GpRegion *rgn;
     GpMatrix transform;
     GpStatus stat;
+    BOOL identity;
 
     stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceDevice, &transform);
 
+    if (stat == Ok)
+        stat = GdipIsMatrixIdentity(&transform, &identity);
+
     if (stat == Ok)
         stat = GdipCloneRegion(graphics->clip, &rgn);
 
     if (stat == Ok)
     {
-        stat = GdipTransformRegion(rgn, &transform);
+        if (!identity)
+            stat = GdipTransformRegion(rgn, &transform);
 
         if (stat == Ok)
             stat = GdipGetRegionHRgn(rgn, NULL, hrgn);
@@ -1695,9 +1700,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF 
color, GpLineCap cap, REAL s
             ptf[3].X = x2 - dbig;
             ptf[2].X = x2 + dsmall;
 
-            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 3);
+            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 4);
 
-            round_points(pt, ptf, 3);
+            round_points(pt, ptf, 4);
 
             Polygon(graphics->hdc, pt, 4);
 
@@ -1735,9 +1740,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF 
color, GpLineCap cap, REAL s
             ptf[1].X = x2 + dx;
             ptf[1].Y = y2 + dy;
 
-            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 3);
+            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 2);
 
-            round_points(pt, ptf, 3);
+            round_points(pt, ptf, 2);
 
             Ellipse(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
 
@@ -1781,9 +1786,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF 
color, GpLineCap cap, REAL s
             ptf[3].X = x2 + dx;
             ptf[3].Y = y2 + dy;
 
-            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 3);
+            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 4);
 
-            round_points(pt, ptf, 3);
+            round_points(pt, ptf, 4);
 
             Pie(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y, pt[2].x,
                 pt[2].y, pt[3].x, pt[3].y);
@@ -1793,6 +1798,13 @@ static void draw_cap(GpGraphics *graphics, COLORREF 
color, GpLineCap cap, REAL s
             if(!custom)
                 break;
 
+            if (custom->type == CustomLineCapTypeAdjustableArrow)
+            {
+                GpAdjustableArrowCap *arrow = (GpAdjustableArrowCap *)custom;
+                if (arrow->cap.fill && arrow->height <= 0.0)
+                    break;
+            }
+
             count = custom->pathdata.Count;
             custptf = heap_alloc_zero(count * sizeof(PointF));
             custpt = heap_alloc_zero(count * sizeof(POINT));
@@ -1810,9 +1822,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF 
color, GpLineCap cap, REAL s
             GdipTranslateMatrix(&matrix, x2, y2, MatrixOrderAppend);
             GdipTransformMatrixPoints(&matrix, custptf, count);
 
-            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, ptf, 3);
+            gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, 
CoordinateSpaceWorld, custptf, count);
 
-            round_points(pt, ptf, 3);
+            round_points(custpt, custptf, count);
 
             for(i = 0; i < count; i++)
                 tp[i] = convert_path_point_type(custom->pathdata.Types[i]);
@@ -6469,9 +6481,12 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics 
*graphics, REAL x, REAL y,
     if (status == Ok)
     {
         GpMatrix world_to_device;
+        BOOL identity;
 
         get_graphics_transform(graphics, CoordinateSpaceDevice, 
CoordinateSpaceWorld, &world_to_device);
-        status = GdipTransformRegion(region, &world_to_device);
+        status = GdipIsMatrixIdentity(&world_to_device, &identity);
+        if (status == Ok && !identity)
+            status = GdipTransformRegion(region, &world_to_device);
         if (status == Ok)
             status = GdipCombineRegionRegion(graphics->clip, region, mode);
 
@@ -6520,9 +6535,12 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics 
*graphics, GpRegion *region,
     if (status == Ok)
     {
         GpMatrix world_to_device;
+        BOOL identity;
 
         get_graphics_transform(graphics, CoordinateSpaceDevice, 
CoordinateSpaceWorld, &world_to_device);
-        status = GdipTransformRegion(clip, &world_to_device);
+        status = GdipIsMatrixIdentity(&world_to_device, &identity);
+        if (status == Ok && !identity)
+            status = GdipTransformRegion(clip, &world_to_device);
         if (status == Ok)
             status = GdipCombineRegionRegion(graphics->clip, clip, mode);
 
diff --git a/dll/win32/gdiplus/image.c b/dll/win32/gdiplus/image.c
index ff9bd9be7f..afa2afeac7 100644
--- a/dll/win32/gdiplus/image.c
+++ b/dll/win32/gdiplus/image.c
@@ -2560,7 +2560,7 @@ static UINT vt_to_itemtype(UINT vt)
         { VT_BLOB, PropertyTagTypeUndefined }
     };
     UINT i;
-    for (i = 0; i < sizeof(vt2type)/sizeof(vt2type[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(vt2type); i++)
     {
         if (vt2type[i].vt == vt) return vt2type[i].type;
     }
@@ -3460,10 +3460,10 @@ static void png_metadata_reader(GpBitmap *bitmap, 
IWICBitmapDecoder *decoder, UI
                         {
                             if (name.vt == VT_LPSTR)
                             {
-                                for (j=0; 
j<sizeof(keywords)/sizeof(keywords[0]); j++)
+                                for (j = 0; j < ARRAY_SIZE(keywords); j++)
                                     if (!strcmp(keywords[j].name, 
name.u.pszVal))
                                         break;
-                                if (j < sizeof(keywords)/sizeof(keywords[0]) 
&& !keywords[j].seen)
+                                if (j < ARRAY_SIZE(keywords) && 
!keywords[j].seen)
                                 {
                                     keywords[j].seen = TRUE;
                                     item = create_prop(keywords[j].propid, 
&value);
@@ -4586,7 +4586,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, 
IStream* stream,
     encode_image_func encode_image;
     int i;
 
-    TRACE("%p %p %s %p\n", image, stream, wine_dbgstr_guid(clsid), params);
+    TRACE("%p, %p, %s, %p\n", image, stream, wine_dbgstr_guid(clsid), params);
 
     if(!image || !stream)
         return InvalidParameter;
diff --git a/dll/win32/gdiplus/metafile.c b/dll/win32/gdiplus/metafile.c
index 77673a7ea3..08dde2fec6 100644
--- a/dll/win32/gdiplus/metafile.c
+++ b/dll/win32/gdiplus/metafile.c
@@ -606,7 +606,7 @@ void METAFILE_Free(GpMetafile *metafile)
     if (metafile->record_stream)
         IStream_Release(metafile->record_stream);
 
-    for (i = 0; i < sizeof(metafile->objtable)/sizeof(metafile->objtable[0]); 
i++)
+    for (i = 0; i < ARRAY_SIZE(metafile->objtable); i++)
         metafile_free_object_table_entry(metafile, i);
 }
 
diff --git a/dll/win32/gdiplus/pen.c b/dll/win32/gdiplus/pen.c
index 2c49371bd5..b86808b87e 100644
--- a/dll/win32/gdiplus/pen.c
+++ b/dll/win32/gdiplus/pen.c
@@ -460,17 +460,12 @@ GpStatus WINGDIPAPI GdipGetPenTransform(GpPen *pen, 
GpMatrix *matrix)
 
 GpStatus WINGDIPAPI GdipTranslatePenTransform(GpPen *pen, REAL dx, REAL dy, 
GpMatrixOrder order)
 {
-    static int calls;
-
     TRACE("(%p,%0.2f,%0.2f,%u)\n", pen, dx, dy, order);
 
     if(!pen)
         return InvalidParameter;
 
-    if(!(calls++))
-        FIXME("not implemented\n");
-
-    return NotImplemented;
+    return GdipTranslateMatrix(&pen->transform, dx, dy, order);
 }
 
 GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, 
GpMatrixOrder order)
diff --git a/dll/win32/gdiplus/region.c b/dll/win32/gdiplus/region.c
index 8eb3ff3535..470bcd20ce 100644
--- a/dll/win32/gdiplus/region.c
+++ b/dll/win32/gdiplus/region.c
@@ -1398,10 +1398,46 @@ static GpStatus 
transform_region_element(region_element* element, GpMatrix *matr
             return Ok;
         case RegionDataRect:
         {
-            /* We can't transform a rectangle, so convert it to a path. */
             GpRegion *new_region;
             GpPath *path;
 
+            if (matrix->matrix[1] == 0.0 && matrix->matrix[2] == 0.0)
+            {
+                GpPointF points[2];
+
+                points[0].X = element->elementdata.rect.X;
+                points[0].Y = element->elementdata.rect.Y;
+                points[1].X = element->elementdata.rect.X + 
element->elementdata.rect.Width;
+                points[1].Y = element->elementdata.rect.Y + 
element->elementdata.rect.Height;
+
+                stat = GdipTransformMatrixPoints(matrix, points, 2);
+                if (stat != Ok)
+                    return stat;
+
+                if (points[0].X > points[1].X)
+                {
+                    REAL temp;
+                    temp = points[0].X;
+                    points[0].X = points[1].X;
+                    points[1].X = temp;
+                }
+
+                if (points[0].Y > points[1].Y)
+                {
+                    REAL temp;
+                    temp = points[0].Y;
+                    points[0].Y = points[1].Y;
+                    points[1].Y = temp;
+                }
+
+                element->elementdata.rect.X = points[0].X;
+                element->elementdata.rect.Y = points[0].Y;
+                element->elementdata.rect.Width = points[1].X - points[0].X;
+                element->elementdata.rect.Height = points[1].Y - points[0].Y;
+                return Ok;
+            }
+
+            /* We can't rotate/shear a rectangle, so convert it to a path. */
             stat = GdipCreatePath(FillModeAlternate, &path);
             if (stat == Ok)
             {
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 08dcf59cac..e17deddf22 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -68,7 +68,7 @@ reactos/dll/win32/dciman32            # Synced to 
WineStaging-3.3
 reactos/dll/win32/faultrep            # Synced to WineStaging-2.9
 reactos/dll/win32/fontsub             # Synced to WineStaging-2.9
 reactos/dll/win32/fusion              # Synced to WineStaging-3.3
-reactos/dll/win32/gdiplus             # Synced to WineStaging-3.3
+reactos/dll/win32/gdiplus             # Synced to WineStaging-3.9
 reactos/dll/win32/hhctrl.ocx          # Synced to WineStaging-3.3
 reactos/dll/win32/hlink               # Synced to WineStaging-3.3
 reactos/dll/win32/hnetcfg             # Synced to WineStaging-3.3

Reply via email to