git clone https://git.lucas.co/go_mono.git
font/opentype/opentype.go (8.4K)
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package opentype implements a glyph rasterizer for TTF (TrueType Fonts) and
6 // OTF (OpenType Fonts).
7 //
8 // This package provides a high-level API, centered on the NewFace function,
9 // implementing the golang.org/x/image/font.Face interface.
10 //
11 // The sibling golang.org/x/image/font/sfnt package provides a low-level API.
12 package opentype // import "golang.org/x/image/font/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 // ParseCollection parses an OpenType font collection, such as TTC or OTC data,
26 // from a []byte data source.
27 //
28 // If passed data for a single font, a TTF or OTF instead of a TTC or OTC, it
29 // will return a collection containing 1 font.
30 func ParseCollection(src []byte) (*Collection, error) {
31 return sfnt.ParseCollection(src)
32 }
33
34 // ParseCollectionReaderAt parses an OpenType collection, such as TTC or OTC
35 // data, from an io.ReaderAt data source.
36 //
37 // If passed data for a single font, a TTF or OTF instead of a TTC or OTC, it
38 // will return a collection containing 1 font.
39 func ParseCollectionReaderAt(src io.ReaderAt) (*Collection, error) {
40 return sfnt.ParseCollectionReaderAt(src)
41 }
42
43 // Collection is a collection of one or more fonts.
44 //
45 // All of the Collection methods are safe to call concurrently.
46 type Collection = sfnt.Collection
47
48 // Parse parses an OpenType font, such as TTF or OTF data, from a []byte data
49 // source.
50 func Parse(src []byte) (*Font, error) {
51 return sfnt.Parse(src)
52 }
53
54 // ParseReaderAt parses an OpenType font, such as TTF or OTF data, from an
55 // io.ReaderAt data source.
56 func ParseReaderAt(src io.ReaderAt) (*Font, error) {
57 return sfnt.ParseReaderAt(src)
58 }
59
60 // Font is an OpenType font, also known as an SFNT font.
61 //
62 // All of the Font methods are safe to call concurrently, as long as each call
63 // has a different *sfnt.Buffer (or nil).
64 //
65 // The Font methods that don't take a *sfnt.Buffer argument are always safe to
66 // call concurrently.
67 type Font = sfnt.Font
68
69 // FaceOptions describes the possible options given to NewFace when
70 // creating a new font.Face from a Font.
71 type FaceOptions struct {
72 Size float64 // Size is the font size in points
73 DPI float64 // DPI is the dots per inch resolution
74 Hinting font.Hinting // Hinting selects how to quantize a vector font's glyph nodes
75 }
76
77 func defaultFaceOptions() *FaceOptions {
78 return &FaceOptions{
79 Size: 12,
80 DPI: 72,
81 Hinting: font.HintingNone,
82 }
83 }
84
85 // Face implements the font.Face interface for Font values.
86 //
87 // A Face is not safe to use concurrently.
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 // NewFace returns a new font.Face for the given Font.
102 //
103 // If opts is nil, sensible defaults will be used.
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 // Close satisfies the font.Face interface.
117 func (f *Face) Close() error {
118 return nil
119 }
120
121 // Metrics satisfies the font.Face interface.
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 // Kern satisfies the font.Face interface.
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 // Glyph satisfies the font.Face interface.
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 // Call f.f.GlyphAdvance before f.f.LoadGlyph because the LoadGlyph docs
153 // say this about the &f.buf argument: the segments become invalid to use
154 // once [the buffer] is re-used.
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 // Numerical notation used below:
167 // - 2 is an integer, "two"
168 // - 2:16 is a 26.6 fixed point number, "two and a quarter"
169 // - 2.5 is a float32 number, "two and a half"
170 // Using 26.6 fixed point numbers means that there are 64 sub-pixel units
171 // in 1 integer pixel unit.
172
173 // Translate the sub-pixel bounding box from glyph space (where the glyph
174 // origin is at (0:00, 0:00)) to dst space (where the glyph origin is at
175 // the dot). dst space is the coordinate space that contains both the dot
176 // (a sub-pixel position) and dr (an integer-pixel rectangle).
177 dBounds := segments.Bounds().Add(dot)
178
179 // Quantize the sub-pixel bounds (dBounds) to integer-pixel bounds (dr).
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 // Calculate the sub-pixel bias to convert from glyph space to rasterizer
191 // space. In glyph space, the segments may be to the left or right and
192 // above or below the glyph origin. In rasterizer space, the segments
193 // should only be right and below (or equal to) the top-left corner (0.0,
194 // 0.0). They should also be left and above (or equal to) the bottom-right
195 // corner (width, height), as the rasterizer should enclose the glyph
196 // bounding box.
197 //
198 // For example, suppose that dot.X was at the sub-pixel position 25:48,
199 // three quarters of the way into the 26th pixel, and that bounds.Min.X was
200 // 1:20. We then have dBounds.Min.X = 1:20 + 25:48 = 27:04, dr.Min.X = 27
201 // and biasX = 25:48 - 27:00 = -1:16. A vertical stroke at 1:20 in glyph
202 // space becomes (1:20 + -1:16) = 0:04 in rasterizer space. 0:04 as a
203 // fixed.Int26_6 value is float32(4)/64.0 = 0.0625 as a float32 value.
204 biasX := dot.X - fixed.Int26_6(dr.Min.X<<6)
205 biasY := dot.Y - fixed.Int26_6(dr.Min.Y<<6)
206
207 // Configure the mask image, re-allocating its buffer if necessary.
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 // Rasterize the biased segments, converting from fixed.Int26_6 to float32.
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 // GlyphBounds satisfies the font.Face interface.
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 // GlyphAdvance satisfies the font.Face interface.
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 }