Module: wine Branch: master Commit: 3f6faddd565b3465c17da6748e069a3ceb320316 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f6faddd565b3465c17da6748e...
Author: Vincent Povirk vincent@codeweavers.com Date: Tue Aug 16 16:00:26 2016 -0500
gdiplus: Implement playback/recording for SetClipRect.
Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/gdiplus/gdiplus_private.h | 6 +++ dlls/gdiplus/graphics.c | 12 ++++-- dlls/gdiplus/metafile.c | 83 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 4ad49ca..678daed 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -81,6 +81,9 @@ extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN; extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN; extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
+extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, + GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN; + extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN; @@ -89,6 +92,8 @@ extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDE extern GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN; extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush, GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile, + REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN; @@ -372,6 +377,7 @@ struct GpMetafile{ GpUnit page_unit; REAL page_scale; GpRegion *base_clip; /* clip region in device space for all metafile output */ + GpRegion *clip; /* clip region within the metafile */ struct list containers; };
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 370fa88..84afee1 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -51,9 +51,6 @@ static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix);
-static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, - GpCoordinateSpace src_space, GpMatrix *matrix); - /* Converts from gdiplus path point type to gdi path point type. */ static BYTE convert_path_point_type(BYTE type) { @@ -5642,6 +5639,13 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y, if(graphics->busy) return ObjectBusy;
+ if (graphics->image && graphics->image->type == ImageTypeMetafile) + { + status = METAFILE_SetClipRect((GpMetafile*)graphics->image, x, y, width, height, mode); + if (status != Ok) + return status; + } + rect.X = x; rect.Y = y; rect.Width = width; @@ -5983,7 +5987,7 @@ GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region) return Ok; }
-static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, +GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix) { GpStatus stat = Ok; diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index a854e55..02cacb2 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -70,6 +70,12 @@ typedef struct EmfPlusFillRects DWORD Count; } EmfPlusFillRects;
+typedef struct EmfPlusSetClipRect +{ + EmfPlusRecordHeader Header; + GpRectF ClipRect; +} EmfPlusSetClipRect; + typedef struct EmfPlusSetPageTransform { EmfPlusRecordHeader Header; @@ -137,6 +143,7 @@ typedef struct container GpMatrix world_transform; GpUnit page_unit; REAL page_scale; + GpRegion *clip; } container;
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result) @@ -588,6 +595,32 @@ GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush, return Ok; }
+GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width, REAL height, CombineMode mode) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusSetClipRect *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusSetClipRect), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeSetClipRect; + record->Header.Flags = (mode & 0xf) << 8; + record->ClipRect.X = x; + record->ClipRect.Y = y; + record->ClipRect.Width = width; + record->ClipRect.Height = height; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) { if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) @@ -1014,7 +1047,11 @@ static void METAFILE_PlaybackReleaseDC(GpMetafile *metafile)
static GpStatus METAFILE_PlaybackUpdateClip(GpMetafile *metafile) { - return GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace); + GpStatus stat; + stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace); + if (stat == Ok) + stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->clip, CombineModeIntersect); + return stat; }
static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile) @@ -1166,6 +1203,32 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
return stat; } + case EmfPlusRecordTypeSetClipRect: + { + EmfPlusSetClipRect *record = (EmfPlusSetClipRect*)header; + CombineMode mode = (CombineMode)((flags >> 8) & 0xf); + GpRegion *region; + GpMatrix world_to_device; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(*record)) + return InvalidParameter; + + stat = GdipCreateRegionRect(&record->ClipRect, ®ion); + + if (stat == Ok) + { + get_graphics_transform(real_metafile->playback_graphics, + CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device); + + GdipTransformRegion(region, &world_to_device); + + GdipCombineRegionRegion(real_metafile->clip, region, mode); + + GdipDeleteRegion(region); + } + + return METAFILE_PlaybackUpdateClip(real_metafile); + } case EmfPlusRecordTypeSetPageTransform: { EmfPlusSetPageTransform *record = (EmfPlusSetPageTransform*)header; @@ -1257,6 +1320,13 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, if (!cont) return OutOfMemory;
+ stat = GdipCloneRegion(metafile->clip, &cont->clip); + if (stat != Ok) + { + heap_free(cont); + return stat; + } + if (recordType == EmfPlusRecordTypeBeginContainerNoParams) stat = GdipBeginContainer2(metafile->playback_graphics, &cont->state); else @@ -1264,6 +1334,7 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
if (stat != Ok) { + GdipDeleteRegion(cont->clip); heap_free(cont); return stat; } @@ -1310,6 +1381,7 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, while ((cont2 = LIST_ENTRY(list_head(&real_metafile->containers), container, entry)) != cont) { list_remove(&cont2->entry); + GdipDeleteRegion(cont2->clip); heap_free(cont2); }
@@ -1321,8 +1393,10 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, *real_metafile->world_transform = cont->world_transform; real_metafile->page_unit = cont->page_unit; real_metafile->page_scale = cont->page_scale; + GdipCombineRegionRegion(real_metafile->clip, cont->clip, CombineModeReplace);
list_remove(&cont->entry); + GdipDeleteRegion(cont->clip); heap_free(cont); }
@@ -1453,6 +1527,9 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics, stat = GdipGetClip(graphics, real_metafile->base_clip);
if (stat == Ok) + stat = GdipCreateRegion(&real_metafile->clip); + + if (stat == Ok) stat = GdipCreatePath(FillModeAlternate, &dst_path);
if (stat == Ok) @@ -1506,10 +1583,14 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics, GdipDeleteRegion(real_metafile->base_clip); real_metafile->base_clip = NULL;
+ GdipDeleteRegion(real_metafile->clip); + real_metafile->clip = NULL; + while (list_head(&real_metafile->containers)) { container* cont = LIST_ENTRY(list_head(&real_metafile->containers), container, entry); list_remove(&cont->entry); + GdipDeleteRegion(cont->clip); heap_free(cont); }