mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 00:45:35 +00:00
ui: remove ui.Ops parameters from layouts and path builder structs
Layouts and path builders are transient and need an ops list for operation. However, instead of passing the ops list to every method, pass the list in an init method and store it for subsequent methods. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+36
-31
@@ -14,6 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type PathBuilder struct {
|
||||
ops *ui.Ops
|
||||
firstVert int
|
||||
nverts int
|
||||
maxy float32
|
||||
@@ -38,17 +39,21 @@ func (p opClip) Add(o *ui.Ops) {
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
func (p *PathBuilder) Init(ops *ui.Ops) {
|
||||
p.ops = ops
|
||||
}
|
||||
|
||||
// MoveTo moves the pen to the given position.
|
||||
func (p *PathBuilder) Move(ops *ui.Ops, to f32.Point) {
|
||||
p.end(ops)
|
||||
func (p *PathBuilder) Move(to f32.Point) {
|
||||
p.end()
|
||||
to = to.Add(p.pen)
|
||||
p.maxy = to.Y
|
||||
p.pen = to
|
||||
}
|
||||
|
||||
// end completes the current contour.
|
||||
func (p *PathBuilder) end(ops *ui.Ops) {
|
||||
aux := ops.Aux()
|
||||
func (p *PathBuilder) end() {
|
||||
aux := p.ops.Aux()
|
||||
bo := binary.LittleEndian
|
||||
// Fill in maximal Y coordinates of the NW and NE corners.
|
||||
for i := p.firstVert; i < p.nverts; i++ {
|
||||
@@ -59,25 +64,25 @@ func (p *PathBuilder) end(ops *ui.Ops) {
|
||||
}
|
||||
|
||||
// Line records a line from the pen to end.
|
||||
func (p *PathBuilder) Line(ops *ui.Ops, to f32.Point) {
|
||||
func (p *PathBuilder) Line(to f32.Point) {
|
||||
to = to.Add(p.pen)
|
||||
p.lineTo(ops, to)
|
||||
p.lineTo(to)
|
||||
}
|
||||
|
||||
func (p *PathBuilder) lineTo(ops *ui.Ops, to f32.Point) {
|
||||
func (p *PathBuilder) lineTo(to f32.Point) {
|
||||
// Model lines as degenerate quadratic beziers.
|
||||
p.quadTo(ops, to.Add(p.pen).Mul(.5), to)
|
||||
p.quadTo(to.Add(p.pen).Mul(.5), to)
|
||||
}
|
||||
|
||||
// Quad records a quadratic bezier from the pen to end
|
||||
// with the control point ctrl.
|
||||
func (p *PathBuilder) Quad(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
func (p *PathBuilder) Quad(ctrl, to f32.Point) {
|
||||
ctrl = ctrl.Add(p.pen)
|
||||
to = to.Add(p.pen)
|
||||
p.quadTo(ops, ctrl, to)
|
||||
p.quadTo(ctrl, to)
|
||||
}
|
||||
|
||||
func (p *PathBuilder) quadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
func (p *PathBuilder) quadTo(ctrl, to f32.Point) {
|
||||
// Zero width curves don't contribute to stenciling.
|
||||
if p.pen.X == to.X && p.pen.X == ctrl.X {
|
||||
p.pen = to
|
||||
@@ -104,8 +109,8 @@ func (p *PathBuilder) quadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
ctrl0 := p.pen.Mul(1 - t).Add(ctrl.Mul(t))
|
||||
ctrl1 := ctrl.Mul(1 - t).Add(to.Mul(t))
|
||||
mid := ctrl0.Mul(1 - t).Add(ctrl1.Mul(t))
|
||||
p.simpleQuadTo(ops, ctrl0, mid)
|
||||
p.simpleQuadTo(ops, ctrl1, to)
|
||||
p.simpleQuadTo(ctrl0, mid)
|
||||
p.simpleQuadTo(ctrl1, to)
|
||||
if mid.X > bounds.Max.X {
|
||||
bounds.Max.X = mid.X
|
||||
}
|
||||
@@ -113,7 +118,7 @@ func (p *PathBuilder) quadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
bounds.Min.X = mid.X
|
||||
}
|
||||
} else {
|
||||
p.simpleQuadTo(ops, ctrl, to)
|
||||
p.simpleQuadTo(ctrl, to)
|
||||
}
|
||||
// Find the y extremum, if any.
|
||||
d = v0.Y - v1.Y
|
||||
@@ -132,7 +137,7 @@ func (p *PathBuilder) quadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
|
||||
// Cube records a cubic bezier from the pen through
|
||||
// two control points ending in to.
|
||||
func (p *PathBuilder) Cube(ops *ui.Ops, ctrl0, ctrl1, to f32.Point) {
|
||||
func (p *PathBuilder) Cube(ctrl0, ctrl1, to f32.Point) {
|
||||
ctrl0 = ctrl0.Add(p.pen)
|
||||
ctrl1 = ctrl1.Add(p.pen)
|
||||
to = to.Add(p.pen)
|
||||
@@ -146,12 +151,12 @@ func (p *PathBuilder) Cube(ops *ui.Ops, ctrl0, ctrl1, to f32.Point) {
|
||||
if h := hull.Dy(); h > l {
|
||||
l = h
|
||||
}
|
||||
p.approxCubeTo(ops, 0, l*0.001, ctrl0, ctrl1, to)
|
||||
p.approxCubeTo(0, l*0.001, ctrl0, ctrl1, to)
|
||||
}
|
||||
|
||||
// approxCube approximates a cubic beziér by a series of quadratic
|
||||
// curves.
|
||||
func (p *PathBuilder) approxCubeTo(ops *ui.Ops, splits int, maxDist float32, ctrl0, ctrl1, to f32.Point) int {
|
||||
func (p *PathBuilder) approxCubeTo(splits int, maxDist float32, ctrl0, ctrl1, to f32.Point) int {
|
||||
// The idea is from
|
||||
// https://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
|
||||
// where a quadratic approximates a cubic by eliminating its t³ term
|
||||
@@ -179,7 +184,7 @@ func (p *PathBuilder) approxCubeTo(ops *ui.Ops, splits int, maxDist float32, ctr
|
||||
c := ctrl0.Mul(3).Sub(p.pen).Add(ctrl1.Mul(3)).Sub(to).Mul(1.0 / 4.0)
|
||||
const maxSplits = 32
|
||||
if splits >= maxSplits {
|
||||
p.quadTo(ops, c, to)
|
||||
p.quadTo(c, to)
|
||||
return splits
|
||||
}
|
||||
// The maximum distance between the cubic P and its approximation Q given t
|
||||
@@ -191,7 +196,7 @@ func (p *PathBuilder) approxCubeTo(ops *ui.Ops, splits int, maxDist float32, ctr
|
||||
v := to.Sub(ctrl1.Mul(3)).Add(ctrl0.Mul(3)).Sub(p.pen)
|
||||
d2 := (v.X*v.X + v.Y*v.Y) * 3 / (36 * 36)
|
||||
if d2 <= maxDist*maxDist {
|
||||
p.quadTo(ops, c, to)
|
||||
p.quadTo(c, to)
|
||||
return splits
|
||||
}
|
||||
// De Casteljau split the curve and approximate the halves.
|
||||
@@ -203,8 +208,8 @@ func (p *PathBuilder) approxCubeTo(ops *ui.Ops, splits int, maxDist float32, ctr
|
||||
c12 := c1.Add(c2.Sub(c1).Mul(t))
|
||||
c0112 := c01.Add(c12.Sub(c01).Mul(t))
|
||||
splits++
|
||||
splits = p.approxCubeTo(ops, splits, maxDist, c0, c01, c0112)
|
||||
splits = p.approxCubeTo(ops, splits, maxDist, c12, c2, to)
|
||||
splits = p.approxCubeTo(splits, maxDist, c0, c01, c0112)
|
||||
splits = p.approxCubeTo(splits, maxDist, c12, c2, to)
|
||||
return splits
|
||||
}
|
||||
|
||||
@@ -220,7 +225,7 @@ func (p *PathBuilder) expand(b f32.Rectangle) {
|
||||
p.bounds = p.bounds.Union(b)
|
||||
}
|
||||
|
||||
func (p *PathBuilder) vertex(o *ui.Ops, cornerx, cornery int16, ctrl, to f32.Point) {
|
||||
func (p *PathBuilder) vertex(cornerx, cornery int16, ctrl, to f32.Point) {
|
||||
p.nverts++
|
||||
v := path.Vertex{
|
||||
CornerX: cornerx,
|
||||
@@ -246,10 +251,10 @@ func (p *PathBuilder) vertex(o *ui.Ops, cornerx, cornery int16, ctrl, to f32.Poi
|
||||
bo.PutUint32(data[21:], math.Float32bits(v.CtrlY))
|
||||
bo.PutUint32(data[25:], math.Float32bits(v.ToX))
|
||||
bo.PutUint32(data[29:], math.Float32bits(v.ToY))
|
||||
o.Write(data)
|
||||
p.ops.Write(data)
|
||||
}
|
||||
|
||||
func (p *PathBuilder) simpleQuadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
func (p *PathBuilder) simpleQuadTo(ctrl, to f32.Point) {
|
||||
if p.pen.Y > p.maxy {
|
||||
p.maxy = p.pen.Y
|
||||
}
|
||||
@@ -260,19 +265,19 @@ func (p *PathBuilder) simpleQuadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
||||
p.maxy = to.Y
|
||||
}
|
||||
// NW.
|
||||
p.vertex(ops, -1, 1, ctrl, to)
|
||||
p.vertex(-1, 1, ctrl, to)
|
||||
// NE.
|
||||
p.vertex(ops, 1, 1, ctrl, to)
|
||||
p.vertex(1, 1, ctrl, to)
|
||||
// SW.
|
||||
p.vertex(ops, -1, -1, ctrl, to)
|
||||
p.vertex(-1, -1, ctrl, to)
|
||||
// SE.
|
||||
p.vertex(ops, 1, -1, ctrl, to)
|
||||
p.vertex(1, -1, ctrl, to)
|
||||
p.pen = to
|
||||
}
|
||||
|
||||
func (p *PathBuilder) End(ops *ui.Ops) {
|
||||
p.end(ops)
|
||||
func (p *PathBuilder) End() {
|
||||
p.end()
|
||||
opClip{
|
||||
bounds: p.bounds,
|
||||
}.Add(ops)
|
||||
}.Add(p.ops)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user