gdiplus: Reimplement GdipCreateMetafileFromEmf without using IPicture.

This commit is contained in:
Vincent Povirk 2012-10-31 15:37:16 -05:00 committed by Alexandre Julliard
parent d8a855305f
commit 91a3e5fc10
4 changed files with 70 additions and 43 deletions

View File

@ -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;

View File

@ -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 (GetEnhMetaFileHeader(hemf, sizeof(header), &header) == 0)
return GenericError;
if(CreateStreamOnHGlobal(copy, TRUE, &stream) != S_OK){
ERR("could not make stream\n");
GdipFree(copy);
retval = GenericError;
goto err;
}
metafile_type = METAFILE_GetEmfType(hemf);
if (metafile_type == MetafileTypeInvalid)
return GenericError;
*metafile = GdipAlloc(sizeof(GpMetafile));
if(!*metafile){
retval = OutOfMemory;
goto err;
}
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
(LPVOID*) &((*metafile)->image.picture)) != S_OK)
{
retval = GenericError;
goto err;
}
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;
}

View File

@ -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");

View File

@ -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;
}