[GDIPLUS] Sync with Wine Staging 1.9.16. CORE-11866

svn path=/trunk/; revision=72341
This commit is contained in:
Amine Khaldi 2016-08-19 09:28:13 +00:00
parent ee606040a1
commit 3f043d113a
9 changed files with 441 additions and 27 deletions

View file

@ -191,7 +191,7 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
if (stat == Ok)
{
new_texture->transform = texture->transform;
*clone = (GpBrush*)new_texture;
*clone = &new_texture->brush;
}
else
*clone = NULL;

View file

@ -264,7 +264,7 @@
264 stdcall GdipGetHatchForegroundColor(ptr ptr)
265 stdcall GdipGetHatchStyle(ptr ptr)
266 stdcall GdipGetHemfFromMetafile(ptr ptr)
267 stub GdipGetImageAttributesAdjustedPalette
267 stdcall GdipGetImageAttributesAdjustedPalette(ptr ptr long)
268 stdcall GdipGetImageBounds(ptr ptr ptr)
269 stdcall GdipGetImageDecoders(long long ptr)
270 stdcall GdipGetImageDecodersSize(ptr ptr)

View file

@ -94,9 +94,12 @@ extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLS
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) 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_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
@ -184,6 +187,9 @@ extern GpStatus convert_pixels(INT width, INT height,
INT dst_stride, BYTE *dst_bits, PixelFormat dst_format,
INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN;
extern PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt) DECLSPEC_HIDDEN;
struct GpMatrix{
REAL matrix[6];
};
@ -322,7 +328,7 @@ struct GpCustomLineCap{
REAL scale;
};
struct GpAdustableArrowCap{
struct GpAdjustableArrowCap{
GpCustomLineCap cap;
};
@ -351,6 +357,8 @@ struct GpMetafile{
DWORD comment_data_size;
DWORD comment_data_length;
IStream *record_stream;
BOOL auto_frame; /* If true, determine the frame automatically */
GpPointF auto_frame_min, auto_frame_max;
/* playback */
GpGraphics *playback_graphics;
@ -362,6 +370,7 @@ struct GpMetafile{
GpMatrix *world_transform;
GpUnit page_unit;
REAL page_scale;
GpRegion *base_clip; /* clip region in device space for all metafile output */
};
struct GpBitmap{

View file

@ -657,7 +657,7 @@ static BOOL color_is_gray(ARGB color)
}
/* returns preferred pixel format for the applied attributes */
static PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt)
{
UINT x, y;
@ -4277,6 +4277,7 @@ GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics *graphics, GpRectF *rect
{
GpRegion *clip_rgn;
GpStatus stat;
GpMatrix device_to_world;
TRACE("(%p, %p)\n", graphics, rect);
@ -4293,6 +4294,13 @@ GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics *graphics, GpRectF *rect
if((stat = get_visible_clip_region(graphics, clip_rgn)) != Ok)
goto cleanup;
/* transform to world coordinates */
if((stat = get_graphics_transform(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &device_to_world)) != Ok)
goto cleanup;
if((stat = GdipTransformRegion(clip_rgn, &device_to_world)) != Ok)
goto cleanup;
/* get bounds of the region */
stat = GdipGetRegionBounds(clip_rgn, graphics, rect);
@ -4351,10 +4359,13 @@ GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color)
if(graphics->busy)
return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile)
return METAFILE_GraphicsClear((GpMetafile*)graphics->image, color);
if((stat = GdipCreateSolidFill(color, &brush)) != Ok)
return stat;
if((stat = get_graphics_bounds(graphics, &wnd_rect)) != Ok){
if((stat = GdipGetVisibleClipBounds(graphics, &wnd_rect)) != Ok){
GdipDeleteBrush((GpBrush*)brush);
return stat;
}
@ -5097,6 +5108,8 @@ GpStatus WINGDIPAPI GdipResetClip(GpGraphics *graphics)
GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics)
{
GpStatus stat;
TRACE("(%p)\n", graphics);
if(!graphics)
@ -5105,6 +5118,13 @@ GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics)
if(graphics->busy)
return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile) {
stat = METAFILE_ResetWorldTransform((GpMetafile*)graphics->image);
if (stat != Ok)
return stat;
}
return GdipSetMatrixElements(&graphics->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
}
@ -5211,6 +5231,8 @@ GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsContainer sta
GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx,
REAL sy, GpMatrixOrder order)
{
GpStatus stat;
TRACE("(%p, %.2f, %.2f, %d)\n", graphics, sx, sy, order);
if(!graphics)
@ -5219,6 +5241,13 @@ GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx,
if(graphics->busy)
return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile) {
stat = METAFILE_ScaleWorldTransform((GpMetafile*)graphics->image, sx, sy, order);
if (stat != Ok)
return stat;
}
return GdipScaleMatrix(&graphics->worldtrans, sx, sy, order);
}

