diff --git a/font/opentype/opentype.go b/font/opentype/opentype.go index b46fdd4f..1f42330d 100644 --- a/font/opentype/opentype.go +++ b/font/opentype/opentype.go @@ -119,7 +119,7 @@ func (f *Font) Layout(ppem fixed.Int26_6, maxWidth int, txt io.Reader) ([]text.L return layoutText(&buf, ppem, maxWidth, fonts, glyphs) } -func (f *Font) Shape(ppem fixed.Int26_6, str text.Layout) clip.Op { +func (f *Font) Shape(ppem fixed.Int26_6, str text.Layout) clip.PathSpec { var buf sfnt.Buffer return textPath(&buf, ppem, []*opentype{{Font: f.font, Hinting: font.HintingFull}}, str) } @@ -139,7 +139,7 @@ func (c *Collection) Layout(ppem fixed.Int26_6, maxWidth int, txt io.Reader) ([] return layoutText(&buf, ppem, maxWidth, c.fonts, glyphs) } -func (c *Collection) Shape(ppem fixed.Int26_6, str text.Layout) clip.Op { +func (c *Collection) Shape(ppem fixed.Int26_6, str text.Layout) clip.PathSpec { var buf sfnt.Buffer return textPath(&buf, ppem, c.fonts, str) } @@ -261,12 +261,11 @@ func toLayout(glyphs []glyph) text.Layout { return text.Layout{Text: buf.String(), Advances: advs} } -func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, fonts []*opentype, str text.Layout) clip.Op { +func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, fonts []*opentype, str text.Layout) clip.PathSpec { var lastPos f32.Point var builder clip.Path - ops := new(op.Ops) var x fixed.Int26_6 - builder.Begin(ops) + builder.Begin(new(op.Ops)) rune := 0 for _, r := range str.Text { if !unicode.IsSpace(r) { @@ -323,9 +322,7 @@ func textPath(buf *sfnt.Buffer, ppem fixed.Int26_6, fonts []*opentype, str text. x += str.Advances[rune] rune++ } - return clip.Outline{ - Path: builder.End(), - }.Op() + return builder.End() } func readGlyphs(r io.Reader) ([]glyph, error) { diff --git a/font/opentype/opentype_test.go b/font/opentype/opentype_test.go index 748b8e9c..67683c35 100644 --- a/font/opentype/opentype_test.go +++ b/font/opentype/opentype_test.go @@ -70,7 +70,7 @@ func TestCollectionAsFace(t *testing.T) { // All shapes from the original fonts should be distinct because the glyphs are distinct, including the replacement // glyphs. - distinctShapes := []clip.Op{shapeValid1, shapeInvalid1, shapeValid2, shapeInvalid2} + distinctShapes := []clip.PathSpec{shapeValid1, shapeInvalid1, shapeValid2, shapeInvalid2} for i := 0; i < len(distinctShapes); i++ { for j := i + 1; j < len(distinctShapes); j++ { if areShapesEqual(distinctShapes[i], distinctShapes[j]) { @@ -174,23 +174,23 @@ func mergeFonts(ttf1, ttf2 []byte) []byte { } // shapeRune uses a given Face to shape exactly one rune at a fixed size, then returns the resulting shape data. -func shapeRune(f text.Face, r rune) (clip.Op, error) { +func shapeRune(f text.Face, r rune) (clip.PathSpec, error) { ppem := fixed.I(200) lines, err := f.Layout(ppem, 2000, strings.NewReader(string(r))) if err != nil { - return clip.Op{}, err + return clip.PathSpec{}, err } if len(lines) != 1 { - return clip.Op{}, fmt.Errorf("unexpected rendering for \"U+%08X\": got %d lines (expected: 1)", r, len(lines)) + return clip.PathSpec{}, fmt.Errorf("unexpected rendering for \"U+%08X\": got %d lines (expected: 1)", r, len(lines)) } return f.Shape(ppem, lines[0].Layout), nil } // areShapesEqual returns true iff both given text shapes are produced with identical operations. -func areShapesEqual(shape1, shape2 clip.Op) bool { +func areShapesEqual(shape1, shape2 clip.PathSpec) bool { var ops1, ops2 op.Ops - shape1.Push(&ops1).Pop() - shape2.Push(&ops2).Pop() + clip.Outline{Path: shape1}.Op().Push(&ops1).Pop() + clip.Outline{Path: shape2}.Op().Push(&ops2).Pop() var r1, r2 ops.Reader r1.Reset(&ops1.Internal) r2.Reset(&ops2.Internal) diff --git a/text/lru.go b/text/lru.go index 8cc56fc7..10448b16 100644 --- a/text/lru.go +++ b/text/lru.go @@ -26,7 +26,7 @@ type layoutElem struct { type path struct { next, prev *path key pathKey - val clip.Op + val clip.PathSpec } type layoutKey struct { @@ -81,16 +81,16 @@ func (l *layoutCache) insert(lt *layoutElem) { lt.next.prev = lt } -func (c *pathCache) Get(k pathKey) (clip.Op, bool) { +func (c *pathCache) Get(k pathKey) (clip.PathSpec, bool) { if v, ok := c.m[k]; ok { c.remove(v) c.insert(v) return v.val, true } - return clip.Op{}, false + return clip.PathSpec{}, false } -func (c *pathCache) Put(k pathKey, v clip.Op) { +func (c *pathCache) Put(k pathKey, v clip.PathSpec) { if c.m == nil { c.m = make(map[pathKey]*path) c.head = new(path) diff --git a/text/lru_test.go b/text/lru_test.go index 192f6392..820de5a7 100644 --- a/text/lru_test.go +++ b/text/lru_test.go @@ -24,7 +24,7 @@ func TestLayoutLRU(t *testing.T) { func TestPathLRU(t *testing.T) { c := new(pathCache) put := func(i int) { - c.Put(pathKey{str: strconv.Itoa(i)}, clip.Op{}) + c.Put(pathKey{str: strconv.Itoa(i)}, clip.PathSpec{}) } get := func(i int) bool { _, ok := c.Get(pathKey{str: strconv.Itoa(i)}) diff --git a/text/shaper.go b/text/shaper.go index 48b08725..59020e07 100644 --- a/text/shaper.go +++ b/text/shaper.go @@ -18,7 +18,7 @@ type Shaper interface { // LayoutString is Layout for strings. LayoutString(font Font, size fixed.Int26_6, maxWidth int, str string) []Line // Shape a line of text and return a clipping operation for its outline. - Shape(font Font, size fixed.Int26_6, layout Layout) clip.Op + Shape(font Font, size fixed.Int26_6, layout Layout) clip.PathSpec } // A FontFace is a Font and a matching Face. @@ -121,7 +121,7 @@ func (c *Cache) LayoutString(font Font, size fixed.Int26_6, maxWidth int, str st // Shape is a caching implementation of the Shaper interface. Shape assumes that the layout // argument is unchanged from a call to Layout or LayoutString. -func (c *Cache) Shape(font Font, size fixed.Int26_6, layout Layout) clip.Op { +func (c *Cache) Shape(font Font, size fixed.Int26_6, layout Layout) clip.PathSpec { cache := c.lookup(font) return cache.shape(size, layout) } @@ -143,9 +143,9 @@ func (f *faceCache) layout(ppem fixed.Int26_6, maxWidth int, str string) []Line return l } -func (f *faceCache) shape(ppem fixed.Int26_6, layout Layout) clip.Op { +func (f *faceCache) shape(ppem fixed.Int26_6, layout Layout) clip.PathSpec { if f == nil { - return clip.Op{} + return clip.PathSpec{} } pk := pathKey{ ppem: ppem, diff --git a/text/text.go b/text/text.go index 935b14d8..12d39f5c 100644 --- a/text/text.go +++ b/text/text.go @@ -48,7 +48,7 @@ type Font struct { // methods must be safe for concurrent use. type Face interface { Layout(ppem fixed.Int26_6, maxWidth int, txt io.Reader) ([]Line, error) - Shape(ppem fixed.Int26_6, str Layout) clip.Op + Shape(ppem fixed.Int26_6, str Layout) clip.PathSpec } // Typeface identifies a particular typeface design. The empty diff --git a/widget/editor.go b/widget/editor.go index 31045f25..a20bc46c 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -531,8 +531,8 @@ func (e *Editor) layout(gtx layout.Context, content layout.Widget) layout.Dimens if !ok { break } - path := e.shaper.Shape(e.font, e.textSize, layout) - e.shapes = append(e.shapes, line{off, path, selected, yOffs, size}) + op := clip.Outline{Path: e.shaper.Shape(e.font, e.textSize, layout)}.Op() + e.shapes = append(e.shapes, line{off, op, selected, yOffs, size}) } key.InputOp{Tag: &e.eventKey, Hint: e.InputHint}.Add(gtx.Ops) diff --git a/widget/label.go b/widget/label.go index fbcbfb74..c45a89da 100644 --- a/widget/label.go +++ b/widget/label.go @@ -179,7 +179,7 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un } t := op.Offset(layout.FPt(off)).Push(gtx.Ops) rcl := clip.Rect(cl.Sub(off)).Push(gtx.Ops) - cl := s.Shape(font, textSize, l).Push(gtx.Ops) + cl := clip.Outline{Path: s.Shape(font, textSize, l)}.Op().Push(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) cl.Pop() rcl.Pop()