-
Notifications
You must be signed in to change notification settings - Fork 12
/
tinyfont.go
125 lines (106 loc) · 3.69 KB
/
tinyfont.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package tinyfont // import "tinygo.org/x/tinyfont"
import (
"image/color"
"tinygo.org/x/drivers"
)
const (
NO_ROTATION Rotation = 0
ROTATION_90 Rotation = 1 // 90 degrees clock-wise rotation
ROTATION_180 Rotation = 2
ROTATION_270 Rotation = 3
LineFeed = 0x0A
CarriageReturn = 0x0D
)
type Rotation uint8
// GlyphInfo is a structure that holds information about glyphs.
type GlyphInfo struct {
Rune rune
Width uint8
Height uint8
XAdvance uint8
XOffset int8
YOffset int8
}
// Fonter is an interface that represents a set of glyphs.
type Fonter interface {
GetGlyph(r rune) Glypher
GetYAdvance() uint8
}
// Glypher is glyph itself, and it knows how to draw itself.
type Glypher interface {
Draw(display drivers.Displayer, x int16, y int16, color color.RGBA)
Info() GlyphInfo
}
// DrawChar sets a single rune in the buffer of the display.
func DrawChar(display drivers.Displayer, font Fonter, x int16, y int16, char rune, color color.RGBA) {
DrawCharRotated(display, font, x, y, char, color, NO_ROTATION)
}
// DrawCharRotated sets a single rune in the buffer of the display.
func DrawCharRotated(display drivers.Displayer, font Fonter, x int16, y int16, char rune, color color.RGBA, rotation Rotation) {
glyph := font.GetGlyph(char)
rd := NewRotatedDisplay(display, rotation, x, y)
glyph.Draw(rd, 0, 0, color)
}
// WriteLine writes a string in the selected font in the buffer.
func WriteLine(display drivers.Displayer, font Fonter, x int16, y int16, str string, c color.RGBA) {
WriteLineColorsRotated(display, font, x, y, str, []color.RGBA{c}, NO_ROTATION)
}
// WriteLineRotated writes a string in the selected font in the buffer.
func WriteLineRotated(display drivers.Displayer, font Fonter, x int16, y int16, str string, c color.RGBA, rotation Rotation) {
WriteLineColorsRotated(display, font, x, y, str, []color.RGBA{c}, rotation)
}
// WriteLineColors writes a string in the selected font in the buffer. Each char is in a different color
// if not enough colors are defined, colors are cycled.
func WriteLineColors(display drivers.Displayer, font Fonter, x int16, y int16, str string, colors []color.RGBA) {
WriteLineColorsRotated(display, font, x, y, str, colors, NO_ROTATION)
}
// WriteLineColorsRotated writes a string in the selected font in the buffer. Each char is in a different color
// if not enough colors are defined, colors are cycled.
func WriteLineColorsRotated(display drivers.Displayer, font Fonter, x int16, y int16, str string, colors []color.RGBA, rotation Rotation) {
numColors := uint16(len(colors))
if numColors == 0 {
return
}
rotation = rotation % 4
rd := NewRotatedDisplay(display, rotation, x, y)
c := uint16(0)
nx := int16(0)
ny := int16(0)
for _, text := range str {
if text == LineFeed || text == CarriageReturn {
/* CR or LF */
nx = 0
ny += int16(font.GetYAdvance())
continue
}
glyph := font.GetGlyph(text)
glyph.Draw(rd, nx, ny, colors[c])
c++
if c >= numColors {
c = 0
}
nx += int16(glyph.Info().XAdvance)
}
}
// LineWidth returns the inner and outbox widths corresponding to font and str.
func LineWidth(f Fonter, str string) (innerWidth uint32, outboxWidth uint32) {
if len(str) == 0 {
return
}
for _, text := range str {
glyph := f.GetGlyph(text)
outboxWidth += uint32(glyph.Info().XAdvance)
}
innerWidth = outboxWidth
// first glyph
glyph := f.GetGlyph(rune(str[0]))
innerWidth -= uint32(glyph.Info().XOffset)
// last glyph
glyph = f.GetGlyph(rune(str[len(str)-1]))
innerWidth += -uint32(glyph.Info().XAdvance) + uint32(glyph.Info().XOffset) + uint32(glyph.Info().Width)
return
}
// GetGlyph returns the glyph corresponding to the specified rune in the font.
func GetGlyph(f Fonter, r rune) Glypher {
return f.GetGlyph(r)
}