gdiplus: Implement BeginContainer metafile record.

Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Vincent Povirk 2016-09-16 14:37:29 -05:00 committed by Alexandre Julliard
parent 18964c9665
commit 410163a9f2
4 changed files with 136 additions and 1 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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:
{

View File

@ -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);