gdiplus: Account for GDI+ drawing operations in the metafile frame.
Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0f3db73628
commit
da31ddb797
|
@ -348,6 +348,8 @@ struct GpMetafile{
|
|||
DWORD comment_data_size;
|
||||
DWORD comment_data_length;
|
||||
IStream *record_stream;
|
||||
BOOL auto_frame; /* If true, determine the frame automatically */
|
||||
GpPointF auto_frame_min, auto_frame_max;
|
||||
|
||||
/* playback */
|
||||
GpGraphics *playback_graphics;
|
||||
|
|
|
@ -277,6 +277,15 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
|
|||
(*metafile)->comment_data_length = 0;
|
||||
(*metafile)->hemf = NULL;
|
||||
|
||||
if (!frameRect)
|
||||
{
|
||||
(*metafile)->auto_frame = TRUE;
|
||||
(*metafile)->auto_frame_min.X = 0;
|
||||
(*metafile)->auto_frame_min.Y = 0;
|
||||
(*metafile)->auto_frame_max.X = -1;
|
||||
(*metafile)->auto_frame_max.Y = -1;
|
||||
}
|
||||
|
||||
stat = METAFILE_WriteHeader(*metafile, hdc);
|
||||
|
||||
if (stat != Ok)
|
||||
|
@ -335,6 +344,30 @@ GpStatus WINGDIPAPI GdipRecordMetafileStream(IStream *stream, HDC hdc, EmfType t
|
|||
return stat;
|
||||
}
|
||||
|
||||
static void METAFILE_AdjustFrame(GpMetafile* metafile, const GpPointF *points,
|
||||
UINT num_points)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!metafile->auto_frame || !num_points)
|
||||
return;
|
||||
|
||||
if (metafile->auto_frame_max.X < metafile->auto_frame_min.X)
|
||||
metafile->auto_frame_max = metafile->auto_frame_min = points[0];
|
||||
|
||||
for (i=0; i<num_points; i++)
|
||||
{
|
||||
if (points[i].X < metafile->auto_frame_min.X)
|
||||
metafile->auto_frame_min.X = points[i].X;
|
||||
if (points[i].X > metafile->auto_frame_max.X)
|
||||
metafile->auto_frame_max.X = points[i].X;
|
||||
if (points[i].Y < metafile->auto_frame_min.Y)
|
||||
metafile->auto_frame_min.Y = points[i].Y;
|
||||
if (points[i].Y > metafile->auto_frame_max.Y)
|
||||
metafile->auto_frame_max.Y = points[i].Y;
|
||||
}
|
||||
}
|
||||
|
||||
GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result)
|
||||
{
|
||||
GpStatus stat;
|
||||
|
@ -473,6 +506,29 @@ GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
|
|||
METAFILE_WriteRecords(metafile);
|
||||
}
|
||||
|
||||
if (metafile->auto_frame)
|
||||
{
|
||||
GpPointF corners[4];
|
||||
int i;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
corners[0].X = rects[i].X;
|
||||
corners[0].Y = rects[i].Y;
|
||||
corners[1].X = rects[i].X + rects[i].Width;
|
||||
corners[1].Y = rects[i].Y;
|
||||
corners[2].X = rects[i].X;
|
||||
corners[2].Y = rects[i].Y + rects[i].Height;
|
||||
corners[3].X = rects[i].X + rects[i].Width;
|
||||
corners[3].Y = rects[i].Y + rects[i].Height;
|
||||
|
||||
GdipTransformPoints(metafile->record_graphics, CoordinateSpaceDevice,
|
||||
CoordinateSpaceWorld, corners, 4);
|
||||
|
||||
METAFILE_AdjustFrame(metafile, corners, 4);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -526,6 +582,57 @@ GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile)
|
|||
MetafileHeader header;
|
||||
|
||||
stat = GdipGetMetafileHeaderFromEmf(metafile->hemf, &header);
|
||||
if (stat == Ok && metafile->auto_frame &&
|
||||
metafile->auto_frame_max.X >= metafile->auto_frame_min.X)
|
||||
{
|
||||
RECTL bounds_rc, gdi_bounds_rc;
|
||||
REAL x_scale = 2540.0 / header.DpiX;
|
||||
REAL y_scale = 2540.0 / header.DpiY;
|
||||
BYTE* buffer;
|
||||
UINT buffer_size;
|
||||
|
||||
bounds_rc.left = floorf(metafile->auto_frame_min.X * x_scale);
|
||||
bounds_rc.top = floorf(metafile->auto_frame_min.Y * y_scale);
|
||||
bounds_rc.right = ceilf(metafile->auto_frame_max.X * x_scale);
|
||||
bounds_rc.bottom = ceilf(metafile->auto_frame_max.Y * y_scale);
|
||||
|
||||
gdi_bounds_rc = header.EmfHeader.rclBounds;
|
||||
if (gdi_bounds_rc.right > gdi_bounds_rc.left && gdi_bounds_rc.bottom > gdi_bounds_rc.top)
|
||||
{
|
||||
bounds_rc.left = min(bounds_rc.left, gdi_bounds_rc.left);
|
||||
bounds_rc.top = min(bounds_rc.top, gdi_bounds_rc.top);
|
||||
bounds_rc.right = max(bounds_rc.right, gdi_bounds_rc.right);
|
||||
bounds_rc.bottom = max(bounds_rc.bottom, gdi_bounds_rc.bottom);
|
||||
}
|
||||
|
||||
buffer_size = GetEnhMetaFileBits(metafile->hemf, 0, NULL);
|
||||
buffer = heap_alloc(buffer_size);
|
||||
if (buffer)
|
||||
{
|
||||
HENHMETAFILE new_hemf;
|
||||
|
||||
GetEnhMetaFileBits(metafile->hemf, buffer_size, buffer);
|
||||
|
||||
((ENHMETAHEADER*)buffer)->rclFrame = bounds_rc;
|
||||
|
||||
new_hemf = SetEnhMetaFileBits(buffer_size, buffer);
|
||||
|
||||
if (new_hemf)
|
||||
{
|
||||
DeleteEnhMetaFile(metafile->hemf);
|
||||
metafile->hemf = new_hemf;
|
||||
}
|
||||
else
|
||||
stat = OutOfMemory;
|
||||
|
||||
heap_free(buffer);
|
||||
}
|
||||
else
|
||||
stat = OutOfMemory;
|
||||
|
||||
if (stat == Ok)
|
||||
stat = GdipGetMetafileHeaderFromEmf(metafile->hemf, &header);
|
||||
}
|
||||
if (stat == Ok)
|
||||
{
|
||||
metafile->bounds.X = header.X;
|
||||
|
|
|
@ -1010,10 +1010,10 @@ static void test_nullframerect(void) {
|
|||
stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
|
||||
expect(Ok, stat);
|
||||
expect(UnitPixel, unit);
|
||||
todo_wine expectf_(25.0, bounds.X, 0.05);
|
||||
todo_wine expectf_(25.0, bounds.Y, 0.05);
|
||||
todo_wine expectf_(75.0, bounds.Width, 0.05);
|
||||
todo_wine expectf_(75.0, bounds.Height, 0.05);
|
||||
expectf_(25.0, bounds.X, 0.05);
|
||||
expectf_(25.0, bounds.Y, 0.05);
|
||||
expectf_(75.0, bounds.Width, 0.05);
|
||||
expectf_(75.0, bounds.Height, 0.05);
|
||||
|
||||
stat = GdipDisposeImage((GpImage*)metafile);
|
||||
expect(Ok, stat);
|
||||
|
|
Loading…
Reference in New Issue