mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 01:15: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 {
|
type PathBuilder struct {
|
||||||
|
ops *ui.Ops
|
||||||
firstVert int
|
firstVert int
|
||||||
nverts int
|
nverts int
|
||||||
maxy float32
|
maxy float32
|
||||||
@@ -38,17 +39,21 @@ func (p opClip) Add(o *ui.Ops) {
|
|||||||
o.Write(data)
|
o.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PathBuilder) Init(ops *ui.Ops) {
|
||||||
|
p.ops = ops
|
||||||
|
}
|
||||||
|
|
||||||
// MoveTo moves the pen to the given position.
|
// MoveTo moves the pen to the given position.
|
||||||
func (p *PathBuilder) Move(ops *ui.Ops, to f32.Point) {
|
func (p *PathBuilder) Move(to f32.Point) {
|
||||||
p.end(ops)
|
p.end()
|
||||||
to = to.Add(p.pen)
|
to = to.Add(p.pen)
|
||||||
p.maxy = to.Y
|
p.maxy = to.Y
|
||||||
p.pen = to
|
p.pen = to
|
||||||
}
|
}
|
||||||
|
|
||||||
// end completes the current contour.
|
// end completes the current contour.
|
||||||
func (p *PathBuilder) end(ops *ui.Ops) {
|
func (p *PathBuilder) end() {
|
||||||
aux := ops.Aux()
|
aux := p.ops.Aux()
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
// Fill in maximal Y coordinates of the NW and NE corners.
|
// Fill in maximal Y coordinates of the NW and NE corners.
|
||||||
for i := p.firstVert; i < p.nverts; i++ {
|
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.
|
// 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)
|
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.
|
// 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
|
// Quad records a quadratic bezier from the pen to end
|
||||||
// with the control point ctrl.
|
// 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)
|
ctrl = ctrl.Add(p.pen)
|
||||||
to = to.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.
|
// Zero width curves don't contribute to stenciling.
|
||||||
if p.pen.X == to.X && p.pen.X == ctrl.X {
|
if p.pen.X == to.X && p.pen.X == ctrl.X {
|
||||||
p.pen = to
|
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))
|
ctrl0 := p.pen.Mul(1 - t).Add(ctrl.Mul(t))
|
||||||
ctrl1 := ctrl.Mul(1 - t).Add(to.Mul(t))
|
ctrl1 := ctrl.Mul(1 - t).Add(to.Mul(t))
|
||||||
mid := ctrl0.Mul(1 - t).Add(ctrl1.Mul(t))
|
mid := ctrl0.Mul(1 - t).Add(ctrl1.Mul(t))
|
||||||
p.simpleQuadTo(ops, ctrl0, mid)
|
p.simpleQuadTo(ctrl0, mid)
|
||||||
p.simpleQuadTo(ops, ctrl1, to)
|
p.simpleQuadTo(ctrl1, to)
|
||||||
if mid.X > bounds.Max.X {
|
if mid.X > bounds.Max.X {
|
||||||
bounds.Max.X = mid.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
|
bounds.Min.X = mid.X
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.simpleQuadTo(ops, ctrl, to)
|
p.simpleQuadTo(ctrl, to)
|
||||||
}
|
}
|
||||||
// Find the y extremum, if any.
|
// Find the y extremum, if any.
|
||||||
d = v0.Y - v1.Y
|
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
|
// Cube records a cubic bezier from the pen through
|
||||||
// two control points ending in to.
|
// 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)
|
ctrl0 = ctrl0.Add(p.pen)
|
||||||
ctrl1 = ctrl1.Add(p.pen)
|
ctrl1 = ctrl1.Add(p.pen)
|
||||||
to = to.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 {
|
if h := hull.Dy(); h > l {
|
||||||
l = h
|
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
|
// approxCube approximates a cubic beziér by a series of quadratic
|
||||||
// curves.
|
// 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
|
// The idea is from
|
||||||
// https://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
|
// https://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
|
||||||
// where a quadratic approximates a cubic by eliminating its t³ term
|
// 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)
|
c := ctrl0.Mul(3).Sub(p.pen).Add(ctrl1.Mul(3)).Sub(to).Mul(1.0 / 4.0)
|
||||||
const maxSplits = 32
|
const maxSplits = 32
|
||||||
if splits >= maxSplits {
|
if splits >= maxSplits {
|
||||||
p.quadTo(ops, c, to)
|
p.quadTo(c, to)
|
||||||
return splits
|
return splits
|
||||||
}
|
}
|
||||||
// The maximum distance between the cubic P and its approximation Q given t
|
// 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)
|
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)
|
d2 := (v.X*v.X + v.Y*v.Y) * 3 / (36 * 36)
|
||||||
if d2 <= maxDist*maxDist {
|
if d2 <= maxDist*maxDist {
|
||||||
p.quadTo(ops, c, to)
|
p.quadTo(c, to)
|
||||||
return splits
|
return splits
|
||||||
}
|
}
|
||||||
// De Casteljau split the curve and approximate the halves.
|
// 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))
|
c12 := c1.Add(c2.Sub(c1).Mul(t))
|
||||||
c0112 := c01.Add(c12.Sub(c01).Mul(t))
|
c0112 := c01.Add(c12.Sub(c01).Mul(t))
|
||||||
splits++
|
splits++
|
||||||
splits = p.approxCubeTo(ops, splits, maxDist, c0, c01, c0112)
|
splits = p.approxCubeTo(splits, maxDist, c0, c01, c0112)
|
||||||
splits = p.approxCubeTo(ops, splits, maxDist, c12, c2, to)
|
splits = p.approxCubeTo(splits, maxDist, c12, c2, to)
|
||||||
return splits
|
return splits
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +225,7 @@ func (p *PathBuilder) expand(b f32.Rectangle) {
|
|||||||
p.bounds = p.bounds.Union(b)
|
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++
|
p.nverts++
|
||||||
v := path.Vertex{
|
v := path.Vertex{
|
||||||
CornerX: cornerx,
|
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[21:], math.Float32bits(v.CtrlY))
|
||||||
bo.PutUint32(data[25:], math.Float32bits(v.ToX))
|
bo.PutUint32(data[25:], math.Float32bits(v.ToX))
|
||||||
bo.PutUint32(data[29:], math.Float32bits(v.ToY))
|
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 {
|
if p.pen.Y > p.maxy {
|
||||||
p.maxy = p.pen.Y
|
p.maxy = p.pen.Y
|
||||||
}
|
}
|
||||||
@@ -260,19 +265,19 @@ func (p *PathBuilder) simpleQuadTo(ops *ui.Ops, ctrl, to f32.Point) {
|
|||||||
p.maxy = to.Y
|
p.maxy = to.Y
|
||||||
}
|
}
|
||||||
// NW.
|
// NW.
|
||||||
p.vertex(ops, -1, 1, ctrl, to)
|
p.vertex(-1, 1, ctrl, to)
|
||||||
// NE.
|
// NE.
|
||||||
p.vertex(ops, 1, 1, ctrl, to)
|
p.vertex(1, 1, ctrl, to)
|
||||||
// SW.
|
// SW.
|
||||||
p.vertex(ops, -1, -1, ctrl, to)
|
p.vertex(-1, -1, ctrl, to)
|
||||||
// SE.
|
// SE.
|
||||||
p.vertex(ops, 1, -1, ctrl, to)
|
p.vertex(1, -1, ctrl, to)
|
||||||
p.pen = to
|
p.pen = to
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PathBuilder) End(ops *ui.Ops) {
|
func (p *PathBuilder) End() {
|
||||||
p.end(ops)
|
p.end()
|
||||||
opClip{
|
opClip{
|
||||||
bounds: p.bounds,
|
bounds: p.bounds,
|
||||||
}.Add(ops)
|
}.Add(p.ops)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-15
@@ -15,6 +15,7 @@ type Flex struct {
|
|||||||
CrossAxisAlignment CrossAxisAlignment
|
CrossAxisAlignment CrossAxisAlignment
|
||||||
MainAxisSize MainAxisSize
|
MainAxisSize MainAxisSize
|
||||||
|
|
||||||
|
ops *ui.Ops
|
||||||
constrained bool
|
constrained bool
|
||||||
cs Constraints
|
cs Constraints
|
||||||
begun bool
|
begun bool
|
||||||
@@ -57,10 +58,11 @@ const (
|
|||||||
Stretch
|
Stretch
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Flex) Init(cs Constraints) {
|
func (f *Flex) Init(ops *ui.Ops, cs Constraints) {
|
||||||
if f.constrained {
|
if f.constrained {
|
||||||
panic("Constrain must be called exactly once")
|
panic("Constrain must be called exactly once")
|
||||||
}
|
}
|
||||||
|
f.ops = ops
|
||||||
f.constrained = true
|
f.constrained = true
|
||||||
f.cs = cs
|
f.cs = cs
|
||||||
f.taken = 0
|
f.taken = 0
|
||||||
@@ -68,7 +70,7 @@ func (f *Flex) Init(cs Constraints) {
|
|||||||
f.maxBaseline = 0
|
f.maxBaseline = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) begin(ops *ui.Ops) {
|
func (f *Flex) begin() {
|
||||||
if !f.constrained {
|
if !f.constrained {
|
||||||
panic("must Constrain before adding a child")
|
panic("must Constrain before adding a child")
|
||||||
}
|
}
|
||||||
@@ -76,12 +78,12 @@ func (f *Flex) begin(ops *ui.Ops) {
|
|||||||
panic("must End before adding a child")
|
panic("must End before adding a child")
|
||||||
}
|
}
|
||||||
f.begun = true
|
f.begun = true
|
||||||
ops.Begin()
|
f.ops.Begin()
|
||||||
ui.OpLayer{}.Add(ops)
|
ui.OpLayer{}.Add(f.ops)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) Rigid(ops *ui.Ops) Constraints {
|
func (f *Flex) Rigid() Constraints {
|
||||||
f.begin(ops)
|
f.begin()
|
||||||
mainc := axisMainConstraint(f.Axis, f.cs)
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
mainMax := mainc.Max
|
mainMax := mainc.Max
|
||||||
if mainc.Max != ui.Inf {
|
if mainc.Max != ui.Inf {
|
||||||
@@ -90,8 +92,8 @@ func (f *Flex) Rigid(ops *ui.Ops) Constraints {
|
|||||||
return axisConstraints(f.Axis, Constraint{Max: mainMax}, f.crossConstraintChild(f.cs))
|
return axisConstraints(f.Axis, Constraint{Max: mainMax}, f.crossConstraintChild(f.cs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode) Constraints {
|
func (f *Flex) Flexible(flex float32, mode FlexMode) Constraints {
|
||||||
f.begin(ops)
|
f.begin()
|
||||||
mainc := axisMainConstraint(f.Axis, f.cs)
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
var flexSize int
|
var flexSize int
|
||||||
if mainc.Max != ui.Inf && mainc.Max > f.taken {
|
if mainc.Max != ui.Inf && mainc.Max > f.taken {
|
||||||
@@ -104,12 +106,12 @@ func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode) Constraints {
|
|||||||
return axisConstraints(f.Axis, submainc, f.crossConstraintChild(f.cs))
|
return axisConstraints(f.Axis, submainc, f.crossConstraintChild(f.cs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) End(ops *ui.Ops, dims Dimens) FlexChild {
|
func (f *Flex) End(dims Dimens) FlexChild {
|
||||||
if !f.begun {
|
if !f.begun {
|
||||||
panic("End called without an active child")
|
panic("End called without an active child")
|
||||||
}
|
}
|
||||||
f.begun = false
|
f.begun = false
|
||||||
block := ops.End()
|
block := f.ops.End()
|
||||||
f.taken += axisMain(f.Axis, dims.Size)
|
f.taken += axisMain(f.Axis, dims.Size)
|
||||||
if c := axisCross(f.Axis, dims.Size); c > f.maxCross {
|
if c := axisCross(f.Axis, dims.Size); c > f.maxCross {
|
||||||
f.maxCross = c
|
f.maxCross = c
|
||||||
@@ -120,7 +122,7 @@ func (f *Flex) End(ops *ui.Ops, dims Dimens) FlexChild {
|
|||||||
return FlexChild{block, dims}
|
return FlexChild{block, dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) Layout(ops *ui.Ops, children ...FlexChild) Dimens {
|
func (f *Flex) Layout(children ...FlexChild) Dimens {
|
||||||
mainc := axisMainConstraint(f.Axis, f.cs)
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
crossSize := axisCrossConstraint(f.Axis, f.cs).Constrain(f.maxCross)
|
crossSize := axisCrossConstraint(f.Axis, f.cs).Constrain(f.maxCross)
|
||||||
var space int
|
var space int
|
||||||
@@ -157,12 +159,12 @@ func (f *Flex) Layout(ops *ui.Ops, children ...FlexChild) Dimens {
|
|||||||
cross = f.maxBaseline - b
|
cross = f.maxBaseline - b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.OpPush{}.Add(ops)
|
ui.OpPush{}.Add(f.ops)
|
||||||
ui.OpTransform{
|
ui.OpTransform{
|
||||||
Transform: ui.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))),
|
Transform: ui.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))),
|
||||||
}.Add(ops)
|
}.Add(f.ops)
|
||||||
child.block.Add(ops)
|
child.block.Add(f.ops)
|
||||||
ui.OpPop{}.Add(ops)
|
ui.OpPop{}.Add(f.ops)
|
||||||
mainSize += axisMain(f.Axis, dims.Size)
|
mainSize += axisMain(f.Axis, dims.Size)
|
||||||
switch f.MainAxisAlignment {
|
switch f.MainAxisAlignment {
|
||||||
case SpaceEvenly:
|
case SpaceEvenly:
|
||||||
|
|||||||
+9
-3
@@ -70,10 +70,12 @@ func ExactConstraints(size image.Point) Constraints {
|
|||||||
type Insets struct {
|
type Insets struct {
|
||||||
Top, Right, Bottom, Left float32
|
Top, Right, Bottom, Left float32
|
||||||
|
|
||||||
cs Constraints
|
ops *ui.Ops
|
||||||
|
cs Constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Insets) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
func (in *Insets) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
||||||
|
in.ops = ops
|
||||||
in.cs = cs
|
in.cs = cs
|
||||||
mcs := cs
|
mcs := cs
|
||||||
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
||||||
@@ -102,7 +104,8 @@ func (in *Insets) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
|||||||
return mcs
|
return mcs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Insets) End(ops *ui.Ops, dims Dimens) Dimens {
|
func (in *Insets) End(dims Dimens) Dimens {
|
||||||
|
ops := in.ops
|
||||||
ui.OpPop{}.Add(ops)
|
ui.OpPop{}.Add(ops)
|
||||||
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
||||||
return Dimens{
|
return Dimens{
|
||||||
@@ -144,17 +147,20 @@ func (s Sized) Constrain(cs Constraints) Constraints {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Align struct {
|
type Align struct {
|
||||||
|
ops *ui.Ops
|
||||||
Alignment Direction
|
Alignment Direction
|
||||||
cs Constraints
|
cs Constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Align) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
func (a *Align) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
||||||
|
a.ops = ops
|
||||||
a.cs = cs
|
a.cs = cs
|
||||||
ops.Begin()
|
ops.Begin()
|
||||||
return cs.Loose()
|
return cs.Loose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Align) End(ops *ui.Ops, dims Dimens) Dimens {
|
func (a *Align) End(dims Dimens) Dimens {
|
||||||
|
ops := a.ops
|
||||||
block := ops.End()
|
block := ops.End()
|
||||||
sz := dims.Size
|
sz := dims.Size
|
||||||
if a.cs.Width.Max != ui.Inf {
|
if a.cs.Width.Max != ui.Inf {
|
||||||
|
|||||||
+15
-16
@@ -24,6 +24,7 @@ type List struct {
|
|||||||
// The distance scrolled since last call to Init.
|
// The distance scrolled since last call to Init.
|
||||||
Distance int
|
Distance int
|
||||||
|
|
||||||
|
ops *ui.Ops
|
||||||
scroll gesture.Scroll
|
scroll gesture.Scroll
|
||||||
scrollDir int
|
scrollDir int
|
||||||
|
|
||||||
@@ -46,7 +47,8 @@ const (
|
|||||||
iterateBackward
|
iterateBackward
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *List) Init(cs Constraints, len int) {
|
func (l *List) Init(ops *ui.Ops, cs Constraints, len int) {
|
||||||
|
l.ops = ops
|
||||||
l.dir = iterateNone
|
l.dir = iterateNone
|
||||||
l.maxSize = 0
|
l.maxSize = 0
|
||||||
l.children = l.children[:0]
|
l.children = l.children[:0]
|
||||||
@@ -55,6 +57,7 @@ func (l *List) Init(cs Constraints, len int) {
|
|||||||
if l.first > len {
|
if l.first > len {
|
||||||
l.first = len
|
l.first = len
|
||||||
}
|
}
|
||||||
|
ops.Begin()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Dragging() bool {
|
func (l *List) Dragging() bool {
|
||||||
@@ -69,19 +72,16 @@ func (l *List) Update(c *ui.Config, q pointer.Events) {
|
|||||||
l.offset += d
|
l.offset += d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Next(ops *ui.Ops) (int, Constraints, bool) {
|
func (l *List) Next() (int, Constraints, bool) {
|
||||||
if l.dir != iterateNone {
|
if l.dir != iterateNone {
|
||||||
panic("a previous Next was not finished with Elem")
|
panic("a previous Next was not finished with Elem")
|
||||||
}
|
}
|
||||||
i, ok := l.next()
|
i, ok := l.next()
|
||||||
var cs Constraints
|
var cs Constraints
|
||||||
if ok {
|
if ok {
|
||||||
if len(l.children) == 0 {
|
|
||||||
ops.Begin()
|
|
||||||
}
|
|
||||||
cs = axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
|
cs = axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
|
||||||
ops.Begin()
|
l.ops.Begin()
|
||||||
ui.OpLayer{}.Add(ops)
|
ui.OpLayer{}.Add(l.ops)
|
||||||
}
|
}
|
||||||
return i, cs, ok
|
return i, cs, ok
|
||||||
}
|
}
|
||||||
@@ -110,8 +110,8 @@ func (l *List) next() (int, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) End(ops *ui.Ops, dims Dimens) {
|
func (l *List) End(dims Dimens) {
|
||||||
block := ops.End()
|
block := l.ops.End()
|
||||||
child := scrollChild{dims.Size, block}
|
child := scrollChild{dims.Size, block}
|
||||||
switch l.dir {
|
switch l.dir {
|
||||||
case iterateForward:
|
case iterateForward:
|
||||||
@@ -130,7 +130,7 @@ func (l *List) End(ops *ui.Ops, dims Dimens) {
|
|||||||
l.dir = iterateNone
|
l.dir = iterateNone
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Layout(ops *ui.Ops) Dimens {
|
func (l *List) Layout() Dimens {
|
||||||
mainc := axisMainConstraint(l.Axis, l.cs)
|
mainc := axisMainConstraint(l.Axis, l.cs)
|
||||||
for len(l.children) > 0 {
|
for len(l.children) > 0 {
|
||||||
sz := l.children[0].size
|
sz := l.children[0].size
|
||||||
@@ -155,6 +155,7 @@ func (l *List) Layout(ops *ui.Ops) Dimens {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ops := l.ops
|
||||||
pos := -l.offset
|
pos := -l.offset
|
||||||
for _, child := range l.children {
|
for _, child := range l.children {
|
||||||
sz := child.size
|
sz := child.size
|
||||||
@@ -192,12 +193,10 @@ func (l *List) Layout(ops *ui.Ops) Dimens {
|
|||||||
l.scroll.Stop()
|
l.scroll.Stop()
|
||||||
}
|
}
|
||||||
dims := axisPoint(l.Axis, mainc.Constrain(pos), maxCross)
|
dims := axisPoint(l.Axis, mainc.Constrain(pos), maxCross)
|
||||||
if len(l.children) > 0 {
|
block := ops.End()
|
||||||
block := ops.End()
|
pointer.AreaRect(dims).Add(ops)
|
||||||
pointer.AreaRect(dims).Add(ops)
|
l.scroll.Add(ops)
|
||||||
l.scroll.Add(ops)
|
block.Add(ops)
|
||||||
block.Add(ops)
|
|
||||||
}
|
|
||||||
return Dimens{Size: dims}
|
return Dimens{Size: dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-15
@@ -11,6 +11,7 @@ import (
|
|||||||
type Stack struct {
|
type Stack struct {
|
||||||
Alignment Direction
|
Alignment Direction
|
||||||
|
|
||||||
|
ops *ui.Ops
|
||||||
constrained bool
|
constrained bool
|
||||||
cs Constraints
|
cs Constraints
|
||||||
begun bool
|
begun bool
|
||||||
@@ -36,14 +37,15 @@ const (
|
|||||||
W
|
W
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Stack) Init(cs Constraints) {
|
func (s *Stack) Init(ops *ui.Ops, cs Constraints) {
|
||||||
|
s.ops = ops
|
||||||
s.cs = cs
|
s.cs = cs
|
||||||
s.constrained = true
|
s.constrained = true
|
||||||
s.maxSZ = image.Point{}
|
s.maxSZ = image.Point{}
|
||||||
s.baseline = 0
|
s.baseline = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) begin(ops *ui.Ops) {
|
func (s *Stack) begin() {
|
||||||
if !s.constrained {
|
if !s.constrained {
|
||||||
panic("must Constrain before adding a child")
|
panic("must Constrain before adding a child")
|
||||||
}
|
}
|
||||||
@@ -51,25 +53,25 @@ func (s *Stack) begin(ops *ui.Ops) {
|
|||||||
panic("must End before adding a child")
|
panic("must End before adding a child")
|
||||||
}
|
}
|
||||||
s.begun = true
|
s.begun = true
|
||||||
ops.Begin()
|
s.ops.Begin()
|
||||||
ui.OpLayer{}.Add(ops)
|
ui.OpLayer{}.Add(s.ops)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) Rigid(ops *ui.Ops) Constraints {
|
func (s *Stack) Rigid() Constraints {
|
||||||
s.begin(ops)
|
s.begin()
|
||||||
return s.cs
|
return s.cs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) Expand(ops *ui.Ops) Constraints {
|
func (s *Stack) Expand() Constraints {
|
||||||
s.begin(ops)
|
s.begin()
|
||||||
return Constraints{
|
return Constraints{
|
||||||
Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X},
|
Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X},
|
||||||
Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y},
|
Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) End(ops *ui.Ops, dims Dimens) StackChild {
|
func (s *Stack) End(dims Dimens) StackChild {
|
||||||
b := ops.End()
|
b := s.ops.End()
|
||||||
s.begun = false
|
s.begun = false
|
||||||
if w := dims.Size.X; w > s.maxSZ.X {
|
if w := dims.Size.X; w > s.maxSZ.X {
|
||||||
s.maxSZ.X = w
|
s.maxSZ.X = w
|
||||||
@@ -85,7 +87,7 @@ func (s *Stack) End(ops *ui.Ops, dims Dimens) StackChild {
|
|||||||
return StackChild{b, dims}
|
return StackChild{b, dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) Layout(ops *ui.Ops, children ...StackChild) Dimens {
|
func (s *Stack) Layout(children ...StackChild) Dimens {
|
||||||
for _, ch := range children {
|
for _, ch := range children {
|
||||||
sz := ch.dims.Size
|
sz := ch.dims.Size
|
||||||
var p image.Point
|
var p image.Point
|
||||||
@@ -101,10 +103,10 @@ func (s *Stack) Layout(ops *ui.Ops, children ...StackChild) Dimens {
|
|||||||
case SW, S, SE:
|
case SW, S, SE:
|
||||||
p.Y = s.maxSZ.Y - sz.Y
|
p.Y = s.maxSZ.Y - sz.Y
|
||||||
}
|
}
|
||||||
ui.OpPush{}.Add(ops)
|
ui.OpPush{}.Add(s.ops)
|
||||||
ui.OpTransform{Transform: ui.Offset(toPointF(p))}.Add(ops)
|
ui.OpTransform{Transform: ui.Offset(toPointF(p))}.Add(s.ops)
|
||||||
ch.block.Add(ops)
|
ch.block.Add(s.ops)
|
||||||
ui.OpPop{}.Add(ops)
|
ui.OpPop{}.Add(s.ops)
|
||||||
}
|
}
|
||||||
b := s.baseline
|
b := s.baseline
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ func textPath(ppem fixed.Int26_6, f *opentype, str text.String) ui.OpBlock {
|
|||||||
var lastPos f32.Point
|
var lastPos f32.Point
|
||||||
var builder draw.PathBuilder
|
var builder draw.PathBuilder
|
||||||
ops := new(ui.Ops)
|
ops := new(ui.Ops)
|
||||||
|
builder.Init(ops)
|
||||||
var x fixed.Int26_6
|
var x fixed.Int26_6
|
||||||
var advIdx int
|
var advIdx int
|
||||||
ops.Begin()
|
ops.Begin()
|
||||||
@@ -246,7 +247,7 @@ func textPath(ppem fixed.Int26_6, f *opentype, str text.String) ui.OpBlock {
|
|||||||
pos := f32.Point{
|
pos := f32.Point{
|
||||||
X: float32(x) / 64,
|
X: float32(x) / 64,
|
||||||
}
|
}
|
||||||
builder.Move(ops, pos.Sub(lastPos))
|
builder.Move(pos.Sub(lastPos))
|
||||||
lastPos = pos
|
lastPos = pos
|
||||||
var lastArg f32.Point
|
var lastArg f32.Point
|
||||||
// Convert sfnt.Segments to relative segments.
|
// Convert sfnt.Segments to relative segments.
|
||||||
@@ -271,13 +272,13 @@ func textPath(ppem fixed.Int26_6, f *opentype, str text.String) ui.OpBlock {
|
|||||||
}
|
}
|
||||||
switch fseg.Op {
|
switch fseg.Op {
|
||||||
case sfnt.SegmentOpMoveTo:
|
case sfnt.SegmentOpMoveTo:
|
||||||
builder.Move(ops, args[0])
|
builder.Move(args[0])
|
||||||
case sfnt.SegmentOpLineTo:
|
case sfnt.SegmentOpLineTo:
|
||||||
builder.Line(ops, args[0])
|
builder.Line(args[0])
|
||||||
case sfnt.SegmentOpQuadTo:
|
case sfnt.SegmentOpQuadTo:
|
||||||
builder.Quad(ops, args[0], args[1])
|
builder.Quad(args[0], args[1])
|
||||||
case sfnt.SegmentOpCubeTo:
|
case sfnt.SegmentOpCubeTo:
|
||||||
builder.Cube(ops, args[0], args[1], args[2])
|
builder.Cube(args[0], args[1], args[2])
|
||||||
default:
|
default:
|
||||||
panic("unsupported segment op")
|
panic("unsupported segment op")
|
||||||
}
|
}
|
||||||
@@ -287,6 +288,6 @@ func textPath(ppem fixed.Int26_6, f *opentype, str text.String) ui.OpBlock {
|
|||||||
x += str.Advances[advIdx]
|
x += str.Advances[advIdx]
|
||||||
advIdx++
|
advIdx++
|
||||||
}
|
}
|
||||||
builder.End(ops)
|
builder.End()
|
||||||
return ops.End()
|
return ops.End()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user