ui: move ops reader to ui package

To prepare support for cached OpBlock to refer to other Ops lists.

The exposure of OpsReader is alleviated by the removal of the Refs
and Data accessors for Ops.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-06-01 19:46:46 +02:00
parent 528a588f2e
commit 5966aab77e
6 changed files with 90 additions and 102 deletions
+78 -9
View File
@@ -6,7 +6,7 @@ import (
"gioui.org/ui/internal/ops"
)
// Ops hold a list of serialized Ops.
// Ops holds a list of serialized Ops.
type Ops struct {
// Stack of block start indices.
stack []int
@@ -16,6 +16,37 @@ type Ops struct {
refs []interface{}
}
type OpsReader struct {
pc int
stack []block
Refs []interface{}
data []byte
pseudoOp [1]byte
}
type block struct {
retPC int
endPC int
}
var typeLengths = [...]int{
ops.TypeBlockDefLen,
ops.TypeBlockLen,
ops.TypeTransformLen,
ops.TypeLayerLen,
ops.TypeRedrawLen,
ops.TypeClipLen,
ops.TypeImageLen,
ops.TypeDrawLen,
ops.TypeColorLen,
ops.TypePointerHandlerLen,
ops.TypeKeyHandlerLen,
ops.TypeHideInputLen,
ops.TypePushLen,
ops.TypePopLen,
}
type OpBlock struct {
idx int
}
@@ -46,14 +77,6 @@ func (o *Ops) Reset() {
o.data = o.data[:0]
}
func (o *Ops) Refs() []interface{} {
return o.refs
}
func (o *Ops) Data() []byte {
return o.data
}
func (o *Ops) Ref(r interface{}) int {
o.refs = append(o.refs, r)
return len(o.refs) - 1
@@ -75,3 +98,49 @@ func (b OpBlock) Add(o *Ops) {
bo.PutUint32(data[1:], uint32(b.idx))
o.Write(data)
}
// Reset start reading from the op list.
func (r *OpsReader) Reset(ops *Ops) {
r.Refs = ops.refs
r.data = ops.data
r.stack = r.stack[:0]
r.pc = 0
}
func (r *OpsReader) Decode() ([]byte, bool) {
bo := binary.LittleEndian
for {
if r.pc == len(r.data) {
return nil, false
}
if len(r.stack) > 0 {
b := r.stack[len(r.stack)-1]
if r.pc == b.endPC {
r.pc = b.retPC
r.stack = r.stack[:len(r.stack)-1]
r.pseudoOp[0] = byte(ops.TypePop)
return r.pseudoOp[:], true
}
}
t := ops.OpType(r.data[r.pc])
n := typeLengths[t]
data := r.data[r.pc : r.pc+n]
switch t {
case ops.TypeBlock:
blockIdx := int(bo.Uint32(data[1:]))
if ops.OpType(r.data[blockIdx]) != ops.TypeBlockDef {
panic("invalid block reference")
}
blockLen := int(bo.Uint32(r.data[blockIdx+1:]))
r.stack = append(r.stack, block{r.pc + n, blockIdx + blockLen})
r.pc = blockIdx + ops.TypeBlockDefLen
r.pseudoOp[0] = byte(ops.TypePush)
return r.pseudoOp[:], true
case ops.TypeBlockDef:
r.pc += int(bo.Uint32(data[1:]))
continue
}
r.pc += n
return data, true
}
}