Commit 3f6faddd authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Implement playback/recording for SetClipRect.

parent 03181015
......@@ -81,6 +81,9 @@ extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN;
extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN;
......@@ -89,6 +92,8 @@ extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDE
extern GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile,
REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
......@@ -372,6 +377,7 @@ struct GpMetafile{
GpUnit page_unit;
REAL page_scale;
GpRegion *base_clip; /* clip region in device space for all metafile output */
GpRegion *clip; /* clip region within the metafile */
struct list containers;
};
......
......@@ -51,9 +51,6 @@ static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text,
GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
INT flags, GDIPCONST GpMatrix *matrix);
static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
GpCoordinateSpace src_space, GpMatrix *matrix);
/* Converts from gdiplus path point type to gdi path point type. */
static BYTE convert_path_point_type(BYTE type)
{
......@@ -5642,6 +5639,13 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y,
if(graphics->busy)
return ObjectBusy;
if (graphics->image && graphics->image->type == ImageTypeMetafile)
{
status = METAFILE_SetClipRect((GpMetafile*)graphics->image, x, y, width, height, mode);
if (status != Ok)
return status;
}
rect.X = x;
rect.Y = y;
rect.Width = width;
......@@ -5983,7 +5987,7 @@ GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region)
return Ok;
}
static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
GpCoordinateSpace src_space, GpMatrix *matrix)
{
GpStatus stat = Ok;
......
......@@ -70,6 +70,12 @@ typedef struct EmfPlusFillRects
DWORD Count;
} EmfPlusFillRects;
typedef struct EmfPlusSetClipRect
{
EmfPlusRecordHeader Header;
GpRectF ClipRect;
} EmfPlusSetClipRect;
typedef struct EmfPlusSetPageTransform
{
EmfPlusRecordHeader Header;
......@@ -137,6 +143,7 @@ typedef struct container
GpMatrix world_transform;
GpUnit page_unit;
REAL page_scale;
GpRegion *clip;
} container;
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result)
......@@ -588,6 +595,32 @@ GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
return Ok;
}
GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width, REAL height, CombineMode mode)
{
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
{
EmfPlusSetClipRect *record;
GpStatus stat;
stat = METAFILE_AllocateRecord(metafile,
sizeof(EmfPlusSetClipRect),
(void**)&record);
if (stat != Ok)
return stat;
record->Header.Type = EmfPlusRecordTypeSetClipRect;
record->Header.Flags = (mode & 0xf) << 8;
record->ClipRect.X = x;
record->ClipRect.Y = y;
record->ClipRect.Width = width;
record->ClipRect.Height = height;
METAFILE_WriteRecords(metafile);
}
return Ok;
}
GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale)
{
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
......@@ -1014,7 +1047,11 @@ static void METAFILE_PlaybackReleaseDC(GpMetafile *metafile)
static GpStatus METAFILE_PlaybackUpdateClip(GpMetafile *metafile)
{
return GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace);
GpStatus stat;
stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace);
if (stat == Ok)
stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->clip, CombineModeIntersect);
return stat;
}
static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
......@@ -1166,6 +1203,32 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
return stat;
}
case EmfPlusRecordTypeSetClipRect:
{
EmfPlusSetClipRect *record = (EmfPlusSetClipRect*)header;
CombineMode mode = (CombineMode)((flags >> 8) & 0xf);
GpRegion *region;
GpMatrix world_to_device;
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(*record))
return InvalidParameter;
stat = GdipCreateRegionRect(&record->ClipRect, &region);
if (stat == Ok)
{
get_graphics_transform(real_metafile->playback_graphics,
CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
GdipTransformRegion(region, &world_to_device);
GdipCombineRegionRegion(real_metafile->clip, region, mode);
GdipDeleteRegion(region);
}
return METAFILE_PlaybackUpdateClip(real_metafile);
}
case EmfPlusRecordTypeSetPageTransform:
{
EmfPlusSetPageTransform *record = (EmfPlusSetPageTransform*)header;
......@@ -1257,6 +1320,13 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
if (!cont)
return OutOfMemory;
stat = GdipCloneRegion(metafile->clip, &cont->clip);
if (stat != Ok)
{
heap_free(cont);
return stat;
}
if (recordType == EmfPlusRecordTypeBeginContainerNoParams)
stat = GdipBeginContainer2(metafile->playback_graphics, &cont->state);
else
......@@ -1264,6 +1334,7 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
if (stat != Ok)
{
GdipDeleteRegion(cont->clip);
heap_free(cont);
return stat;
}
......@@ -1310,6 +1381,7 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
while ((cont2 = LIST_ENTRY(list_head(&real_metafile->containers), container, entry)) != cont)
{
list_remove(&cont2->entry);
GdipDeleteRegion(cont2->clip);
heap_free(cont2);
}
......@@ -1321,8 +1393,10 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
*real_metafile->world_transform = cont->world_transform;
real_metafile->page_unit = cont->page_unit;
real_metafile->page_scale = cont->page_scale;
GdipCombineRegionRegion(real_metafile->clip, cont->clip, CombineModeReplace);
list_remove(&cont->entry);
GdipDeleteRegion(cont->clip);
heap_free(cont);
}
......@@ -1453,6 +1527,9 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
stat = GdipGetClip(graphics, real_metafile->base_clip);
if (stat == Ok)
stat = GdipCreateRegion(&real_metafile->clip);
if (stat == Ok)
stat = GdipCreatePath(FillModeAlternate, &dst_path);
if (stat == Ok)
......@@ -1506,10 +1583,14 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
GdipDeleteRegion(real_metafile->base_clip);
real_metafile->base_clip = NULL;
GdipDeleteRegion(real_metafile->clip);
real_metafile->clip = NULL;
while (list_head(&real_metafile->containers))
{
container* cont = LIST_ENTRY(list_head(&real_metafile->containers), container, entry);
list_remove(&cont->entry);
GdipDeleteRegion(cont->clip);
heap_free(cont);
}
......
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