gdiplus: Implement GdipPlayMetafileRecord for EMF records.
This commit is contained in:
parent
3a6ba94011
commit
fda2fc7684
|
@ -274,12 +274,21 @@ struct GpMetafile{
|
||||||
GpRectF bounds;
|
GpRectF bounds;
|
||||||
GpUnit unit;
|
GpUnit unit;
|
||||||
MetafileType metafile_type;
|
MetafileType metafile_type;
|
||||||
|
HENHMETAFILE hemf;
|
||||||
|
|
||||||
|
/* recording */
|
||||||
HDC record_dc;
|
HDC record_dc;
|
||||||
GpGraphics *record_graphics;
|
GpGraphics *record_graphics;
|
||||||
BYTE *comment_data;
|
BYTE *comment_data;
|
||||||
DWORD comment_data_size;
|
DWORD comment_data_size;
|
||||||
DWORD comment_data_length;
|
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{
|
struct GpBitmap{
|
||||||
|
|
|
@ -357,18 +357,100 @@ GpStatus WINGDIPAPI GdipGetHemfFromMetafile(GpMetafile *metafile, HENHMETAFILE *
|
||||||
return Ok;
|
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,
|
GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
||||||
EmfPlusRecordType recordType, UINT flags, UINT dataSize, GDIPCONST BYTE *data)
|
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);
|
||||||
|
|
||||||
return NotImplemented;
|
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);
|
||||||
|
|
||||||
|
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
|
struct enum_metafile_data
|
||||||
{
|
{
|
||||||
EnumerateMetafileProc callback;
|
EnumerateMetafileProc callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
|
GpMetafile *metafile;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int CALLBACK enum_metafile_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
|
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;
|
struct enum_metafile_data *data = (struct enum_metafile_data*)lpData;
|
||||||
const BYTE* pStr;
|
const BYTE* pStr;
|
||||||
|
|
||||||
|
data->metafile->handle_table = lpHTable;
|
||||||
|
data->metafile->handle_count = nObj;
|
||||||
|
|
||||||
/* First check for an EMF+ record. */
|
/* First check for an EMF+ record. */
|
||||||
if (lpEMFR->iType == EMR_GDICOMMENT)
|
if (lpEMFR->iType == EMR_GDICOMMENT)
|
||||||
{
|
{
|
||||||
|
@ -424,6 +509,8 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
|
||||||
VOID *callbackData, GDIPCONST GpImageAttributes *imageAttributes)
|
VOID *callbackData, GDIPCONST GpImageAttributes *imageAttributes)
|
||||||
{
|
{
|
||||||
struct enum_metafile_data data;
|
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,
|
TRACE("(%p,%p,%p,%i,%p,%i,%p,%p,%p)\n", graphics, metafile,
|
||||||
destPoints, count, srcRect, srcUnit, callback, callbackData,
|
destPoints, count, srcRect, srcUnit, callback, callbackData,
|
||||||
|
@ -435,14 +522,32 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
|
||||||
if (!metafile->hemf)
|
if (!metafile->hemf)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
|
if (metafile->playback_graphics)
|
||||||
|
return ObjectBusy;
|
||||||
|
|
||||||
TRACE("%s %i -> %s %s %s\n", debugstr_rectf(srcRect), srcUnit,
|
TRACE("%s %i -> %s %s %s\n", debugstr_rectf(srcRect), srcUnit,
|
||||||
debugstr_pointf(&destPoints[0]), debugstr_pointf(&destPoints[1]),
|
debugstr_pointf(&destPoints[0]), debugstr_pointf(&destPoints[1]),
|
||||||
debugstr_pointf(&destPoints[2]));
|
debugstr_pointf(&destPoints[2]));
|
||||||
|
|
||||||
data.callback = callback;
|
data.callback = callback;
|
||||||
data.callback_data = callbackData;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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].record_type)
|
||||||
{
|
{
|
||||||
if (state->expected[state->count].playback_todo)
|
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
|
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++;
|
state->count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -324,16 +324,16 @@ static void test_empty(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const emfplus_record getdc_records[] = {
|
static const emfplus_record getdc_records[] = {
|
||||||
{0, EMR_HEADER, 1},
|
{0, EMR_HEADER},
|
||||||
{0, EmfPlusRecordTypeHeader, 1},
|
{0, EmfPlusRecordTypeHeader},
|
||||||
{0, EmfPlusRecordTypeGetDC, 1},
|
{0, EmfPlusRecordTypeGetDC},
|
||||||
{0, EMR_CREATEBRUSHINDIRECT, 1},
|
{0, EMR_CREATEBRUSHINDIRECT},
|
||||||
{0, EMR_SELECTOBJECT, 1},
|
{0, EMR_SELECTOBJECT},
|
||||||
{0, EMR_RECTANGLE, 1},
|
{0, EMR_RECTANGLE},
|
||||||
{0, EMR_SELECTOBJECT, 1},
|
{0, EMR_SELECTOBJECT},
|
||||||
{0, EMR_DELETEOBJECT, 1},
|
{0, EMR_DELETEOBJECT},
|
||||||
{0, EmfPlusRecordTypeEndOfFile, 1},
|
{0, EmfPlusRecordTypeEndOfFile},
|
||||||
{0, EMR_EOF, 1},
|
{0, EMR_EOF},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ static void test_getdc(void)
|
||||||
|
|
||||||
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
todo_wine expect(0xff0000ff, color);
|
expect(0xff0000ff, color);
|
||||||
|
|
||||||
stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
|
stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
|
@ -420,7 +420,7 @@ static void test_getdc(void)
|
||||||
|
|
||||||
stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
|
stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
todo_wine expect(0xff0000ff, color);
|
expect(0xff0000ff, color);
|
||||||
|
|
||||||
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
|
@ -445,13 +445,13 @@ static void test_getdc(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const emfplus_record emfonly_records[] = {
|
static const emfplus_record emfonly_records[] = {
|
||||||
{0, EMR_HEADER, 1},
|
{0, EMR_HEADER},
|
||||||
{0, EMR_CREATEBRUSHINDIRECT, 1},
|
{0, EMR_CREATEBRUSHINDIRECT},
|
||||||
{0, EMR_SELECTOBJECT, 1},
|
{0, EMR_SELECTOBJECT},
|
||||||
{0, EMR_RECTANGLE, 1},
|
{0, EMR_RECTANGLE},
|
||||||
{0, EMR_SELECTOBJECT, 1},
|
{0, EMR_SELECTOBJECT},
|
||||||
{0, EMR_DELETEOBJECT, 1},
|
{0, EMR_DELETEOBJECT},
|
||||||
{0, EMR_EOF, 1},
|
{0, EMR_EOF},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ static void test_emfonly(void)
|
||||||
|
|
||||||
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
todo_wine expect(0xff0000ff, color);
|
expect(0xff0000ff, color);
|
||||||
|
|
||||||
stat = GdipDeleteGraphics(graphics);
|
stat = GdipDeleteGraphics(graphics);
|
||||||
expect(Ok, stat);
|
expect(Ok, stat);
|
||||||
|
|
Loading…
Reference in New Issue