...

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

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

     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 sfnt
     6  
     7  import (
     8  	"golang.org/x/image/math/fixed"
     9  )
    10  
    11  // Flags for simple (non-compound) glyphs.
    12  //
    13  // See https://www.microsoft.com/typography/OTSPEC/glyf.htm
    14  const (
    15  	flagOnCurve      = 1 << 0 // 0x0001
    16  	flagXShortVector = 1 << 1 // 0x0002
    17  	flagYShortVector = 1 << 2 // 0x0004
    18  	flagRepeat       = 1 << 3 // 0x0008
    19  
    20  	// The same flag bits are overloaded to have two meanings, dependent on the
    21  	// value of the flag{X,Y}ShortVector bits.
    22  	flagPositiveXShortVector = 1 << 4 // 0x0010
    23  	flagThisXIsSame          = 1 << 4 // 0x0010
    24  	flagPositiveYShortVector = 1 << 5 // 0x0020
    25  	flagThisYIsSame          = 1 << 5 // 0x0020
    26  )
    27  
    28  // Flags for compound glyphs.
    29  //
    30  // See https://www.microsoft.com/typography/OTSPEC/glyf.htm
    31  const (
    32  	flagArg1And2AreWords        = 1 << 0  // 0x0001
    33  	flagArgsAreXYValues         = 1 << 1  // 0x0002
    34  	flagRoundXYToGrid           = 1 << 2  // 0x0004
    35  	flagWeHaveAScale            = 1 << 3  // 0x0008
    36  	flagReserved4               = 1 << 4  // 0x0010
    37  	flagMoreComponents          = 1 << 5  // 0x0020
    38  	flagWeHaveAnXAndYScale      = 1 << 6  // 0x0040
    39  	flagWeHaveATwoByTwo         = 1 << 7  // 0x0080
    40  	flagWeHaveInstructions      = 1 << 8  // 0x0100
    41  	flagUseMyMetrics            = 1 << 9  // 0x0200
    42  	flagOverlapCompound         = 1 << 10 // 0x0400
    43  	flagScaledComponentOffset   = 1 << 11 // 0x0800
    44  	flagUnscaledComponentOffset = 1 << 12 // 0x1000
    45  )
    46  
    47  func midPoint(p, q fixed.Point26_6) fixed.Point26_6 {
    48  	return fixed.Point26_6{
    49  		X: (p.X + q.X) / 2,
    50  		Y: (p.Y + q.Y) / 2,
    51  	}
    52  }
    53  
    54  func parseLoca(src *source, loca table, glyfOffset uint32, indexToLocFormat bool, numGlyphs int32) (locations []uint32, err error) {
    55  	if indexToLocFormat {
    56  		if loca.length != 4*uint32(numGlyphs+1) {
    57  			return nil, errInvalidLocaTable
    58  		}
    59  	} else {
    60  		if loca.length != 2*uint32(numGlyphs+1) {
    61  			return nil, errInvalidLocaTable
    62  		}
    63  	}
    64  
    65  	locations = make([]uint32, numGlyphs+1)
    66  	buf, err := src.view(nil, int(loca.offset), int(loca.length))
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	if indexToLocFormat {
    72  		for i := range locations {
    73  			locations[i] = 1*uint32(u32(buf[4*i:])) + glyfOffset
    74  		}
    75  	} else {
    76  		for i := range locations {
    77  			locations[i] = 2*uint32(u16(buf[2*i:])) + glyfOffset
    78  		}
    79  	}
    80  	return locations, err
    81  }
    82  
    83  // https://www.microsoft.com/typography/OTSPEC/glyf.htm says that "Each
    84  // glyph begins with the following [10 byte] header".
    85  const glyfHeaderLen = 10
    86  
    87  func loadGlyf(f *Font, b *Buffer, x GlyphIndex, stackBottom, recursionDepth uint32) error {
    88  	data, _, _, err := f.viewGlyphData(b, x)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	if len(data) == 0 {
    93  		return nil
    94  	}
    95  	if len(data) < glyfHeaderLen {
    96  		return errInvalidGlyphData
    97  	}
    98  	index := glyfHeaderLen
    99  
   100  	numContours, numPoints := int16(u16(data)), 0
   101  	switch {
   102  	case numContours == -1:
   103  		// We have a compound glyph. No-op.
   104  	case numContours == 0:
   105  		return nil
   106  	case numContours > 0:
   107  		// We have a simple (non-compound) glyph.
   108  		index += 2 * int(numContours)
   109  		if index > len(data) {
   110  			return errInvalidGlyphData
   111  		}
   112  		// The +1 for numPoints is because the value in the file format is
   113  		// inclusive, but Go's slice[:index] semantics are exclusive.
   114  		numPoints = 1 + int(u16(data[index-2:]))
   115  	default:
   116  		return errInvalidGlyphData
   117  	}
   118  
   119  	if numContours < 0 {
   120  		return loadCompoundGlyf(f, b, data[glyfHeaderLen:], stackBottom, recursionDepth)
   121  	}
   122  
   123  	// Skip the hinting instructions.
   124  	index += 2
   125  	if index > len(data) {
   126  		return errInvalidGlyphData
   127  	}
   128  	hintsLength := int(u16(data[index-2:]))
   129  	index += hintsLength
   130  	if index > len(data) {
   131  		return errInvalidGlyphData
   132  	}
   133  
   134  	// For simple (non-compound) glyphs, the remainder of the glyf data
   135  	// consists of (flags, x, y) points: the Bézier curve segments. These are
   136  	// stored in columns (all the flags first, then all the x coordinates, then
   137  	// all the y coordinates), not rows, as it compresses better.
   138  	//
   139  	// Decoding those points in row order involves two passes. The first pass
   140  	// determines the indexes (relative to the data slice) of where the flags,
   141  	// the x coordinates and the y coordinates each start.
   142  	flagIndex := int32(index)
   143  	xIndex, yIndex, ok := findXYIndexes(data, index, numPoints)
   144  	if !ok {
   145  		return errInvalidGlyphData
   146  	}
   147  
   148  	// The second pass decodes each (flags, x, y) tuple in row order.
   149  	g := glyfIter{
   150  		data:      data,
   151  		flagIndex: flagIndex,
   152  		xIndex:    xIndex,
   153  		yIndex:    yIndex,
   154  		endIndex:  glyfHeaderLen,
   155  		// The -1 on prevEnd and finalEnd are because the contour-end index in
   156  		// the file format is inclusive, but Go's slice[:index] is exclusive.
   157  		prevEnd:     -1,
   158  		finalEnd:    int32(numPoints - 1),
   159  		numContours: int32(numContours),
   160  	}
   161  	for g.nextContour() {
   162  		for g.nextSegment() {
   163  			b.segments = append(b.segments, g.seg)
   164  		}
   165  	}
   166  	return g.err
   167  }
   168  
   169  func findXYIndexes(data []byte, index, numPoints int) (xIndex, yIndex int32, ok bool) {
   170  	xDataLen := 0
   171  	yDataLen := 0
   172  	for i := 0; ; {
   173  		if i > numPoints {
   174  			return 0, 0, false
   175  		}
   176  		if i == numPoints {
   177  			break
   178  		}
   179  
   180  		repeatCount := 1
   181  		if index >= len(data) {
   182  			return 0, 0, false
   183  		}
   184  		flag := data[index]
   185  		index++
   186  		if flag&flagRepeat != 0 {
   187  			if index >= len(data) {
   188  				return 0, 0, false
   189  			}
   190  			repeatCount += int(data[index])
   191  			index++
   192  		}
   193  
   194  		xSize := 0
   195  		if flag&flagXShortVector != 0 {
   196  			xSize = 1
   197  		} else if flag&flagThisXIsSame == 0 {
   198  			xSize = 2
   199  		}
   200  		xDataLen += xSize * repeatCount
   201  
   202  		ySize := 0
   203  		if flag&flagYShortVector != 0 {
   204  			ySize = 1
   205  		} else if flag&flagThisYIsSame == 0 {
   206  			ySize = 2
   207  		}
   208  		yDataLen += ySize * repeatCount
   209  
   210  		i += repeatCount
   211  	}
   212  	if index+xDataLen+yDataLen > len(data) {
   213  		return 0, 0, false
   214  	}
   215  	return int32(index), int32(index + xDataLen), true
   216  }
   217  
   218  func loadCompoundGlyf(f *Font, b *Buffer, data []byte, stackBottom, recursionDepth uint32) error {
   219  	if recursionDepth++; recursionDepth == maxCompoundRecursionDepth {
   220  		return errUnsupportedCompoundGlyph
   221  	}
   222  
   223  	// Read and process the compound glyph's components. They are two separate
   224  	// for loops, since reading parses the elements of the data slice, and
   225  	// processing can overwrite the backing array.
   226  
   227  	stackTop := stackBottom
   228  	for {
   229  		if stackTop >= maxCompoundStackSize {
   230  			return errUnsupportedCompoundGlyph
   231  		}
   232  		elem := &b.compoundStack[stackTop]
   233  		stackTop++
   234  
   235  		if len(data) < 4 {
   236  			return errInvalidGlyphData
   237  		}
   238  		flags := u16(data)
   239  		elem.glyphIndex = GlyphIndex(u16(data[2:]))
   240  		if flags&flagArg1And2AreWords == 0 {
   241  			if len(data) < 6 {
   242  				return errInvalidGlyphData
   243  			}
   244  			elem.dx = int16(int8(data[4]))
   245  			elem.dy = int16(int8(data[5]))
   246  			data = data[6:]
   247  		} else {
   248  			if len(data) < 8 {
   249  				return errInvalidGlyphData
   250  			}
   251  			elem.dx = int16(u16(data[4:]))
   252  			elem.dy = int16(u16(data[6:]))
   253  			data = data[8:]
   254  		}
   255  
   256  		if flags&flagArgsAreXYValues == 0 {
   257  			return errUnsupportedCompoundGlyph
   258  		}
   259  		elem.hasTransform = flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0
   260  		if elem.hasTransform {
   261  			switch {
   262  			case flags&flagWeHaveAScale != 0:
   263  				if len(data) < 2 {
   264  					return errInvalidGlyphData
   265  				}
   266  				elem.transformXX = int16(u16(data))
   267  				elem.transformXY = 0
   268  				elem.transformYX = 0
   269  				elem.transformYY = elem.transformXX
   270  				data = data[2:]
   271  			case flags&flagWeHaveAnXAndYScale != 0:
   272  				if len(data) < 4 {
   273  					return errInvalidGlyphData
   274  				}
   275  				elem.transformXX = int16(u16(data[0:]))
   276  				elem.transformXY = 0
   277  				elem.transformYX = 0
   278  				elem.transformYY = int16(u16(data[2:]))
   279  				data = data[4:]
   280  			case flags&flagWeHaveATwoByTwo != 0:
   281  				if len(data) < 8 {
   282  					return errInvalidGlyphData
   283  				}
   284  				elem.transformXX = int16(u16(data[0:]))
   285  				elem.transformXY = int16(u16(data[2:]))
   286  				elem.transformYX = int16(u16(data[4:]))
   287  				elem.transformYY = int16(u16(data[6:]))
   288  				data = data[8:]
   289  			}
   290  		}
   291  
   292  		if flags&flagMoreComponents == 0 {
   293  			break
   294  		}
   295  	}
   296  
   297  	// To support hinting, we'd have to save the remaining bytes in data here
   298  	// and interpret them after the for loop below, since that for loop's
   299  	// loadGlyf calls can overwrite the backing array.
   300  
   301  	for i := stackBottom; i < stackTop; i++ {
   302  		elem := &b.compoundStack[i]
   303  		base := len(b.segments)
   304  		if err := loadGlyf(f, b, elem.glyphIndex, stackTop, recursionDepth); err != nil {
   305  			return err
   306  		}
   307  		dx, dy := fixed.Int26_6(elem.dx), fixed.Int26_6(elem.dy)
   308  		segments := b.segments[base:]
   309  		if elem.hasTransform {
   310  			txx := elem.transformXX
   311  			txy := elem.transformXY
   312  			tyx := elem.transformYX
   313  			tyy := elem.transformYY
   314  			for j := range segments {
   315  				transformArgs(&segments[j].Args, txx, txy, tyx, tyy, dx, dy)
   316  			}
   317  		} else {
   318  			for j := range segments {
   319  				translateArgs(&segments[j].Args, dx, dy)
   320  			}
   321  		}
   322  	}
   323  
   324  	return nil
   325  }
   326  
   327  type glyfIter struct {
   328  	data []byte
   329  	err  error
   330  
   331  	// Various indices into the data slice. See the "Decoding those points in
   332  	// row order" comment above.
   333  	flagIndex int32
   334  	xIndex    int32
   335  	yIndex    int32
   336  
   337  	// endIndex points to the uint16 that is the inclusive point index of the
   338  	// current contour's end. prevEnd is the previous contour's end. finalEnd
   339  	// should match the final contour's end.
   340  	endIndex int32
   341  	prevEnd  int32
   342  	finalEnd int32
   343  
   344  	// c and p count the current contour and point, up to numContours and
   345  	// numPoints.
   346  	c, numContours int32
   347  	p, nPoints     int32
   348  
   349  	// The next two groups of fields track points and segments. Points are what
   350  	// the underlying file format provides. Bézier curve segments are what the
   351  	// rasterizer consumes.
   352  	//
   353  	// Points are either on-curve or off-curve. Two consecutive on-curve points
   354  	// define a linear curve segment between them. N off-curve points between
   355  	// on-curve points define N quadratic curve segments. The TrueType glyf
   356  	// format does not use cubic curves. If N is greater than 1, some of these
   357  	// segment end points are implicit, the midpoint of two off-curve points.
   358  	// Given the points A, B1, B2, ..., BN, C, where A and C are on-curve and
   359  	// all the Bs are off-curve, the segments are:
   360  	//
   361  	//	- A,                  B1, midpoint(B1, B2)
   362  	//	- midpoint(B1, B2),   B2, midpoint(B2, B3)
   363  	//	- midpoint(B2, B3),   B3, midpoint(B3, B4)
   364  	//	- ...
   365  	//	- midpoint(BN-1, BN), BN, C
   366  	//
   367  	// Note that the sequence of Bs may wrap around from the last point in the
   368  	// glyf data to the first. A and C may also be the same point (the only
   369  	// explicit on-curve point), or there may be no explicit on-curve points at
   370  	// all (but still implicit ones between explicit off-curve points).
   371  
   372  	// Points.
   373  	x, y    int16
   374  	on      bool
   375  	flag    uint8
   376  	repeats uint8
   377  
   378  	// Segments.
   379  	closing            bool
   380  	closed             bool
   381  	firstOnCurveValid  bool
   382  	firstOffCurveValid bool
   383  	lastOffCurveValid  bool
   384  	firstOnCurve       fixed.Point26_6
   385  	firstOffCurve      fixed.Point26_6
   386  	lastOffCurve       fixed.Point26_6
   387  	seg                Segment
   388  }
   389  
   390  func (g *glyfIter) nextContour() (ok bool) {
   391  	if g.c == g.numContours {
   392  		if g.prevEnd != g.finalEnd {
   393  			g.err = errInvalidGlyphData
   394  		}
   395  		return false
   396  	}
   397  	g.c++
   398  
   399  	end := int32(u16(g.data[g.endIndex:]))
   400  	g.endIndex += 2
   401  	if (end <= g.prevEnd) || (g.finalEnd < end) {
   402  		g.err = errInvalidGlyphData
   403  		return false
   404  	}
   405  	g.nPoints = end - g.prevEnd
   406  	g.p = 0
   407  	g.prevEnd = end
   408  
   409  	g.closing = false
   410  	g.closed = false
   411  	g.firstOnCurveValid = false
   412  	g.firstOffCurveValid = false
   413  	g.lastOffCurveValid = false
   414  
   415  	return true
   416  }
   417  
   418  func (g *glyfIter) close() {
   419  	switch {
   420  	case !g.firstOffCurveValid && !g.lastOffCurveValid:
   421  		g.closed = true
   422  		g.seg = Segment{
   423  			Op:   SegmentOpLineTo,
   424  			Args: [3]fixed.Point26_6{g.firstOnCurve},
   425  		}
   426  	case !g.firstOffCurveValid && g.lastOffCurveValid:
   427  		g.closed = true
   428  		g.seg = Segment{
   429  			Op:   SegmentOpQuadTo,
   430  			Args: [3]fixed.Point26_6{g.lastOffCurve, g.firstOnCurve},
   431  		}
   432  	case g.firstOffCurveValid && !g.lastOffCurveValid:
   433  		g.closed = true
   434  		g.seg = Segment{
   435  			Op:   SegmentOpQuadTo,
   436  			Args: [3]fixed.Point26_6{g.firstOffCurve, g.firstOnCurve},
   437  		}
   438  	case g.firstOffCurveValid && g.lastOffCurveValid:
   439  		g.lastOffCurveValid = false
   440  		g.seg = Segment{
   441  			Op: SegmentOpQuadTo,
   442  			Args: [3]fixed.Point26_6{
   443  				g.lastOffCurve,
   444  				midPoint(g.lastOffCurve, g.firstOffCurve),
   445  			},
   446  		}
   447  	}
   448  }
   449  
   450  func (g *glyfIter) nextSegment() (ok bool) {
   451  	for !g.closed {
   452  		if g.closing || !g.nextPoint() {
   453  			g.closing = true
   454  			g.close()
   455  			return true
   456  		}
   457  
   458  		// Convert the tuple (g.x, g.y) to a fixed.Point26_6, since the latter
   459  		// is what's held in a Segment. The input (g.x, g.y) is a pair of int16
   460  		// values, measured in font units, since that is what the underlying
   461  		// format provides. The output is a pair of fixed.Int26_6 values. A
   462  		// fixed.Int26_6 usually represents a 26.6 fixed number of pixels, but
   463  		// this here is just a straight numerical conversion, with no scaling
   464  		// factor. A later step scales the Segment.Args values by such a factor
   465  		// to convert e.g. 1792 font units to 10.5 pixels at 2048 font units
   466  		// per em and 12 ppem (pixels per em).
   467  		p := fixed.Point26_6{
   468  			X: fixed.Int26_6(g.x),
   469  			Y: fixed.Int26_6(g.y),
   470  		}
   471  
   472  		if !g.firstOnCurveValid {
   473  			if g.on {
   474  				g.firstOnCurve = p
   475  				g.firstOnCurveValid = true
   476  				g.seg = Segment{
   477  					Op:   SegmentOpMoveTo,
   478  					Args: [3]fixed.Point26_6{p},
   479  				}
   480  				return true
   481  			} else if !g.firstOffCurveValid {
   482  				g.firstOffCurve = p
   483  				g.firstOffCurveValid = true
   484  				continue
   485  			} else {
   486  				g.firstOnCurve = midPoint(g.firstOffCurve, p)
   487  				g.firstOnCurveValid = true
   488  				g.lastOffCurve = p
   489  				g.lastOffCurveValid = true
   490  				g.seg = Segment{
   491  					Op:   SegmentOpMoveTo,
   492  					Args: [3]fixed.Point26_6{g.firstOnCurve},
   493  				}
   494  				return true
   495  			}
   496  
   497  		} else if !g.lastOffCurveValid {
   498  			if !g.on {
   499  				g.lastOffCurve = p
   500  				g.lastOffCurveValid = true
   501  				continue
   502  			} else {
   503  				g.seg = Segment{
   504  					Op:   SegmentOpLineTo,
   505  					Args: [3]fixed.Point26_6{p},
   506  				}
   507  				return true
   508  			}
   509  
   510  		} else {
   511  			if !g.on {
   512  				g.seg = Segment{
   513  					Op: SegmentOpQuadTo,
   514  					Args: [3]fixed.Point26_6{
   515  						g.lastOffCurve,
   516  						midPoint(g.lastOffCurve, p),
   517  					},
   518  				}
   519  				g.lastOffCurve = p
   520  				g.lastOffCurveValid = true
   521  				return true
   522  			} else {
   523  				g.seg = Segment{
   524  					Op:   SegmentOpQuadTo,
   525  					Args: [3]fixed.Point26_6{g.lastOffCurve, p},
   526  				}
   527  				g.lastOffCurveValid = false
   528  				return true
   529  			}
   530  		}
   531  	}
   532  	return false
   533  }
   534  
   535  func (g *glyfIter) nextPoint() (ok bool) {
   536  	if g.p == g.nPoints {
   537  		return false
   538  	}
   539  	g.p++
   540  
   541  	if g.repeats > 0 {
   542  		g.repeats--
   543  	} else {
   544  		g.flag = g.data[g.flagIndex]
   545  		g.flagIndex++
   546  		if g.flag&flagRepeat != 0 {
   547  			g.repeats = g.data[g.flagIndex]
   548  			g.flagIndex++
   549  		}
   550  	}
   551  
   552  	if g.flag&flagXShortVector != 0 {
   553  		if g.flag&flagPositiveXShortVector != 0 {
   554  			g.x += int16(g.data[g.xIndex])
   555  		} else {
   556  			g.x -= int16(g.data[g.xIndex])
   557  		}
   558  		g.xIndex += 1
   559  	} else if g.flag&flagThisXIsSame == 0 {
   560  		g.x += int16(u16(g.data[g.xIndex:]))
   561  		g.xIndex += 2
   562  	}
   563  
   564  	if g.flag&flagYShortVector != 0 {
   565  		if g.flag&flagPositiveYShortVector != 0 {
   566  			g.y += int16(g.data[g.yIndex])
   567  		} else {
   568  			g.y -= int16(g.data[g.yIndex])
   569  		}
   570  		g.yIndex += 1
   571  	} else if g.flag&flagThisYIsSame == 0 {
   572  		g.y += int16(u16(g.data[g.yIndex:]))
   573  		g.yIndex += 2
   574  	}
   575  
   576  	g.on = g.flag&flagOnCurve != 0
   577  	return true
   578  }
   579  

View as plain text