From 9142345fd41636140f6e1e24f838f50fff5b837f Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sun, 2 Jun 2019 15:10:09 +0200 Subject: [PATCH] ui: make OpPush and OpPop explicit We're about to allow OpBlock for invoking ops from multiple (cached) Ops containers. To allow for drawing state changes to stick after invoking such a cached block, we can't let OpBlock perform an implicit save and restore of drawing state. Instead, introduce OpPush and OpPop for explicit drawing state stack management. Signed-off-by: Elias Naur --- ui/layout/flex.go | 4 ++-- ui/layout/layout.go | 8 ++++---- ui/layout/list.go | 4 ++-- ui/layout/stack.go | 4 ++-- ui/ops.go | 20 ++++++++++++++------ ui/text/editor.go | 4 ++-- ui/text/label.go | 4 ++-- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ui/layout/flex.go b/ui/layout/flex.go index fc39771f..7f716449 100644 --- a/ui/layout/flex.go +++ b/ui/layout/flex.go @@ -157,12 +157,12 @@ func (f *Flex) Layout(ops *ui.Ops, children ...FlexChild) Dimens { cross = f.maxBaseline - b } } - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{ Transform: ui.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))), }.Add(ops) child.block.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) mainSize += axisMain(f.Axis, dims.Size) switch f.MainAxisAlignment { case SpaceEvenly: diff --git a/ui/layout/layout.go b/ui/layout/layout.go index 973d43f8..61a25375 100644 --- a/ui/layout/layout.go +++ b/ui/layout/layout.go @@ -97,13 +97,13 @@ func (in *Insets) Begin(ops *ui.Ops, cs Constraints) Constraints { mcs.Height.Max = mcs.Height.Min } } - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{Transform: ui.Offset(toPointF(image.Point{X: l, Y: t}))}.Add(ops) return mcs } func (in *Insets) End(ops *ui.Ops, dims Dimens) Dimens { - ops.End().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))) return Dimens{ Size: in.cs.Constrain(dims.Size.Add(image.Point{X: r + l, Y: t + b})), @@ -176,10 +176,10 @@ func (a *Align) End(ops *ui.Ops, dims Dimens) Dimens { case SW, S, SE: p.Y = sz.Y - dims.Size.Y } - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{Transform: ui.Offset(toPointF(p))}.Add(ops) block.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) return Dimens{ Size: sz, Baseline: dims.Baseline, diff --git a/ui/layout/list.go b/ui/layout/list.go index cba4780a..79f2b1d0 100644 --- a/ui/layout/list.go +++ b/ui/layout/list.go @@ -178,13 +178,13 @@ func (l *List) Layout(ops *ui.Ops) Dimens { Min: axisPoint(l.Axis, min, -ui.Inf), Max: axisPoint(l.Axis, max, ui.Inf), } - ops.Begin() + ui.OpPush{}.Add(ops) draw.OpClip{Path: draw.RectPath(r)}.Add(ops) ui.OpTransform{ Transform: ui.Offset(toPointF(axisPoint(l.Axis, pos, cross))), }.Add(ops) child.block.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) pos += axisMain(l.Axis, sz) } atStart := l.first == 0 && l.offset <= 0 diff --git a/ui/layout/stack.go b/ui/layout/stack.go index 6abf1051..1af42404 100644 --- a/ui/layout/stack.go +++ b/ui/layout/stack.go @@ -101,10 +101,10 @@ func (s *Stack) Layout(ops *ui.Ops, children ...StackChild) Dimens { case SW, S, SE: p.Y = s.maxSZ.Y - sz.Y } - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{Transform: ui.Offset(toPointF(p))}.Add(ops) ch.block.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) } b := s.baseline if b == 0 { diff --git a/ui/ops.go b/ui/ops.go index 320c7b93..d84e6953 100644 --- a/ui/ops.go +++ b/ui/ops.go @@ -24,8 +24,6 @@ type OpsReader struct { pc pc stack []block ops opsData - - pseudoOp [1]byte } type block struct { @@ -73,6 +71,10 @@ var refLengths = [...]int{ ops.TypePopRefs, } +type OpPush struct{} + +type OpPop struct{} + type OpBlock struct { ops *Ops pc pc @@ -82,6 +84,14 @@ type opBlockDef struct { endpc pc } +func (p OpPush) Add(o *Ops) { + o.Write([]byte{byte(ops.TypePush)}, nil) +} + +func (p OpPop) Add(o *Ops) { + o.Write([]byte{byte(ops.TypePop)}, nil) +} + // Begin a block of ops. func (o *Ops) Begin() { o.stack = append(o.stack, o.ops.pc()) @@ -183,8 +193,7 @@ func (r *OpsReader) Decode() ([]byte, []interface{}, bool) { r.ops = b.ops r.pc = b.retPC r.stack = r.stack[:len(r.stack)-1] - r.pseudoOp[0] = byte(ops.TypePop) - return r.pseudoOp[:], nil, true + continue } } if r.pc.data == len(r.ops.data) { @@ -217,8 +226,7 @@ func (r *OpsReader) Decode() ([]byte, []interface{}, bool) { r.pc = op.pc r.pc.data += ops.TypeBlockDefLen r.pc.refs += ops.TypeBlockDefRefs - r.pseudoOp[0] = byte(ops.TypePush) - return r.pseudoOp[:], nil, true + continue case ops.TypeBlockDef: var op opBlockDef op.decode(data) diff --git a/ui/text/editor.go b/ui/text/editor.go index 8bcb55c7..ac205a0b 100644 --- a/ui/text/editor.go +++ b/ui/text/editor.go @@ -171,11 +171,11 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens { break } path := e.Face.Path(str) - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{Transform: ui.Offset(lineOff)}.Add(ops) draw.OpClip{Path: path}.Add(ops) draw.OpDraw{Rect: toRectF(clip).Sub(lineOff)}.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) } if e.focused { now := e.cfg.Now diff --git a/ui/text/label.go b/ui/text/label.go index d79a59be..8d483e52 100644 --- a/ui/text/label.go +++ b/ui/text/label.go @@ -102,11 +102,11 @@ func (l Label) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens { } path := l.Face.Path(str) lclip := toRectF(clip).Sub(off) - ops.Begin() + ui.OpPush{}.Add(ops) ui.OpTransform{Transform: ui.Offset(off)}.Add(ops) draw.OpClip{Path: path}.Add(ops) draw.OpDraw{Rect: lclip}.Add(ops) - ops.End().Add(ops) + ui.OpPop{}.Add(ops) } return dims }