Vincent Povirk : gdiplus: Implement BeginContainer metafile record.
Alexandre Julliard
julliard at winehq.org
Mon Sep 19 10:32:12 CDT 2016
Module: wine
Branch: master
Commit: 410163a9f2b03fcc16e8e65975647492ac5b938e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=410163a9f2b03fcc16e8e65975647492ac5b938e
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Fri Sep 16 14:37:29 2016 -0500
gdiplus: Implement BeginContainer metafile record.
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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);
More information about the wine-cvs
mailing list