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  )