gpu,op/clip: implement dashed stroked paths

Signed-off-by: Sebastien Binet <s@sbinet.org>
This commit is contained in:
Sebastien Binet
2020-12-09 09:59:46 +00:00
committed by Elias Naur
parent ac14320bec
commit e71bf13c9a
14 changed files with 745 additions and 7 deletions
+10
View File
@@ -21,6 +21,7 @@ type Op struct {
outline bool
stroke StrokeStyle
dashes DashSpec
}
func (p Op) Add(o *op.Ops) {
@@ -42,6 +43,15 @@ func (p Op) Add(o *op.Ops) {
data[10] = uint8(p.stroke.Join)
}
if p.dashes.phase != 0 || p.dashes.size > 0 {
data := o.Write(opconst.TypeDashLen)
data[0] = byte(opconst.TypeDash)
bo := binary.LittleEndian
bo.PutUint32(data[1:], math.Float32bits(p.dashes.phase))
data[5] = p.dashes.size // FIXME(sbinet) uint16? uint32?
p.dashes.spec.Add(o)
}
data := o.Write(opconst.TypeClipLen)
data[0] = byte(opconst.TypeClip)
bo := binary.LittleEndian
+4 -2
View File
@@ -50,8 +50,9 @@ func (rr RRect) Add(ops *op.Ops) {
// Border represents the clip area of a rectangular border.
type Border struct {
// Rect is the bounds of the border.
Rect f32.Rectangle
Width float32
Rect f32.Rectangle
Width float32
Dashes DashSpec
// The corner radii.
SE, SW, NW, NE float32
}
@@ -68,6 +69,7 @@ func (b Border) Op(ops *op.Ops) Op {
Style: StrokeStyle{
Width: b.Width,
},
Dashes: b.Dashes,
}.Op()
}
+59
View File
@@ -2,10 +2,22 @@
package clip
import (
"encoding/binary"
"math"
"gioui.org/internal/opconst"
"gioui.org/op"
)
// Stroke represents a stroked path.
type Stroke struct {
Path PathSpec
Style StrokeStyle
// Dashes specify the dashes of the stroke.
// The empty value denotes no dashes.
Dashes DashSpec
}
// Op returns a clip operation representing the stroke.
@@ -13,6 +25,7 @@ func (s Stroke) Op() Op {
return Op{
path: s.Path,
stroke: s.Style,
dashes: s.Dashes,
}
}
@@ -57,3 +70,49 @@ const (
// RoundJoin joins path segments with a round segment.
RoundJoin
)
// Dash records dashes' lengths and phase for a stroked path.
type Dash struct {
ops *op.Ops
macro op.MacroOp
phase float32
size uint8 // size of the pattern
}
func (d *Dash) Begin(ops *op.Ops) {
d.ops = ops
d.macro = op.Record(ops)
// Write the TypeAux opcode
data := ops.Write(opconst.TypeAuxLen)
data[0] = byte(opconst.TypeAux)
}
func (d *Dash) Phase(v float32) {
d.phase = v
}
func (d *Dash) Dash(length float32) {
if d.size == math.MaxUint8 {
panic("clip: too large dash pattern")
}
data := d.ops.Write(4)
bo := binary.LittleEndian
bo.PutUint32(data[0:], math.Float32bits(length))
d.size++
}
func (d *Dash) End() DashSpec {
c := d.macro.Stop()
return DashSpec{
spec: c,
phase: d.phase,
size: d.size,
}
}
// DashSpec describes a dashed pattern.
type DashSpec struct {
spec op.CallOp
phase float32
size uint8 // size of the pattern
}