forked from joejulian/gio
gpu,op/clip: implement stroked paths with round caps
Signed-off-by: Sebastien Binet <s@sbinet.org>
This commit is contained in:
committed by
Elias Naur
parent
ae256b5be8
commit
1106d90f11
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/ops"
|
||||
"gioui.org/op"
|
||||
"gioui.org/op/clip"
|
||||
)
|
||||
|
||||
@@ -45,6 +46,10 @@ type strokeState struct {
|
||||
|
||||
type strokeQuads []strokeQuad
|
||||
|
||||
func (qs *strokeQuads) pen() f32.Point {
|
||||
return (*qs)[len(*qs)-1].quad.To
|
||||
}
|
||||
|
||||
func (qs *strokeQuads) lineTo(pt f32.Point) {
|
||||
end := (*qs)[len(*qs)-1].quad.To
|
||||
*qs = append(*qs, strokeQuad{
|
||||
@@ -56,6 +61,27 @@ func (qs *strokeQuads) lineTo(pt f32.Point) {
|
||||
})
|
||||
}
|
||||
|
||||
func (qs *strokeQuads) arc(f1, f2 f32.Point, angle float32) {
|
||||
var (
|
||||
p clip.Path
|
||||
o = new(op.Ops)
|
||||
)
|
||||
p.Begin(o)
|
||||
p.Move(qs.pen())
|
||||
beg := len(o.Data())
|
||||
p.Arc(f1, f2, angle)
|
||||
end := len(o.Data())
|
||||
raw := o.Data()[beg:end]
|
||||
|
||||
for qi := 0; len(raw) >= (ops.QuadSize + 4); qi++ {
|
||||
quad := ops.DecodeQuad(raw[4:])
|
||||
raw = raw[ops.QuadSize+4:]
|
||||
*qs = append(*qs, strokeQuad{
|
||||
quad: quad,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// split splits a slice of quads into slices of quads grouped
|
||||
// by contours (ie: splitted at move-to boundaries).
|
||||
func (qs strokeQuads) split() []strokeQuads {
|
||||
@@ -409,6 +435,8 @@ func strokePathCap(sty clip.StrokeStyle, qs *strokeQuads, hw float32, pivot, n0
|
||||
strokePathFlatCap(qs, hw, pivot, n0)
|
||||
case clip.SquareCap:
|
||||
strokePathSquareCap(qs, hw, pivot, n0)
|
||||
case clip.RoundCap:
|
||||
strokePathRoundCap(qs, hw, pivot, n0)
|
||||
default:
|
||||
panic("impossible")
|
||||
}
|
||||
@@ -433,3 +461,9 @@ func strokePathSquareCap(qs *strokeQuads, hw float32, pivot, n0 f32.Point) {
|
||||
qs.lineTo(corner2)
|
||||
qs.lineTo(end)
|
||||
}
|
||||
|
||||
// strokePathRoundCap caps the start or end of a path with a round cap.
|
||||
func strokePathRoundCap(qs *strokeQuads, hw float32, pivot, n0 f32.Point) {
|
||||
c := pivot.Sub(qs.pen())
|
||||
qs.arc(c, c, math.Pi)
|
||||
}
|
||||
|
||||
@@ -129,6 +129,32 @@ func TestStrokedPathBevelFlat(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrokedPathBevelRound(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
const width = 2.5
|
||||
sty := clip.StrokeStyle{
|
||||
Cap: clip.RoundCap,
|
||||
}
|
||||
|
||||
p := new(clip.Path)
|
||||
p.Begin(o)
|
||||
p.Move(f32.Pt(10, 50))
|
||||
p.Line(f32.Pt(10, 0))
|
||||
p.Arc(f32.Pt(10, 0), f32.Pt(20, 0), math.Pi)
|
||||
p.Line(f32.Pt(10, 0))
|
||||
p.Line(f32.Pt(10, 10))
|
||||
p.Arc(f32.Pt(0, 30), f32.Pt(0, 30), 2*math.Pi)
|
||||
p.Line(f32.Pt(-20, 0))
|
||||
p.Quad(f32.Pt(-10, -10), f32.Pt(-30, 30))
|
||||
p.Stroke(width, sty).Add(o)
|
||||
|
||||
paint.Fill(o, colornames.Red)
|
||||
}, func(r result) {
|
||||
r.expect(0, 0, colornames.White)
|
||||
r.expect(10, 50, colornames.Red)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrokedPathBevelSquare(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
const width = 2.5
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@@ -20,4 +20,9 @@ const (
|
||||
// and left-hand sides of a stroked path with a half square of length
|
||||
// the stroked path's width.
|
||||
SquareCap
|
||||
|
||||
// RoundCap caps stroked paths with a round cap, joining the right-hand and
|
||||
// left-hand sides of a stroked path with a half disc of diameter the
|
||||
// stroked path's width.
|
||||
RoundCap
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user