font.go 11 KB

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