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  )