1
2
3
4
5
6
7
8
9
10
11
12 package opentype
13
14 import (
15 "image"
16 "image/draw"
17 "io"
18
19 "golang.org/x/image/font"
20 "golang.org/x/image/font/sfnt"
21 "golang.org/x/image/math/fixed"
22 "golang.org/x/image/vector"
23 )
24
25
26
27
28
29
30 func ParseCollection(src []byte) (*Collection, error) {
31 return sfnt.ParseCollection(src)
32 }
33
34
35
36
37
38
39 func ParseCollectionReaderAt(src io.ReaderAt) (*Collection, error) {
40 return sfnt.ParseCollectionReaderAt(src)
41 }
42
43
44
45
46 type Collection = sfnt.Collection
47
48
49
50 func Parse(src []byte) (*Font, error) {
51 return sfnt.Parse(src)
52 }
53
54
55
56 func ParseReaderAt(src io.ReaderAt) (*Font, error) {
57 return sfnt.ParseReaderAt(src)
58 }
59
60
61
62
63
64
65
66
67 type Font = sfnt.Font
68
69
70
71 type FaceOptions struct {
72 Size float64
73 DPI float64
74 Hinting font.Hinting
75 }
76
77 func defaultFaceOptions() *FaceOptions {
78 return &FaceOptions{
79 Size: 12,
80 DPI: 72,
81 Hinting: font.HintingNone,
82 }
83 }
84
85
86
87
88 type Face struct {
89 f *Font
90 hinting font.Hinting
91 scale fixed.Int26_6
92
93 metrics font.Metrics
94 metricsSet bool
95
96 buf sfnt.Buffer
97 rast vector.Rasterizer
98 mask image.Alpha
99 }
100
101
102
103
104 func NewFace(f *Font, opts *FaceOptions) (font.Face, error) {
105 if opts == nil {
106 opts = defaultFaceOptions()
107 }
108 face := &Face{
109 f: f,
110 hinting: opts.Hinting,
111 scale: fixed.Int26_6(0.5 + (opts.Size * opts.DPI * 64 / 72)),
112 }
113 return face, nil
114 }
115
116
117 func (f *Face) Close() error {
118 return nil
119 }
120
121
122 func (f *Face) Metrics() font.Metrics {
123 if !f.metricsSet {
124 var err error
125 f.metrics, err = f.f.Metrics(&f.buf, f.scale, f.hinting)
126 if err != nil {
127 f.metrics = font.Metrics{}
128 }
129 f.metricsSet = true
130 }
131 return f.metrics
132 }
133
134
135 func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 {
136 x0, _ := f.f.GlyphIndex(&f.buf, r0)
137 x1, _ := f.f.GlyphIndex(&f.buf, r1)
138 k, err := f.f.Kern(&f.buf, x0, x1, fixed.Int26_6(f.f.UnitsPerEm()), f.hinting)
139 if err != nil {
140 return 0
141 }
142 return k
143 }
144
145
146 func (f *Face) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
147 x, err := f.f.GlyphIndex(&f.buf, r)
148 if err != nil {
149 return image.Rectangle{}, nil, image.Point{}, 0, false
150 }
151
152
153
154
155
156 advance, err = f.f.GlyphAdvance(&f.buf, x, f.scale, f.hinting)
157 if err != nil {
158 return image.Rectangle{}, nil, image.Point{}, 0, false
159 }
160
161 segments, err := f.f.LoadGlyph(&f.buf, x, f.scale, nil)
162 if err != nil {
163 return image.Rectangle{}, nil, image.Point{}, 0, false
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177 dBounds := segments.Bounds().Add(dot)
178
179
180 dr.Min.X = dBounds.Min.X.Floor()
181 dr.Min.Y = dBounds.Min.Y.Floor()
182 dr.Max.X = dBounds.Max.X.Ceil()
183 dr.Max.Y = dBounds.Max.Y.Ceil()
184 width := dr.Dx()
185 height := dr.Dy()
186 if width < 0 || height < 0 {
187 return image.Rectangle{}, nil, image.Point{}, 0, false
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 biasX := dot.X - fixed.Int26_6(dr.Min.X<<6)
205 biasY := dot.Y - fixed.Int26_6(dr.Min.Y<<6)
206
207
208 nPixels := width * height
209 if cap(f.mask.Pix) < nPixels {
210 f.mask.Pix = make([]uint8, 2*nPixels)
211 }
212 f.mask.Pix = f.mask.Pix[:nPixels]
213 f.mask.Stride = width
214 f.mask.Rect.Min.X = 0
215 f.mask.Rect.Min.Y = 0
216 f.mask.Rect.Max.X = width
217 f.mask.Rect.Max.Y = height
218
219
220 f.rast.Reset(width, height)
221 f.rast.DrawOp = draw.Src
222 for _, seg := range segments {
223 switch seg.Op {
224 case sfnt.SegmentOpMoveTo:
225 f.rast.MoveTo(
226 float32(seg.Args[0].X+biasX)/64,
227 float32(seg.Args[0].Y+biasY)/64,
228 )
229 case sfnt.SegmentOpLineTo:
230 f.rast.LineTo(
231 float32(seg.Args[0].X+biasX)/64,
232 float32(seg.Args[0].Y+biasY)/64,
233 )
234 case sfnt.SegmentOpQuadTo:
235 f.rast.QuadTo(
236 float32(seg.Args[0].X+biasX)/64,
237 float32(seg.Args[0].Y+biasY)/64,
238 float32(seg.Args[1].X+biasX)/64,
239 float32(seg.Args[1].Y+biasY)/64,
240 )
241 case sfnt.SegmentOpCubeTo:
242 f.rast.CubeTo(
243 float32(seg.Args[0].X+biasX)/64,
244 float32(seg.Args[0].Y+biasY)/64,
245 float32(seg.Args[1].X+biasX)/64,
246 float32(seg.Args[1].Y+biasY)/64,
247 float32(seg.Args[2].X+biasX)/64,
248 float32(seg.Args[2].Y+biasY)/64,
249 )
250 }
251 }
252 f.rast.Draw(&f.mask, f.mask.Bounds(), image.Opaque, image.Point{})
253
254 return dr, &f.mask, f.mask.Rect.Min, advance, x != 0
255 }
256
257
258 func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
259 x, _ := f.f.GlyphIndex(&f.buf, r)
260 bounds, advance, err := f.f.GlyphBounds(&f.buf, x, f.scale, f.hinting)
261 return bounds, advance, (err == nil) && (x != 0)
262 }
263
264
265 func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
266 x, _ := f.f.GlyphIndex(&f.buf, r)
267 advance, err := f.f.GlyphAdvance(&f.buf, x, f.scale, f.hinting)
268 return advance, (err == nil) && (x != 0)
269 }
270
View as plain text