aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/internal/ops/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/internal/ops/reader.go')
-rw-r--r--vendor/gioui.org/internal/ops/reader.go121
1 files changed, 72 insertions, 49 deletions
diff --git a/vendor/gioui.org/internal/ops/reader.go b/vendor/gioui.org/internal/ops/reader.go
index 5d713db..99b8cb6 100644
--- a/vendor/gioui.org/internal/ops/reader.go
+++ b/vendor/gioui.org/internal/ops/reader.go
@@ -4,17 +4,15 @@ package ops
import (
"encoding/binary"
-
- "gioui.org/f32"
- "gioui.org/internal/opconst"
- "gioui.org/op"
)
// Reader parses an ops list.
type Reader struct {
- pc pc
- stack []macro
- ops *op.Ops
+ pc PC
+ stack []macro
+ ops *Ops
+ deferOps Ops
+ deferDone bool
}
// EncodedOp represents an encoded op returned by
@@ -27,53 +25,52 @@ type EncodedOp struct {
// Key is a unique key for a given op.
type Key struct {
- ops *op.Ops
- pc int
- version int
- sx, hx, sy, hy float32
+ ops *Ops
+ pc int
+ version int
}
// Shadow of op.MacroOp.
type macroOp struct {
- ops *op.Ops
- pc pc
+ ops *Ops
+ pc PC
}
-type pc struct {
+// PC is an instruction counter for an operation list.
+type PC struct {
data int
refs int
}
type macro struct {
- ops *op.Ops
- retPC pc
- endPC pc
+ ops *Ops
+ retPC PC
+ endPC PC
}
type opMacroDef struct {
- endpc pc
+ endpc PC
}
-// Reset start reading from the op list.
-func (r *Reader) Reset(ops *op.Ops) {
- r.stack = r.stack[:0]
- r.pc = pc{}
- r.ops = ops
+// Reset start reading from the beginning of ops.
+func (r *Reader) Reset(ops *Ops) {
+ r.ResetAt(ops, PC{})
}
-func (k Key) SetTransform(t f32.Affine2D) Key {
- sx, hx, _, hy, sy, _ := t.Elems()
- k.sx = sx
- k.hx = hx
- k.hy = hy
- k.sy = sy
- return k
+// ResetAt is like Reset, except it starts reading from pc.
+func (r *Reader) ResetAt(ops *Ops, pc PC) {
+ r.stack = r.stack[:0]
+ Reset(&r.deferOps)
+ r.deferDone = false
+ r.pc = pc
+ r.ops = ops
}
func (r *Reader) Decode() (EncodedOp, bool) {
if r.ops == nil {
return EncodedOp{}, false
}
+ deferring := false
for {
if len(r.stack) > 0 {
b := r.stack[len(r.stack)-1]
@@ -84,35 +81,59 @@ func (r *Reader) Decode() (EncodedOp, bool) {
continue
}
}
- data := r.ops.Data()
+ data := r.ops.data
data = data[r.pc.data:]
+ refs := r.ops.refs
if len(data) == 0 {
- return EncodedOp{}, false
+ if r.deferDone {
+ return EncodedOp{}, false
+ }
+ r.deferDone = true
+ // Execute deferred macros.
+ r.ops = &r.deferOps
+ r.pc = PC{}
+ continue
}
- key := Key{ops: r.ops, pc: r.pc.data, version: r.ops.Version()}
- t := opconst.OpType(data[0])
+ key := Key{ops: r.ops, pc: r.pc.data, version: r.ops.version}
+ t := OpType(data[0])
n := t.Size()
nrefs := t.NumRefs()
data = data[:n]
- refs := r.ops.Refs()
refs = refs[r.pc.refs:]
refs = refs[:nrefs]
switch t {
- case opconst.TypeAux:
+ case TypeDefer:
+ deferring = true
+ r.pc.data += n
+ r.pc.refs += nrefs
+ continue
+ case TypeAux:
// An Aux operations is always wrapped in a macro, and
// its length is the remaining space.
block := r.stack[len(r.stack)-1]
- n += block.endPC.data - r.pc.data - opconst.TypeAuxLen
+ n += block.endPC.data - r.pc.data - TypeAuxLen
data = data[:n]
- case opconst.TypeCall:
+ case TypeCall:
+ if deferring {
+ deferring = false
+ // Copy macro for deferred execution.
+ if t.NumRefs() != 1 {
+ panic("internal error: unexpected number of macro refs")
+ }
+ deferData := Write1(&r.deferOps, t.Size(), refs[0])
+ copy(deferData, data)
+ r.pc.data += n
+ r.pc.refs += nrefs
+ continue
+ }
var op macroOp
op.decode(data, refs)
- macroData := op.ops.Data()[op.pc.data:]
- if opconst.OpType(macroData[0]) != opconst.TypeMacro {
+ macroData := op.ops.data[op.pc.data:]
+ if OpType(macroData[0]) != TypeMacro {
panic("invalid macro reference")
}
var opDef opMacroDef
- opDef.decode(macroData[:opconst.TypeMacro.Size()])
+ opDef.decode(macroData[:TypeMacro.Size()])
retPC := r.pc
retPC.data += n
retPC.refs += nrefs
@@ -123,10 +144,10 @@ func (r *Reader) Decode() (EncodedOp, bool) {
})
r.ops = op.ops
r.pc = op.pc
- r.pc.data += opconst.TypeMacro.Size()
- r.pc.refs += opconst.TypeMacro.NumRefs()
+ r.pc.data += TypeMacro.Size()
+ r.pc.refs += TypeMacro.NumRefs()
continue
- case opconst.TypeMacro:
+ case TypeMacro:
var op opMacroDef
op.decode(data)
r.pc = op.endpc
@@ -139,14 +160,15 @@ func (r *Reader) Decode() (EncodedOp, bool) {
}
func (op *opMacroDef) decode(data []byte) {
- if opconst.OpType(data[0]) != opconst.TypeMacro {
+ if OpType(data[0]) != TypeMacro {
panic("invalid op")
}
bo := binary.LittleEndian
+ data = data[:9]
dataIdx := int(int32(bo.Uint32(data[1:])))
refsIdx := int(int32(bo.Uint32(data[5:])))
*op = opMacroDef{
- endpc: pc{
+ endpc: PC{
data: dataIdx,
refs: refsIdx,
},
@@ -154,15 +176,16 @@ func (op *opMacroDef) decode(data []byte) {
}
func (m *macroOp) decode(data []byte, refs []interface{}) {
- if opconst.OpType(data[0]) != opconst.TypeCall {
+ if OpType(data[0]) != TypeCall {
panic("invalid op")
}
+ data = data[:9]
bo := binary.LittleEndian
dataIdx := int(int32(bo.Uint32(data[1:])))
refsIdx := int(int32(bo.Uint32(data[5:])))
*m = macroOp{
- ops: refs[0].(*op.Ops),
- pc: pc{
+ ops: refs[0].(*Ops),
+ pc: PC{
data: dataIdx,
refs: refsIdx,
},