gdiplus: Add partial support for GdipFillPath on 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-07-13 11:54:00 +02:00 committed by Alexandre Julliard
parent e79c4caf14
commit de37cedb70
4 changed files with 152 additions and 0 deletions

View file

@ -112,6 +112,7 @@ extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *imag
DrawImageAbort callback, VOID *callbackData) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;

View file

@ -4140,6 +4140,9 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p
if(graphics->busy)
return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile)
return METAFILE_FillPath((GpMetafile*)graphics->image, brush, path);
if (!graphics->image && !graphics->alpha_hdc)
stat = GDI32_GdipFillPath(graphics, brush, path);

View file

@ -309,6 +309,7 @@ typedef struct EmfPlusObject
EmfPlusRecordHeader Header;
union
{
EmfPlusBrush brush;
EmfPlusPen pen;
EmfPlusPath path;
EmfPlusImage image;
@ -351,6 +352,16 @@ typedef struct EmfPlusDrawPath
DWORD PenId;
} EmfPlusDrawPath;
typedef struct EmfPlusFillPath
{
EmfPlusRecordHeader Header;
union
{
DWORD BrushId;
EmfPlusARGB Color;
} data;
} EmfPlusFillPath;
static DWORD METAFILE_AddObjectId(GpMetafile *metafile)
{
return (metafile->next_object_id++) % 64;
@ -2915,3 +2926,72 @@ GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path)
METAFILE_WriteRecords(metafile);
return NotImplemented;
}
static GpStatus METAFILE_AddBrushObject(GpMetafile *metafile, GpBrush *brush, DWORD *id)
{
EmfPlusObject *object_record;
GpStatus stat;
DWORD size;
*id = -1;
if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile_type != MetafileTypeEmfPlusDual)
return Ok;
stat = METAFILE_PrepareBrushData(brush, &size);
if (stat != Ok) return stat;
stat = METAFILE_AllocateRecord(metafile,
FIELD_OFFSET(EmfPlusObject, ObjectData) + size, (void**)&object_record);
if (stat != Ok) return stat;
*id = METAFILE_AddObjectId(metafile);
object_record->Header.Type = EmfPlusRecordTypeObject;
object_record->Header.Flags = *id | ObjectTypeBrush << 8;
METAFILE_FillBrushData(brush, &object_record->ObjectData.brush);
return Ok;
}
GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path)
{
EmfPlusFillPath *fill_path_record;
DWORD brush_id = -1, path_id;
BOOL inline_color;
GpStatus stat;
if (metafile->metafile_type == MetafileTypeEmf)
{
FIXME("stub!\n");
return NotImplemented;
}
inline_color = brush->bt == BrushTypeSolidColor;
if (!inline_color)
{
stat = METAFILE_AddBrushObject(metafile, brush, &brush_id);
if (stat != Ok) return stat;
}
stat = METAFILE_AddPathObject(metafile, path, &path_id);
if (stat != Ok) return stat;
stat = METAFILE_AllocateRecord(metafile,
sizeof(EmfPlusFillPath), (void**)&fill_path_record);
if (stat != Ok) return stat;
fill_path_record->Header.Type = EmfPlusRecordTypeFillPath;
if (inline_color)
{
fill_path_record->Header.Flags = 0x8000 | path_id;
fill_path_record->data.Color.Blue = ((GpSolidFill*)brush)->color & 0xff;
fill_path_record->data.Color.Green = (((GpSolidFill*)brush)->color >> 8) & 0xff;
fill_path_record->data.Color.Red = (((GpSolidFill*)brush)->color >> 16) & 0xff;
fill_path_record->data.Color.Alpha = ((GpSolidFill*)brush)->color >> 24;
}
else
{
fill_path_record->Header.Flags = path_id;
fill_path_record->data.BrushId = brush_id;
}
METAFILE_WriteRecords(metafile);
return Ok;
}

View file

@ -2549,6 +2549,73 @@ static void test_drawpath(void)
expect(Ok, stat);
}
static const emfplus_record fill_path_records[] = {
{0, EMR_HEADER},
{0, EmfPlusRecordTypeHeader},
{0, EmfPlusRecordTypeObject},
{0, EmfPlusRecordTypeFillPath},
{1, EMR_SAVEDC},
{1, EMR_SETICMMODE},
{1, EMR_BITBLT},
{1, EMR_RESTOREDC},
{0, EmfPlusRecordTypeEndOfFile},
{0, EMR_EOF},
{0}
};
static void test_fillpath(void)
{
static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
GpMetafile *metafile;
GpGraphics *graphics;
GpSolidFill *brush;
HENHMETAFILE hemf;
GpStatus stat;
GpPath *path;
HDC hdc;
hdc = CreateCompatibleDC(0);
stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
expect(Ok, stat);
DeleteDC(hdc);
stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
expect(Ok, stat);
stat = GdipCreatePath(FillModeAlternate, &path);
expect(Ok, stat);
stat = GdipAddPathLine(path, 5, 5, 30, 30);
expect(Ok, stat);
stat = GdipAddPathLine(path, 30, 30, 5, 30);
expect(Ok, stat);
stat = GdipCreateSolidFill(0xffaabbcc, &brush);
expect(Ok, stat);
stat = GdipFillPath(graphics, (GpBrush*)brush, path);
expect(Ok, stat);
stat = GdipDeleteBrush((GpBrush*)brush);
expect(Ok, stat);
stat = GdipDeletePath(path);
expect(Ok, stat);
stat = GdipDeleteGraphics(graphics);
expect(Ok, stat);
sync_metafile(&metafile, "fill_path.emf");
stat = GdipGetHemfFromMetafile(metafile, &hemf);
expect(Ok, stat);
check_emfplus(hemf, fill_path_records, "fill path");
DeleteEnhMetaFile(hemf);
stat = GdipDisposeImage((GpImage*)metafile);
expect(Ok, stat);
}
START_TEST(metafile)
{
struct GdiplusStartupInput gdiplusStartupInput;
@ -2589,6 +2656,7 @@ START_TEST(metafile)
test_drawimage();
test_properties();
test_drawpath();
test_fillpath();
GdiplusShutdown(gdiplusToken);
}