107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
package tins2021
|
|
|
|
import (
|
|
"image/color"
|
|
|
|
"opslag.de/schobers/geom"
|
|
"opslag.de/schobers/zntg/ui"
|
|
)
|
|
|
|
type BitmapFont struct {
|
|
texture ui.Texture
|
|
height float32
|
|
runes map[rune]*geom.RectangleF32
|
|
}
|
|
|
|
var AllCharacters = []rune(`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ,.?!;:+-=_()[]{}"'@#$%^&*<>\/`)
|
|
var AlphaCharacters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
|
|
var LowerCaseAlphaCharacters = []rune("abcdefghijklmnopqrstuvwxyz")
|
|
var NumericCharacters = []rune("0123456789")
|
|
var SpecialCharacters = []rune(` ,.?!;:+-=_()[]{}"'@#$%^&*<>\/`)
|
|
var UpperCaseAlphaCharacters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
func NewBitmapFont(renderer ui.Renderer, font ui.Font, set ...rune) (*BitmapFont, error) {
|
|
texture, err := renderer.TextTexture(font, color.White, string(set))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
runes := map[rune]*geom.RectangleF32{}
|
|
height := float32(texture.Height())
|
|
var left float32
|
|
for _, r := range set {
|
|
width := font.WidthOf(string([]rune{r}))
|
|
right := left + width
|
|
rect := geom.RectF32(left, 0, right, height)
|
|
runes[r] = &rect
|
|
left = right
|
|
}
|
|
return &BitmapFont{texture, font.Height(), runes}, nil
|
|
}
|
|
|
|
func (f *BitmapFont) Destroy() error { return f.texture.Destroy() }
|
|
func (f *BitmapFont) Height() float32 { return f.height }
|
|
|
|
func (f *BitmapFont) Measure(t string) geom.RectangleF32 {
|
|
if len(t) == 0 {
|
|
return geom.RectF32(0, 0, 0, 0)
|
|
}
|
|
var minY, maxY float32
|
|
var width float32
|
|
var first int
|
|
for i, r := range t {
|
|
rect := f.runes[r]
|
|
if rect == nil {
|
|
continue
|
|
}
|
|
width = rect.Dx()
|
|
minY, maxY = rect.Min.Y, rect.Max.Y
|
|
first = i
|
|
break
|
|
}
|
|
for _, r := range t[first+1:] {
|
|
rect := f.runes[r]
|
|
if rect == nil {
|
|
continue
|
|
}
|
|
width += rect.Dx()
|
|
if minY > rect.Min.Y {
|
|
minY = rect.Min.Y
|
|
}
|
|
if maxY < rect.Max.Y {
|
|
maxY = rect.Max.Y
|
|
}
|
|
}
|
|
return geom.RectF32(0, minY, width, maxY)
|
|
}
|
|
|
|
func (f *BitmapFont) Text(renderer ui.Renderer, pos geom.PointF32, color color.Color, text string) {
|
|
f.text(renderer, pos.X, pos.Y, color, text)
|
|
}
|
|
|
|
func (f *BitmapFont) TextAlign(renderer ui.Renderer, pos geom.PointF32, color color.Color, text string, align ui.HorizontalAlignment) {
|
|
left := pos.X
|
|
width := f.WidthOf(text)
|
|
switch align {
|
|
case ui.AlignCenter:
|
|
left -= .5 * width
|
|
case ui.AlignRight:
|
|
left -= width
|
|
}
|
|
f.text(renderer, left, pos.Y, color, text)
|
|
}
|
|
|
|
func (f *BitmapFont) text(renderer ui.Renderer, left, top float32, color color.Color, text string) {
|
|
for _, r := range text {
|
|
src := f.runes[r]
|
|
if src == nil {
|
|
continue
|
|
}
|
|
renderer.DrawTexturePointOptions(f.texture, geom.PtF32(left, top), ui.DrawOptions{Tint: color, Source: src})
|
|
left += src.Dx()
|
|
}
|
|
}
|
|
|
|
func (f *BitmapFont) WidthOf(t string) float32 {
|
|
return f.Measure(t).Dx()
|
|
}
|