github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/image/font/font.go (about) 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. 10 package font // import "golang.org/x/image/font" 11 12 import ( 13 "image" 14 "image/draw" 15 "io" 16 17 "golang.org/x/image/math/fixed" 18 ) 19 20 // TODO: who is responsible for caches (glyph images, glyph indices, kerns)? 21 // The Drawer or the Face? 22 23 // Face is a font face. Its glyphs are often derived from a font file, such as 24 // "Comic_Sans_MS.ttf", but a face has a specific size, style, weight and 25 // hinting. For example, the 12pt and 18pt versions of Comic Sans are two 26 // different faces, even if derived from the same font file. 27 // 28 // A Face is not safe for concurrent use by multiple goroutines, as its methods 29 // may re-use implementation-specific caches and mask image buffers. 30 // 31 // To create a Face, look to other packages that implement specific font file 32 // formats. 33 type Face interface { 34 io.Closer 35 36 // Glyph returns the draw.DrawMask parameters (dr, mask, maskp) to draw r's 37 // glyph at the sub-pixel destination location dot, and that glyph's 38 // advance width. 39 // 40 // It returns !ok if the face does not contain a glyph for r. 41 // 42 // The contents of the mask image returned by one Glyph call may change 43 // after the next Glyph call. Callers that want to cache the mask must make 44 // a copy. 45 Glyph(dot fixed.Point26_6, r rune) ( 46 dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) 47 48 // GlyphBounds returns the bounding box of r's glyph, drawn at a dot equal 49 // to the origin, and that glyph's advance width. 50 // 51 // It returns !ok if the face does not contain a glyph for r. 52 // 53 // The glyph's ascent and descent equal -bounds.Min.Y and +bounds.Max.Y. A 54 // visual depiction of what these metrics are is at 55 // https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png 56 GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) 57 58 // GlyphAdvance returns the advance width of r's glyph. 59 // 60 // It returns !ok if the face does not contain a glyph for r. 61 GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) 62 63 // Kern returns the horizontal adjustment for the kerning pair (r0, r1). A 64 // positive kern means to move the glyphs further apart. 65 Kern(r0, r1 rune) fixed.Int26_6 66 67 // TODO: per-font Metrics. 68 // TODO: ColoredGlyph for various emoji? 69 // TODO: Ligatures? Shaping? 70 } 71 72 // TODO: Drawer.Layout or Drawer.Measure methods to measure text without 73 // drawing? 74 75 // Drawer draws text on a destination image. 76 // 77 // A Drawer is not safe for concurrent use by multiple goroutines, since its 78 // Face is not. 79 type Drawer struct { 80 // Dst is the destination image. 81 Dst draw.Image 82 // Src is the source image. 83 Src image.Image 84 // Face provides the glyph mask images. 85 Face Face 86 // Dot is the baseline location to draw the next glyph. The majority of the 87 // affected pixels will be above and to the right of the dot, but some may 88 // be below or to the left. For example, drawing a 'j' in an italic face 89 // may affect pixels below and to the left of the dot. 90 Dot fixed.Point26_6 91 92 // TODO: Clip image.Image? 93 // TODO: SrcP image.Point for Src images other than *image.Uniform? How 94 // does it get updated during DrawString? 95 } 96 97 // TODO: should DrawString return the last rune drawn, so the next DrawString 98 // call can kern beforehand? Or should that be the responsibility of the caller 99 // if they really want to do that, since they have to explicitly shift d.Dot 100 // anyway? 101 // 102 // In general, we'd have a DrawBytes([]byte) and DrawRuneReader(io.RuneReader) 103 // and the last case can't assume that you can rewind the stream. 104 // 105 // TODO: how does this work with line breaking: drawing text up until a 106 // vertical line? Should DrawString return the number of runes drawn? 107 108 // DrawString draws s at the dot and advances the dot's location. 109 func (d *Drawer) DrawString(s string) { 110 var prevC rune 111 for i, c := range s { 112 if i != 0 { 113 d.Dot.X += d.Face.Kern(prevC, c) 114 } 115 dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c) 116 if !ok { 117 // TODO: is falling back on the U+FFFD glyph the responsibility of 118 // the Drawer or the Face? 119 // TODO: set prevC = '\ufffd'? 120 continue 121 } 122 draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over) 123 d.Dot.X += advance 124 prevC = c 125 } 126 } 127 128 // MeasureString returns how far dot would advance by drawing s. 129 func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) { 130 var prevC rune 131 for i, c := range s { 132 if i != 0 { 133 advance += d.Face.Kern(prevC, c) 134 } 135 a, ok := d.Face.GlyphAdvance(c) 136 if !ok { 137 // TODO: is falling back on the U+FFFD glyph the responsibility of 138 // the Drawer or the Face? 139 // TODO: set prevC = '\ufffd'? 140 continue 141 } 142 advance += a 143 prevC = c 144 } 145 return advance 146 } 147 148 // Hinting selects how to quantize a vector font's glyph nodes. 149 // 150 // Not all fonts support hinting. 151 type Hinting int 152 153 const ( 154 HintingNone Hinting = iota 155 HintingVertical 156 HintingFull 157 ) 158 159 // Stretch selects a normal, condensed, or expanded face. 160 // 161 // Not all fonts support stretches. 162 type Stretch int 163 164 const ( 165 StretchUltraCondensed Stretch = -4 166 StretchExtraCondensed Stretch = -3 167 StretchCondensed Stretch = -2 168 StretchSemiCondensed Stretch = -1 169 StretchNormal Stretch = +0 170 StretchSemiExpanded Stretch = +1 171 StretchExpanded Stretch = +2 172 StretchExtraExpanded Stretch = +3 173 StretchUltraExpanded Stretch = +4 174 ) 175 176 // Style selects a normal, italic, or oblique face. 177 // 178 // Not all fonts support styles. 179 type Style int 180 181 const ( 182 StyleNormal Style = iota 183 StyleItalic 184 StyleOblique 185 ) 186 187 // Weight selects a normal, light or bold face. 188 // 189 // Not all fonts support weights. 190 type Weight int 191 192 const ( 193 WeightThin Weight = 100 194 WeightExtraLight Weight = 200 195 WeightLight Weight = 300 196 WeightNormal Weight = 400 197 WeightMedium Weight = 500 198 WeightSemiBold Weight = 600 199 WeightBold Weight = 700 200 WeightExtraBold Weight = 800 201 WeightBlack Weight = 900 202 )