1// Copyright 2015 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 font defines an interface for font faces, for drawing text on an
6// image.
7//
8// Other packages provide font face implementations. For example, a truetype
9// package would provide one based on .ttf font files.
10package font // import "golang.org/x/image/font"
11
12import (
13	"image"
14	"image/draw"
15	"io"
16	"unicode/utf8"
17
18	"golang.org/x/image/math/fixed"
19)
20
21// TODO: who is responsible for caches (glyph images, glyph indices, kerns)?
22// The Drawer or the Face?
23
24// Face is a font face. Its glyphs are often derived from a font file, such as
25// "Comic_Sans_MS.ttf", but a face has a specific size, style, weight and
26// hinting. For example, the 12pt and 18pt versions of Comic Sans are two
27// different faces, even if derived from the same font file.
28//
29// A Face is not safe for concurrent use by multiple goroutines, as its methods
30// may re-use implementation-specific caches and mask image buffers.
31//
32// To create a Face, look to other packages that implement specific font file
33// formats.
34type Face interface {
35	io.Closer
36
37	// Glyph returns the draw.DrawMask parameters (dr, mask, maskp) to draw r's
38	// glyph at the sub-pixel destination location dot, and that glyph's
39	// advance width.
40	//
41	// It returns !ok if the face does not contain a glyph for r.
42	//
43	// The contents of the mask image returned by one Glyph call may change
44	// after the next Glyph call. Callers that want to cache the mask must make
45	// a copy.
46	Glyph(dot fixed.Point26_6, r rune) (
47		dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool)
48
49	// GlyphBounds returns the bounding box of r's glyph, drawn at a dot equal
50	// to the origin, and that glyph's advance width.
51	//
52	// It returns !ok if the face does not contain a glyph for r.
53	//
54	// The glyph's ascent and descent are equal to -bounds.Min.Y and
55	// +bounds.Max.Y. The glyph's left-side and right-side bearings are equal
56	// to bounds.Min.X and advance-bounds.Max.X. A visual depiction of what
57	// these metrics are is at
58	// https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyphterms_2x.png
59	GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool)
60
61	// GlyphAdvance returns the advance width of r's glyph.
62	//
63	// It returns !ok if the face does not contain a glyph for r.
64	GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool)
65
66	// Kern returns the horizontal adjustment for the kerning pair (r0, r1). A
67	// positive kern means to move the glyphs further apart.
68	Kern(r0, r1 rune) fixed.Int26_6
69
70	// Metrics returns the metrics for this Face.
71	Metrics() Metrics
72
73	// TODO: ColoredGlyph for various emoji?
74	// TODO: Ligatures? Shaping?
75}
76
77// Metrics holds the metrics for a Face. A visual depiction is at
78// https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png
79type Metrics struct {
80	// Height is the recommended amount of vertical space between two lines of
81	// text.
82	Height fixed.Int26_6
83
84	// Ascent is the distance from the top of a line to its baseline.
85	Ascent fixed.Int26_6
86
87	// Descent is the distance from the bottom of a line to its baseline. The
88	// value is typically positive, even though a descender goes below the
89	// baseline.
90	Descent fixed.Int26_6
91
92	// XHeight is the distance from the top of non-ascending lowercase letters
93	// to the baseline.
94	XHeight fixed.Int26_6
95
96	// CapHeight is the distance from the top of uppercase letters to the
97	// baseline.
98	CapHeight fixed.Int26_6
99
100	// CaretSlope is the slope of a caret as a vector with the Y axis pointing up.
101	// The slope {0, 1} is the vertical caret.
102	CaretSlope image.Point
103}
104
105// Drawer draws text on a destination image.
106//
107// A Drawer is not safe for concurrent use by multiple goroutines, since its
108// Face is not.
109type Drawer struct {
110	// Dst is the destination image.
111	Dst draw.Image
112	// Src is the source image.
113	Src image.Image
114	// Face provides the glyph mask images.
115	Face Face
116	// Dot is the baseline location to draw the next glyph. The majority of the
117	// affected pixels will be above and to the right of the dot, but some may
118	// be below or to the left. For example, drawing a 'j' in an italic face
119	// may affect pixels below and to the left of the dot.
120	Dot fixed.Point26_6
121
122	// TODO: Clip image.Image?
123	// TODO: SrcP image.Point for Src images other than *image.Uniform? How
124	// does it get updated during DrawString?
125}
126
127// TODO: should DrawString return the last rune drawn, so the next DrawString
128// call can kern beforehand? Or should that be the responsibility of the caller
129// if they really want to do that, since they have to explicitly shift d.Dot
130// anyway? What if ligatures span more than two runes? What if grapheme
131// clusters span multiple runes?
132//
133// TODO: do we assume that the input is in any particular Unicode Normalization
134// Form?
135//
136// TODO: have DrawRunes(s []rune)? DrawRuneReader(io.RuneReader)?? If we take
137// io.RuneReader, we can't assume that we can rewind the stream.
138//
139// TODO: how does this work with line breaking: drawing text up until a
140// vertical line? Should DrawString return the number of runes drawn?
141
142// DrawBytes draws s at the dot and advances the dot's location.
143//
144// It is equivalent to DrawString(string(s)) but may be more efficient.
145func (d *Drawer) DrawBytes(s []byte) {
146	prevC := rune(-1)
147	for len(s) > 0 {
148		c, size := utf8.DecodeRune(s)
149		s = s[size:]
150		if prevC >= 0 {
151			d.Dot.X += d.Face.Kern(prevC, c)
152		}
153		dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
154		if !ok {
155			// TODO: is falling back on the U+FFFD glyph the responsibility of
156			// the Drawer or the Face?
157			// TODO: set prevC = '\ufffd'?
158			continue
159		}
160		draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
161		d.Dot.X += advance
162		prevC = c
163	}
164}
165
166// DrawString draws s at the dot and advances the dot's location.
167func (d *Drawer) DrawString(s string) {
168	prevC := rune(-1)
169	for _, c := range s {
170		if prevC >= 0 {
171			d.Dot.X += d.Face.Kern(prevC, c)
172		}
173		dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
174		if !ok {
175			// TODO: is falling back on the U+FFFD glyph the responsibility of
176			// the Drawer or the Face?
177			// TODO: set prevC = '\ufffd'?
178			continue
179		}
180		draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
181		d.Dot.X += advance
182		prevC = c
183	}
184}
185
186// BoundBytes returns the bounding box of s, drawn at the drawer dot, as well as
187// the advance.
188//
189// It is equivalent to BoundBytes(string(s)) but may be more efficient.
190func (d *Drawer) BoundBytes(s []byte) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
191	bounds, advance = BoundBytes(d.Face, s)
192	bounds.Min = bounds.Min.Add(d.Dot)
193	bounds.Max = bounds.Max.Add(d.Dot)
194	return
195}
196
197// BoundString returns the bounding box of s, drawn at the drawer dot, as well
198// as the advance.
199func (d *Drawer) BoundString(s string) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
200	bounds, advance = BoundString(d.Face, s)
201	bounds.Min = bounds.Min.Add(d.Dot)
202	bounds.Max = bounds.Max.Add(d.Dot)
203	return
204}
205
206// MeasureBytes returns how far dot would advance by drawing s.
207//
208// It is equivalent to MeasureString(string(s)) but may be more efficient.
209func (d *Drawer) MeasureBytes(s []byte) (advance fixed.Int26_6) {
210	return MeasureBytes(d.Face, s)
211}
212
213// MeasureString returns how far dot would advance by drawing s.
214func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) {
215	return MeasureString(d.Face, s)
216}
217
218// BoundBytes returns the bounding box of s with f, drawn at a dot equal to the
219// origin, as well as the advance.
220//
221// It is equivalent to BoundString(string(s)) but may be more efficient.
222func BoundBytes(f Face, s []byte) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
223	prevC := rune(-1)
224	for len(s) > 0 {
225		c, size := utf8.DecodeRune(s)
226		s = s[size:]
227		if prevC >= 0 {
228			advance += f.Kern(prevC, c)
229		}
230		b, a, ok := f.GlyphBounds(c)
231		if !ok {
232			// TODO: is falling back on the U+FFFD glyph the responsibility of
233			// the Drawer or the Face?
234			// TODO: set prevC = '\ufffd'?
235			continue
236		}
237		b.Min.X += advance
238		b.Max.X += advance
239		bounds = bounds.Union(b)
240		advance += a
241		prevC = c
242	}
243	return
244}
245
246// BoundString returns the bounding box of s with f, drawn at a dot equal to the
247// origin, as well as the advance.
248func BoundString(f Face, s string) (bounds fixed.Rectangle26_6, advance fixed.Int26_6) {
249	prevC := rune(-1)
250	for _, c := range s {
251		if prevC >= 0 {
252			advance += f.Kern(prevC, c)
253		}
254		b, a, ok := f.GlyphBounds(c)
255		if !ok {
256			// TODO: is falling back on the U+FFFD glyph the responsibility of
257			// the Drawer or the Face?
258			// TODO: set prevC = '\ufffd'?
259			continue
260		}
261		b.Min.X += advance
262		b.Max.X += advance
263		bounds = bounds.Union(b)
264		advance += a
265		prevC = c
266	}
267	return
268}
269
270// MeasureBytes returns how far dot would advance by drawing s with f.
271//
272// It is equivalent to MeasureString(string(s)) but may be more efficient.
273func MeasureBytes(f Face, s []byte) (advance fixed.Int26_6) {
274	prevC := rune(-1)
275	for len(s) > 0 {
276		c, size := utf8.DecodeRune(s)
277		s = s[size:]
278		if prevC >= 0 {
279			advance += f.Kern(prevC, c)
280		}
281		a, ok := f.GlyphAdvance(c)
282		if !ok {
283			// TODO: is falling back on the U+FFFD glyph the responsibility of
284			// the Drawer or the Face?
285			// TODO: set prevC = '\ufffd'?
286			continue
287		}
288		advance += a
289		prevC = c
290	}
291	return advance
292}
293
294// MeasureString returns how far dot would advance by drawing s with f.
295func MeasureString(f Face, s string) (advance fixed.Int26_6) {
296	prevC := rune(-1)
297	for _, c := range s {
298		if prevC >= 0 {
299			advance += f.Kern(prevC, c)
300		}
301		a, ok := f.GlyphAdvance(c)
302		if !ok {
303			// TODO: is falling back on the U+FFFD glyph the responsibility of
304			// the Drawer or the Face?
305			// TODO: set prevC = '\ufffd'?
306			continue
307		}
308		advance += a
309		prevC = c
310	}
311	return advance
312}
313
314// Hinting selects how to quantize a vector font's glyph nodes.
315//
316// Not all fonts support hinting.
317type Hinting int
318
319const (
320	HintingNone Hinting = iota
321	HintingVertical
322	HintingFull
323)
324
325// Stretch selects a normal, condensed, or expanded face.
326//
327// Not all fonts support stretches.
328type Stretch int
329
330const (
331	StretchUltraCondensed Stretch = -4
332	StretchExtraCondensed Stretch = -3
333	StretchCondensed      Stretch = -2
334	StretchSemiCondensed  Stretch = -1
335	StretchNormal         Stretch = +0
336	StretchSemiExpanded   Stretch = +1
337	StretchExpanded       Stretch = +2
338	StretchExtraExpanded  Stretch = +3
339	StretchUltraExpanded  Stretch = +4
340)
341
342// Style selects a normal, italic, or oblique face.
343//
344// Not all fonts support styles.
345type Style int
346
347const (
348	StyleNormal Style = iota
349	StyleItalic
350	StyleOblique
351)
352
353// Weight selects a normal, light or bold face.
354//
355// Not all fonts support weights.
356//
357// The named Weight constants (e.g. WeightBold) correspond to CSS' common
358// weight names (e.g. "Bold"), but the numerical values differ, so that in Go,
359// the zero value means to use a normal weight. For the CSS names and values,
360// see https://developer.mozilla.org/en/docs/Web/CSS/font-weight
361type Weight int
362
363const (
364	WeightThin       Weight = -3 // CSS font-weight value 100.
365	WeightExtraLight Weight = -2 // CSS font-weight value 200.
366	WeightLight      Weight = -1 // CSS font-weight value 300.
367	WeightNormal     Weight = +0 // CSS font-weight value 400.
368	WeightMedium     Weight = +1 // CSS font-weight value 500.
369	WeightSemiBold   Weight = +2 // CSS font-weight value 600.
370	WeightBold       Weight = +3 // CSS font-weight value 700.
371	WeightExtraBold  Weight = +4 // CSS font-weight value 800.
372	WeightBlack      Weight = +5 // CSS font-weight value 900.
373)
374