gdiplus: Implement GdipPlayMetafileRecord for EMF records.
This commit is contained in:
parent
3a6ba94011
commit
fda2fc7684
|
@ -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{
|
||||
|
|
|
@ -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);
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue