Skip to content

Commit f91bb54

Browse files
authored
Merge pull request #1670 from cogentcore/transpose
transpose: fix crash in transpose, and update to non-deprecated typesetting api to fix web text rendering
2 parents 9de5c1c + a51c822 commit f91bb54

9 files changed

Lines changed: 51 additions & 24 deletions

File tree

content/examples/basic/basic.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
var econtent embed.FS
2020

2121
func main() {
22+
// rasterx.UseGlyphCache = false
2223
content.Settings.SiteTitle = "Cogent Content Example"
2324
content.OfflineURL = "https://example.com"
2425
b := core.NewBody("Cogent Content Example")

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ require (
6666
github.com/pkg/errors v0.9.1 // indirect
6767
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
6868
github.com/rivo/uniseg v0.4.7 // indirect
69+
github.com/rogpeppe/go-internal v1.13.1 // indirect
6970
golang.org/x/exp/shiny v0.0.0-20240416160154-fe59bbe5cc7f // indirect
7071
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
7172
golang.org/x/mod v0.34.0 // indirect

go.sum

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
135135
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
136136
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
137137
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
138-
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
139138
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
139+
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
140+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
140141
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
141142
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
142143
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

paint/renderers/rasterx/glyphcache.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ const (
3636
// glyphMaskOffsets is the number of different subpixel offsets to render, in each axis.
3737
// The memory usage goes as the square of this number, and 4 produces very good results,
3838
// while 2 is acceptable, and is significantly better than 1. 8 is overkill.
39-
glyphMaskOffsets = 4
39+
glyphMaskOffsetsX = 4
40+
glyphMaskOffsetsY = 4
4041
)
4142

4243
func init() {
@@ -83,7 +84,7 @@ func (gc *glyphCache) Glyph(face *font.Face, g *shaping.Glyph, outline font.Glyp
8384
gc.Lock()
8485
defer gc.Unlock()
8586

86-
fsize := image.Point{X: int(g.Width.Ceil()), Y: -int(g.Height.Ceil())}
87+
fsize := image.Point{X: int(g.Width.Round()), Y: -int(g.Height.Round())}
8788
size := fsize.Add(image.Point{2 * glyphMaskBorder, 2 * glyphMaskBorder})
8889
if size.X <= 0 || size.X > glyphMaxSize || size.Y <= 0 || size.Y > glyphMaxSize {
8990
return nil, image.Point{}
@@ -95,8 +96,9 @@ func (gc *glyphCache) Glyph(face *font.Face, g *shaping.Glyph, outline font.Glyp
9596
pi := pf.ToPoint().Sub(image.Point{glyphMaskBorder, glyphMaskBorder})
9697
pi.X += g.XBearing.Round()
9798
pi.Y -= g.YBearing.Round()
99+
98100
off := pos.Sub(pf)
99-
oi := off.MulScalar(glyphMaskOffsets).Floor().ToPoint()
101+
oi := off.Mul(math32.Vec2(glyphMaskOffsetsX, glyphMaskOffsetsY)).Round().ToPoint()
100102
// fmt.Println("pos:", pos, "oi:", oi, "pi:", pi)
101103

102104
key := glyphKey{gid: g.GlyphID, sx: uint8(fsize.X), sy: uint8(fsize.Y), ox: uint8(oi.X), oy: uint8(oi.Y)}
@@ -123,9 +125,9 @@ func (gc *glyphCache) renderGlyph(face *font.Face, gid font.GID, g *shaping.Glyp
123125
// clear target:
124126
draw.Draw(gc.image, gc.image.Bounds(), colors.Uniform(color.Transparent), image.Point{0, 0}, draw.Src)
125127

126-
od := float32(1) / glyphMaskOffsets
127-
x := -float32(g.XBearing.Round()) + float32(xo)*od + glyphMaskBorder
128-
y := float32(g.YBearing.Round()) + float32(yo)*od + glyphMaskBorder
128+
od := math32.Vec2(1, 1).Div(math32.Vec2(glyphMaskOffsetsX, glyphMaskOffsetsY))
129+
x := -float32(g.XBearing.Round()) + float32(xo)*od.X + glyphMaskBorder
130+
y := float32(g.YBearing.Round()) + float32(yo)*od.Y + glyphMaskBorder
129131
rs := gc.filler
130132
rs.Clear()
131133
for _, s := range outline.Segments {

paint/renderers/rasterx/text.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,11 @@ func (rs *Renderer) TextRun(ctx *render.Context, run *shapedgt.Run, ln *shaped.L
165165
} else {
166166
fmt.Printf("unrecognized glyph data for glyphID: %v, face: %v\n", g.GlyphID, run.Face.Describe().Family)
167167
}
168-
off.X += math32.FromFixed(g.XAdvance)
169-
off.Y -= math32.FromFixed(g.YAdvance)
168+
if run.Direction.IsVertical() {
169+
off.Y -= math32.FromFixed(g.Advance)
170+
} else {
171+
off.X += math32.FromFixed(g.Advance)
172+
}
170173
}
171174

172175
if run.Decoration.HasFlag(rich.LineThrough) {
@@ -188,7 +191,8 @@ func (rs *Renderer) GlyphOutline(ctx *render.Context, run *shapedgt.Run, g *shap
188191
}
189192

190193
wd := math32.FromFixed(g.Width)
191-
xadv := math32.Abs(math32.FromFixed(g.XAdvance))
194+
// todo: should be conditional on run.Direction
195+
xadv := math32.Abs(math32.FromFixed(g.Advance))
192196
if wd > xadv {
193197
if run.Font.Style(&ctx.Style.Text).Family == rich.Monospace {
194198
scale *= 0.95 * xadv / wd

text/lines/move.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package lines
66

77
import (
8+
"fmt"
9+
810
"cogentcore.org/core/text/textpos"
911
)
1012

@@ -154,6 +156,10 @@ func (ls *Lines) transposeChar(vw *view, pos textpos.Pos) bool {
154156
return false
155157
}
156158
ppos := ls.posFromView(vw, pvp)
159+
if pos.Line >= len(ls.lines) || pos.Char >= len(ls.lines[pos.Line]) {
160+
fmt.Println("transpose err:", pos, "lines:", len(ls.lines))
161+
return false
162+
}
157163
chr := ls.lines[pos.Line][pos.Char]
158164
pchr := ls.lines[ppos.Line][ppos.Char]
159165
repl := string([]rune{chr, pchr})

text/shaped/shaped_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,15 @@ func TestFontList(t *testing.T) {
403403
fmt.Println(fi.Family, "Weight:", fi.Weight, "Slant:", fi.Slant)
404404
}
405405
}
406+
407+
func TestGlyphAlign(t *testing.T) {
408+
RunTest(t, "align", 300, 300, func(pc *paint.Painter, sh Shaper, tsty *text.Style) {
409+
src := "to gopher so"
410+
sty := rich.NewStyle()
411+
sty.Size = 0.845
412+
tx := rich.NewText(sty, []rune(src))
413+
lns := sh.WrapLines(tx, sty, tsty, math32.Vec2(250, 250))
414+
pos := math32.Vec2(10.3, 10.96875)
415+
pc.DrawText(lns, pos)
416+
})
417+
}

text/shaped/shapers/shapedgt/run.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,10 @@ func (run *Run) GlyphsAt(i int) []int {
131131
var gis []int
132132
for gi := range run.Glyphs {
133133
g := &run.Glyphs[gi]
134-
if g.ClusterIndex > i {
134+
if g.TextIndex() > i {
135135
break
136136
}
137-
if g.ClusterIndex == i {
137+
if g.TextIndex() == i {
138138
gis = append(gis, gi)
139139
}
140140
}
@@ -146,7 +146,7 @@ func (run *Run) GlyphsAt(i int) []int {
146146
func (run *Run) FirstGlyphAt(i int) int {
147147
for gi := range run.Glyphs {
148148
g := &run.Glyphs[gi]
149-
if g.ClusterIndex >= i {
149+
if g.TextIndex() >= i {
150150
return gi
151151
}
152152
}
@@ -159,7 +159,7 @@ func (run *Run) LastGlyphAt(i int) int {
159159
ng := len(run.Glyphs)
160160
for gi := ng - 1; gi >= 0; gi-- {
161161
g := &run.Glyphs[gi]
162-
if g.ClusterIndex <= i {
162+
if g.TextIndex() <= i {
163163
return gi
164164
}
165165
}
@@ -171,7 +171,7 @@ func (run *Run) LastGlyphAt(i int) int {
171171
func (run *Run) SetGlyphXAdvance(adv fixed.Int26_6) {
172172
for gi := range run.Glyphs {
173173
g := &run.Glyphs[gi]
174-
g.XAdvance = adv
174+
g.Advance = adv
175175
}
176176
run.Output.Advance = adv * fixed.Int26_6(len(run.Glyphs))
177177
}
@@ -186,8 +186,8 @@ func (run *Run) RuneAtPoint(src rich.Text, pt, off math32.Vector2) int {
186186
rr := run.Runes()
187187
for gi := range run.Glyphs {
188188
g := &run.Glyphs[gi]
189-
cri := g.ClusterIndex
190-
gadv := math32.FromFixed(g.XAdvance)
189+
cri := g.TextIndex()
190+
gadv := math32.FromFixed(g.Advance)
191191
mx := adv + gadv
192192
// fmt.Println(gi, cri, adv, mx, pt.X)
193193
if pt.X >= adv && pt.X < mx {
@@ -222,14 +222,14 @@ func (run *Run) GlyphRegionBounds(st, ed int) math32.Box2 {
222222
off := float32(0)
223223
for gi := 0; gi < st; gi++ {
224224
g := &run.Glyphs[gi]
225-
off += math32.FromFixed(g.XAdvance)
225+
off += math32.FromFixed(g.Advance)
226226
}
227227
mb.Min.X = off + stb.Min.X - 2
228228
for gi := st; gi <= ed; gi++ {
229229
g := &run.Glyphs[gi]
230230
gb := run.GlyphBoundsBox(g)
231231
mb.Max.X = off + gb.Max.X + 2
232-
off += math32.FromFixed(g.XAdvance)
232+
off += math32.FromFixed(g.Advance)
233233
}
234234
return mb
235235
}

text/shaped/shapers/shapedjs/shaper.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,18 @@ func (sh *Shaper) adjustOutput(out *shaping.Output, fnt *text.Font, tx rich.Text
152152
ng := len(out.Glyphs)
153153
for gi := 0; gi < ng; gi++ {
154154
g := &out.Glyphs[gi]
155-
gri := g.ClusterIndex - rng.Start
155+
gri := g.TextIndex() - rng.Start
156156
// nrtx := len(rtx)
157-
ed := gri + g.GlyphCount
157+
ed := gri + g.GlyphsCount()
158158
gtx := rtx[gri:ed]
159159
gm := theGlyphCache.Glyph(ctx, fnt, tsty, gtx, g.GlyphID)
160-
if g.GlyphCount > 1 {
161-
gi += g.GlyphCount - 1
160+
if g.GlyphsCount() > 1 {
161+
gi += g.GlyphsCount() - 1
162162
}
163163
msz := gm.ActualBoundingBoxAscent + gm.ActualBoundingBoxDescent
164164
mwd := -gm.ActualBoundingBoxLeft + gm.ActualBoundingBoxRight
165165
// todo: conditional on vertical / horiz
166-
g.XAdvance = math32.ToFixed(gm.Width)
166+
g.Advance = math32.ToFixed(gm.Width)
167167
g.Width = math32.ToFixed(mwd)
168168
g.Height = -math32.ToFixed(msz)
169169
g.XBearing = -math32.ToFixed(gm.ActualBoundingBoxLeft)

0 commit comments

Comments
 (0)