Module: wine Branch: master Commit: 410163a9f2b03fcc16e8e65975647492ac5b938e URL: http://source.winehq.org/git/wine.git/?a=commit;h=410163a9f2b03fcc16e8e65975...
Author: Vincent Povirk vincent@codeweavers.com Date: Fri Sep 16 14:37:29 2016 -0500
gdiplus: Implement BeginContainer metafile record.
Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/gdiplus/gdiplus_private.h | 2 + dlls/gdiplus/graphics.c | 2 +- dlls/gdiplus/metafile.c | 89 ++++++++++++++++++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 44 +++++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 216dd4a..86a29a0 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -101,6 +101,8 @@ extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect, + GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 06a0c95..4ae1f48 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -5236,7 +5236,7 @@ GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF * GdipMultiplyMatrix(&graphics->worldtrans, &transform, MatrixOrderPrepend);
if (graphics->image && graphics->image->type == ImageTypeMetafile) { - FIXME("Write to metafile\n"); + METAFILE_BeginContainer((GpMetafile*)graphics->image, dstrect, srcrect, unit, container->contid); }
return Ok; diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index c0e799c..9de584c 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -122,6 +122,14 @@ typedef struct EmfPlusTranslateWorldTransform REAL dy; } EmfPlusTranslateWorldTransform;
+typedef struct EmfPlusBeginContainer +{ + EmfPlusRecordHeader Header; + GpRectF DestRect; + GpRectF SrcRect; + DWORD StackIndex; +} EmfPlusBeginContainer; + typedef struct EmfPlusContainerRecord { EmfPlusRecordHeader Header; @@ -782,6 +790,30 @@ GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) return Ok; }
+GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect, + GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusBeginContainer *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, sizeof(*record), (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeBeginContainer; + record->Header.Flags = unit & 0xff; + record->DestRect = *dstrect; + record->SrcRect = *srcrect; + record->StackIndex = StackIndex; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) { if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) @@ -1309,6 +1341,63 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
return METAFILE_PlaybackUpdateWorldTransform(real_metafile); } + case EmfPlusRecordTypeBeginContainer: + { + EmfPlusBeginContainer *record = (EmfPlusBeginContainer*)header; + container* cont; + GpUnit unit; + REAL scale_x, scale_y; + GpRectF scaled_srcrect; + GpMatrix transform; + + cont = heap_alloc_zero(sizeof(*cont)); + if (!cont) + return OutOfMemory; + + stat = GdipCloneRegion(metafile->clip, &cont->clip); + if (stat != Ok) + { + heap_free(cont); + return stat; + } + + GdipBeginContainer2(metafile->playback_graphics, &cont->state); + + if (stat != Ok) + { + GdipDeleteRegion(cont->clip); + heap_free(cont); + return stat; + } + + cont->id = record->StackIndex; + cont->type = BEGIN_CONTAINER; + cont->world_transform = *metafile->world_transform; + cont->page_unit = metafile->page_unit; + cont->page_scale = metafile->page_scale; + list_add_head(&real_metafile->containers, &cont->entry); + + unit = record->Header.Flags & 0xff; + + scale_x = units_to_pixels(1.0, unit, metafile->image.xres); + scale_y = units_to_pixels(1.0, unit, metafile->image.yres); + + scaled_srcrect.X = scale_x * record->SrcRect.X; + scaled_srcrect.Y = scale_y * record->SrcRect.Y; + scaled_srcrect.Width = scale_x * record->SrcRect.Width; + scaled_srcrect.Height = scale_y * record->SrcRect.Height; + + transform.matrix[0] = record->DestRect.Width / scaled_srcrect.Width; + transform.matrix[1] = 0.0; + transform.matrix[2] = 0.0; + transform.matrix[3] = record->DestRect.Height / scaled_srcrect.Height; + transform.matrix[4] = record->DestRect.X - scaled_srcrect.X; + transform.matrix[5] = record->DestRect.Y - scaled_srcrect.Y; + + GdipMultiplyMatrix(real_metafile->world_transform, &transform, MatrixOrderPrepend); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } case EmfPlusRecordTypeBeginContainerNoParams: case EmfPlusRecordTypeSave: { diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 6a21afa..60890d9 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -1846,6 +1846,9 @@ static const emfplus_record container_records[] = { {0, EmfPlusRecordTypeBeginContainerNoParams}, {0, EmfPlusRecordTypeEndContainer}, {0, EmfPlusRecordTypeFillRects}, + {0, EmfPlusRecordTypeBeginContainer}, + {0, EmfPlusRecordTypeFillRects}, + {0, EmfPlusRecordTypeEndContainer}, {0, EmfPlusRecordTypeBeginContainerNoParams}, {0, EmfPlusRecordTypeEndOfFile}, {0, EMR_EOF}, @@ -1865,6 +1868,8 @@ static void test_containers(void) static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}}; static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0}; GraphicsContainer state1, state2; + GpRectF srcrect, dstrect; + REAL dpix, dpiy;
hdc = CreateCompatibleDC(0);
@@ -1938,6 +1943,41 @@ static void test_containers(void) stat = GdipFillRectangle(graphics, brush, 20.0, 20.0, 5.0, 5.0); expect(Ok, stat);
+ stat = GdipDeleteBrush(brush); + expect(Ok, stat); + + /* With transform applied */ + stat = GdipGetDpiX(graphics, &dpix); + expect(Ok, stat); + + stat = GdipGetDpiY(graphics, &dpiy); + expect(Ok, stat); + + srcrect.X = 0.0; + srcrect.Y = 0.0; + srcrect.Width = 1.0; + srcrect.Height = 1.0; + + dstrect.X = 25.0; + dstrect.Y = 0.0; + dstrect.Width = 5.0; + dstrect.Height = 5.0; + + stat = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state1); + expect(Ok, stat); + + stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush); + expect(Ok, stat); + + stat = GdipFillRectangle(graphics, brush, 0.0, 0.0, dpix, dpiy); + expect(Ok, stat); + + stat = GdipDeleteBrush(brush); + expect(Ok, stat); + + stat = GdipEndContainer(graphics, state1); + expect(Ok, stat); + /* Restoring an invalid state seems to break the graphics object? */ if (0) { stat = GdipEndContainer(graphics, state1); @@ -1979,6 +2019,10 @@ static void test_containers(void) expect(Ok, stat); expect(0xff00ff00, color);
+ stat = GdipBitmapGetPixel(bitmap, 55, 5, &color); + expect(Ok, stat); + expect(0xff00ffff, color); + stat = GdipDeleteGraphics(graphics); expect(Ok, stat);