op/paint: return ClipOp from Path.End

Instead of adding an implicit ClipOp, return a ClipOp ready to use, freeing the
caller from recording a macro.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-10-09 15:05:09 +02:00
parent a937a76534
commit ef5cf5b724
6 changed files with 36 additions and 29 deletions
+13 -7
View File
@@ -210,17 +210,22 @@ func (o *Ops) Write(op []byte, refs ...interface{}) {
} }
o.auxLen += len(op) o.auxLen += len(op)
default: default:
if o.inAux { o.endAux()
o.inAux = false
bo := binary.LittleEndian
bo.PutUint32(o.data[o.auxOff+1:], uint32(o.auxLen))
}
} }
o.write(op, refs...) o.write(op, refs...)
} }
func (d *Ops) pc() pc { func (o *Ops) endAux() {
return pc{data: len(d.data), refs: len(d.refs)} if !o.inAux {
return
}
o.inAux = false
bo := binary.LittleEndian
bo.PutUint32(o.data[o.auxOff+1:], uint32(o.auxLen))
}
func (o *Ops) pc() pc {
return pc{data: len(o.data), refs: len(o.refs)}
} }
// Record a macro of operations. // Record a macro of operations.
@@ -242,6 +247,7 @@ func (m *MacroOp) Stop() {
if !m.recording { if !m.recording {
panic("not recording") panic("not recording")
} }
m.ops.endAux()
m.ops.macroDepth-- m.ops.macroDepth--
m.recording = false m.recording = false
m.fill() m.fill()
+10 -5
View File
@@ -25,14 +25,17 @@ type Path struct {
pen f32.Point pen f32.Point
bounds f32.Rectangle bounds f32.Rectangle
hasBounds bool hasBounds bool
macro op.MacroOp
} }
// ClipOp sets the current clip path. // ClipOp sets the current clip path.
type ClipOp struct { type ClipOp struct {
macro op.MacroOp
bounds f32.Rectangle bounds f32.Rectangle
} }
func (p ClipOp) Add(o *op.Ops) { func (p ClipOp) Add(o *op.Ops) {
p.macro.Add(o)
data := make([]byte, opconst.TypeClipLen) data := make([]byte, opconst.TypeClipLen)
data[0] = byte(opconst.TypeClip) data[0] = byte(opconst.TypeClip)
bo := binary.LittleEndian bo := binary.LittleEndian
@@ -46,6 +49,7 @@ func (p ClipOp) Add(o *op.Ops) {
// Begin the path, storing the path data and final ClipOp into ops. // Begin the path, storing the path data and final ClipOp into ops.
func (p *Path) Begin(ops *op.Ops) { func (p *Path) Begin(ops *op.Ops) {
p.ops = ops p.ops = ops
p.macro.Record(ops)
} }
// MoveTo moves the pen to the given position. // MoveTo moves the pen to the given position.
@@ -280,11 +284,12 @@ func (p *Path) simpleQuadTo(ctrl, to f32.Point) {
p.pen = to p.pen = to
} }
// End the path and add the resulting ClipOp to // End the path and return the resulting ClipOp.
// the operation list passed to Init. func (p *Path) End() ClipOp {
func (p *Path) End() {
p.end() p.end()
ClipOp{ p.macro.Stop()
return ClipOp{
macro: p.macro,
bounds: p.bounds, bounds: p.bounds,
}.Add(p.ops) }
} }
+3 -3
View File
@@ -7,7 +7,7 @@ import (
"image" "image"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op/paint"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
) )
@@ -64,8 +64,8 @@ type Family interface {
// Layout returns the text layout for a string given a set of // Layout returns the text layout for a string given a set of
// options. // options.
Layout(face Face, size float32, s string, opts LayoutOptions) *Layout Layout(face Face, size float32, s string, opts LayoutOptions) *Layout
// Path returns the ClipOp outline of a text recorded in a macro. // Path returns the ClipOp outline of a text.
Shape(face Face, size float32, s String) op.MacroOp Shape(face Face, size float32, s String) paint.ClipOp
} }
type Alignment uint8 type Alignment uint8
+5 -5
View File
@@ -3,7 +3,7 @@
package shape package shape
import ( import (
"gioui.org/op" "gioui.org/op/paint"
"gioui.org/text" "gioui.org/text"
"golang.org/x/image/font/sfnt" "golang.org/x/image/font/sfnt"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
@@ -28,7 +28,7 @@ type layout struct {
type path struct { type path struct {
next, prev *path next, prev *path
key pathKey key pathKey
val op.MacroOp val paint.ClipOp
} }
type layoutKey struct { type layoutKey struct {
@@ -85,16 +85,16 @@ func (l *layoutCache) insert(lt *layout) {
lt.next.prev = lt lt.next.prev = lt
} }
func (c *pathCache) Get(k pathKey) (op.MacroOp, bool) { func (c *pathCache) Get(k pathKey) (paint.ClipOp, bool) {
if v, ok := c.m[k]; ok { if v, ok := c.m[k]; ok {
c.remove(v) c.remove(v)
c.insert(v) c.insert(v)
return v.val, true return v.val, true
} }
return op.MacroOp{}, false return paint.ClipOp{}, false
} }
func (c *pathCache) Put(k pathKey, v op.MacroOp) { func (c *pathCache) Put(k pathKey, v paint.ClipOp) {
if c.m == nil { if c.m == nil {
c.m = make(map[pathKey]*path) c.m = make(map[pathKey]*path)
c.head = new(path) c.head = new(path)
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"gioui.org/op" "gioui.org/op/paint"
) )
func TestLayoutLRU(t *testing.T) { func TestLayoutLRU(t *testing.T) {
@@ -24,7 +24,7 @@ func TestLayoutLRU(t *testing.T) {
func TestuPathLRU(t *testing.T) { func TestuPathLRU(t *testing.T) {
c := new(pathCache) c := new(pathCache)
put := func(i int) { put := func(i int) {
c.Put(pathKey{str: strconv.Itoa(i)}, op.MacroOp{}) c.Put(pathKey{str: strconv.Itoa(i)}, paint.ClipOp{})
} }
get := func(i int) bool { get := func(i int) bool {
_, ok := c.Get(pathKey{str: strconv.Itoa(i)}) _, ok := c.Get(pathKey{str: strconv.Itoa(i)})
+3 -7
View File
@@ -64,7 +64,7 @@ func (f *Family) Layout(face text.Face, size float32, str string, opts text.Layo
return l return l
} }
func (f *Family) Shape(face text.Face, size float32, str text.String) op.MacroOp { func (f *Family) Shape(face text.Face, size float32, str text.String) paint.ClipOp {
fnt := f.fontFor(face) fnt := f.fontFor(face)
ppem := fixed.Int26_6(size * 64) ppem := fixed.Int26_6(size * 64)
pk := pathKey{ pk := pathKey{
@@ -169,14 +169,12 @@ func layoutText(buf *sfnt.Buffer, ppem fixed.Int26_6, str string, f *opentype, o
return &text.Layout{Lines: lines} return &text.Layout{Lines: lines}
} }
func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, f *opentype, str text.String) op.MacroOp { func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, f *opentype, str text.String) paint.ClipOp {
var lastPos f32.Point var lastPos f32.Point
var builder paint.Path var builder paint.Path
ops := new(op.Ops) ops := new(op.Ops)
var x fixed.Int26_6 var x fixed.Int26_6
var advIdx int var advIdx int
var m op.MacroOp
m.Record(ops)
builder.Begin(ops) builder.Begin(ops)
for _, r := range str.String { for _, r := range str.String {
if !unicode.IsSpace(r) { if !unicode.IsSpace(r) {
@@ -229,7 +227,5 @@ func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, f *opentype, str text.String
x += str.Advances[advIdx] x += str.Advances[advIdx]
advIdx++ advIdx++
} }
builder.End() return builder.End()
m.Stop()
return m
} }