gdiplus: Improved GdipGetPathWorldBounds handling of both matrix and pen's effect on bounding box.
This commit is contained in:
parent
41a9a83890
commit
3dc17d2544
@ -212,12 +212,9 @@ GpStatus WINGDIPAPI GdipGetPathTypes(GpPath *path, BYTE* types, INT count)
|
|||||||
GpStatus WINGDIPAPI GdipGetPathWorldBounds(GpPath* path, GpRectF* bounds,
|
GpStatus WINGDIPAPI GdipGetPathWorldBounds(GpPath* path, GpRectF* bounds,
|
||||||
GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
|
GDIPCONST GpMatrix *matrix, GDIPCONST GpPen *pen)
|
||||||
{
|
{
|
||||||
/* extrema[0] is upper left corner of bounding box,
|
GpPointF * points, temp_pts[4];
|
||||||
* extrema[1] is lower right corner */
|
|
||||||
GpPointF extrema[2];
|
|
||||||
GpPointF * points;
|
|
||||||
INT count, i;
|
INT count, i;
|
||||||
REAL path_width;
|
REAL path_width = 1.0, width, height, temp, low_x, low_y, high_x, high_y;
|
||||||
|
|
||||||
/* Matrix and pen can be null. */
|
/* Matrix and pen can be null. */
|
||||||
if(!path || !bounds)
|
if(!path || !bounds)
|
||||||
@ -231,33 +228,64 @@ GpStatus WINGDIPAPI GdipGetPathWorldBounds(GpPath* path, GpRectF* bounds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
points = path->pathdata.Points;
|
points = path->pathdata.Points;
|
||||||
extrema[0].X = extrema[1].X = points[0].X;
|
|
||||||
extrema[0].Y = extrema[1].Y = points[0].Y;
|
low_x = high_x = points[0].X;
|
||||||
|
low_y = high_y = points[0].Y;
|
||||||
|
|
||||||
for(i = 1; i < count; i++){
|
for(i = 1; i < count; i++){
|
||||||
extrema[0].X = min(points[i].X, extrema[0].X);
|
low_x = min(low_x, points[i].X);
|
||||||
extrema[0].Y = min(points[i].Y, extrema[0].Y);
|
low_y = min(low_y, points[i].Y);
|
||||||
extrema[1].X = max(points[i].X, extrema[1].X);
|
high_x = max(high_x, points[i].X);
|
||||||
extrema[1].Y = max(points[i].Y, extrema[1].Y);
|
high_y = max(high_y, points[i].Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If matrix is non-null transform the points. */
|
width = high_x - low_x;
|
||||||
|
height = high_y - low_y;
|
||||||
|
|
||||||
|
/* This looks unusual but it's the only way I can imitate windows. */
|
||||||
if(matrix){
|
if(matrix){
|
||||||
GdipTransformMatrixPoints((GpMatrix*)matrix, extrema, 2);
|
temp_pts[0].X = low_x;
|
||||||
|
temp_pts[0].Y = low_y;
|
||||||
|
temp_pts[1].X = low_x;
|
||||||
|
temp_pts[1].Y = high_y;
|
||||||
|
temp_pts[2].X = high_x;
|
||||||
|
temp_pts[2].Y = high_y;
|
||||||
|
temp_pts[3].X = high_x;
|
||||||
|
temp_pts[3].Y = low_y;
|
||||||
|
|
||||||
|
GdipTransformMatrixPoints((GpMatrix*)matrix, temp_pts, 4);
|
||||||
|
low_x = temp_pts[0].X;
|
||||||
|
low_y = temp_pts[0].Y;
|
||||||
|
|
||||||
|
for(i = 1; i < 4; i++){
|
||||||
|
low_x = min(low_x, temp_pts[i].X);
|
||||||
|
low_y = min(low_y, temp_pts[i].Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = width;
|
||||||
|
width = height * fabs(matrix->matrix[2]) + width * fabs(matrix->matrix[0]);
|
||||||
|
height = height * fabs(matrix->matrix[3]) + temp * fabs(matrix->matrix[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pen){
|
if(pen){
|
||||||
path_width = pen->width * pen->miterlimit / 2.0;
|
path_width = pen->width / 2.0;
|
||||||
extrema[0].X -= path_width;
|
|
||||||
extrema[0].Y -= path_width;
|
if(count > 2)
|
||||||
extrema[1].X += path_width;
|
path_width = max(path_width, pen->width * pen->miterlimit / 2.0);
|
||||||
extrema[1].Y += path_width;
|
/* FIXME: this should probably also check for the startcap */
|
||||||
|
if(pen->endcap & LineCapNoAnchor)
|
||||||
|
path_width = max(path_width, pen->width * 2.2);
|
||||||
|
|
||||||
|
low_x -= path_width;
|
||||||
|
low_y -= path_width;
|
||||||
|
width += 2.0 * path_width;
|
||||||
|
height += 2.0 * path_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds->X = extrema[0].X;
|
bounds->X = low_x;
|
||||||
bounds->Y = extrema[0].Y;
|
bounds->Y = low_y;
|
||||||
bounds->Width = extrema[1].X - extrema[0].X;
|
bounds->Width = width;
|
||||||
bounds->Height = extrema[1].Y - extrema[0].Y;
|
bounds->Height = height;
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -315,12 +315,10 @@ static void test_worldbounds(void)
|
|||||||
expect(Ok, status);
|
expect(Ok, status);
|
||||||
GdipDeletePath(path);
|
GdipDeletePath(path);
|
||||||
|
|
||||||
todo_wine{
|
expectf(156.0, bounds.X);
|
||||||
expectf(156.0, bounds.X);
|
expectf(156.0, bounds.Y);
|
||||||
expectf(156.0, bounds.Y);
|
expectf(138.0, bounds.Width);
|
||||||
expectf(138.0, bounds.Width);
|
expectf(88.0, bounds.Height);
|
||||||
expectf(88.0, bounds.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
|
line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
|
||||||
line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
|
line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
|
||||||
@ -379,12 +377,10 @@ static void test_worldbounds(void)
|
|||||||
expect(Ok, status);
|
expect(Ok, status);
|
||||||
GdipDeletePath(path);
|
GdipDeletePath(path);
|
||||||
|
|
||||||
todo_wine{
|
expectf(-209.6, bounds.X);
|
||||||
expectf(-209.6, bounds.X);
|
expectf(-1274.8, bounds.Y);
|
||||||
expectf(-1274.8, bounds.Y);
|
expectf(705.0, bounds.Width);
|
||||||
expectf(705.0, bounds.Width);
|
expectf(945.0, bounds.Height);
|
||||||
expectf(945.0, bounds.Height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(graphicspath)
|
START_TEST(graphicspath)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user