1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-04 07:37:48 -05:00
OpenDiablo2/d2core/d2bitmapfont/bitmap_font.go
gravestench deb63a95c8 changes to d2components, d2systems, d2ui, d2enum
go.mod, go.sum:
* updating akara, bugfix in akara.EntityManager.RemoveEntity

d2core
* adding d2core/d2label
* adding d2core/d2bitmapfont

d2ui
* exporting some constants for use elsewhere

d2components
* added bitmap font component (for ui labels)
* added FileLoaded tag component to simplify asset loading filters
* added locale component
* FilePath component renamed to File
* sprite component now contains the sprite and palette path as strings
* adding ui label component

d2enum
* added locale as file type for file "/data/local/use"

d2systems
* changed most info prints to debug prints
* removed unused scene graph testing file (oops!)
* terminal is now rendered above mouse cursor scene
* adding ui widget system for use by the game object factory
* adding test scene for ui labels created with the ui widget system

d2systems/AppBootstrap
* added command line args for profiler
* `--testscene labels` launches the label test
* now adds the local file for processing
* game loop init logic now inside of Init method (the call to
world.Update does this)

d2systems/AssetLoader
* loads the locale file and adds a locale component that other systems
can use
* adds a FileLoaded component after finished loading a file which other
systems can use (like the loading scene)

d2systems/FileSourceResolver
* Now looks for and uses the locale for language/charset filepath
substitution

d2systems/GameClientBootstrap
* game loop init moved to end of AppBootstrap.Init

d2systems/GameObjectFactory
* embedding UI widget factory system

d2systems/BaseScene
* made base scene a little more clear by breaking the process into more
methods

d2systems/LoadingScene
* simplified the entity subscriptions by using the new FileLoaded
component

d2systems/SceneObjectFactory
* adding method for adding labels, buttons to scenes (buttons still WIP)

d2systems/SceneSpriteSystem
* the sprite system now maintains a cache of rendered sprites
2020-12-08 11:24:10 -08:00

129 lines
2.5 KiB
Go

package d2bitmapfont
import (
"encoding/binary"
"image/color"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
)
func New(s d2interface.Sprite, table []byte, col color.Color) *BitmapFont {
return &BitmapFont{
Sprite: s,
Table: table,
Color: col,
}
}
type Glyph struct {
frame int
width int
height int
}
// BitmapFont represents a rasterized font, made from a font Table, sprite, and palette
type BitmapFont struct {
Sprite d2interface.Sprite
Table []byte
Glyphs map[rune]Glyph
Color color.Color
}
// SetColor sets the fonts Color
func (f *BitmapFont) SetColor(c color.Color) {
f.Color = c
}
// GetTextMetrics returns the dimensions of the BitmapFont element in pixels
func (f *BitmapFont) GetTextMetrics(text string) (width, height int) {
if f.Glyphs == nil {
f.initGlyphs()
}
var (
lineWidth int
lineHeight int
)
for _, c := range text {
if c == '\n' {
width = d2math.MaxInt(width, lineWidth)
height += lineHeight
lineWidth = 0
lineHeight = 0
} else if glyph, ok := f.Glyphs[c]; ok {
lineWidth += glyph.width
lineHeight = d2math.MaxInt(lineHeight, glyph.height)
}
}
width = d2math.MaxInt(width, lineWidth)
height += lineHeight
return width, height
}
// RenderText prints a text using its configured style on a Surface (multi-lines are left-aligned, use label otherwise)
func (f *BitmapFont) RenderText(text string, target d2interface.Surface) error {
if f.Glyphs == nil {
f.initGlyphs()
}
f.Sprite.SetColorMod(f.Color)
lines := strings.Split(text, "\n")
for _, line := range lines {
var (
lineHeight int
lineLength int
)
for _, c := range line {
glyph, ok := f.Glyphs[c]
if !ok {
continue
}
if err := f.Sprite.SetCurrentFrame(glyph.frame); err != nil {
return err
}
f.Sprite.Render(target)
lineHeight = d2math.MaxInt(lineHeight, glyph.height)
lineLength++
target.PushTranslation(glyph.width, 0)
}
target.PopN(lineLength)
target.PushTranslation(0, lineHeight)
}
target.PopN(len(lines))
return nil
}
func (f *BitmapFont) initGlyphs() {
_, maxCharHeight := f.Sprite.GetFrameBounds()
glyphs := make(map[rune]Glyph)
for i := 12; i < len(f.Table); i += 14 {
code := rune(binary.LittleEndian.Uint16(f.Table[i : i+2]))
var glyph Glyph
glyph.frame = int(binary.LittleEndian.Uint16(f.Table[i+8 : i+10]))
glyph.width = int(f.Table[i+3])
glyph.height = maxCharHeight
glyphs[code] = glyph
}
f.Glyphs = glyphs
}