Module: wine Branch: master Commit: 91a3e5fc10b7fb0faae5498ae8bfb0d83478514b URL: http://source.winehq.org/git/wine.git/?a=commit;h=91a3e5fc10b7fb0faae5498ae8...
Author: Vincent Povirk vincent@codeweavers.com Date: Wed Oct 31 15:37:16 2012 -0500
gdiplus: Reimplement GdipCreateMetafileFromEmf without using IPicture.
---
dlls/gdiplus/gdiplus_private.h | 2 + dlls/gdiplus/graphics.c | 70 ++++++++++++++++------------------------ dlls/gdiplus/image.c | 3 +- dlls/gdiplus/metafile.c | 38 +++++++++++++++++++++ 4 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 53f978c..13a63e6 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -58,6 +58,7 @@ extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **r extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN; +extern MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; @@ -280,6 +281,7 @@ struct GpMetafile{ GpUnit unit; MetafileType metafile_type; HENHMETAFILE hemf; + int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */
/* recording */ HDC record_dc; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 7380c5d..b3eaa86d 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -2350,62 +2350,43 @@ GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics) GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete, GpMetafile **metafile) { - IStream *stream = NULL; - UINT read; - ENHMETAHEADER *copy; - GpStatus retval = Ok; + ENHMETAHEADER header; + MetafileType metafile_type;
TRACE("(%p,%i,%p)\n", hemf, delete, metafile);
if(!hemf || !metafile) return InvalidParameter;
- read = GetEnhMetaFileBits(hemf, 0, NULL); - copy = GdipAlloc(read); - GetEnhMetaFileBits(hemf, read, (BYTE *)copy); - - if(CreateStreamOnHGlobal(copy, TRUE, &stream) != S_OK){ - ERR("could not make stream\n"); - GdipFree(copy); - retval = GenericError; - goto err; - } + if (GetEnhMetaFileHeader(hemf, sizeof(header), &header) == 0) + return GenericError;
- *metafile = GdipAlloc(sizeof(GpMetafile)); - if(!*metafile){ - retval = OutOfMemory; - goto err; - } + metafile_type = METAFILE_GetEmfType(hemf);
- if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, - (LPVOID*) &((*metafile)->image.picture)) != S_OK) - { - retval = GenericError; - goto err; - } + if (metafile_type == MetafileTypeInvalid) + return GenericError;
+ *metafile = GdipAlloc(sizeof(GpMetafile)); + if (!*metafile) + return OutOfMemory;
(*metafile)->image.type = ImageTypeMetafile; - memcpy(&(*metafile)->image.format, &ImageFormatWMF, sizeof(GUID)); - (*metafile)->image.palette = NULL; - (*metafile)->image.xres = (REAL)copy->szlDevice.cx; - (*metafile)->image.yres = (REAL)copy->szlDevice.cy; - (*metafile)->bounds.X = (REAL)copy->rclBounds.left; - (*metafile)->bounds.Y = (REAL)copy->rclBounds.top; - (*metafile)->bounds.Width = (REAL)(copy->rclBounds.right - copy->rclBounds.left); - (*metafile)->bounds.Height = (REAL)(copy->rclBounds.bottom - copy->rclBounds.top); + (*metafile)->image.format = ImageFormatEMF; + (*metafile)->image.frame_count = 1; + (*metafile)->image.xres = (REAL)header.szlDevice.cx; + (*metafile)->image.yres = (REAL)header.szlDevice.cy; + (*metafile)->bounds.X = (REAL)header.rclBounds.left; + (*metafile)->bounds.Y = (REAL)header.rclBounds.top; + (*metafile)->bounds.Width = (REAL)(header.rclBounds.right - header.rclBounds.left); + (*metafile)->bounds.Height = (REAL)(header.rclBounds.bottom - header.rclBounds.top); (*metafile)->unit = UnitPixel; - - if(delete) - DeleteEnhMetaFile(hemf); + (*metafile)->metafile_type = metafile_type; + (*metafile)->hemf = hemf; + (*metafile)->preserve_hemf = !delete;
TRACE("<-- %p\n", *metafile);
-err: - if (retval != Ok) - GdipFree(*metafile); - IStream_Release(stream); - return retval; + return Ok; }
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, @@ -2431,7 +2412,8 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, hemf = SetWinMetaFileBits(read, copy, NULL, NULL); GdipFree(copy);
- retval = GdipCreateMetafileFromEmf(hemf, FALSE, metafile); + /* FIXME: We should store and use hwmf instead of converting to hemf */ + retval = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
if (retval == Ok) { @@ -2443,9 +2425,13 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, placeable->BoundingBox.Left); (*metafile)->bounds.Height = (REAL)(placeable->BoundingBox.Bottom - placeable->BoundingBox.Top); + (*metafile)->metafile_type = MetafileTypeWmfPlaceable; + (*metafile)->image.format = ImageFormatWMF;
if (delete) DeleteMetaFile(hwmf); } + else + DeleteEnhMetaFile(hemf); return retval; }
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 3918301..73f08b9 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -2189,7 +2189,8 @@ static GpStatus free_image_data(GpImage *image) GpMetafile *metafile = (GpMetafile*)image; GdipFree(metafile->comment_data); DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc)); - DeleteEnhMetaFile(metafile->hemf); + if (!metafile->preserve_hemf) + DeleteEnhMetaFile(metafile->hemf); if (metafile->record_graphics) { WARN("metafile closed while recording\n"); diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index 030b2a2..4345ece 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -548,3 +548,41 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
return stat; } + +static int CALLBACK get_metafile_type_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, + int nObj, LPARAM lpData) +{ + MetafileType *result = (MetafileType*)lpData; + + if (lpEMFR->iType == EMR_GDICOMMENT) + { + const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR; + + if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0) + { + const EmfPlusRecordHeader *header = (const EmfPlusRecordHeader*)&comment->Data[4]; + + if (4 + sizeof(EmfPlusRecordHeader) <= comment->cbData && + header->Type == EmfPlusRecordTypeHeader) + { + if ((header->Flags & 1) == 1) + *result = MetafileTypeEmfPlusDual; + else + *result = MetafileTypeEmfPlusOnly; + } + } + else + *result = MetafileTypeEmf; + } + else + *result = MetafileTypeEmf; + + return FALSE; +} + +MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf) +{ + MetafileType result = MetafileTypeInvalid; + EnumEnhMetaFile(NULL, hemf, get_metafile_type_proc, &result, NULL); + return result; +}