mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +00:00
Make TextRun struct to clean GetTextRuns
This commit is contained in:
@ -71,44 +71,32 @@ func (gr *GlyphRend) DrawTextOpenGLAbs(text string, screenPos *gglm.Vec3, color
|
|||||||
|
|
||||||
bufIndex := gr.GlyphCount * floatsPerGlyph
|
bufIndex := gr.GlyphCount * floatsPerGlyph
|
||||||
|
|
||||||
for _, run := range runs {
|
for runIndex := 0; runIndex < len(runs); runIndex++ {
|
||||||
|
|
||||||
rs := run
|
run := &runs[runIndex]
|
||||||
prevRune := invalidRune
|
prevRune := invalidRune
|
||||||
|
|
||||||
//TODO: Information on run (like bidi) should come from GetTextRuns.
|
if run.IsLtr {
|
||||||
//Default is left in case we hav a run of neutrals
|
|
||||||
bidiCat := BidiCategory_L
|
|
||||||
for _, r := range rs {
|
|
||||||
if !unicode.Is(unicode.Common, r) {
|
|
||||||
bidiCat = RuneInfos[r].BidiCat
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isLtr := !(bidiCat == BidiCategory_R || bidiCat == BidiCategory_AL || bidiCat == BidiCategory_RLE || bidiCat == BidiCategory_RLO || bidiCat == BidiCategory_RLI || bidiCat == BidiCategory_RLM)
|
|
||||||
|
|
||||||
if isLtr {
|
for i := 0; i < len(run.Runes); i++ {
|
||||||
|
gr.drawRune(run, i, prevRune, screenPos, pos, color, advanceF32, lineHeightF32, &bufIndex)
|
||||||
for i := 0; i < len(rs); i++ {
|
prevRune = run.Runes[i]
|
||||||
gr.drawRune(rs, i, prevRune, screenPos, pos, color, advanceF32, lineHeightF32, &bufIndex, isLtr)
|
|
||||||
prevRune = rs[i]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for i := len(rs) - 1; i >= 0; i-- {
|
for i := len(run.Runes) - 1; i >= 0; i-- {
|
||||||
gr.drawRune(rs, i, prevRune, screenPos, pos, color, advanceF32, lineHeightF32, &bufIndex, isLtr)
|
gr.drawRune(run, i, prevRune, screenPos, pos, color, advanceF32, lineHeightF32, &bufIndex)
|
||||||
prevRune = rs[i]
|
prevRune = run.Runes[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gr *GlyphRend) drawRune(rs []rune, i int, prevRune rune, screenPos, pos *gglm.Vec3, color *gglm.Vec4, advanceF32, lineHeightF32 float32, bufIndex *uint32, isLtr bool) {
|
func (gr *GlyphRend) drawRune(run *TextRun, i int, prevRune rune, screenPos, pos *gglm.Vec3, color *gglm.Vec4, advanceF32, lineHeightF32 float32, bufIndex *uint32) {
|
||||||
|
|
||||||
r := rs[i]
|
r := run.Runes[i]
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
screenPos.SetY(screenPos.Y() - lineHeightF32)
|
screenPos.SetY(screenPos.Y() - lineHeightF32)
|
||||||
*pos = *screenPos.Clone()
|
*pos = *screenPos.Clone()
|
||||||
@ -125,10 +113,10 @@ func (gr *GlyphRend) drawRune(rs []rune, i int, prevRune rune, screenPos, pos *g
|
|||||||
}
|
}
|
||||||
|
|
||||||
var g FontAtlasGlyph
|
var g FontAtlasGlyph
|
||||||
if isLtr {
|
if run.IsLtr {
|
||||||
if i < len(rs)-1 {
|
if i < len(run.Runes)-1 {
|
||||||
//start or middle of sentence
|
//start or middle of sentence
|
||||||
g = gr.glyphFromRunes(r, prevRune, rs[i+1])
|
g = gr.glyphFromRunes(r, prevRune, run.Runes[i+1])
|
||||||
} else {
|
} else {
|
||||||
//Last character
|
//Last character
|
||||||
g = gr.glyphFromRunes(r, prevRune, invalidRune)
|
g = gr.glyphFromRunes(r, prevRune, invalidRune)
|
||||||
@ -136,7 +124,7 @@ func (gr *GlyphRend) drawRune(rs []rune, i int, prevRune rune, screenPos, pos *g
|
|||||||
} else {
|
} else {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
//start or middle of sentence
|
//start or middle of sentence
|
||||||
g = gr.glyphFromRunes(r, rs[i-1], prevRune)
|
g = gr.glyphFromRunes(r, run.Runes[i-1], prevRune)
|
||||||
} else {
|
} else {
|
||||||
//Last character
|
//Last character
|
||||||
g = gr.glyphFromRunes(r, invalidRune, prevRune)
|
g = gr.glyphFromRunes(r, invalidRune, prevRune)
|
||||||
@ -187,16 +175,21 @@ func (gr *GlyphRend) drawRune(rs []rune, i int, prevRune rune, screenPos, pos *g
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gr *GlyphRend) GetTextRuns(t string) [][]rune {
|
type TextRun struct {
|
||||||
|
Runes []rune
|
||||||
|
IsLtr bool
|
||||||
|
}
|
||||||
|
|
||||||
//PERF: Might be better to pass a [][]rune buffer to avoid allocating on the heap
|
func (gr *GlyphRend) GetTextRuns(t string) []TextRun {
|
||||||
|
|
||||||
|
//PERF: Might be better to pass a []TextRun buffer to avoid allocating on the heap
|
||||||
rs := []rune(t)
|
rs := []rune(t)
|
||||||
|
|
||||||
if len(rs) == 0 {
|
if len(rs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
runs := make([][]rune, 0, 10)
|
runs := make([]TextRun, 0, 10)
|
||||||
currRunScript := RuneInfos[rs[0]].ScriptTable
|
currRunScript := RuneInfos[rs[0]].ScriptTable
|
||||||
|
|
||||||
//TODO: We need to detect neutral characters through BiDi category, not being in common
|
//TODO: We need to detect neutral characters through BiDi category, not being in common
|
||||||
@ -211,10 +204,10 @@ func (gr *GlyphRend) GetTextRuns(t string) [][]rune {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//We reached a new run so count trailing neutrals to be removed from this run
|
//We reached a new run so count trailing neutrals to be removed from this run
|
||||||
newRun := rs[runStartIndex:i]
|
newRunRunes := rs[runStartIndex:i]
|
||||||
trailingCommonsCount := 0
|
trailingCommonsCount := 0
|
||||||
for j := len(newRun) - 1; j >= 0; j-- {
|
for j := len(newRunRunes) - 1; j >= 0; j-- {
|
||||||
if !unicode.Is(unicode.Common, newRun[j]) {
|
if !unicode.Is(unicode.Common, newRunRunes[j]) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
trailingCommonsCount++
|
trailingCommonsCount++
|
||||||
@ -222,10 +215,11 @@ func (gr *GlyphRend) GetTextRuns(t string) [][]rune {
|
|||||||
|
|
||||||
//If we have a run without trailing neutrals or had a run of just neutrals (e.g. starting sentence with spaces)
|
//If we have a run without trailing neutrals or had a run of just neutrals (e.g. starting sentence with spaces)
|
||||||
//then the full run is added, otherwise we slice the run to put neturals in a separate run
|
//then the full run is added, otherwise we slice the run to put neturals in a separate run
|
||||||
if trailingCommonsCount == 0 || len(newRun) == trailingCommonsCount {
|
if trailingCommonsCount == 0 || len(newRunRunes) == trailingCommonsCount {
|
||||||
runs = append(runs, newRun)
|
runs = append(runs, TextRun{Runes: newRunRunes})
|
||||||
} else {
|
} else {
|
||||||
runs = append(runs, newRun[:len(newRun)-trailingCommonsCount], newRun[len(newRun)-trailingCommonsCount:])
|
runs = append(runs,
|
||||||
|
TextRun{Runes: newRunRunes[:len(newRunRunes)-trailingCommonsCount]}, TextRun{Runes: newRunRunes[len(newRunRunes)-trailingCommonsCount:]})
|
||||||
}
|
}
|
||||||
|
|
||||||
//The removed neutrals are included as the start of the new run
|
//The removed neutrals are included as the start of the new run
|
||||||
@ -233,7 +227,21 @@ func (gr *GlyphRend) GetTextRuns(t string) [][]rune {
|
|||||||
currRunScript = ri.ScriptTable
|
currRunScript = ri.ScriptTable
|
||||||
}
|
}
|
||||||
|
|
||||||
runs = append(runs, rs[runStartIndex:])
|
runs = append(runs, TextRun{Runes: rs[runStartIndex:]})
|
||||||
|
|
||||||
|
//Detect directionality of each run
|
||||||
|
for i := 0; i < len(runs); i++ {
|
||||||
|
|
||||||
|
run := &runs[i]
|
||||||
|
bidiCat := BidiCategory_L
|
||||||
|
for _, r := range run.Runes {
|
||||||
|
if !unicode.Is(unicode.Common, r) {
|
||||||
|
bidiCat = RuneInfos[r].BidiCat
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run.IsLtr = !(bidiCat == BidiCategory_R || bidiCat == BidiCategory_AL || bidiCat == BidiCategory_RLE || bidiCat == BidiCategory_RLO || bidiCat == BidiCategory_RLI || bidiCat == BidiCategory_RLM)
|
||||||
|
}
|
||||||
|
|
||||||
return runs
|
return runs
|
||||||
}
|
}
|
||||||
|
|||||||
4
main.go
4
main.go
@ -165,8 +165,8 @@ func (p *program) Update() {
|
|||||||
|
|
||||||
if imgui.Button("Print Runs") {
|
if imgui.Button("Print Runs") {
|
||||||
runs := p.GlyphRend.GetTextRuns(textToShow)
|
runs := p.GlyphRend.GetTextRuns(textToShow)
|
||||||
for _, r := range runs {
|
for _, run := range runs {
|
||||||
fmt.Printf("%s; runes: %#x\n\n", string(r), r)
|
fmt.Printf("%s; runes: %#x\n\n", string(run.Runes), run.Runes)
|
||||||
}
|
}
|
||||||
fmt.Printf("----------------\n")
|
fmt.Printf("----------------\n")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user