...

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

Documentation: golang.org/x/image/font/opentype

     1  // Copyright 2017 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 opentype implements a glyph rasterizer for TTF (TrueType Fonts) and
     6  // OTF (OpenType Fonts).
     7  //
     8  // This package provides a high-level API, centered on the NewFace function,
     9  // implementing the golang.org/x/image/font.Face interface.
    10  //
    11  // The sibling golang.org/x/image/font/sfnt package provides a low-level API.
    12  package opentype // import "golang.org/x/image/font/opentype"
    13  
    14  import (
    15  	"image"
    16  	"image/draw"
    17  	"io"
    18  
    19  	"golang.org/x/image/font"
    20  	"golang.org/x/image/font/sfnt"
    21  	"golang.org/x/image/math/fixed"
    22  	"golang.org/x/image/vector"
    23  )
    24  
    25  // ParseCollection parses an OpenType font collection, such as TTC or OTC data,
    26  // from a []byte data source.
    27  //
    28  // If passed data for a single font, a TTF or OTF instead of a TTC or OTC, it
    29  // will return a collection containing 1 font.
    30  func ParseCollection(src []byte) (*Collection, error) {
    31  	return sfnt.ParseCollection(src)
    32  }
    33  
    34  // ParseCollectionReaderAt parses an OpenType collection, such as TTC or OTC
    35  // data, from an io.ReaderAt data source.
    36  //
    37  // If passed data for a single font, a TTF or OTF instead of a TTC or OTC, it
    38  // will return a collection containing 1 font.
    39  func ParseCollectionReaderAt(src io.ReaderAt) (*Collection, error) {
    40  	return sfnt.ParseCollectionReaderAt(src)
    41  }
    42  
    43  // Collection is a collection of one or more fonts.
    44  //
    45  // All of the Collection methods are safe to call concurrently.
    46  type Collection = sfnt.Collection
    47  
    48  // Parse parses an OpenType font, such as TTF or OTF data, from a []byte data
    49  // source.
    50  func Parse(src []byte) (*Font, error) {
    51  	return sfnt.Parse(src)
    52  }
    53  
    54  // ParseReaderAt parses an OpenType font, such as TTF or OTF data, from an
    55  // io.ReaderAt data source.
    56  func ParseReaderAt(src io.ReaderAt) (*Font, error) {
    57  	return sfnt.ParseReaderAt(src)
    58  }
    59  
    60  // Font is an OpenType font, also known as an SFNT font.
    61  //
    62  // All of the Font methods are safe to call concurrently, as long as each call
    63  // has a different *sfnt.Buffer (or nil).
    64  //
    65  // The Font methods that don't take a *sfnt.Buffer argument are always safe to
    66  // call concurrently.
    67  type Font = sfnt.Font
    68  
    69  // FaceOptions describes the possible options given to NewFace when
    70  // creating a new font.Face from a Font.
    71  type FaceOptions struct {
    72  	Size    float64      // Size is the font size in points
    73  	DPI     float64      // DPI is the dots per inch resolution
    74  	Hinting font.Hinting // Hinting selects how to quantize a vector font's glyph nodes
    75  }
    76  
    77  func defaultFaceOptions() *FaceOptions {
    78  	return &FaceOptions{
    79  		Size:    12,
    80  		DPI:     72,
    81  		Hinting: font.HintingNone,
    82  	}
    83  }
    84  
    85  // Face implements the font.Face interface for Font values.
    86  //
    87  // A Face is not safe to use concurrently.
    88  type Face struct {
    89  	f       *Font
    90  	hinting font.Hinting
    91  	scale   fixed.Int26_6
    92  
    93  	metrics    font.Metrics
    94  	metricsSet bool
    95  
    96  	buf  sfnt.Buffer
    97  	rast vector.Rasterizer
    98  	mask image.Alpha
    99  }
   100  
   101  // NewFace returns a new font.Face for the given Font.
   102  //
   103  // If opts is nil, sensible defaults will be used.
   104  func NewFace(f *Font, opts *FaceOptions) (font.Face, error) {
   105  	if opts == nil {
   106  		opts = defaultFaceOptions()
   107  	}
   108  	face := &Face{
   109  		f:       f,
   110  		hinting: opts.Hinting,
   111  		scale:   fixed.Int26_6(0.5 + (opts.Size * opts.DPI * 64 / 72)),
   112  	}
   113  	return face, nil
   114  }
   115  
   116  // Close satisfies the font.Face interface.
   117  func (f *Face) Close() error {
   118  	return nil
   119  }
   120  
   121  // Metrics satisfies the font.Face interface.
   122  func (f *Face) Metrics() font.Metrics {
   123  	if !f.metricsSet {
   124  		var err error
   125  		f.metrics, err = f.f.Metrics(&f.buf, f.scale, f.hinting)
   126  		if err != nil {
   127  			f.metrics = font.Metrics{}
   128  		}
   129  		f.metricsSet = true
   130  	}
   131  	return f.metrics
   132  }
   133  
   134  // Kern satisfies the font.Face interface.
   135  func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 {
   136  	x0, _ := f.f.GlyphIndex(&f.buf, r0)
   137  	x1, _ := f.f.GlyphIndex(&f.buf, r1)
   138  	k, err := f.f.Kern(&f.buf, x0, x1, fixed.Int26_6(f.f.UnitsPerEm()), f.hinting)
   139  	if err != nil {
   140  		return 0
   141  	}
   142  	return k
   143  }
   144  
   145  // Glyph satisfies the font.Face interface.
   146  func (f *Face) Glyph(dot fixed.Point26_6, r rune) (dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
   147  	x, err := f.f.GlyphIndex(&f.buf, r)
   148  	if err != nil {
   149  		return image.Rectangle{}, nil, image.Point{}, 0, false
   150  	}
   151  
   152  	// Call f.f.GlyphAdvance before f.f.LoadGlyph because the LoadGlyph docs
   153  	// say this about the &f.buf argument: the segments become invalid to use
   154  	// once [the buffer] is re-used.
   155  
   156  	advance, err = f.f.GlyphAdvance(&f.buf, x, f.scale, f.hinting)
   157  	if err != nil {
   158  		return image.Rectangle{}, nil, image.Point{}, 0, false
   159  	}
   160  
   161  	segments, err := f.f.LoadGlyph(&f.buf, x, f.scale, nil)
   162  	if err != nil {
   163  		return image.Rectangle{}, nil, image.Point{}, 0, false
   164  	}
   165  
   166  	// Numerical notation used below:
   167  	//  - 2    is an integer, "two"
   168  	//  - 2:16 is a 26.6 fixed point number, "two and a quarter"
   169  	//  - 2.5  is a float32 number, "two and a half"
   170  	// Using 26.6 fixed point numbers means that there are 64 sub-pixel units
   171  	// in 1 integer pixel unit.
   172  
   173  	// Translate the sub-pixel bounding box from glyph space (where the glyph
   174  	// origin is at (0:00, 0:00)) to dst space (where the glyph origin is at
   175  	// the dot). dst space is the coordinate space that contains both the dot
   176  	// (a sub-pixel position) and dr (an integer-pixel rectangle).
   177  	dBounds := segments.Bounds().Add(dot)
   178  
   179  	// Quantize the sub-pixel bounds (dBounds) to integer-pixel bounds (dr).
   180  	dr.Min.X = dBounds.Min.X.Floor()
   181  	dr.Min.Y = dBounds.Min.Y.Floor()
   182  	dr.Max.X = dBounds.Max.X.Ceil()
   183  	dr.Max.Y = dBounds.Max.Y.Ceil()
   184  	width := dr.Dx()
   185  	height := dr.Dy()
   186  	if width < 0 || height < 0 {
   187  		return image.Rectangle{}, nil, image.Point{}, 0, false
   188  	}
   189  
   190  	// Calculate the sub-pixel bias to convert from glyph space to rasterizer
   191  	// space. In glyph space, the segments may be to the left or right and
   192  	// above or below the glyph origin. In rasterizer space, the segments
   193  	// should only be right and below (or equal to) the top-left corner (0.0,
   194  	// 0.0). They should also be left and above (or equal to) the bottom-right
   195  	// corner (width, height), as the rasterizer should enclose the glyph
   196  	// bounding box.
   197  	//
   198  	// For example, suppose that dot.X was at the sub-pixel position 25:48,
   199  	// three quarters of the way into the 26th pixel, and that bounds.Min.X was
   200  	// 1:20. We then have dBounds.Min.X = 1:20 + 25:48 = 27:04, dr.Min.X = 27
   201  	// and biasX = 25:48 - 27:00 = -1:16. A vertical stroke at 1:20 in glyph
   202  	// space becomes (1:20 + -1:16) = 0:04 in rasterizer space. 0:04 as a
   203  	// fixed.Int26_6 value is float32(4)/64.0 = 0.0625 as a float32 value.
   204  	biasX := dot.X - fixed.Int26_6(dr.Min.X<<6)
   205  	biasY := dot.Y - fixed.Int26_6(dr.Min.Y<<6)
   206  
   207  	// Configure the mask image, re-allocating its buffer if necessary.
   208  	nPixels := width * height
   209  	if cap(f.mask.Pix) < nPixels {
   210  		f.mask.Pix = make([]uint8, 2*nPixels)
   211  	}
   212  	f.mask.Pix = f.mask.Pix[:nPixels]
   213  	f.mask.Stride = width
   214  	f.mask.Rect.Min.X = 0
   215  	f.mask.Rect.Min.Y = 0
   216  	f.mask.Rect.Max.X = width
   217  	f.mask.Rect.Max.Y = height
   218  
   219  	// Rasterize the biased segments, converting from fixed.Int26_6 to float32.
   220  	f.rast.Reset(width, height)
   221  	f.rast.DrawOp = draw.Src
   222  	for _, seg := range segments {
   223  		switch seg.Op {
   224  		case sfnt.SegmentOpMoveTo:
   225  			f.rast.MoveTo(
   226  				float32(seg.Args[0].X+biasX)/64,
   227  				float32(seg.Args[0].Y+biasY)/64,
   228  			)
   229  		case sfnt.SegmentOpLineTo:
   230  			f.rast.LineTo(
   231  				float32(seg.Args[0].X+biasX)/64,
   232  				float32(seg.Args[0].Y+biasY)/64,
   233  			)
   234  		case sfnt.SegmentOpQuadTo:
   235  			f.rast.QuadTo(
   236  				float32(seg.Args[0].X+biasX)/64,
   237  				float32(seg.Args[0].Y+biasY)/64,
   238  				float32(seg.Args[1].X+biasX)/64,
   239  				float32(seg.Args[1].Y+biasY)/64,
   240  			)
   241  		case sfnt.SegmentOpCubeTo:
   242  			f.rast.CubeTo(
   243  				float32(seg.Args[0].X+biasX)/64,
   244  				float32(seg.Args[0].Y+biasY)/64,
   245  				float32(seg.Args[1].X+biasX)/64,
   246  				float32(seg.Args[1].Y+biasY)/64,
   247  				float32(seg.Args[2].X+biasX)/64,
   248  				float32(seg.Args[2].Y+biasY)/64,
   249  			)
   250  		}
   251  	}
   252  	f.rast.Draw(&f.mask, f.mask.Bounds(), image.Opaque, image.Point{})
   253  
   254  	return dr, &f.mask, f.mask.Rect.Min, advance, x != 0
   255  }
   256  
   257  // GlyphBounds satisfies the font.Face interface.
   258  func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
   259  	x, _ := f.f.GlyphIndex(&f.buf, r)
   260  	bounds, advance, err := f.f.GlyphBounds(&f.buf, x, f.scale, f.hinting)
   261  	return bounds, advance, (err == nil) && (x != 0)
   262  }
   263  
   264  // GlyphAdvance satisfies the font.Face interface.
   265  func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
   266  	x, _ := f.f.GlyphIndex(&f.buf, r)
   267  	advance, err := f.f.GlyphAdvance(&f.buf, x, f.scale, f.hinting)
   268  	return advance, (err == nil) && (x != 0)
   269  }
   270  

View as plain text