Use shaper.Shape() and shaper.Bitmaps() to draw glyphs directly (no double-shaping)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
0fdaea990f
commit
16719afb95
|
|
@ -2,10 +2,13 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"gioui.org/f32"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
|
"gioui.org/op/paint"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
|
|
@ -107,10 +110,8 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position filename at (reg.X + 8, filenameLineY)
|
// Position filename at (reg.X + 8, filenameLineY) - draw using shaper to avoid double-shaping
|
||||||
call1 := op.Offset(image.Point{X: int(reg.X + unit.Dp(8)), Y: int(filenameLineY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, displayFilename, r.theme.FontSize, reg.X+unit.Dp(8), filenameLineY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, displayFilename).Layout(gtx)
|
|
||||||
call1.Pop()
|
|
||||||
|
|
||||||
// Line 2: Icons
|
// Line 2: Icons
|
||||||
iconsLineY := filenameLineY + filenameLineH
|
iconsLineY := filenameLineY + filenameLineH
|
||||||
|
|
@ -120,21 +121,15 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
|
||||||
iconY := iconsLineY
|
iconY := iconsLineY
|
||||||
|
|
||||||
if sb.CutCopy {
|
if sb.CutCopy {
|
||||||
call := op.Offset(image.Point{X: int(leftX), Y: int(iconY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, "✂", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, "✂").Layout(gtx)
|
|
||||||
call.Pop()
|
|
||||||
leftX += unit.Dp(36)
|
leftX += unit.Dp(36)
|
||||||
}
|
}
|
||||||
if sb.Copy {
|
if sb.Copy {
|
||||||
call := op.Offset(image.Point{X: int(leftX), Y: int(iconY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, "⎘", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, "⎘").Layout(gtx)
|
|
||||||
call.Pop()
|
|
||||||
leftX += unit.Dp(36)
|
leftX += unit.Dp(36)
|
||||||
}
|
}
|
||||||
if sb.Paste {
|
if sb.Paste {
|
||||||
call := op.Offset(image.Point{X: int(leftX), Y: int(iconY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, "⎘", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, "⎘").Layout(gtx)
|
|
||||||
call.Pop()
|
|
||||||
leftX += unit.Dp(36)
|
leftX += unit.Dp(36)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,15 +137,11 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
|
||||||
rightX := reg.X + reg.W - unit.Dp(8)
|
rightX := reg.X + reg.W - unit.Dp(8)
|
||||||
if sb.Search {
|
if sb.Search {
|
||||||
rightX -= unit.Dp(36)
|
rightX -= unit.Dp(36)
|
||||||
call := op.Offset(image.Point{X: int(rightX), Y: int(iconY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, "🔍", r.theme.FontSize, rightX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, "🔍").Layout(gtx)
|
|
||||||
call.Pop()
|
|
||||||
}
|
}
|
||||||
if sb.ConflictIcon {
|
if sb.ConflictIcon {
|
||||||
rightX -= unit.Dp(36)
|
rightX -= unit.Dp(36)
|
||||||
call := op.Offset(image.Point{X: int(rightX), Y: int(iconY)}).Push(gtx.Ops)
|
r.drawText(gtx, th.Shaper, "⚠", r.theme.FontSize, rightX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||||
material.Label(th, r.theme.FontSize, "⚠").Layout(gtx)
|
|
||||||
call.Pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Pop()
|
c.Pop()
|
||||||
|
|
@ -205,6 +196,48 @@ func boolToString(b bool) string {
|
||||||
return "Off"
|
return "Off"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drawText draws text using the same approach as Gio's textView:
|
||||||
|
// layout text, iterate glyphs, buffer into lines, and draw using shaper.Shape().
|
||||||
|
func (r *Renderer) drawText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, col color.NRGBA) {
|
||||||
|
// Layout text
|
||||||
|
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str)
|
||||||
|
|
||||||
|
// Draw glyphs using the same approach as Gio's textView
|
||||||
|
var glyphs [32]text.Glyph
|
||||||
|
line := glyphs[:0]
|
||||||
|
for g, ok := shp.NextGlyph(); ok; g, ok = shp.NextGlyph() {
|
||||||
|
line = append(line, g)
|
||||||
|
if g.Flags&text.FlagLineBreak != 0 || cap(line)-len(line) == 0 {
|
||||||
|
r.drawLine(gtx, shp, line, x, y, col)
|
||||||
|
line = line[:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(line) > 0 {
|
||||||
|
r.drawLine(gtx, shp, line, x, y, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// drawLine draws a line of glyphs using shaper.Shape() and shaper.Bitmaps().
|
||||||
|
func (r *Renderer) drawLine(gtx layout.Context, shp *text.Shaper, line []text.Glyph, x, y unit.Dp, col color.NRGBA) {
|
||||||
|
// Apply offset transform
|
||||||
|
off := f32.Point{X: float32(x), Y: float32(y)}
|
||||||
|
t := op.Affine(f32.Affine2D{}.Offset(off)).Push(gtx.Ops)
|
||||||
|
|
||||||
|
// Draw vector glyphs
|
||||||
|
path := shp.Shape(line)
|
||||||
|
outline := clip.Outline{Path: path}.Op().Push(gtx.Ops)
|
||||||
|
paint.ColorOp{Color: col}.Add(gtx.Ops)
|
||||||
|
paint.PaintOp{}.Add(gtx.Ops)
|
||||||
|
outline.Pop()
|
||||||
|
|
||||||
|
// Draw bitmap glyphs (emoji, etc.)
|
||||||
|
if call := shp.Bitmaps(line); call != (op.CallOp{}) {
|
||||||
|
call.Add(gtx.Ops)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Pop()
|
||||||
|
}
|
||||||
|
|
||||||
// charWidths returns the cumulative width after each rune in str.
|
// charWidths returns the cumulative width after each rune in str.
|
||||||
func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int {
|
func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int {
|
||||||
// Match Gio's textView: PxPerEm = font size in device pixels
|
// Match Gio's textView: PxPerEm = font size in device pixels
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user