gdiplus: Reimplement metafile loading using gdi32 instead of IPicture.
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a83d5d3b83
commit
2f7a2fdea3
|
@ -1,6 +1,6 @@
|
|||
MODULE = gdiplus.dll
|
||||
IMPORTLIB = gdiplus
|
||||
IMPORTS = uuid shlwapi oleaut32 ole32 user32 gdi32
|
||||
IMPORTS = uuid shlwapi ole32 user32 gdi32
|
||||
DELAYIMPORTS = windowscodecs
|
||||
|
||||
C_SRCS = \
|
||||
|
|
|
@ -338,7 +338,6 @@ struct GpAdjustableArrowCap{
|
|||
};
|
||||
|
||||
struct GpImage{
|
||||
IPicture *picture;
|
||||
IWICBitmapDecoder *decoder;
|
||||
ImageType type;
|
||||
GUID format;
|
||||
|
|
|
@ -2901,23 +2901,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
srcheight = units_to_pixels(srcheight, srcUnit, image->yres);
|
||||
TRACE("src pixels: %f,%f %fx%f\n", srcx, srcy, srcwidth, srcheight);
|
||||
|
||||
if (image->picture)
|
||||
{
|
||||
if (!graphics->hdc)
|
||||
{
|
||||
FIXME("graphics object has no HDC\n");
|
||||
}
|
||||
|
||||
if(IPicture_Render(image->picture, graphics->hdc,
|
||||
pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y,
|
||||
srcx, srcy, srcwidth, srcheight, NULL) != S_OK)
|
||||
{
|
||||
if(callback)
|
||||
callback(callbackData);
|
||||
return GenericError;
|
||||
}
|
||||
}
|
||||
else if (image->type == ImageTypeBitmap)
|
||||
if (image->type == ImageTypeBitmap)
|
||||
{
|
||||
GpBitmap* bitmap = (GpBitmap*)image;
|
||||
BOOL do_resampling = FALSE;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Google (Evan Stade)
|
||||
* Copyright (C) 2012 Dmitry Timoshkov
|
||||
* Copyright (C) 2012,2016 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -43,6 +43,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
|
|||
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
|
||||
|
||||
#define PIXELFORMATBPP(x) ((x) ? ((x) >> 8) & 255 : 24)
|
||||
#define WMF_PLACEABLE_KEY 0x9ac6cdd7
|
||||
|
||||
static const struct
|
||||
{
|
||||
|
@ -124,34 +125,6 @@ static ColorPalette *get_palette(IWICBitmapFrameDecode *frame, WICBitmapPaletteT
|
|||
return palette;
|
||||
}
|
||||
|
||||
static INT ipicture_pixel_height(IPicture *pic)
|
||||
{
|
||||
HDC hdcref;
|
||||
OLE_YSIZE_HIMETRIC y;
|
||||
|
||||
IPicture_get_Height(pic, &y);
|
||||
|
||||
hdcref = CreateCompatibleDC(0);
|
||||
y = MulDiv(y, GetDeviceCaps(hdcref, LOGPIXELSY), INCH_HIMETRIC);
|
||||
DeleteDC(hdcref);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
static INT ipicture_pixel_width(IPicture *pic)
|
||||
{
|
||||
HDC hdcref;
|
||||
OLE_XSIZE_HIMETRIC x;
|
||||
|
||||
IPicture_get_Width(pic, &x);
|
||||
|
||||
hdcref = CreateCompatibleDC(0);
|
||||
x = MulDiv(x, GetDeviceCaps(hdcref, LOGPIXELSX), INCH_HIMETRIC);
|
||||
DeleteDC(hdcref);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap* bitmap, CGpEffect* effect,
|
||||
RECT* roi, BOOL useAuxData, VOID** auxData, INT* auxDataSize)
|
||||
{
|
||||
|
@ -1309,45 +1282,12 @@ GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height,
|
|||
|
||||
GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
|
||||
{
|
||||
GpStatus stat = GenericError;
|
||||
|
||||
TRACE("%p, %p\n", image, cloneImage);
|
||||
|
||||
if (!image || !cloneImage)
|
||||
return InvalidParameter;
|
||||
|
||||
if (image->picture)
|
||||
{
|
||||
IStream* stream;
|
||||
HRESULT hr;
|
||||
INT size;
|
||||
LARGE_INTEGER move;
|
||||
|
||||
hr = CreateStreamOnHGlobal(0, TRUE, &stream);
|
||||
if (FAILED(hr))
|
||||
return GenericError;
|
||||
|
||||
hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
WARN("Failed to save image on stream\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set seek pointer back to the beginning of the picture */
|
||||
move.QuadPart = 0;
|
||||
hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr))
|
||||
goto out;
|
||||
|
||||
stat = GdipLoadImageFromStream(stream, cloneImage);
|
||||
if (stat != Ok) WARN("Failed to load image from stream\n");
|
||||
|
||||
out:
|
||||
IStream_Release(stream);
|
||||
return stat;
|
||||
}
|
||||
else if (image->type == ImageTypeBitmap)
|
||||
if (image->type == ImageTypeBitmap)
|
||||
{
|
||||
GpBitmap *bitmap = (GpBitmap *)image;
|
||||
|
||||
|
@ -1884,7 +1824,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
|||
(*bitmap)->width = width;
|
||||
(*bitmap)->height = height;
|
||||
(*bitmap)->format = format;
|
||||
(*bitmap)->image.picture = NULL;
|
||||
(*bitmap)->image.decoder = NULL;
|
||||
(*bitmap)->hbitmap = hbitmap;
|
||||
(*bitmap)->hdc = NULL;
|
||||
|
@ -2152,8 +2091,6 @@ static GpStatus free_image_data(GpImage *image)
|
|||
WARN("invalid image: %p\n", image);
|
||||
return ObjectBusy;
|
||||
}
|
||||
if (image->picture)
|
||||
IPicture_Release(image->picture);
|
||||
if (image->decoder)
|
||||
IWICBitmapDecoder_Release(image->decoder);
|
||||
heap_free(image->palette);
|
||||
|
@ -2220,10 +2157,8 @@ GpStatus WINGDIPAPI GdipGetImageBounds(GpImage *image, GpRectF *srcRect,
|
|||
*srcUnit = UnitPixel;
|
||||
}
|
||||
else{
|
||||
srcRect->X = srcRect->Y = 0.0;
|
||||
srcRect->Width = ipicture_pixel_width(image->picture);
|
||||
srcRect->Height = ipicture_pixel_height(image->picture);
|
||||
*srcUnit = UnitPixel;
|
||||
WARN("GpImage with no image data\n");
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y,
|
||||
|
@ -2249,8 +2184,8 @@ GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width,
|
|||
*width = ((GpBitmap*)image)->width;
|
||||
}
|
||||
else{
|
||||
*height = ipicture_pixel_height(image->picture);
|
||||
*width = ipicture_pixel_width(image->picture);
|
||||
WARN("GpImage with no image data\n");
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
TRACE("returning (%f, %f)\n", *height, *width);
|
||||
|
@ -2307,7 +2242,10 @@ GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height)
|
|||
else if(image->type == ImageTypeBitmap)
|
||||
*height = ((GpBitmap*)image)->height;
|
||||
else
|
||||
*height = ipicture_pixel_height(image->picture);
|
||||
{
|
||||
WARN("GpImage with no image data\n");
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
TRACE("returning %d\n", *height);
|
||||
|
||||
|
@ -2407,7 +2345,10 @@ GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
|
|||
else if(image->type == ImageTypeBitmap)
|
||||
*width = ((GpBitmap*)image)->width;
|
||||
else
|
||||
*width = ipicture_pixel_width(image->picture);
|
||||
{
|
||||
WARN("GpImage with no image data\n");
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
TRACE("returning %d\n", *width);
|
||||
|
||||
|
@ -4037,33 +3978,144 @@ static GpStatus decode_image_tiff(IStream* stream, GpImage **image)
|
|||
return decode_image_wic(stream, &GUID_ContainerFormatTiff, NULL, image);
|
||||
}
|
||||
|
||||
static GpStatus decode_image_olepicture_metafile(IStream* stream, GpImage **image)
|
||||
static GpStatus load_wmf(IStream *stream, GpMetafile **metafile)
|
||||
{
|
||||
IPicture *pic;
|
||||
WmfPlaceableFileHeader pfh;
|
||||
BOOL is_placeable = FALSE;
|
||||
LARGE_INTEGER seek;
|
||||
GpStatus status;
|
||||
METAHEADER mh;
|
||||
HMETAFILE hmf;
|
||||
HRESULT hr;
|
||||
UINT size;
|
||||
void *buf;
|
||||
|
||||
TRACE("%p %p\n", stream, image);
|
||||
hr = IStream_Read(stream, &mh, sizeof(mh), &size);
|
||||
if (hr != S_OK || size != sizeof(mh))
|
||||
return GenericError;
|
||||
|
||||
if(!stream || !image)
|
||||
return InvalidParameter;
|
||||
if (((WmfPlaceableFileHeader *)&mh)->Key == WMF_PLACEABLE_KEY)
|
||||
{
|
||||
seek.QuadPart = 0;
|
||||
hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr)) return hresult_to_status(hr);
|
||||
|
||||
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
|
||||
(LPVOID*) &pic) != S_OK){
|
||||
TRACE("Could not load picture\n");
|
||||
hr = IStream_Read(stream, &pfh, sizeof(pfh), &size);
|
||||
if (hr != S_OK || size != sizeof(pfh))
|
||||
return GenericError;
|
||||
|
||||
hr = IStream_Read(stream, &mh, sizeof(mh), &size);
|
||||
if (hr != S_OK || size != sizeof(mh))
|
||||
return GenericError;
|
||||
|
||||
is_placeable = TRUE;
|
||||
}
|
||||
|
||||
seek.QuadPart = is_placeable ? sizeof(pfh) : 0;
|
||||
hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr)) return hresult_to_status(hr);
|
||||
|
||||
buf = heap_alloc(mh.mtSize * 2);
|
||||
if (!buf) return OutOfMemory;
|
||||
|
||||
hr = IStream_Read(stream, buf, mh.mtSize * 2, &size);
|
||||
if (hr != S_OK || size != mh.mtSize * 2)
|
||||
{
|
||||
heap_free(buf);
|
||||
return GenericError;
|
||||
}
|
||||
|
||||
/* FIXME: missing initialization code */
|
||||
*image = heap_alloc_zero(sizeof(GpMetafile));
|
||||
if(!*image) return OutOfMemory;
|
||||
(*image)->type = ImageTypeMetafile;
|
||||
(*image)->decoder = NULL;
|
||||
(*image)->picture = pic;
|
||||
(*image)->flags = ImageFlagsNone;
|
||||
(*image)->frame_count = 1;
|
||||
(*image)->current_frame = 0;
|
||||
(*image)->palette = NULL;
|
||||
list_init(&(*(GpMetafile**)image)->containers);
|
||||
hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf);
|
||||
heap_free(buf);
|
||||
if (!hmf)
|
||||
return GenericError;
|
||||
|
||||
status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile);
|
||||
if (status != Ok)
|
||||
DeleteMetaFile(hmf);
|
||||
return status;
|
||||
}
|
||||
|
||||
static GpStatus decode_image_wmf(IStream *stream, GpImage **image)
|
||||
{
|
||||
GpMetafile *metafile;
|
||||
GpStatus status;
|
||||
|
||||
TRACE("%p %p\n", stream, image);
|
||||
|
||||
if (!stream || !image)
|
||||
return InvalidParameter;
|
||||
|
||||
status = load_wmf(stream, &metafile);
|
||||
if (status != Ok)
|
||||
{
|
||||
TRACE("Could not load metafile\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
*image = (GpImage *)metafile;
|
||||
TRACE("<-- %p\n", *image);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
static GpStatus load_emf(IStream *stream, GpMetafile **metafile)
|
||||
{
|
||||
LARGE_INTEGER seek;
|
||||
ENHMETAHEADER emh;
|
||||
HENHMETAFILE hemf;
|
||||
GpStatus status;
|
||||
HRESULT hr;
|
||||
UINT size;
|
||||
void *buf;
|
||||
|
||||
hr = IStream_Read(stream, &emh, sizeof(emh), &size);
|
||||
if (hr != S_OK || size != sizeof(emh) || emh.dSignature != ENHMETA_SIGNATURE)
|
||||
return GenericError;
|
||||
|
||||
seek.QuadPart = 0;
|
||||
hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr)) return hresult_to_status(hr);
|
||||
|
||||
buf = heap_alloc(emh.nBytes);
|
||||
if (!buf) return OutOfMemory;
|
||||
|
||||
hr = IStream_Read(stream, buf, emh.nBytes, &size);
|
||||
if (hr != S_OK || size != emh.nBytes)
|
||||
{
|
||||
heap_free(buf);
|
||||
return GenericError;
|
||||
}
|
||||
|
||||
hemf = SetEnhMetaFileBits(emh.nBytes, buf);
|
||||
heap_free(buf);
|
||||
if (!hemf)
|
||||
return GenericError;
|
||||
|
||||
status = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
|
||||
if (status != Ok)
|
||||
DeleteEnhMetaFile(hemf);
|
||||
return status;
|
||||
}
|
||||
|
||||
static GpStatus decode_image_emf(IStream *stream, GpImage **image)
|
||||
{
|
||||
GpMetafile *metafile;
|
||||
GpStatus status;
|
||||
|
||||
TRACE("%p %p\n", stream, image);
|
||||
|
||||
if (!stream || !image)
|
||||
return InvalidParameter;
|
||||
|
||||
status = load_emf(stream, &metafile);
|
||||
if (status != Ok)
|
||||
{
|
||||
TRACE("Could not load metafile\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
*image = (GpImage *)metafile;
|
||||
TRACE("<-- %p\n", *image);
|
||||
|
||||
return Ok;
|
||||
|
@ -4721,7 +4773,7 @@ static const struct image_codec codecs[NUM_CODECS] = {
|
|||
/* SigMask */ emf_sig_mask,
|
||||
},
|
||||
NULL,
|
||||
decode_image_olepicture_metafile,
|
||||
decode_image_emf,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
|
@ -4741,7 +4793,7 @@ static const struct image_codec codecs[NUM_CODECS] = {
|
|||
/* SigMask */ wmf_sig_mask,
|
||||
},
|
||||
NULL,
|
||||
decode_image_olepicture_metafile,
|
||||
decode_image_wmf,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
|
|
|
@ -324,7 +324,6 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
|
|||
}
|
||||
|
||||
(*metafile)->image.type = ImageTypeMetafile;
|
||||
(*metafile)->image.picture = NULL;
|
||||
(*metafile)->image.flags = ImageFlagsNone;
|
||||
(*metafile)->image.palette = NULL;
|
||||
(*metafile)->image.xres = dpix;
|
||||
|
|
|
@ -1446,19 +1446,19 @@ static void test_loadwmf(void)
|
|||
|
||||
stat = GdipGetImageBounds(img, &bounds, &unit);
|
||||
expect(Ok, stat);
|
||||
todo_wine expect(UnitPixel, unit);
|
||||
expect(UnitPixel, unit);
|
||||
expectf(0.0, bounds.X);
|
||||
expectf(0.0, bounds.Y);
|
||||
todo_wine expectf(320.0, bounds.Width);
|
||||
todo_wine expectf(320.0, bounds.Height);
|
||||
expectf(320.0, bounds.Width);
|
||||
expectf(320.0, bounds.Height);
|
||||
|
||||
stat = GdipGetImageHorizontalResolution(img, &res);
|
||||
expect(Ok, stat);
|
||||
todo_wine expectf(1440.0, res);
|
||||
expectf(1440.0, res);
|
||||
|
||||
stat = GdipGetImageVerticalResolution(img, &res);
|
||||
expect(Ok, stat);
|
||||
todo_wine expectf(1440.0, res);
|
||||
expectf(1440.0, res);
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
|
||||
|
|
Loading…
Reference in New Issue