mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-02 16:06:19 +00:00
ui,internal/ops,internal/opconst: move OpsReader to internal ops package
To avoid import cycles, move the op constants to its own package, internal/opconst. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -3,7 +3,7 @@ package gpu
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/internal/ops"
|
||||
)
|
||||
|
||||
type resourceCache struct {
|
||||
@@ -11,11 +11,11 @@ type resourceCache struct {
|
||||
newRes map[interface{}]resource
|
||||
}
|
||||
|
||||
// opCache is like a resourceCache using the concrete OpKey
|
||||
// opCache is like a resourceCache using the concrete Key
|
||||
// key type to avoid allocations.
|
||||
type opCache struct {
|
||||
res map[ui.OpKey]resource
|
||||
newRes map[ui.OpKey]resource
|
||||
res map[ops.Key]resource
|
||||
newRes map[ops.Key]resource
|
||||
}
|
||||
|
||||
func newResourceCache() *resourceCache {
|
||||
@@ -64,12 +64,12 @@ func (r *resourceCache) release(ctx *context) {
|
||||
|
||||
func newOpCache() *opCache {
|
||||
return &opCache{
|
||||
res: make(map[ui.OpKey]resource),
|
||||
newRes: make(map[ui.OpKey]resource),
|
||||
res: make(map[ops.Key]resource),
|
||||
newRes: make(map[ops.Key]resource),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *opCache) get(key ui.OpKey) (resource, bool) {
|
||||
func (r *opCache) get(key ops.Key) (resource, bool) {
|
||||
v, exists := r.res[key]
|
||||
if exists {
|
||||
r.newRes[key] = v
|
||||
@@ -77,7 +77,7 @@ func (r *opCache) get(key ui.OpKey) (resource, bool) {
|
||||
return v, exists
|
||||
}
|
||||
|
||||
func (r *opCache) put(key ui.OpKey, val resource) {
|
||||
func (r *opCache) put(key ops.Key, val resource) {
|
||||
if _, exists := r.newRes[key]; exists {
|
||||
panic(fmt.Errorf("key exists, %p", key))
|
||||
}
|
||||
|
||||
+17
-16
@@ -16,6 +16,7 @@ import (
|
||||
"gioui.org/ui/app/internal/gl"
|
||||
gdraw "gioui.org/ui/draw"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"golang.org/x/image/draw"
|
||||
)
|
||||
@@ -58,7 +59,7 @@ type renderer struct {
|
||||
}
|
||||
|
||||
type drawOps struct {
|
||||
reader ui.OpsReader
|
||||
reader ops.Reader
|
||||
cache *resourceCache
|
||||
viewport image.Point
|
||||
clearColor [3]float32
|
||||
@@ -90,7 +91,7 @@ type pathOp struct {
|
||||
// clip is the union of all
|
||||
// later clip rectangles.
|
||||
clip image.Rectangle
|
||||
pathKey ui.OpKey
|
||||
pathKey ops.Key
|
||||
path bool
|
||||
pathVerts []byte
|
||||
parent *pathOp
|
||||
@@ -124,7 +125,7 @@ type opClip struct {
|
||||
}
|
||||
|
||||
func (op *opClip) decode(data []byte) {
|
||||
if ops.OpType(data[0]) != ops.TypeClip {
|
||||
if opconst.OpType(data[0]) != opconst.TypeClip {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
@@ -641,20 +642,20 @@ func (d *drawOps) newPathOp() *pathOp {
|
||||
return &d.pathOpCache[len(d.pathOpCache)-1]
|
||||
}
|
||||
|
||||
func (d *drawOps) collectOps(r *ui.OpsReader, state drawState) int {
|
||||
func (d *drawOps) collectOps(r *ops.Reader, state drawState) int {
|
||||
var aux []byte
|
||||
var auxKey ui.OpKey
|
||||
var auxKey ops.Key
|
||||
loop:
|
||||
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypeTransform:
|
||||
switch opconst.OpType(encOp.Data[0]) {
|
||||
case opconst.TypeTransform:
|
||||
var op ui.TransformOp
|
||||
op.Decode(encOp.Data)
|
||||
state.t = state.t.Multiply(op)
|
||||
case ops.TypeAux:
|
||||
aux = encOp.Data[ops.TypeAuxLen:]
|
||||
case opconst.TypeAux:
|
||||
aux = encOp.Data[opconst.TypeAuxLen:]
|
||||
auxKey = encOp.Key
|
||||
case ops.TypeClip:
|
||||
case opconst.TypeClip:
|
||||
var op opClip
|
||||
op.decode(encOp.Data)
|
||||
off := state.t.Transform(f32.Point{})
|
||||
@@ -676,18 +677,18 @@ loop:
|
||||
d.pathOps = append(d.pathOps, state.cpath)
|
||||
}
|
||||
aux = nil
|
||||
auxKey = ui.OpKey{}
|
||||
case ops.TypeColor:
|
||||
auxKey = ops.Key{}
|
||||
case opconst.TypeColor:
|
||||
var op gdraw.ColorOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
state.img = nil
|
||||
state.color = op.Color
|
||||
case ops.TypeImage:
|
||||
case opconst.TypeImage:
|
||||
var op gdraw.ImageOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
state.img = op.Src
|
||||
state.imgRect = op.Rect
|
||||
case ops.TypeDraw:
|
||||
case opconst.TypeDraw:
|
||||
var op gdraw.DrawOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
off := state.t.Transform(f32.Point{})
|
||||
@@ -723,9 +724,9 @@ loop:
|
||||
} else {
|
||||
d.imageOps = append(d.imageOps, img)
|
||||
}
|
||||
case ops.TypePush:
|
||||
case opconst.TypePush:
|
||||
state.z = d.collectOps(r, state)
|
||||
case ops.TypePop:
|
||||
case opconst.TypePop:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package input
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/key"
|
||||
)
|
||||
@@ -14,7 +15,7 @@ type TextInputState uint8
|
||||
type keyQueue struct {
|
||||
focus input.Key
|
||||
handlers map[input.Key]*keyHandler
|
||||
reader ui.OpsReader
|
||||
reader ops.Reader
|
||||
state TextInputState
|
||||
}
|
||||
|
||||
@@ -94,8 +95,8 @@ func (q *keyQueue) resolveFocus(events *handlerEvents) (input.Key, listenerPrior
|
||||
var hide bool
|
||||
loop:
|
||||
for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() {
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypeKeyHandler:
|
||||
switch opconst.OpType(encOp.Data[0]) {
|
||||
case opconst.TypeKeyHandler:
|
||||
var op key.HandlerOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
var newPri listenerPriority
|
||||
@@ -119,15 +120,15 @@ loop:
|
||||
events.Set(op.Key, []input.Event{key.FocusEvent{Focus: false}})
|
||||
}
|
||||
h.active = true
|
||||
case ops.TypeHideInput:
|
||||
case opconst.TypeHideInput:
|
||||
hide = true
|
||||
case ops.TypePush:
|
||||
case opconst.TypePush:
|
||||
newK, newPri, h := q.resolveFocus(events)
|
||||
hide = hide || h
|
||||
if newPri.replaces(pri) {
|
||||
k, pri = newK, newPri
|
||||
}
|
||||
case ops.TypePop:
|
||||
case opconst.TypePop:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
@@ -18,7 +19,7 @@ type pointerQueue struct {
|
||||
areas []areaNode
|
||||
handlers map[input.Key]*pointerHandler
|
||||
pointers []pointerInfo
|
||||
reader ui.OpsReader
|
||||
reader ops.Reader
|
||||
scratch []input.Key
|
||||
}
|
||||
|
||||
@@ -63,18 +64,18 @@ const (
|
||||
areaEllipse
|
||||
)
|
||||
|
||||
func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events *handlerEvents, t ui.TransformOp, area, node int, pass bool) {
|
||||
func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t ui.TransformOp, area, node int, pass bool) {
|
||||
for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() {
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypePush:
|
||||
switch opconst.OpType(encOp.Data[0]) {
|
||||
case opconst.TypePush:
|
||||
q.collectHandlers(r, events, t, area, node, pass)
|
||||
case ops.TypePop:
|
||||
case opconst.TypePop:
|
||||
return
|
||||
case ops.TypePass:
|
||||
case opconst.TypePass:
|
||||
var op pointer.PassOp
|
||||
op.Decode(encOp.Data)
|
||||
pass = op.Pass
|
||||
case ops.TypeArea:
|
||||
case opconst.TypeArea:
|
||||
var op areaOp
|
||||
op.Decode(encOp.Data)
|
||||
q.areas = append(q.areas, areaNode{trans: t, next: area, area: op})
|
||||
@@ -85,11 +86,11 @@ func (q *pointerQueue) collectHandlers(r *ui.OpsReader, events *handlerEvents, t
|
||||
pass: pass,
|
||||
})
|
||||
node = len(q.hitTree) - 1
|
||||
case ops.TypeTransform:
|
||||
case opconst.TypeTransform:
|
||||
var op ui.TransformOp
|
||||
op.Decode(encOp.Data)
|
||||
t = t.Multiply(op)
|
||||
case ops.TypePointerHandler:
|
||||
case opconst.TypePointerHandler:
|
||||
var op pointer.HandlerOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
q.hitTree = append(q.hitTree, hitNode{
|
||||
@@ -264,7 +265,7 @@ func (q *pointerQueue) Push(e pointer.Event, events *handlerEvents) {
|
||||
}
|
||||
|
||||
func (op *areaOp) Decode(d []byte) {
|
||||
if ops.OpType(d[0]) != ops.TypeArea {
|
||||
if opconst.OpType(d[0]) != opconst.TypeArea {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/key"
|
||||
"gioui.org/ui/pointer"
|
||||
@@ -21,7 +22,7 @@ type Router struct {
|
||||
|
||||
handlers handlerEvents
|
||||
|
||||
reader ui.OpsReader
|
||||
reader ops.Reader
|
||||
|
||||
// InvalidateOp summary.
|
||||
wakeup bool
|
||||
@@ -71,15 +72,15 @@ func (q *Router) TextInputState() TextInputState {
|
||||
|
||||
func (q *Router) collect() {
|
||||
for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() {
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypeInvalidate:
|
||||
switch opconst.OpType(encOp.Data[0]) {
|
||||
case opconst.TypeInvalidate:
|
||||
var op ui.InvalidateOp
|
||||
op.Decode(encOp.Data)
|
||||
if !q.wakeup || op.At.Before(q.wakeupTime) {
|
||||
q.wakeup = true
|
||||
q.wakeupTime = op.At
|
||||
}
|
||||
case ops.TypeProfile:
|
||||
case opconst.TypeProfile:
|
||||
var op system.ProfileOp
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
q.profHandlers = append(q.profHandlers, op.Key)
|
||||
|
||||
+10
-10
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
type ImageOp struct {
|
||||
@@ -27,8 +27,8 @@ type DrawOp struct {
|
||||
}
|
||||
|
||||
func (i ImageOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeImageLen)
|
||||
data[0] = byte(ops.TypeImage)
|
||||
data := make([]byte, opconst.TypeImageLen)
|
||||
data[0] = byte(opconst.TypeImage)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], uint32(i.Rect.Min.X))
|
||||
bo.PutUint32(data[5:], uint32(i.Rect.Min.Y))
|
||||
@@ -39,7 +39,7 @@ func (i ImageOp) Add(o *ui.Ops) {
|
||||
|
||||
func (i *ImageOp) Decode(data []byte, refs []interface{}) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(data[0]) != ops.TypeImage {
|
||||
if opconst.OpType(data[0]) != opconst.TypeImage {
|
||||
panic("invalid op")
|
||||
}
|
||||
sr := image.Rectangle{
|
||||
@@ -59,8 +59,8 @@ func (i *ImageOp) Decode(data []byte, refs []interface{}) {
|
||||
}
|
||||
|
||||
func (c ColorOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeColorLen)
|
||||
data[0] = byte(ops.TypeColor)
|
||||
data := make([]byte, opconst.TypeColorLen)
|
||||
data[0] = byte(opconst.TypeColor)
|
||||
data[1] = c.Color.R
|
||||
data[2] = c.Color.G
|
||||
data[3] = c.Color.B
|
||||
@@ -69,7 +69,7 @@ func (c ColorOp) Add(o *ui.Ops) {
|
||||
}
|
||||
|
||||
func (c *ColorOp) Decode(data []byte, refs []interface{}) {
|
||||
if ops.OpType(data[0]) != ops.TypeColor {
|
||||
if opconst.OpType(data[0]) != opconst.TypeColor {
|
||||
panic("invalid op")
|
||||
}
|
||||
*c = ColorOp{
|
||||
@@ -83,8 +83,8 @@ func (c *ColorOp) Decode(data []byte, refs []interface{}) {
|
||||
}
|
||||
|
||||
func (d DrawOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeDrawLen)
|
||||
data[0] = byte(ops.TypeDraw)
|
||||
data := make([]byte, opconst.TypeDrawLen)
|
||||
data[0] = byte(opconst.TypeDraw)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], math.Float32bits(d.Rect.Min.X))
|
||||
bo.PutUint32(data[5:], math.Float32bits(d.Rect.Min.Y))
|
||||
@@ -95,7 +95,7 @@ func (d DrawOp) Add(o *ui.Ops) {
|
||||
|
||||
func (d *DrawOp) Decode(data []byte, refs []interface{}) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(data[0]) != ops.TypeDraw {
|
||||
if opconst.OpType(data[0]) != opconst.TypeDraw {
|
||||
panic("invalid op")
|
||||
}
|
||||
r := f32.Rectangle{
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
"gioui.org/ui/internal/path"
|
||||
)
|
||||
|
||||
@@ -30,8 +30,8 @@ type ClipOp struct {
|
||||
}
|
||||
|
||||
func (p ClipOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeClipLen)
|
||||
data[0] = byte(ops.TypeClip)
|
||||
data := make([]byte, opconst.TypeClipLen)
|
||||
data[0] = byte(opconst.TypeClip)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], math.Float32bits(p.bounds.Min.X))
|
||||
bo.PutUint32(data[5:], math.Float32bits(p.bounds.Min.Y))
|
||||
@@ -239,7 +239,7 @@ func (p *PathBuilder) vertex(cornerx, cornery int16, ctrl, to f32.Point) {
|
||||
ToY: to.Y,
|
||||
}
|
||||
data := make([]byte, path.VertStride+1)
|
||||
data[0] = byte(ops.TypeAux)
|
||||
data[0] = byte(opconst.TypeAux)
|
||||
bo := binary.LittleEndian
|
||||
data[1] = byte(uint16(v.CornerX))
|
||||
data[2] = byte(uint16(v.CornerX) >> 8)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package ops
|
||||
package opconst
|
||||
|
||||
type OpType byte
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package ops
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
// Reader parses an ops list.
|
||||
type Reader struct {
|
||||
pc pc
|
||||
stack []macro
|
||||
ops *ui.Ops
|
||||
}
|
||||
|
||||
// EncodedOp represents an encoded op returned by
|
||||
// Reader.
|
||||
type EncodedOp struct {
|
||||
Key Key
|
||||
Data []byte
|
||||
Refs []interface{}
|
||||
}
|
||||
|
||||
// Key is a unique key for a given op.
|
||||
type Key struct {
|
||||
ops *ui.Ops
|
||||
pc int
|
||||
version int
|
||||
}
|
||||
|
||||
// Shadow of ui.MacroOp.
|
||||
type macroOp struct {
|
||||
recording bool
|
||||
ops *ui.Ops
|
||||
version int
|
||||
pc pc
|
||||
}
|
||||
|
||||
type pc struct {
|
||||
data int
|
||||
refs int
|
||||
}
|
||||
|
||||
type macro struct {
|
||||
ops *ui.Ops
|
||||
retPC pc
|
||||
endPC pc
|
||||
}
|
||||
|
||||
type opMacroDef struct {
|
||||
endpc pc
|
||||
}
|
||||
|
||||
type opAux struct {
|
||||
len int
|
||||
}
|
||||
|
||||
// Reset start reading from the op list.
|
||||
func (r *Reader) Reset(ops *ui.Ops) {
|
||||
r.stack = r.stack[:0]
|
||||
r.pc = pc{}
|
||||
r.ops = nil
|
||||
if ops == nil {
|
||||
return
|
||||
}
|
||||
r.ops = ops
|
||||
}
|
||||
|
||||
func (r *Reader) Decode() (EncodedOp, bool) {
|
||||
if r.ops == nil {
|
||||
return EncodedOp{}, false
|
||||
}
|
||||
for {
|
||||
if len(r.stack) > 0 {
|
||||
b := r.stack[len(r.stack)-1]
|
||||
if r.pc == b.endPC {
|
||||
r.ops = b.ops
|
||||
r.pc = b.retPC
|
||||
r.stack = r.stack[:len(r.stack)-1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
if r.pc.data == len(r.ops.Data) {
|
||||
return EncodedOp{}, false
|
||||
}
|
||||
key := Key{ops: r.ops, pc: r.pc.data, version: r.ops.Version}
|
||||
t := opconst.OpType(r.ops.Data[r.pc.data])
|
||||
n := t.Size()
|
||||
nrefs := t.NumRefs()
|
||||
data := r.ops.Data[r.pc.data : r.pc.data+n]
|
||||
refs := r.ops.Refs[r.pc.refs : r.pc.refs+nrefs]
|
||||
switch t {
|
||||
case opconst.TypeAux:
|
||||
var op opAux
|
||||
op.decode(data)
|
||||
n += op.len
|
||||
data = r.ops.Data[r.pc.data : r.pc.data+n]
|
||||
case opconst.TypeMacro:
|
||||
var op macroOp
|
||||
op.decode(data, refs)
|
||||
macroOps := op.ops
|
||||
if opconst.OpType(macroOps.Data[op.pc.data]) != opconst.TypeMacroDef {
|
||||
panic("invalid macro reference")
|
||||
}
|
||||
if op.version != op.ops.Version {
|
||||
panic("invalid MacroOp reference to reset Ops")
|
||||
}
|
||||
var opDef opMacroDef
|
||||
opDef.decode(macroOps.Data[op.pc.data : op.pc.data+opconst.TypeMacroDef.Size()])
|
||||
retPC := r.pc
|
||||
retPC.data += n
|
||||
retPC.refs += nrefs
|
||||
r.stack = append(r.stack, macro{
|
||||
ops: r.ops,
|
||||
retPC: retPC,
|
||||
endPC: opDef.endpc,
|
||||
})
|
||||
r.ops = macroOps
|
||||
r.pc = op.pc
|
||||
r.pc.data += opconst.TypeMacroDef.Size()
|
||||
r.pc.refs += opconst.TypeMacroDef.NumRefs()
|
||||
continue
|
||||
case opconst.TypeMacroDef:
|
||||
var op opMacroDef
|
||||
op.decode(data)
|
||||
r.pc = op.endpc
|
||||
continue
|
||||
}
|
||||
r.pc.data += n
|
||||
r.pc.refs += nrefs
|
||||
return EncodedOp{Key: key, Data: data, Refs: refs}, true
|
||||
}
|
||||
}
|
||||
|
||||
func (op *opMacroDef) decode(data []byte) {
|
||||
if opconst.OpType(data[0]) != opconst.TypeMacroDef {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
dataIdx := int(int32(bo.Uint32(data[1:])))
|
||||
refsIdx := int(int32(bo.Uint32(data[5:])))
|
||||
*op = opMacroDef{
|
||||
endpc: pc{
|
||||
data: dataIdx,
|
||||
refs: refsIdx,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (op *opAux) decode(data []byte) {
|
||||
if opconst.OpType(data[0]) != opconst.TypeAux {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
*op = opAux{
|
||||
len: int(int32(bo.Uint32(data[1:]))),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *macroOp) decode(data []byte, refs []interface{}) {
|
||||
if opconst.OpType(data[0]) != opconst.TypeMacro {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
dataIdx := int(int32(bo.Uint32(data[1:])))
|
||||
refsIdx := int(int32(bo.Uint32(data[5:])))
|
||||
version := int(int32(bo.Uint32(data[9:])))
|
||||
*m = macroOp{
|
||||
ops: refs[0].(*ui.Ops),
|
||||
pc: pc{
|
||||
data: dataIdx,
|
||||
refs: refsIdx,
|
||||
},
|
||||
version: version,
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -5,7 +5,7 @@ package key
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
type HandlerOp struct {
|
||||
@@ -56,8 +56,8 @@ func (m Modifiers) Contain(m2 Modifiers) bool {
|
||||
}
|
||||
|
||||
func (h HandlerOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeKeyHandlerLen)
|
||||
data[0] = byte(ops.TypeKeyHandler)
|
||||
data := make([]byte, opconst.TypeKeyHandlerLen)
|
||||
data[0] = byte(opconst.TypeKeyHandler)
|
||||
if h.Focus {
|
||||
data[1] = 1
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func (h HandlerOp) Add(o *ui.Ops) {
|
||||
}
|
||||
|
||||
func (h *HandlerOp) Decode(d []byte, refs []interface{}) {
|
||||
if ops.OpType(d[0]) != ops.TypeKeyHandler {
|
||||
if opconst.OpType(d[0]) != opconst.TypeKeyHandler {
|
||||
panic("invalid op")
|
||||
}
|
||||
*h = HandlerOp{
|
||||
@@ -75,8 +75,8 @@ func (h *HandlerOp) Decode(d []byte, refs []interface{}) {
|
||||
}
|
||||
|
||||
func (h HideInputOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeHideInputLen)
|
||||
data[0] = byte(ops.TypeHideInput)
|
||||
data := make([]byte, opconst.TypeHideInputLen)
|
||||
data[0] = byte(opconst.TypeHideInput)
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@ package ui
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
// Ops holds a list of serialized Ops.
|
||||
type Ops struct {
|
||||
version int
|
||||
Version int
|
||||
// Serialized ops.
|
||||
data []byte
|
||||
Data []byte
|
||||
// Op references.
|
||||
refs []interface{}
|
||||
Refs []interface{}
|
||||
|
||||
stackDepth int
|
||||
|
||||
@@ -21,39 +21,6 @@ type Ops struct {
|
||||
auxLen int
|
||||
}
|
||||
|
||||
// OpsReader parses an ops list. Internal use only.
|
||||
type OpsReader struct {
|
||||
pc pc
|
||||
stack []macro
|
||||
ops *Ops
|
||||
}
|
||||
|
||||
// EncodedOp represents an encoded op returned by
|
||||
// OpsReader. Internal use only.
|
||||
type EncodedOp struct {
|
||||
Key OpKey
|
||||
Data []byte
|
||||
Refs []interface{}
|
||||
}
|
||||
|
||||
// OpKey is a unique key for a given op. Internal use only.
|
||||
type OpKey struct {
|
||||
ops *Ops
|
||||
pc int
|
||||
version int
|
||||
}
|
||||
|
||||
type macro struct {
|
||||
ops *Ops
|
||||
retPC pc
|
||||
endPC pc
|
||||
}
|
||||
|
||||
type pc struct {
|
||||
data int
|
||||
refs int
|
||||
}
|
||||
|
||||
type StackOp struct {
|
||||
depth int
|
||||
active bool
|
||||
@@ -67,12 +34,9 @@ type MacroOp struct {
|
||||
pc pc
|
||||
}
|
||||
|
||||
type opMacroDef struct {
|
||||
endpc pc
|
||||
}
|
||||
|
||||
type opAux struct {
|
||||
len int
|
||||
type pc struct {
|
||||
data int
|
||||
refs int
|
||||
}
|
||||
|
||||
func (s *StackOp) Push(o *Ops) {
|
||||
@@ -83,7 +47,7 @@ func (s *StackOp) Push(o *Ops) {
|
||||
s.ops = o
|
||||
o.stackDepth++
|
||||
s.depth = o.stackDepth
|
||||
o.Write([]byte{byte(ops.TypePush)})
|
||||
o.Write([]byte{byte(opconst.TypePush)})
|
||||
}
|
||||
|
||||
func (s *StackOp) Pop() {
|
||||
@@ -96,32 +60,7 @@ func (s *StackOp) Pop() {
|
||||
}
|
||||
s.active = false
|
||||
s.ops.stackDepth--
|
||||
s.ops.Write([]byte{byte(ops.TypePop)})
|
||||
}
|
||||
|
||||
func (op *opAux) decode(data []byte) {
|
||||
if ops.OpType(data[0]) != ops.TypeAux {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
*op = opAux{
|
||||
len: int(int32(bo.Uint32(data[1:]))),
|
||||
}
|
||||
}
|
||||
|
||||
func (op *opMacroDef) decode(data []byte) {
|
||||
if ops.OpType(data[0]) != ops.TypeMacroDef {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
dataIdx := int(int32(bo.Uint32(data[1:])))
|
||||
refsIdx := int(int32(bo.Uint32(data[5:])))
|
||||
*op = opMacroDef{
|
||||
endpc: pc{
|
||||
data: dataIdx,
|
||||
refs: refsIdx,
|
||||
},
|
||||
}
|
||||
s.ops.Write([]byte{byte(opconst.TypePop)})
|
||||
}
|
||||
|
||||
// Reset the Ops, preparing it for re-use.
|
||||
@@ -129,12 +68,12 @@ func (o *Ops) Reset() {
|
||||
o.inAux = false
|
||||
o.stackDepth = 0
|
||||
// Leave references to the GC.
|
||||
for i := range o.refs {
|
||||
o.refs[i] = nil
|
||||
for i := range o.Refs {
|
||||
o.Refs[i] = nil
|
||||
}
|
||||
o.data = o.data[:0]
|
||||
o.refs = o.refs[:0]
|
||||
o.version++
|
||||
o.Data = o.Data[:0]
|
||||
o.Refs = o.Refs[:0]
|
||||
o.Version++
|
||||
}
|
||||
|
||||
// Internal use only.
|
||||
@@ -142,29 +81,29 @@ func (o *Ops) Aux() []byte {
|
||||
if !o.inAux {
|
||||
return nil
|
||||
}
|
||||
return o.data[o.auxOff+ops.TypeAuxLen : o.auxOff+ops.TypeAuxLen+o.auxLen]
|
||||
return o.Data[o.auxOff+opconst.TypeAuxLen : o.auxOff+opconst.TypeAuxLen+o.auxLen]
|
||||
}
|
||||
|
||||
func (d *Ops) write(op []byte, refs ...interface{}) {
|
||||
d.data = append(d.data, op...)
|
||||
d.refs = append(d.refs, refs...)
|
||||
d.Data = append(d.Data, op...)
|
||||
d.Refs = append(d.Refs, refs...)
|
||||
}
|
||||
|
||||
func (o *Ops) Write(op []byte, refs ...interface{}) {
|
||||
t := ops.OpType(op[0])
|
||||
t := opconst.OpType(op[0])
|
||||
if len(refs) != t.NumRefs() {
|
||||
panic("invalid ref count")
|
||||
}
|
||||
switch t {
|
||||
case ops.TypeAux:
|
||||
case opconst.TypeAux:
|
||||
// Write only the data.
|
||||
op = op[1:]
|
||||
if !o.inAux {
|
||||
o.inAux = true
|
||||
o.auxOff = o.pc().data
|
||||
o.auxLen = 0
|
||||
header := make([]byte, ops.TypeAuxLen)
|
||||
header[0] = byte(ops.TypeAux)
|
||||
header := make([]byte, opconst.TypeAuxLen)
|
||||
header[0] = byte(opconst.TypeAux)
|
||||
o.write(header)
|
||||
}
|
||||
o.auxLen += len(op)
|
||||
@@ -172,14 +111,14 @@ func (o *Ops) Write(op []byte, refs ...interface{}) {
|
||||
if o.inAux {
|
||||
o.inAux = false
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(o.data[o.auxOff+1:], uint32(o.auxLen))
|
||||
bo.PutUint32(o.Data[o.auxOff+1:], uint32(o.auxLen))
|
||||
}
|
||||
}
|
||||
o.write(op, refs...)
|
||||
}
|
||||
|
||||
func (d *Ops) pc() pc {
|
||||
return pc{data: len(d.data), refs: len(d.refs)}
|
||||
return pc{data: len(d.Data), refs: len(d.Refs)}
|
||||
}
|
||||
|
||||
// Record a macro of operations.
|
||||
@@ -191,7 +130,7 @@ func (m *MacroOp) Record(o *Ops) {
|
||||
m.ops = o
|
||||
m.pc = o.pc()
|
||||
// Make room for a macro definition. Filled out in Stop.
|
||||
m.ops.Write(make([]byte, ops.TypeMacroDefLen))
|
||||
m.ops.Write(make([]byte, opconst.TypeMacroDefLen))
|
||||
}
|
||||
|
||||
// Stop recording the macro.
|
||||
@@ -202,30 +141,12 @@ func (m *MacroOp) Stop() {
|
||||
m.recording = false
|
||||
pc := m.ops.pc()
|
||||
// Fill out the macro definition reserved in Record.
|
||||
data := m.ops.data[m.pc.data : m.pc.data+ops.TypeMacroDefLen]
|
||||
data[0] = byte(ops.TypeMacroDef)
|
||||
data := m.ops.Data[m.pc.data : m.pc.data+opconst.TypeMacroDefLen]
|
||||
data[0] = byte(opconst.TypeMacroDef)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], uint32(pc.data))
|
||||
bo.PutUint32(data[5:], uint32(pc.refs))
|
||||
m.version = m.ops.version
|
||||
}
|
||||
|
||||
func (m *MacroOp) decode(data []byte, refs []interface{}) {
|
||||
if ops.OpType(data[0]) != ops.TypeMacro {
|
||||
panic("invalid op")
|
||||
}
|
||||
bo := binary.LittleEndian
|
||||
dataIdx := int(int32(bo.Uint32(data[1:])))
|
||||
refsIdx := int(int32(bo.Uint32(data[5:])))
|
||||
version := int(int32(bo.Uint32(data[9:])))
|
||||
*m = MacroOp{
|
||||
ops: refs[0].(*Ops),
|
||||
pc: pc{
|
||||
data: dataIdx,
|
||||
refs: refsIdx,
|
||||
},
|
||||
version: version,
|
||||
}
|
||||
m.version = m.ops.Version
|
||||
}
|
||||
|
||||
func (m MacroOp) Add(o *Ops) {
|
||||
@@ -235,88 +156,11 @@ func (m MacroOp) Add(o *Ops) {
|
||||
if m.ops == nil {
|
||||
return
|
||||
}
|
||||
data := make([]byte, ops.TypeMacroLen)
|
||||
data[0] = byte(ops.TypeMacro)
|
||||
data := make([]byte, opconst.TypeMacroLen)
|
||||
data[0] = byte(opconst.TypeMacro)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], uint32(m.pc.data))
|
||||
bo.PutUint32(data[5:], uint32(m.pc.refs))
|
||||
bo.PutUint32(data[9:], uint32(m.version))
|
||||
o.Write(data, m.ops)
|
||||
}
|
||||
|
||||
// Reset start reading from the op list.
|
||||
func (r *OpsReader) Reset(ops *Ops) {
|
||||
r.stack = r.stack[:0]
|
||||
r.pc = pc{}
|
||||
r.ops = nil
|
||||
if ops == nil {
|
||||
return
|
||||
}
|
||||
r.ops = ops
|
||||
}
|
||||
|
||||
func (r *OpsReader) Decode() (EncodedOp, bool) {
|
||||
if r.ops == nil {
|
||||
return EncodedOp{}, false
|
||||
}
|
||||
for {
|
||||
if len(r.stack) > 0 {
|
||||
b := r.stack[len(r.stack)-1]
|
||||
if r.pc == b.endPC {
|
||||
r.ops = b.ops
|
||||
r.pc = b.retPC
|
||||
r.stack = r.stack[:len(r.stack)-1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
if r.pc.data == len(r.ops.data) {
|
||||
return EncodedOp{}, false
|
||||
}
|
||||
key := OpKey{ops: r.ops, pc: r.pc.data, version: r.ops.version}
|
||||
t := ops.OpType(r.ops.data[r.pc.data])
|
||||
n := t.Size()
|
||||
nrefs := t.NumRefs()
|
||||
data := r.ops.data[r.pc.data : r.pc.data+n]
|
||||
refs := r.ops.refs[r.pc.refs : r.pc.refs+nrefs]
|
||||
switch t {
|
||||
case ops.TypeAux:
|
||||
var op opAux
|
||||
op.decode(data)
|
||||
n += op.len
|
||||
data = r.ops.data[r.pc.data : r.pc.data+n]
|
||||
case ops.TypeMacro:
|
||||
var op MacroOp
|
||||
op.decode(data, refs)
|
||||
macroOps := op.ops
|
||||
if ops.OpType(macroOps.data[op.pc.data]) != ops.TypeMacroDef {
|
||||
panic("invalid macro reference")
|
||||
}
|
||||
if op.version != op.ops.version {
|
||||
panic("invalid MacroOp reference to reset Ops")
|
||||
}
|
||||
var opDef opMacroDef
|
||||
opDef.decode(macroOps.data[op.pc.data : op.pc.data+ops.TypeMacroDef.Size()])
|
||||
retPC := r.pc
|
||||
retPC.data += n
|
||||
retPC.refs += nrefs
|
||||
r.stack = append(r.stack, macro{
|
||||
ops: r.ops,
|
||||
retPC: retPC,
|
||||
endPC: opDef.endpc,
|
||||
})
|
||||
r.ops = macroOps
|
||||
r.pc = op.pc
|
||||
r.pc.data += ops.TypeMacroDef.Size()
|
||||
r.pc.refs += ops.TypeMacroDef.NumRefs()
|
||||
continue
|
||||
case ops.TypeMacroDef:
|
||||
var op opMacroDef
|
||||
op.decode(data)
|
||||
r.pc = op.endpc
|
||||
continue
|
||||
}
|
||||
r.pc.data += n
|
||||
r.pc.refs += nrefs
|
||||
return EncodedOp{Key: key, Data: data, Refs: refs}, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
@@ -95,8 +95,8 @@ func (op EllipseAreaOp) Add(ops *ui.Ops) {
|
||||
}
|
||||
|
||||
func (op areaOp) add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeAreaLen)
|
||||
data[0] = byte(ops.TypeArea)
|
||||
data := make([]byte, opconst.TypeAreaLen)
|
||||
data[0] = byte(opconst.TypeArea)
|
||||
data[1] = byte(op.kind)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[2:], uint32(op.rect.Min.X))
|
||||
@@ -107,8 +107,8 @@ func (op areaOp) add(o *ui.Ops) {
|
||||
}
|
||||
|
||||
func (h HandlerOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypePointerHandlerLen)
|
||||
data[0] = byte(ops.TypePointerHandler)
|
||||
data := make([]byte, opconst.TypePointerHandlerLen)
|
||||
data[0] = byte(opconst.TypePointerHandler)
|
||||
if h.Grab {
|
||||
data[1] = 1
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (h HandlerOp) Add(o *ui.Ops) {
|
||||
}
|
||||
|
||||
func (h *HandlerOp) Decode(d []byte, refs []interface{}) {
|
||||
if ops.OpType(d[0]) != ops.TypePointerHandler {
|
||||
if opconst.OpType(d[0]) != opconst.TypePointerHandler {
|
||||
panic("invalid op")
|
||||
}
|
||||
*h = HandlerOp{
|
||||
@@ -126,8 +126,8 @@ func (h *HandlerOp) Decode(d []byte, refs []interface{}) {
|
||||
}
|
||||
|
||||
func (op PassOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypePassLen)
|
||||
data[0] = byte(ops.TypePass)
|
||||
data := make([]byte, opconst.TypePassLen)
|
||||
data[0] = byte(opconst.TypePass)
|
||||
if op.Pass {
|
||||
data[1] = 1
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func (op PassOp) Add(o *ui.Ops) {
|
||||
}
|
||||
|
||||
func (op *PassOp) Decode(d []byte) {
|
||||
if ops.OpType(d[0]) != ops.TypePass {
|
||||
if opconst.OpType(d[0]) != opconst.TypePass {
|
||||
panic("invalid op")
|
||||
}
|
||||
*op = PassOp{
|
||||
|
||||
+4
-4
@@ -7,7 +7,7 @@ package system
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
// ProfileOp registers a handler for receiving
|
||||
@@ -24,13 +24,13 @@ type ProfileEvent struct {
|
||||
}
|
||||
|
||||
func (p ProfileOp) Add(o *ui.Ops) {
|
||||
data := make([]byte, ops.TypeProfileLen)
|
||||
data[0] = byte(ops.TypeProfile)
|
||||
data := make([]byte, opconst.TypeProfileLen)
|
||||
data[0] = byte(opconst.TypeProfile)
|
||||
o.Write(data, p.Key)
|
||||
}
|
||||
|
||||
func (p *ProfileOp) Decode(d []byte, refs []interface{}) {
|
||||
if ops.OpType(d[0]) != ops.TypeProfile {
|
||||
if opconst.OpType(d[0]) != opconst.TypeProfile {
|
||||
panic("invalid op")
|
||||
}
|
||||
*p = ProfileOp{
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/internal/opconst"
|
||||
)
|
||||
|
||||
// Config represents the essential configuration for
|
||||
@@ -33,8 +33,8 @@ type TransformOp struct {
|
||||
}
|
||||
|
||||
func (r InvalidateOp) Add(o *Ops) {
|
||||
data := make([]byte, ops.TypeRedrawLen)
|
||||
data[0] = byte(ops.TypeInvalidate)
|
||||
data := make([]byte, opconst.TypeRedrawLen)
|
||||
data[0] = byte(opconst.TypeInvalidate)
|
||||
bo := binary.LittleEndian
|
||||
// UnixNano cannot represent the zero time.
|
||||
if t := r.At; !t.IsZero() {
|
||||
@@ -48,7 +48,7 @@ func (r InvalidateOp) Add(o *Ops) {
|
||||
|
||||
func (r *InvalidateOp) Decode(d []byte) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(d[0]) != ops.TypeInvalidate {
|
||||
if opconst.OpType(d[0]) != opconst.TypeInvalidate {
|
||||
panic("invalid op")
|
||||
}
|
||||
if nanos := bo.Uint64(d[1:]); nanos > 0 {
|
||||
@@ -79,8 +79,8 @@ func (t TransformOp) Multiply(t2 TransformOp) TransformOp {
|
||||
}
|
||||
|
||||
func (t TransformOp) Add(o *Ops) {
|
||||
data := make([]byte, ops.TypeTransformLen)
|
||||
data[0] = byte(ops.TypeTransform)
|
||||
data := make([]byte, opconst.TypeTransformLen)
|
||||
data[0] = byte(opconst.TypeTransform)
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(data[1:], math.Float32bits(t.offset.X))
|
||||
bo.PutUint32(data[5:], math.Float32bits(t.offset.Y))
|
||||
@@ -89,7 +89,7 @@ func (t TransformOp) Add(o *Ops) {
|
||||
|
||||
func (t *TransformOp) Decode(d []byte) {
|
||||
bo := binary.LittleEndian
|
||||
if ops.OpType(d[0]) != ops.TypeTransform {
|
||||
if opconst.OpType(d[0]) != opconst.TypeTransform {
|
||||
panic("invalid op")
|
||||
}
|
||||
*t = TransformOp{f32.Point{
|
||||
|
||||
Reference in New Issue
Block a user