mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
text: Refactoring
This commit is contained in:
parent
9efc794547
commit
86296ea89b
64
text/text.go
64
text/text.go
@ -39,29 +39,36 @@ func now() int64 {
|
|||||||
return monotonicClock
|
return monotonicClock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
charBounds = map[char]fixed.Rectangle26_6{}
|
||||||
|
)
|
||||||
|
|
||||||
type char struct {
|
type char struct {
|
||||||
face font.Face
|
face font.Face
|
||||||
rune rune
|
rune rune
|
||||||
}
|
}
|
||||||
|
|
||||||
type glyph struct {
|
func (c *char) bounds() fixed.Rectangle26_6 {
|
||||||
char char
|
if b, ok := charBounds[*c]; ok {
|
||||||
index int
|
return b
|
||||||
bounds fixed.Rectangle26_6
|
}
|
||||||
atime int64
|
b, _, _ := c.face.GlyphBounds(c.rune)
|
||||||
|
charBounds[*c] = b
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *glyph) size() fixed.Point26_6 {
|
func (c *char) size() fixed.Point26_6 {
|
||||||
return g.bounds.Max.Sub(g.bounds.Min)
|
b := c.bounds()
|
||||||
|
return b.Max.Sub(b.Min)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *glyph) empty() bool {
|
func (c *char) empty() bool {
|
||||||
s := g.size()
|
s := c.size()
|
||||||
return s.X == 0 || s.Y == 0
|
return s.X == 0 || s.Y == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *glyph) atlasGroup() int {
|
func (c *char) atlasGroup() int {
|
||||||
s := g.size()
|
s := c.size()
|
||||||
w, h := s.X.Ceil(), s.Y.Ceil()
|
w, h := s.X.Ceil(), s.Y.Ceil()
|
||||||
t := w
|
t := w
|
||||||
if t < h {
|
if t < h {
|
||||||
@ -76,6 +83,12 @@ func (g *glyph) atlasGroup() int {
|
|||||||
return graphics.NextPowerOf2Int(t)
|
return graphics.NextPowerOf2Int(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type glyph struct {
|
||||||
|
char char
|
||||||
|
index int
|
||||||
|
atime int64
|
||||||
|
}
|
||||||
|
|
||||||
func fixed26_6ToFloat64(x fixed.Int26_6) float64 {
|
func fixed26_6ToFloat64(x fixed.Int26_6) float64 {
|
||||||
return float64(x) / (1 << 6)
|
return float64(x) / (1 << 6)
|
||||||
}
|
}
|
||||||
@ -86,9 +99,10 @@ func (g *glyph) draw(dst *ebiten.Image, x, y fixed.Int26_6, clr color.Color) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b := g.char.bounds()
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(fixed26_6ToFloat64(x), fixed26_6ToFloat64(y))
|
op.GeoM.Translate(fixed26_6ToFloat64(x), fixed26_6ToFloat64(y))
|
||||||
op.GeoM.Translate(fixed26_6ToFloat64(g.bounds.Min.X), fixed26_6ToFloat64(g.bounds.Min.Y))
|
op.GeoM.Translate(fixed26_6ToFloat64(b.Min.X), fixed26_6ToFloat64(b.Min.Y))
|
||||||
|
|
||||||
rf := float64(cr) / float64(ca)
|
rf := float64(cr) / float64(ca)
|
||||||
gf := float64(cg) / float64(ca)
|
gf := float64(cg) / float64(ca)
|
||||||
@ -96,7 +110,7 @@ func (g *glyph) draw(dst *ebiten.Image, x, y fixed.Int26_6, clr color.Color) {
|
|||||||
af := float64(ca) / 0xffff
|
af := float64(ca) / 0xffff
|
||||||
op.ColorM.Scale(rf, gf, bf, af)
|
op.ColorM.Scale(rf, gf, bf, af)
|
||||||
|
|
||||||
a := atlases[g.atlasGroup()]
|
a := atlases[g.char.atlasGroup()]
|
||||||
sx, sy := a.at(g)
|
sx, sy := a.at(g)
|
||||||
r := image.Rect(sx, sy, sx+a.size, sy+a.size)
|
r := image.Rect(sx, sy, sx+a.size, sy+a.size)
|
||||||
op.SourceRect = &r
|
op.SourceRect = &r
|
||||||
@ -128,7 +142,7 @@ type atlas struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *atlas) at(glyph *glyph) (int, int) {
|
func (a *atlas) at(glyph *glyph) (int, int) {
|
||||||
if a.size != glyph.atlasGroup() {
|
if a.size != glyph.char.atlasGroup() {
|
||||||
panic("not reached")
|
panic("not reached")
|
||||||
}
|
}
|
||||||
w, _ := a.image.Size()
|
w, _ := a.image.Size()
|
||||||
@ -185,7 +199,8 @@ func (a *atlas) draw(glyph *glyph) {
|
|||||||
Src: image.White,
|
Src: image.White,
|
||||||
Face: glyph.char.face,
|
Face: glyph.char.face,
|
||||||
}
|
}
|
||||||
d.Dot = fixed.Point26_6{-glyph.bounds.Min.X, -glyph.bounds.Min.Y}
|
b := glyph.char.bounds()
|
||||||
|
d.Dot = fixed.Point26_6{-b.Min.X, -b.Min.Y}
|
||||||
d.DrawString(string(glyph.char.rune))
|
d.DrawString(string(glyph.char.rune))
|
||||||
a.tmpImage.ReplacePixels(dst.Pix)
|
a.tmpImage.ReplacePixels(dst.Pix)
|
||||||
|
|
||||||
@ -206,20 +221,15 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
|
|||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _, ok := face.GlyphBounds(r)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
g = &glyph{
|
g = &glyph{
|
||||||
char: ch,
|
char: ch,
|
||||||
bounds: b,
|
atime: now,
|
||||||
atime: now,
|
|
||||||
}
|
}
|
||||||
if g.empty() {
|
if ch.empty() {
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
a, ok := atlases[g.atlasGroup()]
|
a, ok := atlases[g.char.atlasGroup()]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Don't use ebiten.MaxImageSize here.
|
// Don't use ebiten.MaxImageSize here.
|
||||||
// It's because the back-end image pixels will be restored from GPU
|
// It's because the back-end image pixels will be restored from GPU
|
||||||
@ -235,13 +245,13 @@ func getGlyphFromCache(face font.Face, r rune, now int64) *glyph {
|
|||||||
i, _ := ebiten.NewImage(size, size, ebiten.FilterNearest)
|
i, _ := ebiten.NewImage(size, size, ebiten.FilterNearest)
|
||||||
a = &atlas{
|
a = &atlas{
|
||||||
image: i,
|
image: i,
|
||||||
size: g.atlasGroup(),
|
size: g.char.atlasGroup(),
|
||||||
}
|
}
|
||||||
w, h := a.image.Size()
|
w, h := a.image.Size()
|
||||||
xnum := w / a.size
|
xnum := w / a.size
|
||||||
ynum := h / a.size
|
ynum := h / a.size
|
||||||
a.glyphs = make([]*glyph, xnum*ynum)
|
a.glyphs = make([]*glyph, xnum*ynum)
|
||||||
atlases[g.atlasGroup()] = a
|
atlases[g.char.atlasGroup()] = a
|
||||||
}
|
}
|
||||||
|
|
||||||
a.append(g)
|
a.append(g)
|
||||||
@ -274,7 +284,7 @@ func Draw(dst *ebiten.Image, face font.Face, text string, x, y int, clr color.Co
|
|||||||
fx += face.Kern(prevC, c)
|
fx += face.Kern(prevC, c)
|
||||||
}
|
}
|
||||||
if g := getGlyphFromCache(face, c, n); g != nil {
|
if g := getGlyphFromCache(face, c, n); g != nil {
|
||||||
if !g.empty() {
|
if !g.char.empty() {
|
||||||
g.draw(dst, fx, fixed.I(y), clr)
|
g.draw(dst, fx, fixed.I(y), clr)
|
||||||
}
|
}
|
||||||
a, _ := face.GlyphAdvance(c)
|
a, _ := face.GlyphAdvance(c)
|
||||||
|
Loading…
Reference in New Issue
Block a user