View file

@ -1245,7 +1245,7 @@ GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height,
}
if (stat != Ok)
GdipDisposeImage((GpImage*)*dstBitmap);
GdipDisposeImage(&(*dstBitmap)->image);
}
if (stat != Ok)
@ -1445,8 +1445,8 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
if (!bitmap || !hbmReturn) return InvalidParameter;
GdipGetImageWidth((GpImage*)bitmap, &width);
GdipGetImageHeight((GpImage*)bitmap, &height);
GdipGetImageWidth(&bitmap->image, &width);
GdipGetImageHeight(&bitmap->image, &height);
bih.biSize = sizeof(bih);
bih.biWidth = width;
@ -1570,7 +1570,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap)
if (stat != Ok) {
DeleteObject(iinfo.hbmColor);
DeleteObject(iinfo.hbmMask);
GdipDisposeImage((GpImage*)*bitmap);
GdipDisposeImage(&(*bitmap)->image);
return stat;
}
@ -2932,7 +2932,7 @@ static void add_property(GpBitmap *bitmap, PropertyItem *item)
UINT i;
char *item_value;
GdipGetPropertySize((GpImage *)bitmap, &prop_size, &prop_count);
GdipGetPropertySize(&bitmap->image, &prop_size, &prop_count);
prop_item = heap_alloc_zero(prop_size + item->length + sizeof(PropertyItem));
if (!prop_item) return;
@ -3388,7 +3388,7 @@ static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UI
{ "Source", PropertyTagEquipModel },
{ "Comment", PropertyTagExifUserComment },
};
BOOL seen_gamma=FALSE;
BOOL seen_gamma=FALSE, seen_whitepoint=FALSE, seen_chrm=FALSE;
hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame);
if (hr != S_OK) return;
@ -3457,6 +3457,57 @@ static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UI
}
}
}
else if (SUCCEEDED(hr) && IsEqualGUID(&GUID_MetadataFormatChunkcHRM, &format))
{
PropertyItem* item;
if (!seen_whitepoint)
{
item = GdipAlloc(sizeof(PropertyItem) + sizeof(ULONG) * 4);
if (item)
{
ULONG *rational;
item->length = sizeof(ULONG) * 4;
item->type = PropertyTagTypeRational;
item->id = PropertyTagWhitePoint;
rational = item->value = item + 1;
rational[0] = get_ulong_by_index(reader, 0);
rational[1] = 100000;
rational[2] = get_ulong_by_index(reader, 1);
rational[3] = 100000;
add_property(bitmap, item);
seen_whitepoint = TRUE;
GdipFree(item);
}
}
if (!seen_chrm)
{
item = GdipAlloc(sizeof(PropertyItem) + sizeof(ULONG) * 12);
if (item)
{
ULONG *rational;
item->length = sizeof(ULONG) * 12;
item->type = PropertyTagTypeRational;
item->id = PropertyTagPrimaryChromaticities;
rational = item->value = item + 1;
rational[0] = get_ulong_by_index(reader, 2);
rational[1] = 100000;
rational[2] = get_ulong_by_index(reader, 3);
rational[3] = 100000;
rational[4] = get_ulong_by_index(reader, 4);
rational[5] = 100000;
rational[6] = get_ulong_by_index(reader, 5);
rational[7] = 100000;
rational[8] = get_ulong_by_index(reader, 6);
rational[9] = 100000;
rational[10] = get_ulong_by_index(reader, 7);
rational[11] = 100000;
add_property(bitmap, item);
seen_chrm = TRUE;
GdipFree(item);
}
}
}
IWICMetadataReader_Release(reader);
}
@ -3568,11 +3619,11 @@ static GpStatus decode_frame_wic(IWICBitmapDecoder *decoder, BOOL force_conversi
}
if (SUCCEEDED(hr) && status == Ok)
*image = (GpImage*)bitmap;
*image = &bitmap->image;
else
{
*image = NULL;
GdipDisposeImage((GpImage*)bitmap);
GdipDisposeImage(&bitmap->image);
}
if (SUCCEEDED(hr) && status == Ok)
@ -3614,7 +3665,14 @@ static GpStatus decode_frame_wic(IWICBitmapDecoder *decoder, BOOL force_conversi
if (status == Ok)
{
/* Native GDI+ used to be smarter, but since Win7 it just sets these flags. */
bitmap->image.flags |= ImageFlagsReadOnly|ImageFlagsHasRealPixelSize|ImageFlagsHasRealDPI|ImageFlagsColorSpaceRGB;
bitmap->image.flags |= ImageFlagsReadOnly|ImageFlagsHasRealPixelSize|ImageFlagsHasRealDPI;
if (IsEqualGUID(&wic_format, &GUID_WICPixelFormat2bppGray) ||
IsEqualGUID(&wic_format, &GUID_WICPixelFormat4bppGray) ||
IsEqualGUID(&wic_format, &GUID_WICPixelFormat8bppGray) ||
IsEqualGUID(&wic_format, &GUID_WICPixelFormat16bppGray))
bitmap->image.flags |= ImageFlagsColorSpaceGRAY;
else
bitmap->image.flags |= ImageFlagsColorSpaceRGB;
bitmap->image.frame_count = frame_count;
bitmap->image.current_frame = active_frame;
bitmap->image.decoder = decoder;
@ -3856,7 +3914,37 @@ static GpStatus decode_image_jpeg(IStream* stream, GpImage **image)
static GpStatus decode_image_png(IStream* stream, GpImage **image)
{
return decode_image_wic(stream, &GUID_ContainerFormatPng, png_metadata_reader, image);
IWICBitmapDecoder *decoder;
IWICBitmapFrameDecode *frame;
GpStatus status;
HRESULT hr;
GUID format;
BOOL force_conversion = FALSE;
status = initialize_decoder_wic(stream, &GUID_ContainerFormatPng, &decoder);
if (status != Ok)
return status;
hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
if (hr == S_OK)
{
hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
if (hr == S_OK)
{
if (IsEqualGUID(&format, &GUID_WICPixelFormat8bppGray))
force_conversion = TRUE;
status = decode_frame_wic(decoder, force_conversion, 0, png_metadata_reader, image);
}
else
status = hresult_to_status(hr);
IWICBitmapFrameDecode_Release(frame);
}
else
status = hresult_to_status(hr);
IWICBitmapDecoder_Release(decoder);
return status;
}
static GpStatus decode_image_gif(IStream* stream, GpImage **image)
@ -4987,7 +5075,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
entry[i].peGreen << 8 | entry[i].peBlue;
}
retval = GdipSetImagePalette((GpImage*)*bitmap, palette);
retval = GdipSetImagePalette(&(*bitmap)->image, palette);
}
heap_free(palette);
@ -4995,7 +5083,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
if (retval != Ok)
{
GdipDisposeImage((GpImage*)*bitmap);
GdipDisposeImage(&(*bitmap)->image);
*bitmap = NULL;
}
}
@ -5250,7 +5338,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
if (stat == Ok)
move_bitmap(bitmap, new_bitmap, FALSE);
else
GdipDisposeImage((GpImage*)new_bitmap);
GdipDisposeImage(&new_bitmap->image);
return stat;
}

