diff --git a/ui/app/internal/gpu/gpu.go b/ui/app/internal/gpu/gpu.go index 104c1d41..c2217b68 100644 --- a/ui/app/internal/gpu/gpu.go +++ b/ui/app/internal/gpu/gpu.go @@ -144,6 +144,61 @@ func (op *clipOp) decode(data []byte) { } } +func decodeImageOp(data []byte, refs []interface{}) gdraw.ImageOp { + bo := binary.LittleEndian + if opconst.OpType(data[0]) != opconst.TypeImage { + panic("invalid op") + } + sr := image.Rectangle{ + Min: image.Point{ + X: int(int32(bo.Uint32(data[1:]))), + Y: int(int32(bo.Uint32(data[5:]))), + }, + Max: image.Point{ + X: int(int32(bo.Uint32(data[9:]))), + Y: int(int32(bo.Uint32(data[13:]))), + }, + } + return gdraw.ImageOp{ + Src: refs[0].(image.Image), + Rect: sr, + } +} + +func decodeColorOp(data []byte, refs []interface{}) gdraw.ColorOp { + if opconst.OpType(data[0]) != opconst.TypeColor { + panic("invalid op") + } + return gdraw.ColorOp{ + Color: color.RGBA{ + R: data[1], + G: data[2], + B: data[3], + A: data[4], + }, + } +} + +func decodeDrawOp(data []byte, refs []interface{}) gdraw.DrawOp { + bo := binary.LittleEndian + if opconst.OpType(data[0]) != opconst.TypeDraw { + panic("invalid op") + } + r := f32.Rectangle{ + Min: f32.Point{ + X: math.Float32frombits(bo.Uint32(data[1:])), + Y: math.Float32frombits(bo.Uint32(data[5:])), + }, + Max: f32.Point{ + X: math.Float32frombits(bo.Uint32(data[9:])), + Y: math.Float32frombits(bo.Uint32(data[13:])), + }, + } + return gdraw.DrawOp{ + Rect: r, + } +} + type clipType uint8 type resource interface { @@ -649,9 +704,8 @@ loop: for encOp, ok := r.Decode(); ok; encOp, ok = r.Decode() { switch opconst.OpType(encOp.Data[0]) { case opconst.TypeTransform: - var op ui.TransformOp - op.Decode(encOp.Data) - state.t = state.t.Multiply(op) + op := ops.DecodeTransformOp(encOp.Data) + state.t = state.t.Multiply(ui.TransformOp(op)) case opconst.TypeAux: aux = encOp.Data[opconst.TypeAuxLen:] auxKey = encOp.Key @@ -679,18 +733,15 @@ loop: aux = nil auxKey = ops.Key{} case opconst.TypeColor: - var op gdraw.ColorOp - op.Decode(encOp.Data, encOp.Refs) + op := decodeColorOp(encOp.Data, encOp.Refs) state.img = nil state.color = op.Color case opconst.TypeImage: - var op gdraw.ImageOp - op.Decode(encOp.Data, encOp.Refs) + op := decodeImageOp(encOp.Data, encOp.Refs) state.img = op.Src state.imgRect = op.Rect case opconst.TypeDraw: - var op gdraw.DrawOp - op.Decode(encOp.Data, encOp.Refs) + op := decodeDrawOp(encOp.Data, encOp.Refs) off := state.t.Transform(f32.Point{}) clip := state.clip.Intersect(op.Rect.Add(off)) if clip.Empty() { diff --git a/ui/app/internal/input/key.go b/ui/app/internal/input/key.go index 252a7a70..50b5c906 100644 --- a/ui/app/internal/input/key.go +++ b/ui/app/internal/input/key.go @@ -97,8 +97,7 @@ loop: for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() { switch opconst.OpType(encOp.Data[0]) { case opconst.TypeKeyHandler: - var op key.HandlerOp - op.Decode(encOp.Data, encOp.Refs) + op := decodeKeyHandlerOp(encOp.Data, encOp.Refs) var newPri listenerPriority switch { case op.Focus: @@ -139,3 +138,13 @@ func (p listenerPriority) replaces(p2 listenerPriority) bool { // Favor earliest default focus or latest requested focus. return p > p2 || p == p2 && p == priNewFocus } + +func decodeKeyHandlerOp(d []byte, refs []interface{}) key.HandlerOp { + if opconst.OpType(d[0]) != opconst.TypeKeyHandler { + panic("invalid op") + } + return key.HandlerOp{ + Focus: d[1] != 0, + Key: refs[0].(input.Key), + } +} diff --git a/ui/app/internal/input/pointer.go b/ui/app/internal/input/pointer.go index 47175352..5c220395 100644 --- a/ui/app/internal/input/pointer.go +++ b/ui/app/internal/input/pointer.go @@ -72,8 +72,7 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t u case opconst.TypePop: return case opconst.TypePass: - var op pointer.PassOp - op.Decode(encOp.Data) + op := decodePassOp(encOp.Data) pass = op.Pass case opconst.TypeArea: var op areaOp @@ -87,12 +86,10 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t u }) node = len(q.hitTree) - 1 case opconst.TypeTransform: - var op ui.TransformOp - op.Decode(encOp.Data) - t = t.Multiply(op) + op := ops.DecodeTransformOp(encOp.Data) + t = t.Multiply(ui.TransformOp(op)) case opconst.TypePointerHandler: - var op pointer.HandlerOp - op.Decode(encOp.Data, encOp.Refs) + op := decodePointerHandlerOp(encOp.Data, encOp.Refs) q.hitTree = append(q.hitTree, hitNode{ next: node, area: area, @@ -316,3 +313,22 @@ func (op *areaOp) Hit(pos f32.Point) bool { panic("invalid area kind") } } + +func decodePointerHandlerOp(d []byte, refs []interface{}) pointer.HandlerOp { + if opconst.OpType(d[0]) != opconst.TypePointerHandler { + panic("invalid op") + } + return pointer.HandlerOp{ + Grab: d[1] != 0, + Key: refs[0].(input.Key), + } +} + +func decodePassOp(d []byte) pointer.PassOp { + if opconst.OpType(d[0]) != opconst.TypePass { + panic("invalid op") + } + return pointer.PassOp{ + Pass: d[1] != 0, + } +} diff --git a/ui/app/internal/input/router.go b/ui/app/internal/input/router.go index e3171245..8c336d47 100644 --- a/ui/app/internal/input/router.go +++ b/ui/app/internal/input/router.go @@ -3,6 +3,7 @@ package input import ( + "encoding/binary" "time" "gioui.org/ui" @@ -74,15 +75,13 @@ func (q *Router) collect() { for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() { switch opconst.OpType(encOp.Data[0]) { case opconst.TypeInvalidate: - var op ui.InvalidateOp - op.Decode(encOp.Data) + op := decodeInvalidateOp(encOp.Data) if !q.wakeup || op.At.Before(q.wakeupTime) { q.wakeup = true q.wakeupTime = op.At } case opconst.TypeProfile: - var op system.ProfileOp - op.Decode(encOp.Data, encOp.Refs) + op := decodeProfileOp(encOp.Data, encOp.Refs) q.profHandlers = append(q.profHandlers, op.Key) } } @@ -141,3 +140,24 @@ func (h *handlerEvents) Clear() { delete(h.handlers, k) } } + +func decodeProfileOp(d []byte, refs []interface{}) system.ProfileOp { + if opconst.OpType(d[0]) != opconst.TypeProfile { + panic("invalid op") + } + return system.ProfileOp{ + Key: refs[0].(input.Key), + } +} + +func decodeInvalidateOp(d []byte) ui.InvalidateOp { + bo := binary.LittleEndian + if opconst.OpType(d[0]) != opconst.TypeInvalidate { + panic("invalid op") + } + var o ui.InvalidateOp + if nanos := bo.Uint64(d[1:]); nanos > 0 { + o.At = time.Unix(0, int64(nanos)) + } + return o +} diff --git a/ui/draw/draw.go b/ui/draw/draw.go index fad9df5b..943d28cb 100644 --- a/ui/draw/draw.go +++ b/ui/draw/draw.go @@ -37,27 +37,6 @@ func (i ImageOp) Add(o *ui.Ops) { o.Write(data, i.Src) } -func (i *ImageOp) Decode(data []byte, refs []interface{}) { - bo := binary.LittleEndian - if opconst.OpType(data[0]) != opconst.TypeImage { - panic("invalid op") - } - sr := image.Rectangle{ - Min: image.Point{ - X: int(int32(bo.Uint32(data[1:]))), - Y: int(int32(bo.Uint32(data[5:]))), - }, - Max: image.Point{ - X: int(int32(bo.Uint32(data[9:]))), - Y: int(int32(bo.Uint32(data[13:]))), - }, - } - *i = ImageOp{ - Src: refs[0].(image.Image), - Rect: sr, - } -} - func (c ColorOp) Add(o *ui.Ops) { data := make([]byte, opconst.TypeColorLen) data[0] = byte(opconst.TypeColor) @@ -68,20 +47,6 @@ func (c ColorOp) Add(o *ui.Ops) { o.Write(data) } -func (c *ColorOp) Decode(data []byte, refs []interface{}) { - if opconst.OpType(data[0]) != opconst.TypeColor { - panic("invalid op") - } - *c = ColorOp{ - Color: color.RGBA{ - R: data[1], - G: data[2], - B: data[3], - A: data[4], - }, - } -} - func (d DrawOp) Add(o *ui.Ops) { data := make([]byte, opconst.TypeDrawLen) data[0] = byte(opconst.TypeDraw) @@ -93,26 +58,6 @@ func (d DrawOp) Add(o *ui.Ops) { o.Write(data) } -func (d *DrawOp) Decode(data []byte, refs []interface{}) { - bo := binary.LittleEndian - if opconst.OpType(data[0]) != opconst.TypeDraw { - panic("invalid op") - } - r := f32.Rectangle{ - Min: f32.Point{ - X: math.Float32frombits(bo.Uint32(data[1:])), - Y: math.Float32frombits(bo.Uint32(data[5:])), - }, - Max: f32.Point{ - X: math.Float32frombits(bo.Uint32(data[9:])), - Y: math.Float32frombits(bo.Uint32(data[13:])), - }, - } - *d = DrawOp{ - Rect: r, - } -} - // RectClip returns a ClipOp op corresponding to // a pixel aligned rectangular area. func RectClip(r image.Rectangle) ClipOp { diff --git a/ui/internal/ops/ops.go b/ui/internal/ops/ops.go new file mode 100644 index 00000000..c324efd2 --- /dev/null +++ b/ui/internal/ops/ops.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package ops + +import ( + "encoding/binary" + "math" + + "gioui.org/ui" + "gioui.org/ui/f32" + "gioui.org/ui/internal/opconst" +) + +func DecodeTransformOp(d []byte) ui.TransformOp { + bo := binary.LittleEndian + if opconst.OpType(d[0]) != opconst.TypeTransform { + panic("invalid op") + } + return ui.TransformOp{}.Offset(f32.Point{ + X: math.Float32frombits(bo.Uint32(d[1:])), + Y: math.Float32frombits(bo.Uint32(d[5:])), + }) +} diff --git a/ui/key/key.go b/ui/key/key.go index 34c58cd4..e009089d 100644 --- a/ui/key/key.go +++ b/ui/key/key.go @@ -64,16 +64,6 @@ func (h HandlerOp) Add(o *ui.Ops) { o.Write(data, h.Key) } -func (h *HandlerOp) Decode(d []byte, refs []interface{}) { - if opconst.OpType(d[0]) != opconst.TypeKeyHandler { - panic("invalid op") - } - *h = HandlerOp{ - Focus: d[1] != 0, - Key: refs[0].(input.Key), - } -} - func (h HideInputOp) Add(o *ui.Ops) { data := make([]byte, opconst.TypeHideInputLen) data[0] = byte(opconst.TypeHideInput) diff --git a/ui/pointer/pointer.go b/ui/pointer/pointer.go index 2753dad7..62766513 100644 --- a/ui/pointer/pointer.go +++ b/ui/pointer/pointer.go @@ -115,16 +115,6 @@ func (h HandlerOp) Add(o *ui.Ops) { o.Write(data, h.Key) } -func (h *HandlerOp) Decode(d []byte, refs []interface{}) { - if opconst.OpType(d[0]) != opconst.TypePointerHandler { - panic("invalid op") - } - *h = HandlerOp{ - Grab: d[1] != 0, - Key: refs[0].(input.Key), - } -} - func (op PassOp) Add(o *ui.Ops) { data := make([]byte, opconst.TypePassLen) data[0] = byte(opconst.TypePass) @@ -134,15 +124,6 @@ func (op PassOp) Add(o *ui.Ops) { o.Write(data) } -func (op *PassOp) Decode(d []byte) { - if opconst.OpType(d[0]) != opconst.TypePass { - panic("invalid op") - } - *op = PassOp{ - Pass: d[1] != 0, - } -} - func (t Type) String() string { switch t { case Press: diff --git a/ui/system/system.go b/ui/system/system.go index 71c5615e..8f7c0b13 100644 --- a/ui/system/system.go +++ b/ui/system/system.go @@ -29,13 +29,4 @@ func (p ProfileOp) Add(o *ui.Ops) { o.Write(data, p.Key) } -func (p *ProfileOp) Decode(d []byte, refs []interface{}) { - if opconst.OpType(d[0]) != opconst.TypeProfile { - panic("invalid op") - } - *p = ProfileOp{ - Key: refs[0].(input.Key), - } -} - func (p ProfileEvent) ImplementsEvent() {} diff --git a/ui/ui.go b/ui/ui.go index 92174097..3b604806 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -46,16 +46,6 @@ func (r InvalidateOp) Add(o *Ops) { o.Write(data) } -func (r *InvalidateOp) Decode(d []byte) { - bo := binary.LittleEndian - if opconst.OpType(d[0]) != opconst.TypeInvalidate { - panic("invalid op") - } - if nanos := bo.Uint64(d[1:]); nanos > 0 { - r.At = time.Unix(0, int64(nanos)) - } -} - // Offset the transformation. func (t TransformOp) Offset(o f32.Point) TransformOp { return t.Multiply(TransformOp{o}) @@ -86,14 +76,3 @@ func (t TransformOp) Add(o *Ops) { bo.PutUint32(data[5:], math.Float32bits(t.offset.Y)) o.Write(data) } - -func (t *TransformOp) Decode(d []byte) { - bo := binary.LittleEndian - if opconst.OpType(d[0]) != opconst.TypeTransform { - panic("invalid op") - } - *t = TransformOp{f32.Point{ - X: math.Float32frombits(bo.Uint32(d[1:])), - Y: math.Float32frombits(bo.Uint32(d[5:])), - }} -}