diff options
Diffstat (limited to 'vendor/gioui.org/internal/ops/reader.go')
-rw-r--r-- | vendor/gioui.org/internal/ops/reader.go | 121 |
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, }, |