diff --git a/gpu/internal/rendertest/refs/TestPaintArc.png b/gpu/internal/rendertest/refs/TestPaintArc.png index f432914f..9ebbe5bf 100644 Binary files a/gpu/internal/rendertest/refs/TestPaintArc.png and b/gpu/internal/rendertest/refs/TestPaintArc.png differ diff --git a/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png b/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png index 77540a4b..f589f753 100644 Binary files a/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png and b/gpu/internal/rendertest/refs/TestStrokedPathCoincidentControlPoint.png differ diff --git a/gpu/internal/rendertest/refs/TestTexturedStroke.png b/gpu/internal/rendertest/refs/TestTexturedStroke.png index 637c9329..8da06b39 100644 Binary files a/gpu/internal/rendertest/refs/TestTexturedStroke.png and b/gpu/internal/rendertest/refs/TestTexturedStroke.png differ diff --git a/gpu/internal/rendertest/refs/TestTexturedStrokeClipped.png b/gpu/internal/rendertest/refs/TestTexturedStrokeClipped.png index 637c9329..8da06b39 100644 Binary files a/gpu/internal/rendertest/refs/TestTexturedStrokeClipped.png and b/gpu/internal/rendertest/refs/TestTexturedStrokeClipped.png differ diff --git a/internal/stroke/stroke.go b/internal/stroke/stroke.go index 741e56a1..a115dc79 100644 --- a/internal/stroke/stroke.go +++ b/internal/stroke/stroke.go @@ -91,9 +91,8 @@ func (qs *StrokeQuads) lineTo(pt f32.Point) { } func (qs *StrokeQuads) arc(f1, f2 f32.Point, angle float32) { - const segments = 16 pen := qs.pen() - m := ArcTransform(pen, f1.Add(pen), f2.Add(pen), angle, segments) + m, segments := ArcTransform(pen, f1.Add(pen), f2.Add(pen), angle) for i := 0; i < segments; i++ { p0 := qs.pen() p1 := m.Transform(p0) @@ -546,7 +545,19 @@ func strokePathRoundCap(qs *StrokeQuads, hw float32, pivot, n0 f32.Point) { // cubic Bezier curves", L. Maisonobe // An electronic version may be found at: // http://spaceroots.org/documents/ellipse/elliptical-arc.pdf -func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D { +func ArcTransform(p, f1, f2 f32.Point, angle float32) (transform f32.Affine2D, segments int) { + const segmentsPerCircle = 16 + const anglePerSegment = 2 * math.Pi / segmentsPerCircle + + s := angle / anglePerSegment + if s < 0 { + s = -s + } + segments = int(math.Ceil(float64(s))) + if segments <= 0 { + segments = 1 + } + var rx, ry, alpha float64 if f1 == f2 { // degenerate case of a circle. @@ -605,7 +616,7 @@ func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D // Before applying the rotation matrix rot, transform the coordinates // to a frame centered to the ellipse (and warped into a unit circle), then rotate. // Finally, transform back into the original frame. - return inv.Mul(rot).Mul(ref) + return inv.Mul(rot).Mul(ref), segments } func dist(p1, p2 f32.Point) float64 { diff --git a/op/clip/clip.go b/op/clip/clip.go index d251d7a0..3ac02fe8 100644 --- a/op/clip/clip.go +++ b/op/clip/clip.go @@ -286,9 +286,7 @@ func (p *Path) QuadTo(ctrl, to f32.Point) { // The sign of angle determines the direction; positive being counter-clockwise, // negative clockwise. func (p *Path) ArcTo(f1, f2 f32.Point, angle float32) { - const segments = 16 - m := stroke.ArcTransform(p.pen, f1, f2, angle, segments) - + m, segments := stroke.ArcTransform(p.pen, f1, f2, angle) for i := 0; i < segments; i++ { p0 := p.pen p1 := m.Transform(p0)