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:
Dmitry Timoshkov 2016-08-18 21:22:02 +02:00 committed by Alexandre Julliard
parent a83d5d3b83
commit 2f7a2fdea3
6 changed files with 154 additions and 120 deletions

View File

@ -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 = \

View File

@ -338,7 +338,6 @@ struct GpAdjustableArrowCap{
};
struct GpImage{
IPicture *picture;
IWICBitmapDecoder *decoder;
ImageType type;
GUID format;

View File

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

View File

@ -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
},
{

View File

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

View File

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