"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "dlls/gdiplus/metafile.c" between
wine-5.12.tar.xz and wine-5.13.tar.xz

About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs. Development release.

metafile.c  (wine-5.12.tar.xz):metafile.c  (wine-5.13.tar.xz)
skipping to change at line 381 skipping to change at line 381
typedef struct EmfPlusImageAttributes typedef struct EmfPlusImageAttributes
{ {
DWORD Version; DWORD Version;
DWORD Reserved1; DWORD Reserved1;
DWORD WrapMode; DWORD WrapMode;
EmfPlusARGB ClampColor; EmfPlusARGB ClampColor;
DWORD ObjectClamp; DWORD ObjectClamp;
DWORD Reserved2; DWORD Reserved2;
} EmfPlusImageAttributes; } EmfPlusImageAttributes;
typedef struct EmfPlusFont
{
DWORD Version;
float EmSize;
DWORD SizeUnit;
DWORD FontStyleFlags;
DWORD Reserved;
DWORD Length;
WCHAR FamilyName[1];
} EmfPlusFont;
typedef struct EmfPlusObject typedef struct EmfPlusObject
{ {
EmfPlusRecordHeader Header; EmfPlusRecordHeader Header;
union union
{ {
EmfPlusBrush brush; EmfPlusBrush brush;
EmfPlusPen pen; EmfPlusPen pen;
EmfPlusPath path; EmfPlusPath path;
EmfPlusRegion region; EmfPlusRegion region;
EmfPlusImage image; EmfPlusImage image;
EmfPlusImageAttributes image_attributes; EmfPlusImageAttributes image_attributes;
EmfPlusFont font;
} ObjectData; } ObjectData;
} EmfPlusObject; } EmfPlusObject;
typedef struct EmfPlusPointR7 typedef struct EmfPlusPointR7
{ {
BYTE X; BYTE X;
BYTE Y; BYTE Y;
} EmfPlusPointR7; } EmfPlusPointR7;
typedef struct EmfPlusPoint typedef struct EmfPlusPoint
skipping to change at line 540 skipping to change at line 552
DWORD BrushId; DWORD BrushId;
float StartAngle; float StartAngle;
float SweepAngle; float SweepAngle;
union union
{ {
EmfPlusRect rect; EmfPlusRect rect;
EmfPlusRectF rectF; EmfPlusRectF rectF;
} RectData; } RectData;
} EmfPlusFillPie; } EmfPlusFillPie;
typedef struct EmfPlusFont typedef struct EmfPlusDrawDriverString
{ {
DWORD Version; EmfPlusRecordHeader Header;
float EmSize; union
DWORD SizeUnit; {
DWORD FontStyleFlags; DWORD BrushId;
DWORD Reserved; ARGB Color;
DWORD Length; } brush;
WCHAR FamilyName[1]; DWORD DriverStringOptionsFlags;
} EmfPlusFont; DWORD MatrixPresent;
DWORD GlyphCount;
BYTE VariableData[1];
} EmfPlusDrawDriverString;
static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id) static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id)
{ {
struct emfplus_object *object = &metafile->objtable[id]; struct emfplus_object *object = &metafile->objtable[id];
switch (object->type) switch (object->type)
{ {
case ObjectTypeInvalid: case ObjectTypeInvalid:
break; break;
case ObjectTypeBrush: case ObjectTypeBrush:
skipping to change at line 1004 skipping to change at line 1019
x = rect->X; x = rect->X;
y = rect->Y; y = rect->Y;
width = rect->Width; width = rect->Width;
height = rect->Height; height = rect->Height;
if (rect->X != (REAL)x || rect->Y != (REAL)y || if (rect->X != (REAL)x || rect->Y != (REAL)y ||
rect->Width != (REAL)width || rect->Height != (REAL)height) rect->Width != (REAL)width || rect->Height != (REAL)height)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static GpStatus METAFILE_PrepareBrushData(GpBrush *brush, DWORD *size) static GpStatus METAFILE_PrepareBrushData(GDIPCONST GpBrush *brush, DWORD *size)
{ {
switch (brush->bt) switch (brush->bt)
{ {
case BrushTypeSolidColor: case BrushTypeSolidColor:
*size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusSolidBrush Data); *size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusSolidBrush Data);
break; break;
case BrushTypeHatchFill: case BrushTypeHatchFill:
*size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusHatchBrush Data); *size = FIELD_OFFSET(EmfPlusBrush, BrushData) + sizeof(EmfPlusHatchBrush Data);
break; break;
default: default:
FIXME("unsupported brush type: %d\n", brush->bt); FIXME("unsupported brush type: %d\n", brush->bt);
return NotImplemented; return NotImplemented;
} }
return Ok; return Ok;
} }
static void METAFILE_FillBrushData(GpBrush *brush, EmfPlusBrush *data) static void METAFILE_FillBrushData(GDIPCONST GpBrush *brush, EmfPlusBrush *data)
{ {
data->Version = VERSION_MAGIC2; data->Version = VERSION_MAGIC2;
data->Type = brush->bt; data->Type = brush->bt;
switch (brush->bt) switch (brush->bt)
{ {
case BrushTypeSolidColor: case BrushTypeSolidColor:
{ {
GpSolidFill *solid = (GpSolidFill *)brush; GpSolidFill *solid = (GpSolidFill *)brush;
data->BrushData.solid.SolidColor = solid->color; data->BrushData.solid.SolidColor = solid->color;
skipping to change at line 1048 skipping to change at line 1063
data->BrushData.hatch.HatchStyle = hatch->hatchstyle; data->BrushData.hatch.HatchStyle = hatch->hatchstyle;
data->BrushData.hatch.ForeColor = hatch->forecol; data->BrushData.hatch.ForeColor = hatch->forecol;
data->BrushData.hatch.BackColor = hatch->backcol; data->BrushData.hatch.BackColor = hatch->backcol;
break; break;
} }
default: default:
FIXME("unsupported brush type: %d\n", brush->bt); FIXME("unsupported brush type: %d\n", brush->bt);
} }
} }
static GpStatus METAFILE_AddBrushObject(GpMetafile *metafile, GpBrush *brush, DW ORD *id) static GpStatus METAFILE_AddBrushObject(GpMetafile *metafile, GDIPCONST GpBrush *brush, DWORD *id)
{ {
EmfPlusObject *object_record; EmfPlusObject *object_record;
GpStatus stat; GpStatus stat;
DWORD size; DWORD size;
*id = -1; *id = -1;
if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile _type != MetafileTypeEmfPlusDual) if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile _type != MetafileTypeEmfPlusDual)
return Ok; return Ok;
stat = METAFILE_PrepareBrushData(brush, &size); stat = METAFILE_PrepareBrushData(brush, &size);
skipping to change at line 3336 skipping to change at line 3351
rects[i].Width = draw->RectData.rect[i].Width; rects[i].Width = draw->RectData.rect[i].Width;
rects[i].Height = draw->RectData.rect[i].Height; rects[i].Height = draw->RectData.rect[i].Height;
} }
} }
stat = GdipDrawRectangles(real_metafile->playback_graphics, real_met afile->objtable[pen].u.pen, stat = GdipDrawRectangles(real_metafile->playback_graphics, real_met afile->objtable[pen].u.pen,
rects ? rects : (GpRectF *)draw->RectData.rectF, draw->Count ); rects ? rects : (GpRectF *)draw->RectData.rectF, draw->Count );
GdipFree(rects); GdipFree(rects);
return stat; 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(*positio
ns));
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**)&so
lidfill);
if (stat != Ok)
return InvalidParameter;
brush = (GpBrush*)solidfill;
}
else
{
if (draw->brush.BrushId >= EmfPlusObjectTableSize ||
real_metafile->objtable[draw->brush.BrushId].type != Obj
ectTypeBrush)
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: default:
FIXME("Not implemented for record type %x\n", recordType); FIXME("Not implemented for record type %x\n", recordType);
return NotImplemented; return NotImplemented;
} }
} }
return Ok; return Ok;
} }
struct enum_metafile_data struct enum_metafile_data
skipping to change at line 4547 skipping to change at line 4647
} }
else else
{ {
fill_path_record->Header.Flags = path_id; fill_path_record->Header.Flags = path_id;
fill_path_record->data.BrushId = brush_id; fill_path_record->data.BrushId = brush_id;
} }
METAFILE_WriteRecords(metafile); METAFILE_WriteRecords(metafile);
return Ok; return Ok;
} }
static GpStatus METAFILE_AddFontObject(GpMetafile *metafile, GDIPCONST GpFont *f
ont, 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_re
cord);
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 pad
ding\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;
}
 End of changes. 9 change blocks. 
12 lines changed or deleted 117 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)