Commit 71bb5cd5 authored by Shawn M. Chapla's avatar Shawn M. Chapla Committed by Alexandre Julliard

gdiplus: Add DrawDriverString serialization.

parent 30c7fe69
......@@ -104,6 +104,9 @@ extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *imag
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 GpStatus METAFILE_DrawDriverString(GpMetafile *metafile, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush,
GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix) DECLSPEC_HIDDEN;
extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
......
......@@ -7427,6 +7427,10 @@ static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text,
if (length == -1)
length = lstrlenW(text);
if (graphics->image && graphics->image->type == ImageTypeMetafile)
return METAFILE_DrawDriverString((GpMetafile*)graphics->image, text, length, font,
format, brush, positions, flags, matrix);
if (graphics->hdc && !graphics->alpha_hdc &&
brush->bt == BrushTypeSolidColor &&
(((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
......
......@@ -378,6 +378,17 @@ typedef struct EmfPlusImageAttributes
DWORD Reserved2;
} EmfPlusImageAttributes;
typedef struct EmfPlusFont
{
DWORD Version;
float EmSize;
DWORD SizeUnit;
DWORD FontStyleFlags;
DWORD Reserved;
DWORD Length;
WCHAR FamilyName[1];
} EmfPlusFont;
typedef struct EmfPlusObject
{
EmfPlusRecordHeader Header;
......@@ -389,6 +400,7 @@ typedef struct EmfPlusObject
EmfPlusRegion region;
EmfPlusImage image;
EmfPlusImageAttributes image_attributes;
EmfPlusFont font;
} ObjectData;
} EmfPlusObject;
......@@ -537,17 +549,6 @@ typedef struct EmfPlusFillPie
} RectData;
} EmfPlusFillPie;
typedef struct EmfPlusFont
{
DWORD Version;
float EmSize;
DWORD SizeUnit;
DWORD FontStyleFlags;
DWORD Reserved;
DWORD Length;
WCHAR FamilyName[1];
} EmfPlusFont;
typedef struct EmfPlusDrawDriverString
{
EmfPlusRecordHeader Header;
......@@ -4643,3 +4644,162 @@ GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path)
METAFILE_WriteRecords(metafile);
return Ok;
}
static GpStatus METAFILE_AddFontObject(GpMetafile *metafile, GDIPCONST GpFont *font, DWORD *id)
{
EmfPlusObject *object_record;
EmfPlusFont *font_record;
GpStatus stat;
INT fn_len;
INT style;
*id = -1;
if (metafile->metafile_type != MetafileTypeEmfPlusOnly &&
metafile->metafile_type != MetafileTypeEmfPlusDual)
return Ok;
/* The following cast is ugly, but GdipGetFontStyle does treat
its first parameter as const. */
stat = GdipGetFontStyle((GpFont*)font, &style);
if (stat != Ok)
return stat;
fn_len = lstrlenW(font->family->FamilyName);
stat = METAFILE_AllocateRecord(metafile,
FIELD_OFFSET(EmfPlusObject, ObjectData.font.FamilyName[(fn_len + 1) & ~1]),
(void**)&object_record);
if (stat != Ok)
return stat;
*id = METAFILE_AddObjectId(metafile);
object_record->Header.Type = EmfPlusRecordTypeObject;
object_record->Header.Flags = *id | ObjectTypeFont << 8;
font_record = &object_record->ObjectData.font;
font_record->Version = VERSION_MAGIC2;
font_record->EmSize = font->emSize;
font_record->SizeUnit = font->unit;
font_record->FontStyleFlags = style;
font_record->Reserved = 0;
font_record->Length = fn_len;
memcpy(font_record->FamilyName, font->family->FamilyName,
fn_len * sizeof(*font->family->FamilyName));
return Ok;
}
GpStatus METAFILE_DrawDriverString(GpMetafile *metafile, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush,
GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix)
{
DWORD brush_id;
DWORD font_id;
DWORD alloc_size;
GpStatus stat;
EmfPlusDrawDriverString *draw_string_record;
BYTE *cursor;
BOOL inline_color;
BOOL include_matrix = FALSE;
if (length <= 0)
return InvalidParameter;
if (metafile->metafile_type != MetafileTypeEmfPlusOnly &&
metafile->metafile_type != MetafileTypeEmfPlusDual)
{
FIXME("metafile type not supported: %i\n", metafile->metafile_type);
return NotImplemented;
}
stat = METAFILE_AddFontObject(metafile, font, &font_id);
if (stat != Ok)
return stat;
inline_color = (brush->bt == BrushTypeSolidColor);
if (!inline_color)
{
stat = METAFILE_AddBrushObject(metafile, brush, &brush_id);
if (stat != Ok)
return stat;
}
if (matrix)
{
BOOL identity;
stat = GdipIsMatrixIdentity(matrix, &identity);
if (stat != Ok)
return stat;
include_matrix = !identity;
}
alloc_size = FIELD_OFFSET(EmfPlusDrawDriverString, VariableData) +
length * (sizeof(*text) + sizeof(*positions));
if (include_matrix)
alloc_size += sizeof(*matrix);
/* Pad record to DWORD alignment. */
alloc_size = (alloc_size + 3) & ~3;
stat = METAFILE_AllocateRecord(metafile, alloc_size, (void**)&draw_string_record);
if (stat != Ok)
return stat;
draw_string_record->Header.Type = EmfPlusRecordTypeDrawDriverString;
draw_string_record->Header.Flags = font_id;
draw_string_record->DriverStringOptionsFlags = flags;
draw_string_record->MatrixPresent = include_matrix;
draw_string_record->GlyphCount = length;
if (inline_color)
{
draw_string_record->Header.Flags |= 0x8000;
draw_string_record->brush.Color = ((GpSolidFill*)brush)->color;
}
else
draw_string_record->brush.BrushId = brush_id;
cursor = &draw_string_record->VariableData[0];
memcpy(cursor, text, length * sizeof(*text));
cursor += length * sizeof(*text);
if (flags & DriverStringOptionsRealizedAdvance)
{
static BOOL fixme_written = FALSE;
/* Native never writes DriverStringOptionsRealizedAdvance. Instead,
in the case of RealizedAdvance, each glyph position is computed
and serialized.
While native GDI+ is capable of playing back metafiles with this
flag set, it is possible that some application might rely on
metafiles produced from GDI+ not setting this flag. Ideally we
would also compute the position of each glyph here, serialize those
values, and not set DriverStringOptionsRealizedAdvance. */
if (!fixme_written)
{
fixme_written = TRUE;
FIXME("serializing RealizedAdvance flag and single GlyphPos with padding\n");
}
*((PointF*)cursor) = *positions;
}
else
memcpy(cursor, positions, length * sizeof(*positions));
if (include_matrix)
{
cursor += length * sizeof(*positions);
memcpy(cursor, matrix, sizeof(*matrix));
}
METAFILE_WriteRecords(metafile);
return Ok;
}
......@@ -2956,11 +2956,11 @@ static void test_restoredc(void)
static const emfplus_record drawdriverstring_records[] = {
{ EMR_HEADER },
{ EmfPlusRecordTypeHeader },
{ EmfPlusRecordTypeObject, ObjectTypeFont << 8, 1, 0 },
{ EmfPlusRecordTypeDrawDriverString, 0x8000, 1, 0 },
{ EmfPlusRecordTypeObject, (ObjectTypeFont << 8) | 1, 1 },
{ EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2, 1, 1 },
{ EmfPlusRecordTypeDrawDriverString, 0x1, 1, 1 },
{ EmfPlusRecordTypeObject, ObjectTypeFont << 8 },
{ EmfPlusRecordTypeDrawDriverString, 0x8000 },
{ EmfPlusRecordTypeObject, (ObjectTypeFont << 8) | 1 },
{ EmfPlusRecordTypeObject, (ObjectTypeBrush << 8) | 2 },
{ EmfPlusRecordTypeDrawDriverString, 0x1 },
{ EmfPlusRecordTypeEndOfFile },
{ EMR_EOF },
{ 0 }
......@@ -3022,14 +3022,14 @@ static void test_drawdriverstring(void)
stat = GdipDrawDriverString(graphics, L"Test", 4, solidfont, solidbrush, solidpos,
DriverStringOptionsCmapLookup, matrix);
todo_wine expect(Ok, stat);
expect(Ok, stat);
stat = GdipSetMatrixElements(matrix, 1.5, 0.0, 0.0, 1.5, 0.0, 0.0);
expect(Ok, stat);
stat = GdipDrawDriverString(graphics, L"Test ", 5, hatchfont, hatchbrush, &hatchpos,
DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, matrix);
todo_wine expect(Ok, stat);
expect(Ok, stat);
stat = GdipDeleteGraphics(graphics);
graphics = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment