https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6619d0261f266a3e7cec77...
commit 6619d0261f266a3e7cec775a6b227daf3a352540 Author: Amine Khaldi amine.khaldi@reactos.org AuthorDate: Sun May 27 04:10:39 2018 +0100 Commit: Amine Khaldi amine.khaldi@reactos.org 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