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