-
Notifications
You must be signed in to change notification settings - Fork 10
/
font.go
230 lines (192 loc) · 6.49 KB
/
font.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// SPDX-License-Identifier: Unlicense OR BSD-3-Clause
// Package font provides an high level API to access
// Opentype font properties.
// See packages [loader] and [tables] for a lower level, more detailled API.
package api
import (
"math"
)
// GID is used to identify glyphs in a font.
// It is mostly internal to the font and should not be confused with
// Unicode code points.
// Note that, despite Opentype font files using uint16, we choose to use uint32,
// to allow room for future extension.
type GID uint32
// EmptyGlyph represents an invisible glyph, which should not be drawn,
// but whose advance and offsets should still be accounted for when rendering.
const EmptyGlyph GID = math.MaxUint32
// CmapIter is an interator over a Cmap.
type CmapIter interface {
// Next returns true if the iterator still has data to yield
Next() bool
// Char must be called only when `Next` has returned `true`
Char() (rune, GID)
}
// Cmap stores a compact representation of a cmap,
// offering both on-demand rune lookup and full rune range.
// It is conceptually equivalent to a map[rune]GID, but is often
// implemented more efficiently.
type Cmap interface {
// Iter returns a new iterator over the cmap
// Multiple iterators may be used over the same cmap
// The returned interface is garanted not to be nil.
Iter() CmapIter
// Lookup avoid the construction of a map and provides
// an alternative when only few runes need to be fetched.
// It returns a default value and false when no glyph is provided.
Lookup(rune) (GID, bool)
}
// FontExtents exposes font-wide extent values, measured in font units.
// Note that typically ascender is positive and descender negative in coordinate systems that grow up.
type FontExtents struct {
Ascender float32 // Typographic ascender.
Descender float32 // Typographic descender.
LineGap float32 // Suggested line spacing gap.
}
// LineMetric identifies one metric about the font.
type LineMetric uint8
const (
// Distance above the baseline of the top of the underline.
// Since most fonts have underline positions beneath the baseline, this value is typically negative.
UnderlinePosition LineMetric = iota
// Suggested thickness to draw for the underline.
UnderlineThickness
// Distance above the baseline of the top of the strikethrough.
StrikethroughPosition
// Suggested thickness to draw for the strikethrough.
StrikethroughThickness
SuperscriptEmYSize
SuperscriptEmXOffset
SubscriptEmYSize
SubscriptEmYOffset
SubscriptEmXOffset
CapHeight
XHeight
)
// GlyphExtents exposes extent values, measured in font units.
// Note that height is negative in coordinate systems that grow up.
type GlyphExtents struct {
XBearing float32 // Left side of glyph from origin
YBearing float32 // Top side of glyph from origin
Width float32 // Distance from left to right side
Height float32 // Distance from top to bottom side
}
// GlyphData describe how to graw a glyph.
// It is either an GlyphOutline, GlyphSVG or GlyphBitmap.
type GlyphData interface {
isGlyphData()
}
func (GlyphOutline) isGlyphData() {}
func (GlyphSVG) isGlyphData() {}
func (GlyphBitmap) isGlyphData() {}
// GlyphOutline exposes the path to draw for
// vector glyph.
// Coordinates are expressed in fonts units.
type GlyphOutline struct {
Segments []Segment
}
// Sideways updates the coordinates of the outline by applying
// a 90° clockwise rotation, and adding [yOffset] afterwards.
//
// When used for vertical text, pass
// -Glyph.YOffset, converted in font units, as [yOffset]
// (a positive value to lift the glyph up).
func (o GlyphOutline) Sideways(yOffset float32) {
for i := range o.Segments {
target := o.Segments[i].Args[:]
target[0].X, target[0].Y = target[0].Y, -target[0].X+yOffset
target[1].X, target[1].Y = target[1].Y, -target[1].X+yOffset
target[2].X, target[2].Y = target[2].Y, -target[2].X+yOffset
}
}
type SegmentOp uint8
const (
SegmentOpMoveTo SegmentOp = iota
SegmentOpLineTo
SegmentOpQuadTo
SegmentOpCubeTo
)
type SegmentPoint struct {
X, Y float32 // expressed in fonts units
}
// Move translates the point.
func (pt *SegmentPoint) Move(dx, dy float32) {
pt.X += dx
pt.Y += dy
}
type Segment struct {
Op SegmentOp
// Args is up to three (x, y) coordinates, depending on the
// operation.
// The Y axis increases up.
Args [3]SegmentPoint
}
// ArgsSlice returns the effective slice of points
// used (whose length is between 1 and 3).
func (s *Segment) ArgsSlice() []SegmentPoint {
switch s.Op {
case SegmentOpMoveTo, SegmentOpLineTo:
return s.Args[0:1]
case SegmentOpQuadTo:
return s.Args[0:2]
case SegmentOpCubeTo:
return s.Args[0:3]
default:
panic("unreachable")
}
}
// GlyphSVG is an SVG description for the glyph,
// as found in Opentype SVG table.
type GlyphSVG struct {
// The SVG image content, decompressed if needed.
// The actual glyph description is an SVG element
// with id="glyph<GID>" (as in id="glyph12"),
// and several glyphs may share the same Source
Source []byte
// According to the specification, a fallback outline
// should be specified for each SVG glyphs
Outline GlyphOutline
}
type GlyphBitmap struct {
// The actual image content, whose interpretation depends
// on the Format field.
Data []byte
Format BitmapFormat
Width, Height int // number of columns and rows
// Outline may be specified to be drawn with bitmap
Outline *GlyphOutline
}
// BitmapFormat identifies the format on the glyph
// raw data. Across the various font files, many formats
// may be encountered : black and white bitmaps, PNG, TIFF, JPG.
type BitmapFormat uint8
const (
_ BitmapFormat = iota
// The [GlyphBitmap.Data] slice stores a black or white (0/1)
// bit image, whose length L satisfies
// L * 8 >= [GlyphBitmap.Width] * [GlyphBitmap.Height]
BlackAndWhite
// The [GlyphBitmap.Data] slice stores a PNG encoded image
PNG
// The [GlyphBitmap.Data] slice stores a JPG encoded image
JPG
// The [GlyphBitmap.Data] slice stores a TIFF encoded image
TIFF
)
// BitmapSize expose the size of bitmap glyphs.
// One font may contain several sizes.
type BitmapSize struct {
Height, Width uint16
XPpem, YPpem uint16
}
// FontID represents an identifier of a font (possibly in a collection),
// and an optional variable instance.
type FontID struct {
File string // The filename or identifier of the font file.
// The index of the face in a collection. It is always 0 for
// single font files.
Index uint16
// For variable fonts, stores 1 + the instance index.
// It is set to 0 to ignore variations, or for non variable fonts.
Instance uint16
}