Files
gio/ui/internal/ops/ops.go
T
Elias Naur 00a87f542d ui: introduce OpColor, a specialized OpImage for uniform colors
To avoid allocating an image.Image for OpImage.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2019-06-01 13:01:51 +02:00

119 lines
2.2 KiB
Go

package ops
import (
"encoding/binary"
)
type Reader struct {
pc int
stack []block
Refs []interface{}
data []byte
pseudoOp [1]byte
}
type block struct {
retPC int
endPC int
}
type OpType byte
const (
TypeBlockDef OpType = iota
TypeBlock
TypeTransform
TypeLayer
TypeRedraw
TypeClip
TypeImage
TypeDraw
TypeColor
TypePointerHandler
TypeKeyHandler
TypeHideInput
TypePush
TypePop
)
const (
TypeBlockDefLen = 1 + 4
TypeBlockLen = 1 + 4
TypeTransformLen = 1 + 4*2
TypeLayerLen = 1
TypeRedrawLen = 1 + 8
TypeClipLen = 1 + 4
TypeImageLen = 1 + 4 + 4*4
TypeDrawLen = 1 + 4*4
TypeColorLen = 1 + 4
TypePointerHandlerLen = 1 + 4 + 4 + 1
TypeKeyHandlerLen = 1 + 4 + 1
TypeHideInputLen = 1
TypePushLen = 1
TypePopLen = 1
)
var typeLengths = [...]int{
TypeBlockDefLen,
TypeBlockLen,
TypeTransformLen,
TypeLayerLen,
TypeRedrawLen,
TypeClipLen,
TypeImageLen,
TypeDrawLen,
TypeColorLen,
TypePointerHandlerLen,
TypeKeyHandlerLen,
TypeHideInputLen,
TypePushLen,
TypePopLen,
}
// Reset start reading from the op list.
func (r *Reader) Reset(data []byte, refs []interface{}) {
r.Refs = refs
r.data = data
r.stack = r.stack[:0]
r.pc = 0
}
func (r *Reader) 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(TypePop)
return r.pseudoOp[:], true
}
}
t := OpType(r.data[r.pc])
n := typeLengths[t]
data := r.data[r.pc : r.pc+n]
switch t {
case TypeBlock:
blockIdx := int(bo.Uint32(data[1:]))
if OpType(r.data[blockIdx]) != 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 + TypeBlockDefLen
r.pseudoOp[0] = byte(TypePush)
return r.pseudoOp[:], true
case TypeBlockDef:
r.pc += int(bo.Uint32(data[1:]))
continue
}
r.pc += n
return data, true
}
}