gdiplus/metafile: Implement EmfPlusRecordTypeObject for image attributes object.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2e877152de
commit
825f393299
|
@ -121,6 +121,7 @@ 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 void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
|
||||
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
|
||||
|
@ -371,6 +372,32 @@ struct GpImage{
|
|||
LONG busy;
|
||||
};
|
||||
|
||||
#define EmfPlusObjectTableSize 64
|
||||
|
||||
typedef enum EmfPlusObjectType
|
||||
{
|
||||
ObjectTypeInvalid,
|
||||
ObjectTypeBrush,
|
||||
ObjectTypePen,
|
||||
ObjectTypePath,
|
||||
ObjectTypeRegion,
|
||||
ObjectTypeImage,
|
||||
ObjectTypeFont,
|
||||
ObjectTypeStringFormat,
|
||||
ObjectTypeImageAttributes,
|
||||
ObjectTypeCustomLineCap,
|
||||
ObjectTypeMax = ObjectTypeCustomLineCap,
|
||||
} EmfPlusObjectType;
|
||||
|
||||
/* Deserialized EmfPlusObject record. */
|
||||
struct emfplus_object {
|
||||
EmfPlusObjectType type;
|
||||
union {
|
||||
GpImageAttributes *image_attributes;
|
||||
void *object;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct GpMetafile{
|
||||
GpImage image;
|
||||
GpRectF bounds;
|
||||
|
@ -404,6 +431,7 @@ struct GpMetafile{
|
|||
GpRegion *base_clip; /* clip region in device space for all metafile output */
|
||||
GpRegion *clip; /* clip region within the metafile */
|
||||
struct list containers;
|
||||
struct emfplus_object objtable[EmfPlusObjectTableSize];
|
||||
};
|
||||
|
||||
struct GpBitmap{
|
||||
|
|
|
@ -2085,24 +2085,7 @@ static GpStatus free_image_data(GpImage *image)
|
|||
heap_free(((GpBitmap*)image)->prop_item);
|
||||
}
|
||||
else if (image->type == ImageTypeMetafile)
|
||||
{
|
||||
GpMetafile *metafile = (GpMetafile*)image;
|
||||
heap_free(metafile->comment_data);
|
||||
DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc));
|
||||
if (!metafile->preserve_hemf)
|
||||
DeleteEnhMetaFile(metafile->hemf);
|
||||
if (metafile->record_graphics)
|
||||
{
|
||||
WARN("metafile closed while recording\n");
|
||||
/* not sure what to do here; for now just prevent the graphics from functioning or using this object */
|
||||
metafile->record_graphics->image = NULL;
|
||||
metafile->record_graphics->busy = TRUE;
|
||||
}
|
||||
if (metafile->record_stream)
|
||||
{
|
||||
IStream_Release(metafile->record_stream);
|
||||
}
|
||||
}
|
||||
METAFILE_Free((GpMetafile *)image);
|
||||
else
|
||||
{
|
||||
WARN("invalid image: %p\n", image);
|
||||
|
|
|
@ -297,20 +297,6 @@ typedef struct EmfPlusImageAttributes
|
|||
DWORD Reserved2;
|
||||
} EmfPlusImageAttributes;
|
||||
|
||||
typedef enum ObjectType
|
||||
{
|
||||
ObjectTypeInvalid,
|
||||
ObjectTypeBrush,
|
||||
ObjectTypePen,
|
||||
ObjectTypePath,
|
||||
ObjectTypeRegion,
|
||||
ObjectTypeImage,
|
||||
ObjectTypeFont,
|
||||
ObjectTypeStringFormat,
|
||||
ObjectTypeImageAttributes,
|
||||
ObjectTypeCustomLineCap,
|
||||
} ObjectType;
|
||||
|
||||
typedef struct EmfPlusObject
|
||||
{
|
||||
EmfPlusRecordHeader Header;
|
||||
|
@ -370,9 +356,52 @@ typedef struct EmfPlusFillPath
|
|||
} data;
|
||||
} EmfPlusFillPath;
|
||||
|
||||
static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id)
|
||||
{
|
||||
struct emfplus_object *object = &metafile->objtable[id];
|
||||
|
||||
switch (object->type)
|
||||
{
|
||||
case ObjectTypeInvalid:
|
||||
break;
|
||||
case ObjectTypeImageAttributes:
|
||||
GdipDisposeImageAttributes(object->u.image_attributes);
|
||||
break;
|
||||
default:
|
||||
FIXME("not implemented for object type %u.\n", object->type);
|
||||
return;
|
||||
}
|
||||
|
||||
object->type = ObjectTypeInvalid;
|
||||
object->u.object = NULL;
|
||||
}
|
||||
|
||||
void METAFILE_Free(GpMetafile *metafile)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
heap_free(metafile->comment_data);
|
||||
DeleteEnhMetaFile(CloseEnhMetaFile(metafile->record_dc));
|
||||
if (!metafile->preserve_hemf)
|
||||
DeleteEnhMetaFile(metafile->hemf);
|
||||
if (metafile->record_graphics)
|
||||
{
|
||||
WARN("metafile closed while recording\n");
|
||||
/* not sure what to do here; for now just prevent the graphics from functioning or using this object */
|
||||
metafile->record_graphics->image = NULL;
|
||||
metafile->record_graphics->busy = TRUE;
|
||||
}
|
||||
|
||||
if (metafile->record_stream)
|
||||
IStream_Release(metafile->record_stream);
|
||||
|
||||
for (i = 0; i < sizeof(metafile->objtable)/sizeof(metafile->objtable[0]); i++)
|
||||
metafile_free_object_table_entry(metafile, i);
|
||||
}
|
||||
|
||||
static DWORD METAFILE_AddObjectId(GpMetafile *metafile)
|
||||
{
|
||||
return (metafile->next_object_id++) % 64;
|
||||
return (metafile->next_object_id++) % EmfPlusObjectTableSize;
|
||||
}
|
||||
|
||||
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result)
|
||||
|
@ -1407,6 +1436,55 @@ static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
|
|||
return stat;
|
||||
}
|
||||
|
||||
static void metafile_set_object_table_entry(GpMetafile *metafile, BYTE id, BYTE type, void *object)
|
||||
{
|
||||
metafile_free_object_table_entry(metafile, id);
|
||||
metafile->objtable[id].type = type;
|
||||
metafile->objtable[id].u.object = object;
|
||||
}
|
||||
|
||||
static GpStatus METAFILE_PlaybackObject(GpMetafile *metafile, UINT flags, UINT data_size, const BYTE *record_data)
|
||||
{
|
||||
BYTE type = (flags >> 8) & 0xff;
|
||||
BYTE id = flags & 0xff;
|
||||
void *object = NULL;
|
||||
GpStatus status;
|
||||
|
||||
if (type > ObjectTypeMax || id >= EmfPlusObjectTableSize)
|
||||
return InvalidParameter;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ObjectTypeImageAttributes:
|
||||
{
|
||||
EmfPlusImageAttributes *data = (EmfPlusImageAttributes *)record_data;
|
||||
GpImageAttributes *attributes = NULL;
|
||||
|
||||
if (data_size != sizeof(*data))
|
||||
return InvalidParameter;
|
||||
|
||||
if ((status = GdipCreateImageAttributes(&attributes)) != Ok)
|
||||
return status;
|
||||
|
||||
status = GdipSetImageAttributesWrapMode(attributes, data->WrapMode, *(DWORD *)&data->ClampColor,
|
||||
!!data->ObjectClamp);
|
||||
if (status == Ok)
|
||||
object = attributes;
|
||||
else
|
||||
GdipDisposeImageAttributes(attributes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME("not implemented for object type %d.\n", type);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
if (status == Ok)
|
||||
metafile_set_object_table_entry(metafile, id, type, object);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
||||
EmfPlusRecordType recordType, UINT flags, UINT dataSize, GDIPCONST BYTE *data)
|
||||
{
|
||||
|
@ -1852,6 +1930,10 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
|||
{
|
||||
return GdipSetSmoothingMode(real_metafile->playback_graphics, (flags >> 1) & 0xff);
|
||||
}
|
||||
case EmfPlusRecordTypeObject:
|
||||
{
|
||||
return METAFILE_PlaybackObject(real_metafile, flags, dataSize, data);
|
||||
}
|
||||
default:
|
||||
FIXME("Not implemented for record type %x\n", recordType);
|
||||
return NotImplemented;
|
||||
|
|
Loading…
Reference in New Issue