mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-04 15:04:28 +01:00
text: Add MeasureString method (#1152)
(sorta-kinda continuation from #1151) This PR adds a MeasureString(string, font.Face) method next to the Draw() method in Ebiten's text package. It should work with any supported font.Face, even "non-standard" faces like those produced by packages like https://github.com/AndreKR/multiface. MeasureString's code was adapted from the Draw method, so it's just as reliable.
This commit is contained in:
parent
a3105d6fca
commit
abc2801ff1
65
text/text.go
65
text/text.go
@ -39,7 +39,7 @@ func now() 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 >> 6) + float64(x & ((1 << 6) - 1)) / float64(1 << 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -273,10 +273,13 @@ func colorToColorM(clr color.Color) ebiten.ColorM {
|
|||||||
// Draw is concurrent-safe.
|
// Draw is concurrent-safe.
|
||||||
func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Color) {
|
func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Color) {
|
||||||
textM.Lock()
|
textM.Lock()
|
||||||
|
defer textM.Unlock()
|
||||||
|
|
||||||
fx, fy := fixed.I(x), fixed.I(y)
|
fx, fy := fixed.I(x), fixed.I(y)
|
||||||
prevR := rune(-1)
|
prevR := rune(-1)
|
||||||
|
|
||||||
|
faceHeight := face.Metrics().Height
|
||||||
|
|
||||||
runes := []rune(text)
|
runes := []rune(text)
|
||||||
glyphImgs := getGlyphImages(face, runes)
|
glyphImgs := getGlyphImages(face, runes)
|
||||||
colorm := colorToColorM(clr)
|
colorm := colorToColorM(clr)
|
||||||
@ -287,7 +290,7 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
|||||||
}
|
}
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
fx = fixed.I(x)
|
fx = fixed.I(x)
|
||||||
fy += face.Metrics().Height
|
fy += faceHeight
|
||||||
prevR = rune(-1)
|
prevR = rune(-1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -297,6 +300,60 @@ func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Co
|
|||||||
|
|
||||||
prevR = r
|
prevR = r
|
||||||
}
|
}
|
||||||
|
}
|
||||||
textM.Unlock()
|
|
||||||
|
// MeasureString returns the measured size of a given string using a given font.
|
||||||
|
// This method will return the exact size in pixels that a string drawn by Draw will be.
|
||||||
|
//
|
||||||
|
// text is the string that's being measured.
|
||||||
|
// face is the font for text rendering.
|
||||||
|
//
|
||||||
|
// Be careful that the passed font face is held by this package and is never released.
|
||||||
|
// This is a known issue (#498).
|
||||||
|
//
|
||||||
|
// MeasureString is concurrent-safe.
|
||||||
|
func MeasureString(text string, face font.Face) image.Point {
|
||||||
|
textM.Lock()
|
||||||
|
defer textM.Unlock()
|
||||||
|
|
||||||
|
var w, h fixed.Int26_6
|
||||||
|
|
||||||
|
m := face.Metrics()
|
||||||
|
faceHeight := m.Height
|
||||||
|
faceDescent := m.Descent
|
||||||
|
|
||||||
|
fx, fy := fixed.I(0), fixed.I(0)
|
||||||
|
prevR := rune(-1)
|
||||||
|
|
||||||
|
runes := []rune(text)
|
||||||
|
|
||||||
|
for _, r := range runes {
|
||||||
|
if prevR >= 0 {
|
||||||
|
fx += face.Kern(prevR, r)
|
||||||
|
}
|
||||||
|
if r == '\n' {
|
||||||
|
fx = fixed.I(0)
|
||||||
|
fy += faceHeight
|
||||||
|
prevR = rune(-1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fx += glyphAdvance(face, r)
|
||||||
|
|
||||||
|
if fx > w {
|
||||||
|
w = fx
|
||||||
|
}
|
||||||
|
if (fy+faceHeight) > h {
|
||||||
|
h = fy+faceHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
prevR = r
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds := image.Point{
|
||||||
|
X: int(math.Ceil(fixed26_6ToFloat64(w))),
|
||||||
|
Y: int(math.Ceil(fixed26_6ToFloat64(h+faceDescent))),
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user