/
set.go
94 lines (82 loc) · 2.47 KB
/
set.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package vglyph
import (
"image"
"math"
"github.com/lakal3/vge/vge/vk"
)
type SetKind int
const (
SETDepthField = SetKind(0)
SETGrayScale = SetKind(1)
SETRGBA = SetKind(2)
)
// Glyph is individual glyph in glyph set.
type Glyph struct {
Name string
Location image.Rectangle
CharOffset image.Point
// Edges from 3 or 9 part glyph. left, top, right, bottom
Edges image.Rectangle
}
// GlyphSet is set of prerendered glyph. GlyphSet can be either
// SETDepthField - All glyphs are rendered as signed depth fields. These allows more accurate sampling of glyph edges
// when sizing them. This is ideal for font's and other single colored glyphs
// SETGrayScale - Grays scale glyph mixes blending between font color and back color based on image grayness. Alpha channel is
// used to control glyphs alpha factor.
type GlyphSet struct {
Desc vk.ImageDescription
Advance func(height int, from, to rune) float32
kind SetKind
glyphs map[string]Glyph
pool *vk.MemoryPool
image *vk.Image
}
func (set *GlyphSet) Dispose() {
if set.pool != nil {
set.pool.Dispose()
set.pool, set.image = nil, nil
}
}
// Get glyph from set
func (set *GlyphSet) Get(name string) Glyph {
return set.glyphs[name]
}
// If glyph set is made from font, measure string will calculate length of text using given font height
func (gs *GlyphSet) MeasureString(text string, fontHeight int) int {
pos := float32(0)
prevChar := rune(0)
w := float32(0)
for _, ch := range text {
if prevChar != 0 {
pos += gs.Advance(fontHeight, prevChar, ch)
}
gl := gs.Get(string(ch))
if len(gl.Name) > 0 {
sz := gl.Location.Size()
w = float32(fontHeight*sz.X) / NOMINALFontSize
w += float32(fontHeight*gl.CharOffset.X) / NOMINALFontSize
}
prevChar = ch
pos += w
}
return int(math.Ceil(float64(pos)))
}
func newGlyphSet(ctx vk.APIContext, dev *vk.Device, glyphs int, w int, h int, kind SetKind) *GlyphSet {
gs := &GlyphSet{glyphs: make(map[string]Glyph, glyphs), kind: kind}
gs.pool = vk.NewMemoryPool(dev)
f := vk.FORMATR8Unorm
if kind == SETGrayScale {
f = vk.FORMATR8g8Unorm
}
if kind == SETRGBA {
f = vk.FORMATR8g8b8a8Unorm
}
gs.Desc = vk.ImageDescription{Width: uint32(w), Height: uint32(h), Depth: 1,
Format: f, MipLevels: 1, Layers: 1}
gs.image = gs.pool.ReserveImage(ctx, gs.Desc, vk.IMAGEUsageSampledBit|vk.IMAGEUsageStorageBit|vk.IMAGEUsageTransferSrcBit)
gs.pool.Allocate(ctx)
return gs
}
func DefaultAdvance(height int, from, to rune) float32 {
return float32(height) / 12
}