gdiplus: Support GdipSetClipRegion in metafiles.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2017-08-10 20:56:19 +02:00 committed by Alexandre Julliard
parent 4a02870296
commit 14bb8df8a5
5 changed files with 77 additions and 1 deletions

View File

@ -93,6 +93,7 @@ extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN; GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile, extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile,
REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN; REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
@ -124,6 +125,7 @@ extern void free_installed_fonts(void) DECLSPEC_HIDDEN;
extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN; extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN;
extern DWORD write_region_data(const GpRegion *region, void *data) DECLSPEC_HIDDEN;
extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN; extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN;
extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN; extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;

View File

@ -6269,6 +6269,13 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
if(graphics->busy) if(graphics->busy)
return ObjectBusy; return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile)
{
status = METAFILE_SetClipRegion((GpMetafile*)graphics->image, region, mode);
if (status != Ok)
return status;
}
status = GdipCloneRegion(region, &clip); status = GdipCloneRegion(region, &clip);
if (status == Ok) if (status == Ok)
{ {

View File

@ -239,6 +239,13 @@ typedef struct EmfPlusPath
BYTE data[1]; BYTE data[1];
} EmfPlusPath; } EmfPlusPath;
typedef struct EmfPlusRegion
{
DWORD Version;
DWORD RegionNodeCount;
BYTE RegionNode[1];
} EmfPlusRegion;
typedef enum typedef enum
{ {
BitmapDataTypePixel, BitmapDataTypePixel,
@ -312,6 +319,7 @@ typedef struct EmfPlusObject
EmfPlusBrush brush; EmfPlusBrush brush;
EmfPlusPen pen; EmfPlusPen pen;
EmfPlusPath path; EmfPlusPath path;
EmfPlusRegion region;
EmfPlusImage image; EmfPlusImage image;
EmfPlusImageAttributes image_attributes; EmfPlusImageAttributes image_attributes;
} ObjectData; } ObjectData;
@ -847,6 +855,53 @@ GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width,
return Ok; return Ok;
} }
static GpStatus METAFILE_AddRegionObject(GpMetafile *metafile, GpRegion *region, DWORD *id)
{
EmfPlusObject *object_record;
DWORD size;
GpStatus stat;
*id = -1;
if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile_type != MetafileTypeEmfPlusDual)
return Ok;
size = write_region_data(region, NULL);
stat = METAFILE_AllocateRecord(metafile,
FIELD_OFFSET(EmfPlusObject, ObjectData.region) + size, (void**)&object_record);
if (stat != Ok) return stat;
*id = METAFILE_AddObjectId(metafile);
object_record->Header.Type = EmfPlusRecordTypeObject;
object_record->Header.Flags = *id | ObjectTypeRegion << 8;
write_region_data(region, &object_record->ObjectData.region);
return Ok;
}
GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode)
{
EmfPlusRecordHeader *record;
DWORD region_id;
GpStatus stat;
if (metafile->metafile_type == MetafileTypeEmf)
{
FIXME("stub!\n");
return NotImplemented;
}
stat = METAFILE_AddRegionObject(metafile, region, &region_id);
if (stat != Ok) return stat;
stat = METAFILE_AllocateRecord(metafile, sizeof(*record), (void**)&record);
if (stat != Ok) return stat;
record->Type = EmfPlusRecordTypeSetClipRegion;
record->Flags = region_id | mode << 8;
METAFILE_WriteRecords(metafile);
return Ok;
}
GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale)
{ {
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)

View File

@ -699,7 +699,7 @@ static void write_element(const region_element* element, DWORD *buffer,
} }
} }
static DWORD write_region_data(const GpRegion *region, void *data) DWORD write_region_data(const GpRegion *region, void *data)
{ {
struct region_header *header = data; struct region_header *header = data;
INT filled = 0; INT filled = 0;

View File

@ -2154,6 +2154,8 @@ static const emfplus_record clipping_records[] = {
{0, EmfPlusRecordTypeRestore}, {0, EmfPlusRecordTypeRestore},
{0, EmfPlusRecordTypeSetClipRect}, {0, EmfPlusRecordTypeSetClipRect},
{0, EmfPlusRecordTypeFillRects}, {0, EmfPlusRecordTypeFillRects},
{0, EmfPlusRecordTypeObject, 1},
{0, EmfPlusRecordTypeSetClipRegion, 1},
{0, EmfPlusRecordTypeEndOfFile}, {0, EmfPlusRecordTypeEndOfFile},
{0, EMR_EOF}, {0, EMR_EOF},
{0} {0}
@ -2165,6 +2167,7 @@ static void test_clipping(void)
GpMetafile *metafile; GpMetafile *metafile;
GpGraphics *graphics; GpGraphics *graphics;
GpBitmap *bitmap; GpBitmap *bitmap;
GpRegion *region;
GpBrush *brush; GpBrush *brush;
GpRectF rect; GpRectF rect;
ARGB color; ARGB color;
@ -2231,6 +2234,15 @@ static void test_clipping(void)
stat = GdipDeleteBrush(brush); stat = GdipDeleteBrush(brush);
expect(Ok, stat); expect(Ok, stat);
stat = GdipCreateRegionRect(&rect, &region);
expect(Ok, stat);
stat = GdipSetClipRegion(graphics, region, CombineModeIntersect);
expect(Ok, stat);
stat = GdipDeleteRegion(region);
expect(Ok, stat);
stat = GdipDeleteGraphics(graphics); stat = GdipDeleteGraphics(graphics);
expect(Ok, stat); expect(Ok, stat);