1// Copyright 2015 The Freetype-Go Authors. All rights reserved.
2// Use of this source code is governed by your choice of either the
3// FreeType License or the GNU General Public License version 2 (or
4// any later version), both of which can be found in the LICENSE file.
5
6package truetype
7
8import (
9	"image"
10	"math"
11
12	"github.com/golang/freetype/raster"
13	"golang.org/x/image/font"
14	"golang.org/x/image/math/fixed"
15)
16
17func powerOf2(i int) bool {
18	return i != 0 && (i&(i-1)) == 0
19}
20
21// Options are optional arguments to NewFace.
22type Options struct {
23	// Size is the font size in points, as in "a 10 point font size".
24	//
25	// A zero value means to use a 12 point font size.
26	Size float64
27
28	// DPI is the dots-per-inch resolution.
29	//
30	// A zero value means to use 72 DPI.
31	DPI float64
32
33	// Hinting is how to quantize the glyph nodes.
34	//
35	// A zero value means to use no hinting.
36	Hinting font.Hinting
37
38	// GlyphCacheEntries is the number of entries in the glyph mask image
39	// cache.
40	//
41	// If non-zero, it must be a power of 2.
42	//
43	// A zero value means to use 512 entries.
44	GlyphCacheEntries int
45
46	// SubPixelsX is the number of sub-pixel locations a glyph's dot is
47	// quantized to, in the horizontal direction. For example, a value of 8
48	// means that the dot is quantized to 1/8th of a pixel. This quantization
49	// only affects the glyph mask image, not its bounding box or advance
50	// width. A higher value gives a more faithful glyph image, but reduces the
51	// effectiveness of the glyph cache.
52	//
53	// If non-zero, it must be a power of 2, and be between 1 and 64 inclusive.
54	//
55	// A zero value means to use 4 sub-pixel locations.
56	SubPixelsX int
57
58	// SubPixelsY is the number of sub-pixel locations a glyph's dot is
59	// quantized to, in the vertical direction. For example, a value of 8
60	// means that the dot is quantized to 1/8th of a pixel. This quantization
61	// only affects the glyph mask image, not its bounding box or advance
62	// width. A higher value gives a more faithful glyph image, but reduces the
63	// effectiveness of the glyph cache.
64	//
65	// If non-zero, it must be a power of 2, and be between 1 and 64 inclusive.
66	//
67	// A zero value means to use 1 sub-pixel location.
68	SubPixelsY int
69}
70
71func (o *Options) size() float64 {
72	if o != nil && o.Size > 0 {
73		return o.Size
74	}
75	return 12
76}
77
78func (o *Options) dpi() float64 {
79	if o != nil && o.DPI > 0 {
80		return o.DPI
81	}
82	return 72
83}
84
85func (o *Options) hinting() font.Hinting {
86	if o != nil {
87		switch o.Hinting {
88		case font.HintingVertical, font.HintingFull:
89			// TODO: support vertical hinting.
90			return font.HintingFull
91		}
92	}
93	return font.HintingNone
94}
95
96func (o *Options) glyphCacheEntries() int {
97	if o != nil && powerOf2(o.GlyphCacheEntries) {
98		return o.GlyphCacheEntries
99	}
100	// 512 is 128 * 4 * 1, which lets us cache 128 glyphs at 4 * 1 subpixel
101	// locations in the X and Y direction.
102	return 512
103}
104
105func (o *Options) subPixelsX() (value uint32, halfQuantum, mask fixed.Int26_6) {
106	if o != nil {
107		switch o.SubPixelsX {
108		case 1, 2, 4, 8, 16, 32, 64:
109			return subPixels(o.SubPixelsX)
110		}
111	}
112	// This default value of 4 isn't based on anything scientific, merely as
113	// small a number as possible that looks almost as good as no quantization,
114	// or returning subPixels(64).
115	return subPixels(4)
116}
117
118func (o *Options) subPixelsY() (value uint32, halfQuantum, mask fixed.Int26_6) {
119	if o != nil {
120		switch o.SubPixelsX {
121		case 1, 2, 4, 8, 16, 32, 64:
122			return subPixels(o.SubPixelsX)
123		}
124	}
125	// This default value of 1 isn't based on anything scientific, merely that
126	// vertical sub-pixel glyph rendering is pretty rare. Baseline locations
127	// can usually afford to snap to the pixel grid, so the vertical direction
128	// doesn't have the deal with the horizontal's fractional advance widths.
129	return subPixels(1)
130}
131
132// subPixels returns q and the bias and mask that leads to q quantized
133// sub-pixel locations per full pixel.
134//
135// For example, q == 4 leads to a bias of 8 and a mask of 0xfffffff0, or -16,
136// because we want to round fractions of fixed.Int26_6 as:
137//	-  0 to  7 rounds to 0.
138//	-  8 to 23 rounds to 16.
139//	- 24 to 39 rounds to 32.
140//	- 40 to 55 rounds to 48.
141//	- 56 to 63 rounds to 64.
142// which means to add 8 and then bitwise-and with -16, in two's complement
143// representation.
144//
145// When q ==  1, we want bias == 32 and mask == -64.
146// When q ==  2, we want bias == 16 and mask == -32.
147// When q ==  4, we want bias ==  8 and mask == -16.
148// ...
149// When q == 64, we want bias ==  0 and mask ==  -1. (The no-op case).
150// The pattern is clear.
151func subPixels(q int) (value uint32, bias, mask fixed.Int26_6) {
152	return uint32(q), 32 / fixed.Int26_6(q), -64 / fixed.Int26_6(q)
153}
154
155// glyphCacheEntry caches the arguments and return values of rasterize.
156type glyphCacheEntry struct {
157	key glyphCacheKey
158	val glyphCacheVal
159}
160
161type glyphCacheKey struct {
162	index  Index
163	fx, fy uint8
164}
165
166type glyphCacheVal struct {
167	advanceWidth fixed.Int26_6
168	offset       image.Point
169	gw           int
170	gh           int
171}
172
173type indexCacheEntry struct {
174	rune  rune
175	index Index
176}
177
178// NewFace returns a new font.Face for the given Font.
179func NewFace(f *Font, opts *Options) font.Face {
180	a := &face{
181		f:          f,
182		hinting:    opts.hinting(),
183		scale:      fixed.Int26_6(0.5 + (opts.size() * opts.dpi() * 64 / 72)),
184		glyphCache: make([]glyphCacheEntry, opts.glyphCacheEntries()),
185	}
186	a.subPixelX, a.subPixelBiasX, a.subPixelMaskX = opts.subPixelsX()
187	a.subPixelY, a.subPixelBiasY, a.subPixelMaskY = opts.subPixelsY()
188
189	// Fill the cache with invalid entries. Valid glyph cache entries have fx
190	// and fy in the range [0, 64). Valid index cache entries have rune >= 0.
191	for i := range a.glyphCache {
192		a.glyphCache[i].key.fy = 0xff
193	}
194	for i := range a.indexCache {
195		a.indexCache[i].rune = -1
196	}
197
198	// Set the rasterizer's bounds to be big enough to handle the largest glyph.
199	b := f.Bounds(a.scale)
200	xmin := +int(b.Min.X) >> 6
201	ymin := -int(b.Max.Y) >> 6
202	xmax := +int(b.Max.X+63) >> 6
203	ymax := -int(b.Min.Y-63) >> 6
204	a.maxw = xmax - xmin
205	a.maxh = ymax - ymin
206	a.masks = image.NewAlpha(image.Rect(0, 0, a.maxw, a.maxh*len(a.glyphCache)))
207	a.r.SetBounds(a.maxw, a.maxh)
208	a.p = facePainter{a}
209
210	return a
211}
212
213type face struct {
214	f             *Font
215	hinting       font.Hinting
216	scale         fixed.Int26_6
217	subPixelX     uint32
218	subPixelBiasX fixed.Int26_6
219	subPixelMaskX fixed.Int26_6
220	subPixelY     uint32
221	subPixelBiasY fixed.Int26_6
222	subPixelMaskY fixed.Int26_6
223	masks         *image.Alpha
224	glyphCache    []glyphCacheEntry
225	r             raster.Rasterizer
226	p             raster.Painter
227	paintOffset   int
228	maxw          int
229	maxh          int
230	glyphBuf      GlyphBuf
231	indexCache    [indexCacheLen]indexCacheEntry
232
233	// TODO: clip rectangle?
234}
235
236const indexCacheLen = 256
237
238func (a *face) index(r rune) Index {
239	const mask = indexCacheLen - 1
240	c := &a.indexCache[r&mask]
241	if c.rune == r {
242		return c.index
243	}
244	i := a.f.Index(r)
245	c.rune = r
246	c.index = i
247	return i
248}
249
250// Close satisfies the font.Face interface.
251func (a *face) Close() error { return nil }
252
253// Metrics satisfies the font.Face interface.
254func (a *face) Metrics() font.Metrics {
255	scale := float64(a.scale)
256	fupe := float64(a.f.FUnitsPerEm())
257	return font.Metrics{
258		Height:  a.scale,
259		Ascent:  fixed.Int26_6(math.Ceil(scale * float64(+a.f.ascent) / fupe)),
260		Descent: fixed.Int26_6(math.Ceil(scale * float64(-a.f.descent) / fupe)),
261	}
262}
263
264// Kern satisfies the font.Face interface.
265func (a *face) Kern(r0, r1 rune) fixed.Int26_6 {
266	i0 := a.index(r0)
267	i1 := a.index(r1)
268	kern := a.f.Kern(a.scale, i0, i1)
269	if a.hinting != font.HintingNone {
270		kern = (kern + 32) &^ 63
271	}
272	return kern
273}
274
275// Glyph satisfies the font.Face interface.
276func (a *face) Glyph(dot fixed.Point26_6, r rune) (
277	dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
278
279	// Quantize to the sub-pixel granularity.
280	dotX := (dot.X + a.subPixelBiasX) & a.subPixelMaskX
281	dotY := (dot.Y + a.subPixelBiasY) & a.subPixelMaskY
282
283	// Split the coordinates into their integer and fractional parts.
284	ix, fx := int(dotX>>6), dotX&0x3f
285	iy, fy := int(dotY>>6), dotY&0x3f
286
287	index := a.index(r)
288	cIndex := uint32(index)
289	cIndex = cIndex*a.subPixelX - uint32(fx/a.subPixelMaskX)
290	cIndex = cIndex*a.subPixelY - uint32(fy/a.subPixelMaskY)
291	cIndex &= uint32(len(a.glyphCache) - 1)
292	a.paintOffset = a.maxh * int(cIndex)
293	k := glyphCacheKey{
294		index: index,
295		fx:    uint8(fx),
296		fy:    uint8(fy),
297	}
298	var v glyphCacheVal
299	if a.glyphCache[cIndex].key != k {
300		var ok bool
301		v, ok = a.rasterize(index, fx, fy)
302		if !ok {
303			return image.Rectangle{}, nil, image.Point{}, 0, false
304		}
305		a.glyphCache[cIndex] = glyphCacheEntry{k, v}
306	} else {
307		v = a.glyphCache[cIndex].val
308	}
309
310	dr.Min = image.Point{
311		X: ix + v.offset.X,
312		Y: iy + v.offset.Y,
313	}
314	dr.Max = image.Point{
315		X: dr.Min.X + v.gw,
316		Y: dr.Min.Y + v.gh,
317	}
318	return dr, a.masks, image.Point{Y: a.paintOffset}, v.advanceWidth, true
319}
320
321func (a *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
322	if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil {
323		return fixed.Rectangle26_6{}, 0, false
324	}
325	xmin := +a.glyphBuf.Bounds.Min.X
326	ymin := -a.glyphBuf.Bounds.Max.Y
327	xmax := +a.glyphBuf.Bounds.Max.X
328	ymax := -a.glyphBuf.Bounds.Min.Y
329	if xmin > xmax || ymin > ymax {
330		return fixed.Rectangle26_6{}, 0, false
331	}
332	return fixed.Rectangle26_6{
333		Min: fixed.Point26_6{
334			X: xmin,
335			Y: ymin,
336		},
337		Max: fixed.Point26_6{
338			X: xmax,
339			Y: ymax,
340		},
341	}, a.glyphBuf.AdvanceWidth, true
342}
343
344func (a *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
345	if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil {
346		return 0, false
347	}
348	return a.glyphBuf.AdvanceWidth, true
349}
350
351// rasterize returns the advance width, integer-pixel offset to render at, and
352// the width and height of the given glyph at the given sub-pixel offsets.
353//
354// The 26.6 fixed point arguments fx and fy must be in the range [0, 1).
355func (a *face) rasterize(index Index, fx, fy fixed.Int26_6) (v glyphCacheVal, ok bool) {
356	if err := a.glyphBuf.Load(a.f, a.scale, index, a.hinting); err != nil {
357		return glyphCacheVal{}, false
358	}
359	// Calculate the integer-pixel bounds for the glyph.
360	xmin := int(fx+a.glyphBuf.Bounds.Min.X) >> 6
361	ymin := int(fy-a.glyphBuf.Bounds.Max.Y) >> 6
362	xmax := int(fx+a.glyphBuf.Bounds.Max.X+0x3f) >> 6
363	ymax := int(fy-a.glyphBuf.Bounds.Min.Y+0x3f) >> 6
364	if xmin > xmax || ymin > ymax {
365		return glyphCacheVal{}, false
366	}
367	// A TrueType's glyph's nodes can have negative co-ordinates, but the
368	// rasterizer clips anything left of x=0 or above y=0. xmin and ymin are
369	// the pixel offsets, based on the font's FUnit metrics, that let a
370	// negative co-ordinate in TrueType space be non-negative in rasterizer
371	// space. xmin and ymin are typically <= 0.
372	fx -= fixed.Int26_6(xmin << 6)
373	fy -= fixed.Int26_6(ymin << 6)
374	// Rasterize the glyph's vectors.
375	a.r.Clear()
376	pixOffset := a.paintOffset * a.maxw
377	clear(a.masks.Pix[pixOffset : pixOffset+a.maxw*a.maxh])
378	e0 := 0
379	for _, e1 := range a.glyphBuf.Ends {
380		a.drawContour(a.glyphBuf.Points[e0:e1], fx, fy)
381		e0 = e1
382	}
383	a.r.Rasterize(a.p)
384	return glyphCacheVal{
385		a.glyphBuf.AdvanceWidth,
386		image.Point{xmin, ymin},
387		xmax - xmin,
388		ymax - ymin,
389	}, true
390}
391
392func clear(pix []byte) {
393	for i := range pix {
394		pix[i] = 0
395	}
396}
397
398// drawContour draws the given closed contour with the given offset.
399func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) {
400	if len(ps) == 0 {
401		return
402	}
403
404	// The low bit of each point's Flags value is whether the point is on the
405	// curve. Truetype fonts only have quadratic Bézier curves, not cubics.
406	// Thus, two consecutive off-curve points imply an on-curve point in the
407	// middle of those two.
408	//
409	// See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details.
410
411	// ps[0] is a truetype.Point measured in FUnits and positive Y going
412	// upwards. start is the same thing measured in fixed point units and
413	// positive Y going downwards, and offset by (dx, dy).
414	start := fixed.Point26_6{
415		X: dx + ps[0].X,
416		Y: dy - ps[0].Y,
417	}
418	var others []Point
419	if ps[0].Flags&0x01 != 0 {
420		others = ps[1:]
421	} else {
422		last := fixed.Point26_6{
423			X: dx + ps[len(ps)-1].X,
424			Y: dy - ps[len(ps)-1].Y,
425		}
426		if ps[len(ps)-1].Flags&0x01 != 0 {
427			start = last
428			others = ps[:len(ps)-1]
429		} else {
430			start = fixed.Point26_6{
431				X: (start.X + last.X) / 2,
432				Y: (start.Y + last.Y) / 2,
433			}
434			others = ps
435		}
436	}
437	a.r.Start(start)
438	q0, on0 := start, true
439	for _, p := range others {
440		q := fixed.Point26_6{
441			X: dx + p.X,
442			Y: dy - p.Y,
443		}
444		on := p.Flags&0x01 != 0
445		if on {
446			if on0 {
447				a.r.Add1(q)
448			} else {
449				a.r.Add2(q0, q)
450			}
451		} else {
452			if on0 {
453				// No-op.
454			} else {
455				mid := fixed.Point26_6{
456					X: (q0.X + q.X) / 2,
457					Y: (q0.Y + q.Y) / 2,
458				}
459				a.r.Add2(q0, mid)
460			}
461		}
462		q0, on0 = q, on
463	}
464	// Close the curve.
465	if on0 {
466		a.r.Add1(start)
467	} else {
468		a.r.Add2(q0, start)
469	}
470}
471
472// facePainter is like a raster.AlphaSrcPainter, with an additional Y offset
473// (face.paintOffset) to the painted spans.
474type facePainter struct {
475	a *face
476}
477
478func (p facePainter) Paint(ss []raster.Span, done bool) {
479	m := p.a.masks
480	b := m.Bounds()
481	b.Min.Y = p.a.paintOffset
482	b.Max.Y = p.a.paintOffset + p.a.maxh
483	for _, s := range ss {
484		s.Y += p.a.paintOffset
485		if s.Y < b.Min.Y {
486			continue
487		}
488		if s.Y >= b.Max.Y {
489			return
490		}
491		if s.X0 < b.Min.X {
492			s.X0 = b.Min.X
493		}
494		if s.X1 > b.Max.X {
495			s.X1 = b.Max.X
496		}
497		if s.X0 >= s.X1 {
498			continue
499		}
500		base := (s.Y-m.Rect.Min.Y)*m.Stride - m.Rect.Min.X
501		p := m.Pix[base+s.X0 : base+s.X1]
502		color := uint8(s.Alpha >> 8)
503		for i := range p {
504			p[i] = color
505		}
506	}
507}
508