diff --git a/examples/text/main.go b/examples/text/main.go index 9f66643db..2bbcb92d6 100644 --- a/examples/text/main.go +++ b/examples/text/main.go @@ -61,15 +61,15 @@ type Game struct { counter int kanjiText []rune kanjiTextColor color.RGBA - clusters []text.Cluster + glyphs []text.Glyph } func (g *Game) Update() error { // Initialize the glyphs for special (colorful) rendering. - if len(g.clusters) == 0 { + if len(g.glyphs) == 0 { op := &text.LayoutOptions{} op.LineSpacingInPixels = mplusNormalFace.Size * 1.5 - g.clusters = text.AppendClusters(g.clusters, sampleText, mplusNormalFace, op) + g.glyphs = text.AppendGlyphs(g.glyphs, sampleText, mplusNormalFace, op) } return nil } @@ -121,16 +121,13 @@ func (g *Game) Draw(screen *ebiten.Image) { { const x, y = 240, 360 op := &ebiten.DrawImageOptions{} - // g.glyphs is initialized by text.AppendClusters + // g.glyphs is initialized by text.AppendGlyphs. // You can customize how to render each glyph. // In this example, multiple colors are used to render glyphs. - for i, c := range g.clusters { - if c.Image == nil { - continue - } + for i, gl := range g.glyphs { op.GeoM.Reset() op.GeoM.Translate(x, y) - op.GeoM.Translate(c.X, c.Y) + op.GeoM.Translate(gl.X, gl.Y) op.ColorScale.Reset() r := float32(1) if i%3 == 0 { @@ -145,7 +142,7 @@ func (g *Game) Draw(screen *ebiten.Image) { b = 0.5 } op.ColorScale.Scale(r, g, b, 1) - screen.DrawImage(c.Image, op) + screen.DrawImage(gl.Image, op) } } } diff --git a/text/v2/gotext.go b/text/v2/gotext.go index 438d83272..9e709d069 100644 --- a/text/v2/gotext.go +++ b/text/v2/gotext.go @@ -291,8 +291,8 @@ func (g *GoTextFace) hasGlyph(r rune) bool { return ok } -// appendClustersForLine implements Face. -func (g *GoTextFace) appendClustersForLine(clusters []Cluster, line string, indexOffset int, originX, originY float64) []Cluster { +// appendGlyphsForLine implements Face. +func (g *GoTextFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph { origin := fixed.Point26_6{ X: float64ToFixed26_6(originX), Y: float64ToFixed26_6(originY), @@ -300,23 +300,23 @@ func (g *GoTextFace) appendClustersForLine(clusters []Cluster, line string, inde _, gs := g.Source.shape(line, g) for _, glyph := range gs { img, imgX, imgY := g.glyphImage(glyph, origin) - // Append a glyph even if img is nil. - // This is necessary to return index information for control characters. - clusters = append(clusters, Cluster{ - StartIndexInBytes: indexOffset + glyph.startIndex, - EndIndexInBytes: indexOffset + glyph.endIndex, - GID: uint32(glyph.shapingGlyph.GlyphID), - Image: img, - X: float64(imgX), - Y: float64(imgY), - }) + if img != nil { + glyphs = append(glyphs, Glyph{ + StartIndexInBytes: indexOffset + glyph.startIndex, + EndIndexInBytes: indexOffset + glyph.endIndex, + GID: uint32(glyph.shapingGlyph.GlyphID), + Image: img, + X: float64(imgX), + Y: float64(imgY), + }) + } origin = origin.Add(fixed.Point26_6{ X: glyph.shapingGlyph.XAdvance, Y: -glyph.shapingGlyph.YAdvance, }) } - return clusters + return glyphs } func (g *GoTextFace) glyphImage(glyph glyph, origin fixed.Point26_6) (*ebiten.Image, int, int) { diff --git a/text/v2/layout.go b/text/v2/layout.go index 90b71b9d1..eeb251864 100644 --- a/text/v2/layout.go +++ b/text/v2/layout.go @@ -105,10 +105,7 @@ func Draw(dst *ebiten.Image, text string, face Face, options *DrawOptions) { } geoM := options.GeoM - for _, g := range AppendClusters(nil, text, face, &options.LayoutOptions) { - if g.Image == nil { - continue - } + for _, g := range AppendGlyphs(nil, text, face, &options.LayoutOptions) { op := &options.DrawImageOptions op.GeoM.Reset() op.GeoM.Translate(g.X, g.Y) @@ -117,16 +114,16 @@ func Draw(dst *ebiten.Image, text string, face Face, options *DrawOptions) { } } -// AppendClusters appends glyphs to the given slice and returns a slice. +// AppendGlyphs appends glyphs to the given slice and returns a slice. // -// AppendClusters is a low-level API, and you can use AppendClusters to have more control than Draw. -// AppendClusters is also available to precache glyphs. +// AppendGlyphs is a low-level API, and you can use AppendGlyphs to have more control than Draw. +// AppendGlyphs is also available to precache glyphs. // // For the details of options, see Draw function. // -// AppendClusters is concurrent-safe. -func AppendClusters(glyphs []Cluster, text string, face Face, options *LayoutOptions) []Cluster { - return appendClusters(glyphs, text, face, 0, 0, options) +// AppendGlyphs is concurrent-safe. +func AppendGlyphs(glyphs []Glyph, text string, face Face, options *LayoutOptions) []Glyph { + return appendGlyphs(glyphs, text, face, 0, 0, options) } // AppndVectorPath appends a vector path for glyphs to the given path. @@ -139,13 +136,13 @@ func AppendVectorPath(path *vector.Path, text string, face Face, options *Layout }) } -// appendClusters appends glyphs to the given slice and returns a slice. +// appendGlyphs appends glyphs to the given slice and returns a slice. // -// appendClusters assumes the text is rendered with the position (x, y). +// appendGlyphs assumes the text is rendered with the position (x, y). // (x, y) might affect the subpixel rendering results. -func appendClusters(glyphs []Cluster, text string, face Face, x, y float64, options *LayoutOptions) []Cluster { +func appendGlyphs(glyphs []Glyph, text string, face Face, x, y float64, options *LayoutOptions) []Glyph { forEachLine(text, face, options, func(line string, indexOffset int, originX, originY float64) { - glyphs = face.appendClustersForLine(glyphs, line, indexOffset, originX+x, originY+y) + glyphs = face.appendGlyphsForLine(glyphs, line, indexOffset, originX+x, originY+y) }) return glyphs } diff --git a/text/v2/limited.go b/text/v2/limited.go index e75bc4209..cefeb9c27 100644 --- a/text/v2/limited.go +++ b/text/v2/limited.go @@ -55,9 +55,9 @@ func (l *LimitedFace) hasGlyph(r rune) bool { return l.unicodeRanges.contains(r) && l.face.hasGlyph(r) } -// appendClustersForLine implements Face. -func (l *LimitedFace) appendClustersForLine(clusters []Cluster, line string, indexOffset int, originX, originY float64) []Cluster { - return l.face.appendClustersForLine(clusters, l.unicodeRanges.filter(line), indexOffset, originX, originY) +// appendGlyphsForLine implements Face. +func (l *LimitedFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph { + return l.face.appendGlyphsForLine(glyphs, l.unicodeRanges.filter(line), indexOffset, originX, originY) } // appendVectorPathForLine implements Face. diff --git a/text/v2/multi.go b/text/v2/multi.go index 32db63c80..92d517c29 100644 --- a/text/v2/multi.go +++ b/text/v2/multi.go @@ -102,15 +102,15 @@ func (m *MultiFace) hasGlyph(r rune) bool { return false } -// appendClustersForLine implements Face. -func (m *MultiFace) appendClustersForLine(clusters []Cluster, line string, indexOffset int, originX, originY float64) []Cluster { +// appendGlyphsForLine implements Face. +func (m *MultiFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph { for _, c := range m.splitText(line) { if c.faceIndex == -1 { continue } f := m.faces[c.faceIndex] t := line[c.textStartIndex:c.textEndIndex] - clusters = f.appendClustersForLine(clusters, t, indexOffset, originX, originY) + glyphs = f.appendGlyphsForLine(glyphs, t, indexOffset, originX, originY) if a := f.advance(t); f.direction().isHorizontal() { originX += a } else { @@ -118,7 +118,7 @@ func (m *MultiFace) appendClustersForLine(clusters []Cluster, line string, index } indexOffset += len(t) } - return clusters + return glyphs } // appendVectorPathForLine implements Face. diff --git a/text/v2/std.go b/text/v2/std.go index 4f1f46f93..46cfaeded 100644 --- a/text/v2/std.go +++ b/text/v2/std.go @@ -93,8 +93,8 @@ func (s *StdFace) hasGlyph(r rune) bool { return ok } -// appendClustersForLine implements Face. -func (s *StdFace) appendClustersForLine(clusters []Cluster, line string, indexOffset int, originX, originY float64) []Cluster { +// appendGlyphsForLine implements Face. +func (s *StdFace) appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph { s.copyCheck() origin := fixed.Point26_6{ @@ -108,25 +108,23 @@ func (s *StdFace) appendClustersForLine(clusters []Cluster, line string, indexOf origin.X += s.f.Kern(prevR, r) } img, imgX, imgY, a := s.glyphImage(r, origin) - - // Adjust the position to the integers. - // The current glyph images assume that they are rendered on integer positions so far. - _, size := utf8.DecodeRuneInString(line[i:]) - - // Append a glyph even if img is nil. - // This is necessary to return index information for control characters. - clusters = append(clusters, Cluster{ - StartIndexInBytes: indexOffset + i, - EndIndexInBytes: indexOffset + i + size, - Image: img, - X: float64(imgX), - Y: float64(imgY), - }) + if img != nil { + // Adjust the position to the integers. + // The current glyph images assume that they are rendered on integer positions so far. + _, size := utf8.DecodeRuneInString(line[i:]) + glyphs = append(glyphs, Glyph{ + StartIndexInBytes: indexOffset + i, + EndIndexInBytes: indexOffset + i + size, + Image: img, + X: float64(imgX), + Y: float64(imgY), + }) + } origin.X += a prevR = r } - return clusters + return glyphs } func (s *StdFace) glyphImage(r rune, origin fixed.Point26_6) (*ebiten.Image, int, int, fixed.Int26_6) { diff --git a/text/v2/text.go b/text/v2/text.go index 21512e1fa..9d133435b 100644 --- a/text/v2/text.go +++ b/text/v2/text.go @@ -36,7 +36,7 @@ type Face interface { hasGlyph(r rune) bool - appendClustersForLine(glyphs []Cluster, line string, indexOffset int, originX, originY float64) []Cluster + appendGlyphsForLine(glyphs []Glyph, line string, indexOffset int, originX, originY float64) []Glyph appendVectorPathForLine(path *vector.Path, line string, originX, originY float64) direction() Direction @@ -117,12 +117,12 @@ func adjustGranularity(x fixed.Int26_6, face Face) fixed.Int26_6 { return x / factor * factor } -// Cluster represents one grapheme cluster. -type Cluster struct { - // StartIndexInBytes is the start index in bytes for the given string at AppendClusters. +// Glyph represents one glyph to render. +type Glyph struct { + // StartIndexInBytes is the start index in bytes for the given string at AppendGlyphs. StartIndexInBytes int - // EndIndexInBytes is the end index in bytes for the given string at AppendClusters. + // EndIndexInBytes is the end index in bytes for the given string at AppendGlyphs. EndIndexInBytes int // GID is an ID for a glyph of TrueType or OpenType font. GID is valid when the face is GoTextFace. @@ -134,12 +134,12 @@ type Cluster struct { Image *ebiten.Image // X is the X position to render this glyph. - // The position is determined in a sequence of characters given at AppendClusters. + // The position is determined in a sequence of characters given at AppendGlyphs. // The position's origin is the first character's origin position. X float64 // Y is the Y position to render this glyph. - // The position is determined in a sequence of characters given at AppendClusters. + // The position is determined in a sequence of characters given at AppendGlyphs. // The position's origin is the first character's origin position. Y float64 } @@ -245,10 +245,10 @@ func CacheGlyphs(text string, face Face) { c := glyphVariationCount(face) - var buf []Cluster + var buf []Glyph // Create all the possible variations (#2528). for i := 0; i < c; i++ { - buf = appendClusters(buf, text, face, x, y, nil) + buf = appendGlyphs(buf, text, face, x, y, nil) buf = buf[:0] if face.direction().isHorizontal() { diff --git a/text/v2/text_test.go b/text/v2/text_test.go index 0de32e4fd..01e123d62 100644 --- a/text/v2/text_test.go +++ b/text/v2/text_test.go @@ -40,7 +40,7 @@ over the lazy dog.` f := text.NewStdFace(bitmapfont.Face) got := sampleText - for _, g := range text.AppendClusters(nil, sampleText, f, nil) { + for _, g := range text.AppendGlyphs(nil, sampleText, f, nil) { got = got[:g.StartIndexInBytes] + strings.Repeat(" ", g.EndIndexInBytes-g.StartIndexInBytes) + got[g.EndIndexInBytes:] } want := regexp.MustCompile(`\S`).ReplaceAllString(sampleText, " ")