git.lucas.co / go_mono
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 }