[PATCH 3/4] gdiplus: Add DrawDriverString record deserialization.
Shawn M. Chapla
schapla at codeweavers.com
Fri Jul 10 17:25:17 CDT 2020
Signed-off-by: Shawn M. Chapla <schapla at codeweavers.com>
---
dlls/gdiplus/metafile.c | 99 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index b50a106e98..d25278d115 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -548,6 +548,20 @@ typedef struct EmfPlusFont
WCHAR FamilyName[1];
} EmfPlusFont;
+typedef struct EmfPlusDrawDriverString
+{
+ EmfPlusRecordHeader Header;
+ union
+ {
+ DWORD BrushId;
+ ARGB Color;
+ } brush;
+ DWORD DriverStringOptionsFlags;
+ DWORD MatrixPresent;
+ DWORD GlyphCount;
+ BYTE VariableData[1];
+} EmfPlusDrawDriverString;
+
static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id)
{
struct emfplus_object *object = &metafile->objtable[id];
@@ -3333,6 +3347,91 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
GdipFree(rects);
return stat;
}
+ case EmfPlusRecordTypeDrawDriverString:
+ {
+ GpBrush *brush;
+ DWORD expected_size;
+ UINT16 *text;
+ PointF *positions;
+ GpSolidFill *solidfill = NULL;
+ void* alignedmem = NULL;
+ GpMatrix *matrix = NULL;
+ BYTE font = flags & 0xff;
+ EmfPlusDrawDriverString *draw = (EmfPlusDrawDriverString*)header;
+
+ if (font >= EmfPlusObjectTableSize ||
+ real_metafile->objtable[font].type != ObjectTypeFont)
+ return InvalidParameter;
+
+ expected_size = FIELD_OFFSET(EmfPlusDrawDriverString, VariableData) -
+ sizeof(EmfPlusRecordHeader);
+ if (dataSize < expected_size || draw->GlyphCount <= 0)
+ return InvalidParameter;
+
+ expected_size += draw->GlyphCount * (sizeof(*text) + sizeof(*positions));
+ if (draw->MatrixPresent)
+ expected_size += sizeof(*matrix);
+
+ /* Pad expected size to DWORD alignment. */
+ expected_size = (expected_size + 3) & ~3;
+
+ if (dataSize != expected_size)
+ return InvalidParameter;
+
+ if (flags & 0x8000)
+ {
+ stat = GdipCreateSolidFill(draw->brush.Color, (GpSolidFill**)&solidfill);
+
+ if (stat != Ok)
+ return InvalidParameter;
+
+ brush = (GpBrush*)solidfill;
+ }
+ else
+ {
+ if (draw->brush.BrushId >= EmfPlusObjectTableSize ||
+ real_metafile->objtable[draw->brush.BrushId].type != ObjectTypeBrush)
+ return InvalidParameter;
+
+ brush = real_metafile->objtable[draw->brush.BrushId].u.brush;
+ }
+
+ text = (UINT16*)&draw->VariableData[0];
+
+ /* If GlyphCount is odd, all subsequent fields will be 2-byte
+ aligned rather than 4-byte aligned, which may lead to access
+ issues. Handle this case by making our own copy of positions. */
+ if (draw->GlyphCount % 2)
+ {
+ SIZE_T alloc_size = draw->GlyphCount * sizeof(*positions);
+
+ if (draw->MatrixPresent)
+ alloc_size += sizeof(*matrix);
+
+ positions = alignedmem = heap_alloc(alloc_size);
+ if (!positions)
+ {
+ GdipDeleteBrush((GpBrush*)solidfill);
+ return OutOfMemory;
+ }
+
+ memcpy(positions, &text[draw->GlyphCount], alloc_size);
+ }
+ else
+ positions = (PointF*)&text[draw->GlyphCount];
+
+ if (draw->MatrixPresent)
+ matrix = (GpMatrix*)&positions[draw->GlyphCount];
+
+ stat = GdipDrawDriverString(real_metafile->playback_graphics, text, draw->GlyphCount,
+ real_metafile->objtable[font].u.font, brush, positions,
+ draw->DriverStringOptionsFlags, matrix);
+
+ GdipDeleteBrush((GpBrush*)solidfill);
+ heap_free(alignedmem);
+
+ return stat;
+ }
default:
FIXME("Not implemented for record type %x\n", recordType);
return NotImplemented;
--
2.27.0
More information about the wine-devel
mailing list