load font at new size on demand
This commit is contained in:
parent
23d0b4499a
commit
acebca9739
1 changed files with 46 additions and 60 deletions
|
|
@ -76,6 +76,8 @@ type Ruler struct {
|
||||||
|
|
||||||
atlases map[d2fonts.Font]*atlas
|
atlases map[d2fonts.Font]*atlas
|
||||||
|
|
||||||
|
ttfs map[d2fonts.Font]*truetype.Font
|
||||||
|
|
||||||
buf []byte
|
buf []byte
|
||||||
prevR rune
|
prevR rune
|
||||||
bounds *rect
|
bounds *rect
|
||||||
|
|
@ -97,84 +99,68 @@ type Ruler struct {
|
||||||
// })
|
// })
|
||||||
// txt := text.New(orig, text.NewAtlas(face, text.ASCII))
|
// txt := text.New(orig, text.NewAtlas(face, text.ASCII))
|
||||||
func NewRuler() (*Ruler, error) {
|
func NewRuler() (*Ruler, error) {
|
||||||
lineHeights := make(map[d2fonts.Font]float64)
|
origin := geo.NewPoint(0, 0)
|
||||||
tabWidths := make(map[d2fonts.Font]float64)
|
r := &Ruler{
|
||||||
atlases := make(map[d2fonts.Font]*atlas)
|
Orig: origin,
|
||||||
|
Dot: origin.Copy(),
|
||||||
|
LineHeightFactor: 1.,
|
||||||
|
lineHeights: make(map[d2fonts.Font]float64),
|
||||||
|
tabWidths: make(map[d2fonts.Font]float64),
|
||||||
|
atlases: make(map[d2fonts.Font]*atlas),
|
||||||
|
ttfs: make(map[d2fonts.Font]*truetype.Font),
|
||||||
|
}
|
||||||
|
|
||||||
for _, fontFamily := range d2fonts.FontFamilies {
|
for _, fontFamily := range d2fonts.FontFamilies {
|
||||||
for _, fontSize := range d2fonts.FontSizes {
|
for _, fontStyle := range d2fonts.FontStyles {
|
||||||
for _, fontStyle := range d2fonts.FontStyles {
|
font := d2fonts.Font{
|
||||||
font := d2fonts.Font{
|
Family: fontFamily,
|
||||||
Family: fontFamily,
|
Style: fontStyle,
|
||||||
Style: fontStyle,
|
}
|
||||||
}
|
// Note: FontFaces lookup is size-agnostic
|
||||||
if _, ok := d2fonts.FontFaces[font]; !ok {
|
if _, ok := d2fonts.FontFaces[font]; !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if _, loaded := r.ttfs[font]; !loaded {
|
||||||
ttf, err := truetype.Parse(d2fonts.FontFaces[font])
|
ttf, err := truetype.Parse(d2fonts.FontFaces[font])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Added after, since FontFaces lookup is size-agnostic
|
r.ttfs[font] = ttf
|
||||||
font.Size = fontSize
|
}
|
||||||
face := truetype.NewFace(ttf, &truetype.Options{
|
|
||||||
Size: float64(fontSize),
|
for _, fontSize := range d2fonts.FontSizes {
|
||||||
})
|
r.addFontSize(font, fontSize)
|
||||||
atlas := NewAtlas(face, ASCII)
|
|
||||||
atlases[font] = atlas
|
|
||||||
lineHeights[font] = atlas.lineHeight
|
|
||||||
tabWidths[font] = atlas.glyph(' ').advance * TAB_SIZE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
origin := geo.NewPoint(0, 0)
|
|
||||||
txt := &Ruler{
|
|
||||||
Orig: origin,
|
|
||||||
Dot: origin.Copy(),
|
|
||||||
LineHeightFactor: 1.,
|
|
||||||
lineHeights: lineHeights,
|
|
||||||
tabWidths: tabWidths,
|
|
||||||
atlases: atlases,
|
|
||||||
}
|
|
||||||
|
|
||||||
txt.clear()
|
r.clear()
|
||||||
|
|
||||||
return txt, nil
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Ruler) addFontSize(font d2fonts.Font, fontSize int) {
|
||||||
|
sizeless := font
|
||||||
|
sizeless.Size = 0
|
||||||
|
face := truetype.NewFace(r.ttfs[sizeless], &truetype.Options{
|
||||||
|
Size: float64(fontSize),
|
||||||
|
})
|
||||||
|
font.Size = fontSize
|
||||||
|
atlas := NewAtlas(face, ASCII)
|
||||||
|
r.atlases[font] = atlas
|
||||||
|
r.lineHeights[font] = atlas.lineHeight
|
||||||
|
r.tabWidths[font] = atlas.glyph(' ').advance * TAB_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) {
|
func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) {
|
||||||
hasSize := false
|
w, h := t.MeasurePrecise(font, s)
|
||||||
for _, size := range d2fonts.FontSizes {
|
|
||||||
if size == font.Size {
|
|
||||||
hasSize = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var w, h float64
|
|
||||||
if hasSize {
|
|
||||||
w, h = t.MeasurePrecise(font, s)
|
|
||||||
} else {
|
|
||||||
// find the closest font size we have and scale the measurement
|
|
||||||
closestSize := d2fonts.FontSizes[0]
|
|
||||||
smallestDiff := math.Abs(float64(closestSize - font.Size))
|
|
||||||
for i := 1; i < len(d2fonts.FontSizes); i++ {
|
|
||||||
diff := math.Abs(float64(d2fonts.FontSizes[i] - font.Size))
|
|
||||||
if diff < smallestDiff {
|
|
||||||
smallestDiff = diff
|
|
||||||
closestSize = d2fonts.FontSizes[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scaledFont := font
|
|
||||||
scaledFont.Size = closestSize
|
|
||||||
w, h = t.MeasurePrecise(scaledFont, s)
|
|
||||||
f := float64(font.Size) / float64(closestSize)
|
|
||||||
w *= f
|
|
||||||
h *= f
|
|
||||||
}
|
|
||||||
return int(math.Ceil(w)), int(math.Ceil(h))
|
return int(math.Ceil(w)), int(math.Ceil(h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Ruler) MeasurePrecise(font d2fonts.Font, s string) (width, height float64) {
|
func (t *Ruler) MeasurePrecise(font d2fonts.Font, s string) (width, height float64) {
|
||||||
|
if _, ok := t.atlases[font]; !ok {
|
||||||
|
t.addFontSize(font, font.Size)
|
||||||
|
}
|
||||||
t.clear()
|
t.clear()
|
||||||
t.buf = append(t.buf, s...)
|
t.buf = append(t.buf, s...)
|
||||||
t.drawBuf(font)
|
t.drawBuf(font)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue