Files
prevara/glyphiter_test.go

204 lines
4.9 KiB
Go

package gel
import (
"image"
"testing"
"gioui.org/text"
"golang.org/x/image/math/fixed"
)
func TestFixedToFloat(t *testing.T) {
tests := []struct {
input fixed.Int26_6
want float32
}{
{fixed.I(0), 0.0},
{fixed.I(1), 1.0},
{fixed.I(10), 10.0},
{fixed.I(64), 64.0},
{fixed.Int26_6(32), 0.5}, // 32/64 = 0.5
{fixed.Int26_6(96), 1.5}, // 96/64 = 1.5
}
for _, tc := range tests {
got := FixedToFloat(tc.input)
if got != tc.want {
t.Errorf("FixedToFloat(%v) = %v, want %v", tc.input, got, tc.want)
}
}
}
func TestGlyphIteratorProcessGlyph(t *testing.T) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(100, 100)},
MaxLines: 0,
}
// Create a test glyph within the viewport
g := text.Glyph{
X: fixed.I(10),
Y: 20,
Advance: fixed.I(10),
Ascent: fixed.I(12),
Descent: fixed.I(4),
Bounds: fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(0), Y: fixed.I(-12)},
Max: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(4)},
},
}
visibleOrBefore := it.ProcessGlyph(g, true)
if !visibleOrBefore {
t.Error("ProcessGlyph returned false for visible glyph")
}
if !it.Visible {
t.Error("glyph should be marked visible")
}
if !it.First {
t.Error("First should be true after first glyph")
}
}
func TestGlyphIteratorProcessGlyphOutsideViewport(t *testing.T) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(100, 100)},
MaxLines: 0,
}
// Create a glyph below the viewport
g := text.Glyph{
X: fixed.I(10),
Y: 200, // Below viewport
Advance: fixed.I(10),
Ascent: fixed.I(12),
Descent: fixed.I(4),
Bounds: fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(0), Y: fixed.I(-12)},
Max: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(4)},
},
}
visibleOrBefore := it.ProcessGlyph(g, true)
// Should return false because glyph is below viewport
if visibleOrBefore {
t.Error("ProcessGlyph should return false for glyph below viewport")
}
if it.Visible {
t.Error("glyph below viewport should not be marked visible")
}
}
func TestGlyphIteratorMaxLines(t *testing.T) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(100, 100)},
MaxLines: 2,
}
// Simulate two line breaks
g := text.Glyph{
X: fixed.I(10),
Y: 10,
Advance: fixed.I(10),
Ascent: fixed.I(12),
Descent: fixed.I(4),
Flags: text.FlagLineBreak,
Bounds: fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(0), Y: fixed.I(-12)},
Max: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(4)},
},
}
// First line break
it.ProcessGlyph(g, true)
if it.LinesSeen != 1 {
t.Errorf("LinesSeen = %d after first line break, want 1", it.LinesSeen)
}
// Second line break
it.ProcessGlyph(g, true)
if it.LinesSeen != 2 {
t.Errorf("LinesSeen = %d after second line break, want 2", it.LinesSeen)
}
}
func TestGlyphIteratorBoundsAccumulation(t *testing.T) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(200, 200)},
MaxLines: 0,
}
// Process multiple glyphs and check bounds accumulate
glyphs := []text.Glyph{
{X: fixed.I(0), Y: 10, Advance: fixed.I(10), Ascent: fixed.I(8), Descent: fixed.I(2)},
{X: fixed.I(10), Y: 10, Advance: fixed.I(10), Ascent: fixed.I(8), Descent: fixed.I(2)},
{X: fixed.I(20), Y: 10, Advance: fixed.I(10), Ascent: fixed.I(8), Descent: fixed.I(2)},
}
for i, g := range glyphs {
g.Bounds = fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(0), Y: fixed.I(-8)},
Max: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(2)},
}
it.ProcessGlyph(g, true)
if i == 0 && !it.First {
t.Error("First should be true after processing first glyph")
}
}
// Bounds should encompass all glyphs
if it.Bounds.Max.X < 30 {
t.Errorf("Bounds.Max.X = %d, should be >= 30", it.Bounds.Max.X)
}
}
func TestGlyphIteratorPaddingCalculation(t *testing.T) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(100, 100)},
MaxLines: 0,
}
g := text.Glyph{
X: fixed.I(10),
Y: 20,
Advance: fixed.I(10),
Ascent: fixed.I(12),
Descent: fixed.I(4),
Bounds: fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(-2), Y: fixed.I(-14)}, // Extends left and above
Max: fixed.Point26_6{X: fixed.I(12), Y: fixed.I(6)}, // Extends right and below
},
}
it.ProcessGlyph(g, true)
// Padding should capture the glyph bounds that extend beyond advance/metrics
if it.Padding.Min.X >= 0 {
t.Errorf("Padding.Min.X = %d, expected negative for left extension", it.Padding.Min.X)
}
}
func BenchmarkGlyphIteratorProcessGlyph(b *testing.B) {
it := &GlyphIterator{
Viewport: image.Rectangle{Max: image.Pt(1000, 1000)},
MaxLines: 0,
}
g := text.Glyph{
X: fixed.I(10),
Y: 20,
Advance: fixed.I(10),
Ascent: fixed.I(12),
Descent: fixed.I(4),
Bounds: fixed.Rectangle26_6{
Min: fixed.Point26_6{X: fixed.I(0), Y: fixed.I(-12)},
Max: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(4)},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
it.ProcessGlyph(g, true)
}
}