Update shaper_usage.md with correct glyph drawing approach
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
fcd2fea870
commit
0f62ef32fa
|
|
@ -159,34 +159,52 @@ func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp)
|
||||||
|
|
||||||
## 5. Rendering Glyphs Directly
|
## 5. Rendering Glyphs Directly
|
||||||
|
|
||||||
Instead of using `material.Label()` (which shapes text again), draw glyphs directly:
|
Gio's textView draws glyphs using `shaper.Shape()` (for vector glyphs) and `shaper.Bitmaps()` (for bitmap glyphs like emoji). This is the correct approach to avoid double-shaping.
|
||||||
|
|
||||||
### 5.1 Drawing a Single Glyph
|
### 5.1 Drawing Text Using Gio's textView Approach
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// After layout, iterate through glyphs
|
func drawText(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp, x, y unit.Dp, col color.NRGBA) {
|
||||||
for {
|
// Layout text
|
||||||
g, ok := shp.NextGlyph()
|
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str)
|
||||||
if !ok {
|
|
||||||
break
|
// 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 {
|
||||||
|
drawLine(gtx, shp, line, x, y, col)
|
||||||
|
line = line[:0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Draw glyph at position (g.X, g.Y)
|
if len(line) > 0 {
|
||||||
// Use shp.DrawGlyph() or manual drawing
|
drawLine(gtx, shp, line, x, y, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func 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()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.2 Using Shaper's Drawing Functions
|
### 5.2 Avoiding Double-Shaping
|
||||||
|
|
||||||
The shaper provides drawing functions that use the already-computed glyph data:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Draw all laid-out glyphs
|
|
||||||
shp.Draw(gtx, ops, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important**: Call `shp.Draw()` AFTER calling `LayoutString()` or `Layout()`. The drawing functions use the glyph data computed during the layout phase.
|
|
||||||
|
|
||||||
### 5.3 Avoiding Double-Shaping
|
|
||||||
|
|
||||||
**WRONG** (shapes text twice):
|
**WRONG** (shapes text twice):
|
||||||
|
|
||||||
|
|
@ -198,14 +216,19 @@ widths := charWidths(gtx, shp, text, size)
|
||||||
material.Label(th, size, text).Layout(gtx)
|
material.Label(th, size, text).Layout(gtx)
|
||||||
```
|
```
|
||||||
|
|
||||||
**CORRECT** (shapes text once):
|
**CORRECT** (shapes text once for rendering):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Single pass: layout and draw
|
// Single pass: layout and draw using shaper.Shape()
|
||||||
shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, text)
|
drawText(gtx, shp, text, size, x, y, col)
|
||||||
shp.Draw(gtx, ops, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**NOTE**: For truncation, we may need to layout twice:
|
||||||
|
1. First layout to measure widths and find truncation point
|
||||||
|
2. Second layout to draw the truncated text
|
||||||
|
|
||||||
|
This is acceptable because truncation is only needed when text doesn't fit, and the string is short (filename in StatusBar).
|
||||||
|
|
||||||
## 6. Comparison with Gio's textView
|
## 6. Comparison with Gio's textView
|
||||||
|
|
||||||
Gio's textView (`widget/text.go`) demonstrates the correct approach:
|
Gio's textView (`widget/text.go`) demonstrates the correct approach:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user