Commit 91a3e5fc authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Reimplement GdipCreateMetafileFromEmf without using IPicture.

parent d8a85530
...@@ -58,6 +58,7 @@ extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **r ...@@ -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_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ReleaseDC(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 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, extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
...@@ -280,6 +281,7 @@ struct GpMetafile{ ...@@ -280,6 +281,7 @@ struct GpMetafile{
GpUnit unit; GpUnit unit;
MetafileType metafile_type; MetafileType metafile_type;
HENHMETAFILE hemf; HENHMETAFILE hemf;
int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */
/* recording */ /* recording */
HDC record_dc; HDC record_dc;
......
...@@ -2350,62 +2350,43 @@ GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics) ...@@ -2350,62 +2350,43 @@ GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics)
GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete, GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete,
GpMetafile **metafile) GpMetafile **metafile)
{ {
IStream *stream = NULL; ENHMETAHEADER header;
UINT read; MetafileType metafile_type;
ENHMETAHEADER *copy;
GpStatus retval = Ok;
TRACE("(%p,%i,%p)\n", hemf, delete, metafile); TRACE("(%p,%i,%p)\n", hemf, delete, metafile);
if(!hemf || !metafile) if(!hemf || !metafile)
return InvalidParameter; return InvalidParameter;
read = GetEnhMetaFileBits(hemf, 0, NULL); if (GetEnhMetaFileHeader(hemf, sizeof(header), &header) == 0)
copy = GdipAlloc(read); return GenericError;
GetEnhMetaFileBits(hemf, read, (BYTE *)copy);
if(CreateStreamOnHGlobal(copy, TRUE, &stream) != S_OK){
ERR("could not make stream\n");
GdipFree(copy);
retval = GenericError;
goto err;
}
*metafile = GdipAlloc(sizeof(GpMetafile)); metafile_type = METAFILE_GetEmfType(hemf);
if(!*metafile){
retval = OutOfMemory;
goto err;
}
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, if (metafile_type == MetafileTypeInvalid)
(LPVOID*) &((*metafile)->image.picture)) != S_OK) return GenericError;
{
retval = GenericError;
goto err;
}
*metafile = GdipAlloc(sizeof(GpMetafile));
if (!*metafile)
return OutOfMemory;
(*metafile)->image.type = ImageTypeMetafile; (*metafile)->image.type = ImageTypeMetafile;
memcpy(&(*metafile)->image.format, &ImageFormatWMF, sizeof(GUID)); (*metafile)->image.format = ImageFormatEMF;
(*metafile)->image.palette = NULL; (*metafile)->image.frame_count = 1;
(*metafile)->image.xres = (REAL)copy->szlDevice.cx; (*metafile)->image.xres = (REAL)header.szlDevice.cx;
(*metafile)->image.yres = (REAL)copy->szlDevice.cy; (*metafile)->image.yres = (REAL)header.szlDevice.cy;
(*metafile)->bounds.X = (REAL)copy->rclBounds.left; (*metafile)->bounds.X = (REAL)header.rclBounds.left;
(*metafile)->bounds.Y = (REAL)copy->rclBounds.top; (*metafile)->bounds.Y = (REAL)header.rclBounds.top;
(*metafile)->bounds.Width = (REAL)(copy->rclBounds.right - copy->rclBounds.left); (*metafile)->bounds.Width = (REAL)(header.rclBounds.right - header.rclBounds.left);
(*metafile)->bounds.Height = (REAL)(copy->rclBounds.bottom - copy->rclBounds.top); (*metafile)->bounds.Height = (REAL)(header.rclBounds.bottom - header.rclBounds.top);
(*metafile)->unit = UnitPixel; (*metafile)->unit = UnitPixel;
(*metafile)->metafile_type = metafile_type;
if(delete) (*metafile)->hemf = hemf;
DeleteEnhMetaFile(hemf); (*metafile)->preserve_hemf = !delete;
TRACE("<-- %p\n", *metafile); TRACE("<-- %p\n", *metafile);
err: return Ok;
if (retval != Ok)
GdipFree(*metafile);
IStream_Release(stream);
return retval;
} }
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete,
...@@ -2431,7 +2412,8 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, ...@@ -2431,7 +2412,8 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete,
hemf = SetWinMetaFileBits(read, copy, NULL, NULL); hemf = SetWinMetaFileBits(read, copy, NULL, NULL);
GdipFree(copy); 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) if (retval == Ok)
{ {
...@@ -2443,9 +2425,13 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, ...@@ -2443,9 +2425,13 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete,
placeable->BoundingBox.Left); placeable->BoundingBox.Left);
(*metafile)->bounds.Height = (REAL)(placeable->BoundingBox.Bottom - (*metafile)->bounds.Height = (REAL)(placeable->BoundingBox.Bottom -
placeable->BoundingBox.Top); placeable->BoundingBox.Top);
(*metafile)->metafile_type = MetafileTypeWmfPlaceable;
(*metafile)->image.format = ImageFormatWMF;
if (delete) DeleteMetaFile(hwmf); if (delete) DeleteMetaFile(hwmf);
} }
else
DeleteEnhMetaFile(hemf);
return retval; return retval;
} }
......
...@@ -2189,7 +2189,8 @@ static GpStatus free_image_data(GpImage *image) ...@@ -2189,7 +2189,8 @@ static GpStatus free_image_data(GpImage *image)
GpMetafile *metafile = (GpMetafile*)image; GpMetafile *metafile = (GpMetafile*)image;
GdipFree(metafile->comment_data); GdipFree(metafile->comment_data);
DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc)); DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc));
DeleteEnhMetaFile(metafile->hemf); if (!metafile->preserve_hemf)
DeleteEnhMetaFile(metafile->hemf);
if (metafile->record_graphics) if (metafile->record_graphics)
{ {
WARN("metafile closed while recording\n"); WARN("metafile closed while recording\n");
......
...@@ -548,3 +548,41 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics, ...@@ -548,3 +548,41 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
return stat; 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment