...

Source file src/golang.org/x/image/font/font.go

Documentation: golang.org/x/image/font

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

View as plain text