Vincent Povirk : gdiplus: Implement GdipPlayMetafileRecord for EMF records.
Alexandre Julliard
julliard at winehq.org
Fri Jul 8 11:23:41 CDT 2011
Module: wine
Branch: master
Commit: fda2fc7684bc73a1dc89cad53e0a05bfee5c2826
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fda2fc7684bc73a1dc89cad53e0a05bfee5c2826
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Thu Jul 7 16:25:25 2011 -0500
gdiplus: Implement GdipPlayMetafileRecord for EMF records.
---
dlls/gdiplus/gdiplus_private.h | 11 ++++-
dlls/gdiplus/metafile.c | 113 ++++++++++++++++++++++++++++++++++++++--
dlls/gdiplus/tests/metafile.c | 44 ++++++++--------
3 files changed, 141 insertions(+), 27 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index d6888d9..9afe15b 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -274,12 +274,21 @@ struct GpMetafile{
GpRectF bounds;
GpUnit unit;
MetafileType metafile_type;
+ HENHMETAFILE hemf;
+
+ /* recording */
HDC record_dc;
GpGraphics *record_graphics;
BYTE *comment_data;
DWORD comment_data_size;
DWORD comment_data_length;
- HENHMETAFILE hemf;
+
+ /* playback */
+ GpGraphics *playback_graphics;
+ HDC playback_dc;
+ GpPointF playback_points[3];
+ HANDLETABLE *handle_table;
+ int handle_count;
};
struct GpBitmap{
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index 3e79eb7..38923a0 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -357,18 +357,100 @@ GpStatus WINGDIPAPI GdipGetHemfFromMetafile(GpMetafile *metafile, HENHMETAFILE *
return Ok;
}
+static GpStatus METAFILE_PlaybackGetDC(GpMetafile *metafile)
+{
+ GpStatus stat = Ok;
+
+ stat = GdipGetDC(metafile->playback_graphics, &metafile->playback_dc);
+
+ if (stat == Ok)
+ {
+ /* The result of GdipGetDC always expects device co-ordinates, but the
+ * device co-ordinates of the source metafile do not correspond to
+ * device co-ordinates of the destination. Therefore, we set up the DC
+ * so that the metafile's bounds map to the destination points where we
+ * are drawing this metafile. */
+ SetMapMode(metafile->playback_dc, MM_ANISOTROPIC);
+
+ SetWindowOrgEx(metafile->playback_dc, metafile->bounds.X, metafile->bounds.Y, NULL);
+ SetWindowExtEx(metafile->playback_dc, metafile->bounds.Width, metafile->bounds.Height, NULL);
+
+ SetViewportOrgEx(metafile->playback_dc, metafile->playback_points[0].X, metafile->playback_points[0].Y, NULL);
+ SetViewportExtEx(metafile->playback_dc,
+ metafile->playback_points[1].X - metafile->playback_points[0].X,
+ metafile->playback_points[2].Y - metafile->playback_points[0].Y, NULL);
+ }
+
+ return stat;
+}
+
+static void METAFILE_PlaybackReleaseDC(GpMetafile *metafile)
+{
+ if (metafile->playback_dc)
+ {
+ GdipReleaseDC(metafile->playback_graphics, metafile->playback_dc);
+ metafile->playback_dc = NULL;
+ }
+}
+
GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
EmfPlusRecordType recordType, UINT flags, UINT dataSize, GDIPCONST BYTE *data)
{
- FIXME("(%p,%x,%x,%d,%p)\n", metafile, recordType, flags, dataSize, data);
+ TRACE("(%p,%x,%x,%d,%p)\n", metafile, recordType, flags, dataSize, data);
+
+ if (!metafile || (dataSize && !data) || !metafile->playback_graphics)
+ return InvalidParameter;
+
+ if (recordType >= 1 && recordType <= 0x7a)
+ {
+ /* regular EMF record */
+ if (metafile->playback_dc)
+ {
+ ENHMETARECORD *record;
+
+ record = GdipAlloc(dataSize + 8);
+
+ if (record)
+ {
+ record->iType = recordType;
+ record->nSize = dataSize;
+ memcpy(record->dParm, data, dataSize);
- return NotImplemented;
+ PlayEnhMetaFileRecord(metafile->playback_dc, metafile->handle_table,
+ record, metafile->handle_count);
+
+ GdipFree(record);
+ }
+ else
+ return OutOfMemory;
+ }
+ }
+ else
+ {
+ METAFILE_PlaybackReleaseDC((GpMetafile*)metafile);
+
+ switch(recordType)
+ {
+ case EmfPlusRecordTypeHeader:
+ case EmfPlusRecordTypeEndOfFile:
+ break;
+ case EmfPlusRecordTypeGetDC:
+ METAFILE_PlaybackGetDC((GpMetafile*)metafile);
+ break;
+ default:
+ FIXME("Not implemented for record type %x\n", recordType);
+ return NotImplemented;
+ }
+ }
+
+ return Ok;
}
struct enum_metafile_data
{
EnumerateMetafileProc callback;
void *callback_data;
+ GpMetafile *metafile;
};
static int CALLBACK enum_metafile_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
@@ -378,6 +460,9 @@ static int CALLBACK enum_metafile_proc(HDC hDC, HANDLETABLE *lpHTable, const ENH
struct enum_metafile_data *data = (struct enum_metafile_data*)lpData;
const BYTE* pStr;
+ data->metafile->handle_table = lpHTable;
+ data->metafile->handle_count = nObj;
+
/* First check for an EMF+ record. */
if (lpEMFR->iType == EMR_GDICOMMENT)
{
@@ -424,6 +509,8 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
VOID *callbackData, GDIPCONST GpImageAttributes *imageAttributes)
{
struct enum_metafile_data data;
+ GpStatus stat;
+ GpMetafile *real_metafile = (GpMetafile*)metafile; /* whoever made this const was joking */
TRACE("(%p,%p,%p,%i,%p,%i,%p,%p,%p)\n", graphics, metafile,
destPoints, count, srcRect, srcUnit, callback, callbackData,
@@ -435,14 +522,32 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
if (!metafile->hemf)
return InvalidParameter;
+ if (metafile->playback_graphics)
+ return ObjectBusy;
+
TRACE("%s %i -> %s %s %s\n", debugstr_rectf(srcRect), srcUnit,
debugstr_pointf(&destPoints[0]), debugstr_pointf(&destPoints[1]),
debugstr_pointf(&destPoints[2]));
data.callback = callback;
data.callback_data = callbackData;
+ data.metafile = real_metafile;
- EnumEnhMetaFile(0, metafile->hemf, enum_metafile_proc, &data, NULL);
+ real_metafile->playback_graphics = graphics;
+ real_metafile->playback_dc = NULL;
- return Ok;
+ memcpy(real_metafile->playback_points, destPoints, sizeof(PointF) * 3);
+ stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, real_metafile->playback_points, 3);
+
+ if (stat == Ok && metafile->metafile_type == MetafileTypeEmf)
+ stat = METAFILE_PlaybackGetDC((GpMetafile*)metafile);
+
+ if (stat == Ok)
+ EnumEnhMetaFile(0, metafile->hemf, enum_metafile_proc, &data, NULL);
+
+ METAFILE_PlaybackReleaseDC((GpMetafile*)metafile);
+
+ real_metafile->playback_graphics = NULL;
+
+ return stat;
}
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index 5323751..9530b0c 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -212,9 +212,9 @@ static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned
if (state->expected[state->count].record_type)
{
if (state->expected[state->count].playback_todo)
- todo_wine ok(stat == Ok, "%s: GdipPlayMetafileRecord failed with stat %i\n", state->desc, stat);
+ todo_wine ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
else
- ok(stat == Ok, "%s: GdipPlayMetafileRecord failed with stat %i\n", state->desc, stat);
+ ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
state->count++;
}
else
@@ -324,16 +324,16 @@ static void test_empty(void)
}
static const emfplus_record getdc_records[] = {
- {0, EMR_HEADER, 1},
- {0, EmfPlusRecordTypeHeader, 1},
- {0, EmfPlusRecordTypeGetDC, 1},
- {0, EMR_CREATEBRUSHINDIRECT, 1},
- {0, EMR_SELECTOBJECT, 1},
- {0, EMR_RECTANGLE, 1},
- {0, EMR_SELECTOBJECT, 1},
- {0, EMR_DELETEOBJECT, 1},
- {0, EmfPlusRecordTypeEndOfFile, 1},
- {0, EMR_EOF, 1},
+ {0, EMR_HEADER},
+ {0, EmfPlusRecordTypeHeader},
+ {0, EmfPlusRecordTypeGetDC},
+ {0, EMR_CREATEBRUSHINDIRECT},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_RECTANGLE},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_DELETEOBJECT},
+ {0, EmfPlusRecordTypeEndOfFile},
+ {0, EMR_EOF},
{0}
};
@@ -411,7 +411,7 @@ static void test_getdc(void)
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
expect(Ok, stat);
- todo_wine expect(0xff0000ff, color);
+ expect(0xff0000ff, color);
stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
expect(Ok, stat);
@@ -420,7 +420,7 @@ static void test_getdc(void)
stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
expect(Ok, stat);
- todo_wine expect(0xff0000ff, color);
+ expect(0xff0000ff, color);
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
expect(Ok, stat);
@@ -445,13 +445,13 @@ static void test_getdc(void)
}
static const emfplus_record emfonly_records[] = {
- {0, EMR_HEADER, 1},
- {0, EMR_CREATEBRUSHINDIRECT, 1},
- {0, EMR_SELECTOBJECT, 1},
- {0, EMR_RECTANGLE, 1},
- {0, EMR_SELECTOBJECT, 1},
- {0, EMR_DELETEOBJECT, 1},
- {0, EMR_EOF, 1},
+ {0, EMR_HEADER},
+ {0, EMR_CREATEBRUSHINDIRECT},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_RECTANGLE},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_DELETEOBJECT},
+ {0, EMR_EOF},
{0}
};
@@ -528,7 +528,7 @@ static void test_emfonly(void)
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
expect(Ok, stat);
- todo_wine expect(0xff0000ff, color);
+ expect(0xff0000ff, color);
stat = GdipDeleteGraphics(graphics);
expect(Ok, stat);
More information about the wine-cvs
mailing list