From cfae34a7e20b3fc6ce26b08766822ad3e715a9ab Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 5 Aug 2016 16:14:38 -0500 Subject: [PATCH] gdiplus: Implement recording/playback for RotateWorldTransform. Signed-off-by: Vincent Povirk Signed-off-by: Alexandre Julliard --- dlls/gdiplus/gdiplus_private.h | 1 + dlls/gdiplus/graphics.c | 9 ++++++++ dlls/gdiplus/metafile.c | 41 ++++++++++++++++++++++++++++++++++ dlls/gdiplus/tests/metafile.c | 31 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 65135f8330f..e42e429e068 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -92,6 +92,7 @@ extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush, extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 9b0d9b5e049..5cab9cb186d 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -5156,6 +5156,8 @@ GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState stat GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, GpMatrixOrder order) { + GpStatus stat; + TRACE("(%p, %.2f, %d)\n", graphics, angle, order); if(!graphics) @@ -5164,6 +5166,13 @@ GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, if(graphics->busy) return ObjectBusy; + if (graphics->image && graphics->image->type == ImageTypeMetafile) { + stat = METAFILE_RotateWorldTransform((GpMetafile*)graphics->image, angle, order); + + if (stat != Ok) + return stat; + } + return GdipRotateMatrix(&graphics->worldtrans, angle, order); } diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 8d4002ccaaf..aa0da214e0d 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -97,6 +97,12 @@ typedef struct EmfPlusMultiplyWorldTransform REAL MatrixData[6]; } EmfPlusMultiplyWorldTransform; +typedef struct EmfPlusRotateWorldTransform +{ + EmfPlusRecordHeader Header; + REAL Angle; +} EmfPlusRotateWorldTransform; + static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result) { DWORD size_needed; @@ -615,6 +621,29 @@ GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatri return Ok; } +GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusRotateWorldTransform *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusRotateWorldTransform), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeRotateWorldTransform; + record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0); + record->Angle = angle; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) { if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) @@ -1001,6 +1030,18 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, return METAFILE_PlaybackUpdateWorldTransform(real_metafile); } + case EmfPlusRecordTypeRotateWorldTransform: + { + EmfPlusRotateWorldTransform *record = (EmfPlusRotateWorldTransform*)header; + MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusRotateWorldTransform)) + return InvalidParameter; + + GdipRotateMatrix(real_metafile->world_transform, record->Angle, order); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } case EmfPlusRecordTypeResetWorldTransform: { GdipSetMatrixElements(real_metafile->world_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c index 98b3f3e0671..67e2b9d8cdc 100644 --- a/dlls/gdiplus/tests/metafile.c +++ b/dlls/gdiplus/tests/metafile.c @@ -1294,6 +1294,8 @@ static const emfplus_record worldtransform_records[] = { {0, EmfPlusRecordTypeFillRects}, {0, EmfPlusRecordTypeMultiplyWorldTransform}, {0, EmfPlusRecordTypeFillRects}, + {0, EmfPlusRecordTypeRotateWorldTransform}, + {0, EmfPlusRecordTypeFillRects}, {0, EmfPlusRecordTypeEndOfFile}, {0, EMR_EOF}, {0} @@ -1421,6 +1423,31 @@ static void test_worldtransform(void) stat = GdipDeleteBrush(brush); expect(Ok, stat); + /* rotate transform */ + stat = GdipRotateWorldTransform(graphics, 90.0, MatrixOrderAppend); + expect(Ok, stat); + + stat = GdipGetWorldTransform(graphics, transform); + expect(Ok, stat); + + stat = GdipGetMatrixElements(transform, elements); + expect(Ok, stat); + expectf(0.0, elements[0]); + expectf(2.0, elements[1]); + expectf(-1.0, elements[2]); + expectf(0.0, elements[3]); + expectf(0.0, elements[4]); + expectf(0.0, elements[5]); + + stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush); + expect(Ok, stat); + + stat = GdipFillRectangle(graphics, brush, 1.0, -1.0, 0.5, 1.0); + expect(Ok, stat); + + stat = GdipDeleteBrush(brush); + expect(Ok, stat); + stat = GdipDeleteMatrix(transform); expect(Ok, stat); @@ -1459,6 +1486,10 @@ static void test_worldtransform(void) expect(Ok, stat); expect(0xffff0000, color); + stat = GdipBitmapGetPixel(bitmap, 10, 50, &color); + expect(Ok, stat); + expect(0xffff00ff, color); + stat = GdipDeleteGraphics(graphics); expect(Ok, stat);