зеркало из https://github.com/mozilla/gecko-dev.git
Bug 459148 - use thebes primitives for SVG rounded rects - r=longsonr,vlad sr=roc
This commit is contained in:
Родитель
d6e15171a0
Коммит
5f09cf12fb
|
@ -210,37 +210,7 @@ nsSVGRectElement::ConstructPath(gfxContext *aCtx)
|
|||
else if (ry > halfHeight)
|
||||
rx = ry = halfHeight;
|
||||
|
||||
// Conversion factor used for ellipse to bezier conversion.
|
||||
// Gives radial error of 0.0273% in circular case.
|
||||
// See comp.graphics.algorithms FAQ 4.04
|
||||
const float magic = 4*(sqrt(2.)-1)/3;
|
||||
const float magic_x = magic*rx;
|
||||
const float magic_y = magic*ry;
|
||||
|
||||
aCtx->MoveTo(gfxPoint(x + rx, y));
|
||||
aCtx->LineTo(gfxPoint(x + width - rx, y));
|
||||
|
||||
aCtx->CurveTo(gfxPoint(x + width - rx + magic_x, y),
|
||||
gfxPoint(x + width, y + ry - magic_y),
|
||||
gfxPoint(x + width, y + ry));
|
||||
|
||||
aCtx->LineTo(gfxPoint(x + width, y + height - ry));
|
||||
|
||||
aCtx->CurveTo(gfxPoint(x + width, y + height - ry + magic_y),
|
||||
gfxPoint(x + width - rx + magic_x, y+height),
|
||||
gfxPoint(x + width - rx, y + height));
|
||||
|
||||
aCtx->LineTo(gfxPoint(x + rx, y + height));
|
||||
|
||||
aCtx->CurveTo(gfxPoint(x + rx - magic_x, y + height),
|
||||
gfxPoint(x, y + height - ry + magic_y),
|
||||
gfxPoint(x, y + height - ry));
|
||||
|
||||
aCtx->LineTo(gfxPoint(x, y + ry));
|
||||
|
||||
aCtx->CurveTo(gfxPoint(x, y + ry - magic_y),
|
||||
gfxPoint(x + rx - magic_x, y),
|
||||
gfxPoint(x + rx, y));
|
||||
|
||||
aCtx->ClosePath();
|
||||
gfxSize corner(rx, ry);
|
||||
aCtx->RoundedRectangle(gfxRect(x, y, width, height),
|
||||
gfxCornerSizes(corner, corner, corner, corner));
|
||||
}
|
||||
|
|
|
@ -817,11 +817,8 @@ gfxContext::RoundedRectangle(const gfxRect& rect,
|
|||
// *
|
||||
// *
|
||||
//
|
||||
// Where 0, 1, 2, 3 are the control points of the Bezier curve for the corner,
|
||||
// and C is the actual corner point.
|
||||
//
|
||||
// For details about representing an elliptical arc as a cubic Bezier curve,
|
||||
// see http://www.spaceroots.org/documents/ellipse/elliptical-arc.pdf
|
||||
// Where 0, 1, 2, 3 are the control points of the Bezier curve for
|
||||
// the corner, and C is the actual corner point.
|
||||
//
|
||||
// At the start of the loop, the current point is assumed to be
|
||||
// the point adjacent to the top left corner on the top
|
||||
|
@ -829,15 +826,54 @@ gfxContext::RoundedRectangle(const gfxRect& rect,
|
|||
// continue clockwise, whereas in our loop i = 0 refers to the top
|
||||
// right corner.
|
||||
//
|
||||
// When going CCW, the control points are swapped, and the first corner
|
||||
// that's drawn is the top left (along with the top segment).
|
||||
|
||||
// This is (sqrt(7) - 1) / 3; this ends up falling out of the equations
|
||||
// given in the above paper -- it's the value of alpha at the end of section
|
||||
// 3.4.1 when n2 and n1 are 90 degrees apart. For the various corners, the
|
||||
// axes the sign of this value changes, or it might be 0 -- it's multiplied by
|
||||
// the appropriate multiplier from the list before using.
|
||||
const gfxFloat alpha = 0.54858377035486361;
|
||||
// When going CCW, the control points are swapped, and the first
|
||||
// corner that's drawn is the top left (along with the top segment).
|
||||
//
|
||||
// There is considerable latitude in how one chooses the four
|
||||
// control points for a Bezier curve approximation to an ellipse.
|
||||
// For the overall path to be continuous and show no corner at the
|
||||
// endpoints of the arc, points 0 and 3 must be at the ends of the
|
||||
// straight segments of the rectangle; points 0, 1, and C must be
|
||||
// collinear; and points 3, 2, and C must also be collinear. This
|
||||
// leaves only two free parameters: the ratio of the line segments
|
||||
// 01 and 0C, and the ratio of the line segments 32 and 3C. See
|
||||
// the following papers for extensive discussion of how to choose
|
||||
// these ratios:
|
||||
//
|
||||
// Dokken, Tor, et al. "Good approximation of circles by
|
||||
// curvature-continuous Bezier curves." Computer-Aided
|
||||
// Geometric Design 7(1990) 33--41.
|
||||
// Goldapp, Michael. "Approximation of circular arcs by cubic
|
||||
// polynomials." Computer-Aided Geometric Design 8(1991) 227--238.
|
||||
// Maisonobe, Luc. "Drawing an elliptical arc using polylines,
|
||||
// quadratic, or cubic Bezier curves."
|
||||
// http://www.spaceroots.org/documents/ellipse/elliptical-arc.pdf
|
||||
//
|
||||
// We follow the approach in section 2 of Goldapp (least-error,
|
||||
// Hermite-type approximation) and make both ratios equal to
|
||||
//
|
||||
// 2 2 + n - sqrt(2n + 28)
|
||||
// alpha = - * ---------------------
|
||||
// 3 n - 4
|
||||
//
|
||||
// where n = 3( cbrt(sqrt(2)+1) - cbrt(sqrt(2)-1) ).
|
||||
//
|
||||
// This is the result of Goldapp's equation (10b) when the angle
|
||||
// swept out by the arc is pi/2, and the parameter "a-bar" is the
|
||||
// expression given immediately below equation (21).
|
||||
//
|
||||
// Using this value, the maximum radial error for a circle, as a
|
||||
// fraction of the radius, is on the order of 0.2 x 10^-3.
|
||||
// Neither Dokken nor Goldapp discusses error for a general
|
||||
// ellipse; Maisonobe does, but his choice of control points
|
||||
// follows different constraints, and Goldapp's expression for
|
||||
// 'alpha' gives much smaller radial error, even for very flat
|
||||
// ellipses, than Maisonobe's equivalent.
|
||||
//
|
||||
// For the various corners and for each axis, the sign of this
|
||||
// constant changes, or it might be 0 -- it's multiplied by the
|
||||
// appropriate multiplier from the list before using.
|
||||
const gfxFloat alpha = 0.55191497064665766025;
|
||||
|
||||
typedef struct { gfxFloat a, b; } twoFloats;
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body style="margin: 0">
|
||||
<svg width="100px" height="100px" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect style="fill: black; stroke: none"
|
||||
width="70" height="70"
|
||||
x="8" y="8"
|
||||
rx="10" ry="10"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html><head>
|
||||
<title>Circular border</title>
|
||||
<style>
|
||||
body { margin: 0 }
|
||||
div {
|
||||
margin-left: 8px; margin-top: 8px;
|
||||
width: 50px; height: 50px;
|
||||
border: 10px solid black;
|
||||
-moz-border-radius: 10px;
|
||||
}
|
||||
div > div {
|
||||
margin: 0; width: 50px; height: 50px;
|
||||
-moz-border-radius: 0;
|
||||
background: black;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body><div><div></div></div></body></html>
|
|
@ -13,3 +13,6 @@
|
|||
!= outline-square.html outline-circle.html
|
||||
!= outline-square.html outline-ellips.html
|
||||
!= outline-circle.html outline-ellips.html
|
||||
|
||||
# more serious tests, using SVG reference
|
||||
== border-circle-2.html border-circle-2-ref.xhtml
|
||||
|
|
Загрузка…
Ссылка в новой задаче