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