View file

@ -68,6 +68,21 @@ GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes *imageattr)
return Ok;
}
GpStatus WINGDIPAPI GdipGetImageAttributesAdjustedPalette(GpImageAttributes *imageattr,
ColorPalette *palette, ColorAdjustType type)
{
TRACE("(%p,%p,%u)\n", imageattr, palette, type);
if (!imageattr || !palette || !palette->Count ||
type >= ColorAdjustTypeCount || type == ColorAdjustTypeDefault)
return InvalidParameter;
apply_image_attributes(imageattr, (LPBYTE)palette->Entries, palette->Count, 1, 0,
type, PixelFormat32bppARGB);
return Ok;
}
GpStatus WINGDIPAPI GdipSetImageAttributesColorKeys(GpImageAttributes *imageattr,
ColorAdjustType type, BOOL enableFlag, ARGB colorLow, ARGB colorHigh)
{

View file

@ -35,6 +35,12 @@ typedef struct EmfPlusHeader
DWORD LogicalDpiY;
} EmfPlusHeader;
typedef struct EmfPlusClear
{
EmfPlusRecordHeader Header;
DWORD Color;
} EmfPlusClear;
typedef struct EmfPlusFillRects
{
EmfPlusRecordHeader Header;
@ -56,6 +62,13 @@ typedef struct EmfPlusRect
SHORT Height;
} EmfPlusRect;
typedef struct EmfPlusScaleWorldTransform
{
EmfPlusRecordHeader Header;
REAL Sx;
REAL Sy;
} EmfPlusScaleWorldTransform;
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result)
{
DWORD size_needed;
@ -248,6 +261,15 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
(*metafile)->comment_data_length = 0;
(*metafile)->hemf = NULL;
if (!frameRect)
{
(*metafile)->auto_frame = TRUE;
(*metafile)->auto_frame_min.X = 0;
(*metafile)->auto_frame_min.Y = 0;
(*metafile)->auto_frame_max.X = -1;
(*metafile)->auto_frame_max.Y = -1;
}
stat = METAFILE_WriteHeader(*metafile, hdc);
if (stat != Ok)
@ -306,6 +328,30 @@ GpStatus WINGDIPAPI GdipRecordMetafileStream(IStream *stream, HDC hdc, EmfType t
return stat;
}
static void METAFILE_AdjustFrame(GpMetafile* metafile, const GpPointF *points,
UINT num_points)
{
int i;
if (!metafile->auto_frame || !num_points)
return;
if (metafile->auto_frame_max.X < metafile->auto_frame_min.X)
metafile->auto_frame_max = metafile->auto_frame_min = points[0];
for (i=0; i<num_points; i++)
{
if (points[i].X < metafile->auto_frame_min.X)
metafile->auto_frame_min.X = points[i].X;
if (points[i].X > metafile->auto_frame_max.X)
metafile->auto_frame_max.X = points[i].X;
if (points[i].Y < metafile->auto_frame_min.Y)
metafile->auto_frame_min.Y = points[i].Y;
if (points[i].Y > metafile->auto_frame_max.Y)
metafile->auto_frame_max.Y = points[i].Y;
}
}
GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result)
{
GpStatus stat;
@ -347,6 +393,27 @@ GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc)
return Ok;
}
GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color)
{
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
{
EmfPlusClear *record;
GpStatus stat;
stat = METAFILE_AllocateRecord(metafile, sizeof(EmfPlusClear), (void**)&record);
if (stat != Ok)
return stat;
record->Header.Type = EmfPlusRecordTypeClear;
record->Header.Flags = 0;
record->Color = color;
METAFILE_WriteRecords(metafile);
}
return Ok;
}
static BOOL is_integer_rect(const GpRectF *rect)
{
SHORT x, y, width, height;
@ -423,6 +490,29 @@ GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
METAFILE_WriteRecords(metafile);
}
if (metafile->auto_frame)
{
GpPointF corners[4];
int i;
for (i=0; i<count; i++)
{
corners[0].X = rects[i].X;
corners[0].Y = rects[i].Y;
corners[1].X = rects[i].X + rects[i].Width;
corners[1].Y = rects[i].Y;
corners[2].X = rects[i].X;
corners[2].Y = rects[i].Y + rects[i].Height;
corners[3].X = rects[i].X + rects[i].Width;
corners[3].Y = rects[i].Y + rects[i].Height;
GdipTransformPoints(metafile->record_graphics, CoordinateSpaceDevice,
CoordinateSpaceWorld, corners, 4);
METAFILE_AdjustFrame(metafile, corners, 4);
}
}
return Ok;
}
@ -449,6 +539,52 @@ GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale
return Ok;
}
GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order)
{
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
{
EmfPlusScaleWorldTransform *record;
GpStatus stat;
stat = METAFILE_AllocateRecord(metafile,
sizeof(EmfPlusScaleWorldTransform),
(void**)&record);
if (stat != Ok)
return stat;
record->Header.Type = EmfPlusRecordTypeScaleWorldTransform;
record->Header.Flags = (order == MatrixOrderAppend ? 4 : 0);
record->Sx = sx;
record->Sy = sy;
METAFILE_WriteRecords(metafile);
}
return Ok;
}
GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile)
{
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
{
EmfPlusRecordHeader *record;
GpStatus stat;
stat = METAFILE_AllocateRecord(metafile,
sizeof(EmfPlusRecordHeader),
(void**)&record);
if (stat != Ok)
return stat;
record->Type = EmfPlusRecordTypeResetWorldTransform;
record->Flags = 0;
METAFILE_WriteRecords(metafile);
}
return Ok;
}
GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc)
{
if (hdc != metafile->record_dc)
@ -476,6 +612,57 @@ GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile)
MetafileHeader header;
stat = GdipGetMetafileHeaderFromEmf(metafile->hemf, &header);
if (stat == Ok && metafile->auto_frame &&
metafile->auto_frame_max.X >= metafile->auto_frame_min.X)
{
RECTL bounds_rc, gdi_bounds_rc;
REAL x_scale = 2540.0 / header.DpiX;
REAL y_scale = 2540.0 / header.DpiY;
BYTE* buffer;
UINT buffer_size;
bounds_rc.left = floorf(metafile->auto_frame_min.X * x_scale);
bounds_rc.top = floorf(metafile->auto_frame_min.Y * y_scale);
bounds_rc.right = ceilf(metafile->auto_frame_max.X * x_scale);
bounds_rc.bottom = ceilf(metafile->auto_frame_max.Y * y_scale);
gdi_bounds_rc = header.u.EmfHeader.rclBounds;
if (gdi_bounds_rc.right > gdi_bounds_rc.left && gdi_bounds_rc.bottom > gdi_bounds_rc.top)
{
bounds_rc.left = min(bounds_rc.left, gdi_bounds_rc.left);
bounds_rc.top = min(bounds_rc.top, gdi_bounds_rc.top);
bounds_rc.right = max(bounds_rc.right, gdi_bounds_rc.right);
bounds_rc.bottom = max(bounds_rc.bottom, gdi_bounds_rc.bottom);
}
buffer_size = GetEnhMetaFileBits(metafile->hemf, 0, NULL);
buffer = heap_alloc(buffer_size);
if (buffer)
{
HENHMETAFILE new_hemf;
GetEnhMetaFileBits(metafile->hemf, buffer_size, buffer);
((ENHMETAHEADER*)buffer)->rclFrame = bounds_rc;
new_hemf = SetEnhMetaFileBits(buffer_size, buffer);
if (new_hemf)
{
DeleteEnhMetaFile(metafile->hemf);
metafile->hemf = new_hemf;
}
else
stat = OutOfMemory;
heap_free(buffer);
}
else
stat = OutOfMemory;
if (stat == Ok)
stat = GdipGetMetafileHeaderFromEmf(metafile->hemf, &header);
}
if (stat == Ok)
{
metafile->bounds.X = header.X;
@ -568,6 +755,11 @@ static void METAFILE_PlaybackReleaseDC(GpMetafile *metafile)
}
}
static GpStatus METAFILE_PlaybackUpdateClip(GpMetafile *metafile)
{
return GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace);
}
static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
{
GpMatrix *real_transform;
@ -645,6 +837,12 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
case EmfPlusRecordTypeGetDC:
METAFILE_PlaybackGetDC((GpMetafile*)metafile);
break;
case EmfPlusRecordTypeClear:
{
EmfPlusClear *record = (EmfPlusClear*)header;
return GdipGraphicsClear(metafile->playback_graphics, record->Color);
}
case EmfPlusRecordTypeFillRects:
{
EmfPlusFillRects *record = (EmfPlusFillRects*)header;
@ -724,6 +922,24 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
}
case EmfPlusRecordTypeScaleWorldTransform:
{
EmfPlusScaleWorldTransform *record = (EmfPlusScaleWorldTransform*)header;
MatrixOrder order = (flags & 0x4) ? MatrixOrderAppend : MatrixOrderPrepend;
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusScaleWorldTransform))
return InvalidParameter;
GdipScaleMatrix(real_metafile->world_transform, record->Sx, record->Sy, order);
return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
}
case EmfPlusRecordTypeResetWorldTransform:
{
GdipSetMatrixElements(real_metafile->world_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
}
default:
FIXME("Not implemented for record type %x\n", recordType);
return NotImplemented;
@ -799,6 +1015,7 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
GpStatus stat;
GpMetafile *real_metafile = (GpMetafile*)metafile; /* whoever made this const was joking */
GraphicsContainer state;
GpPath *dst_path;
TRACE("(%p,%p,%p,%i,%p,%i,%p,%p,%p)\n", graphics, metafile,
destPoints, count, srcRect, srcUnit, callback, callbackData,
@ -838,6 +1055,38 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
if (stat == Ok)
stat = GdipSetPageUnit(graphics, UnitPixel);
if (stat == Ok)
stat = GdipResetWorldTransform(graphics);
if (stat == Ok)
stat = GdipCreateRegion(&real_metafile->base_clip);
if (stat == Ok)
stat = GdipGetClip(graphics, real_metafile->base_clip);
if (stat == Ok)
stat = GdipCreatePath(FillModeAlternate, &dst_path);
if (stat == Ok)
{
GpPointF clip_points[4];
clip_points[0] = real_metafile->playback_points[0];
clip_points[1] = real_metafile->playback_points[1];
clip_points[2].X = real_metafile->playback_points[1].X + real_metafile->playback_points[2].X
- real_metafile->playback_points[0].X;
clip_points[2].Y = real_metafile->playback_points[1].Y + real_metafile->playback_points[2].Y
- real_metafile->playback_points[0].Y;
clip_points[3] = real_metafile->playback_points[2];
stat = GdipAddPathPolygon(dst_path, clip_points, 4);
if (stat == Ok)
stat = GdipCombineRegionPath(real_metafile->base_clip, dst_path, CombineModeIntersect);
GdipDeletePath(dst_path);
}
if (stat == Ok)
stat = GdipCreateMatrix(&real_metafile->world_transform);
@ -848,6 +1097,11 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
stat = METAFILE_PlaybackUpdateWorldTransform(real_metafile);
}
if (stat == Ok)
{
stat = METAFILE_PlaybackUpdateClip(real_metafile);
}
if (stat == Ok && (metafile->metafile_type == MetafileTypeEmf ||
metafile->metafile_type == MetafileTypeWmfPlaceable ||
metafile->metafile_type == MetafileTypeWmf))
@ -861,6 +1115,9 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
GdipDeleteMatrix(real_metafile->world_transform);
real_metafile->world_transform = NULL;
GdipDeleteRegion(real_metafile->base_clip);
real_metafile->base_clip = NULL;
GdipEndContainer(graphics, state);
}
@ -1205,8 +1462,22 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmfFile(GDIPCONST WCHAR *file,
GpStatus WINGDIPAPI GdipCreateMetafileFromFile(GDIPCONST WCHAR *file,
GpMetafile **metafile)
{
FIXME("(%p, %p): stub\n", file, metafile);
return NotImplemented;
GpStatus status;
IStream *stream;
TRACE("(%p, %p)\n", file, metafile);
if (!file || !metafile) return InvalidParameter;
*metafile = NULL;
status = GdipCreateStreamOnFile(file, GENERIC_READ, &stream);
if (status == Ok)
{
status = GdipCreateMetafileFromStream(stream, metafile);
IStream_Release(stream);
}
return status;
}
GpStatus WINGDIPAPI GdipCreateMetafileFromStream(IStream *stream,

View file

@ -809,7 +809,7 @@ static void write_element(const region_element* element, DWORD *buffer,
* their code followed by a second header for the path followed by the actual
* path data. Followed by the flags for each point. The pathheader contains
* the size of the data to follow, a version number again, followed by a count
* of how many points, and any special flags which may apply. 0x4000 means its
* of how many points, and any special flags which may apply. 0x4000 means it's
* a path of shorts instead of FLOAT.
*
* Combining Ops are stored in reverse order from when they were constructed;
@ -1102,6 +1102,12 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
GpStatus stat;
INT save_state;
if (!path->pathdata.Count) /* PathToRegion doesn't support empty paths */
{
*hrgn = CreateRectRgn( 0, 0, 0, 0 );
return *hrgn ? Ok : OutOfMemory;
}
if (!graphics)
{
new_hdc = CreateCompatibleDC(0);
@ -1384,11 +1390,7 @@ GpStatus WINGDIPAPI GdipIsVisibleRegionRect(GpRegion* region, REAL x, REAL y, RE
return Ok;
}
rect.left = ceilr(x);
rect.top = ceilr(y);
rect.right = ceilr(x + w);
rect.bottom = ceilr(y + h);
SetRect(&rect, ceilr(x), ceilr(y), ceilr(x + w), ceilr(y + h));
*res = RectInRegion(hrgn, &rect);
DeleteObject(hrgn);

View file

@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-1.9.11
reactos/dll/win32/faultrep # Synced to WineStaging-1.9.11
reactos/dll/win32/fontsub # Synced to WineStaging-1.9.13
reactos/dll/win32/fusion # Synced to WineStaging-1.9.11
reactos/dll/win32/gdiplus # Synced to WineStaging-1.9.11
reactos/dll/win32/gdiplus # Synced to WineStaging-1.9.16
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-1.9.16
reactos/dll/win32/hlink # Synced to WineStaging-1.9.16
reactos/dll/win32/hnetcfg # Synced to WineStaging-1.9.11