From 75d744ab8d81ef00eb2a0b5b0f58bf45030913d1 Mon Sep 17 00:00:00 2001 From: Chris Waldon Date: Mon, 21 Nov 2022 14:31:40 -0500 Subject: [PATCH] styledtext: [WIP] adapt to new text shaping APIs Signed-off-by: Chris Waldon --- styledtext/styledtext.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/styledtext/styledtext.go b/styledtext/styledtext.go index 3de2e64..a92e04b 100644 --- a/styledtext/styledtext.go +++ b/styledtext/styledtext.go @@ -37,10 +37,7 @@ type spanShape struct { func (ss SpanStyle) Layout(gtx layout.Context, s text.Shaper, shape spanShape) layout.Dimensions { paint.ColorOp{Color: ss.Color}.Add(gtx.Ops) defer op.Offset(shape.offset).Push(gtx.Ops).Pop() - left := text.GlyphPosition{} - right := text.GlyphPosition{Run: len(shape.layout.Runs) - 1} - right.Glyph = len(shape.layout.Runs[right.Run].Glyphs) - 1 - defer clip.Outline{Path: s.Shape(shape.layout, left, right)}.Op().Push(gtx.Ops).Pop() + defer clip.Outline{Path: s.Shape(shape.layout)}.Op().Push(gtx.Ops).Pop() paint.PaintOp{}.Add(gtx.Ops) return layout.Dimensions{Size: shape.size} } @@ -93,13 +90,23 @@ func (t TextStyle) Layout(gtx layout.Context, spanFn func(gtx layout.Context, id maxWidth := gtx.Constraints.Max.X - lineDims.X // shape the text of the current span - lines := t.Shaper.LayoutString(span.Font, fixed.I(gtx.Sp(span.Size)), maxWidth, gtx.Locale, span.Content) + shaped := t.Shaper.LayoutString(text.Parameters{ + Font: span.Font, + PxPerEm: fixed.I(gtx.Sp(span.Size)), + }, 0, maxWidth, gtx.Locale, span.Content) + + shaped.SetViewport(image.Rectangle{Max: image.Pt(1e6, 1e6)}) // grab the first line of the result and compute its dimensions - firstLine := lines[0] - spanWidth := firstLine.Width.Ceil() - spanHeight := (firstLine.Ascent + firstLine.Descent).Ceil() - spanAscent := firstLine.Ascent.Ceil() + firstLine, ok := shaped.Next() + if !ok { + continue + } + width, ascent, descent := firstLine.Metrics() + _, multiLine := shaped.Next() + spanWidth := width.Ceil() + spanHeight := (ascent + descent).Ceil() + spanAscent := ascent.Ceil() // forceToNextLine handles the case in which the first segment of the new span does not fit // AND there is already content on the current line. If there is no content on the line, @@ -133,7 +140,7 @@ func (t TextStyle) Layout(gtx layout.Context, spanFn func(gtx layout.Context, id // if we are breaking the current span across lines or we are on the // last span, lay out all of the spans for the line. - if len(lines) > 1 || i == len(spans)-1 || forceToNextLine { + if multiLine || i == len(spans)-1 || forceToNextLine { lineMacro := op.Record(gtx.Ops) for i, shape := range lineShapes { // lay out this span @@ -181,7 +188,7 @@ func (t TextStyle) Layout(gtx layout.Context, spanFn func(gtx layout.Context, id } // if the current span breaks across lines - if len(lines) > 1 && !forceToNextLine { + if multiLine && !forceToNextLine { // mark where the next line to be laid out starts lineStartIndex = i + 1 lineDims = image.Point{} @@ -195,7 +202,7 @@ func (t TextStyle) Layout(gtx layout.Context, spanFn func(gtx layout.Context, id } // synthesize and insert a new span byteLen := 0 - for i := 0; i < firstLine.RuneCount; i++ { + for i := 0; i < firstLine.Runes(); i++ { _, n := utf8.DecodeRuneInString(span.Content[byteLen:]) byteLen += n } -- 2.45.2