summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go')
-rw-r--r--Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go530
1 files changed, 0 insertions, 530 deletions
diff --git a/Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go b/Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go
deleted file mode 100644
index b5f327851..000000000
--- a/Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go
+++ /dev/null
@@ -1,530 +0,0 @@
-// Copyright 2010 The Freetype-Go Authors. All rights reserved.
-// Use of this source code is governed by your choice of either the
-// FreeType License or the GNU General Public License version 2 (or
-// any later version), both of which can be found in the LICENSE file.
-
-package truetype
-
-// Hinting is the policy for snapping a glyph's contours to pixel boundaries.
-type Hinting int32
-
-const (
- // NoHinting means to not perform any hinting.
- NoHinting Hinting = iota
- // FullHinting means to use the font's hinting instructions.
- FullHinting
-
- // TODO: implement VerticalHinting.
-)
-
-// A Point is a co-ordinate pair plus whether it is ``on'' a contour or an
-// ``off'' control point.
-type Point struct {
- X, Y int32
- // The Flags' LSB means whether or not this Point is ``on'' the contour.
- // Other bits are reserved for internal use.
- Flags uint32
-}
-
-// A GlyphBuf holds a glyph's contours. A GlyphBuf can be re-used to load a
-// series of glyphs from a Font.
-type GlyphBuf struct {
- // AdvanceWidth is the glyph's advance width.
- AdvanceWidth int32
- // B is the glyph's bounding box.
- B Bounds
- // Point contains all Points from all contours of the glyph. If
- // hinting was used to load a glyph then Unhinted contains those
- // Points before they were hinted, and InFontUnits contains those
- // Points before they were hinted and scaled.
- Point, Unhinted, InFontUnits []Point
- // End is the point indexes of the end point of each countour. The
- // length of End is the number of contours in the glyph. The i'th
- // contour consists of points Point[End[i-1]:End[i]], where End[-1]
- // is interpreted to mean zero.
- End []int
-
- font *Font
- scale int32
- hinting Hinting
- hinter hinter
- // phantomPoints are the co-ordinates of the synthetic phantom points
- // used for hinting and bounding box calculations.
- phantomPoints [4]Point
- // pp1x is the X co-ordinate of the first phantom point. The '1' is
- // using 1-based indexing; pp1x is almost always phantomPoints[0].X.
- // TODO: eliminate this and consistently use phantomPoints[0].X.
- pp1x int32
- // metricsSet is whether the glyph's metrics have been set yet. For a
- // compound glyph, a sub-glyph may override the outer glyph's metrics.
- metricsSet bool
- // tmp is a scratch buffer.
- tmp []Point
-}
-
-// Flags for decoding a glyph's contours. These flags are documented at
-// http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html.
-const (
- flagOnCurve = 1 << iota
- flagXShortVector
- flagYShortVector
- flagRepeat
- flagPositiveXShortVector
- flagPositiveYShortVector
-
- // The remaining flags are for internal use.
- flagTouchedX
- flagTouchedY
-)
-
-// The same flag bits (0x10 and 0x20) are overloaded to have two meanings,
-// dependent on the value of the flag{X,Y}ShortVector bits.
-const (
- flagThisXIsSame = flagPositiveXShortVector
- flagThisYIsSame = flagPositiveYShortVector
-)
-
-// Load loads a glyph's contours from a Font, overwriting any previously
-// loaded contours for this GlyphBuf. scale is the number of 26.6 fixed point
-// units in 1 em, i is the glyph index, and h is the hinting policy.
-func (g *GlyphBuf) Load(f *Font, scale int32, i Index, h Hinting) error {
- g.Point = g.Point[:0]
- g.Unhinted = g.Unhinted[:0]
- g.InFontUnits = g.InFontUnits[:0]
- g.End = g.End[:0]
- g.font = f
- g.hinting = h
- g.scale = scale
- g.pp1x = 0
- g.phantomPoints = [4]Point{}
- g.metricsSet = false
-
- if h != NoHinting {
- if err := g.hinter.init(f, scale); err != nil {
- return err
- }
- }
- if err := g.load(0, i, true); err != nil {
- return err
- }
- // TODO: this selection of either g.pp1x or g.phantomPoints[0].X isn't ideal,
- // and should be cleaned up once we have all the testScaling tests passing,
- // plus additional tests for Freetype-Go's bounding boxes matching C Freetype's.
- pp1x := g.pp1x
- if h != NoHinting {
- pp1x = g.phantomPoints[0].X
- }
- if pp1x != 0 {
- for i := range g.Point {
- g.Point[i].X -= pp1x
- }
- }
-
- advanceWidth := g.phantomPoints[1].X - g.phantomPoints[0].X
- if h != NoHinting {
- if len(f.hdmx) >= 8 {
- if n := u32(f.hdmx, 4); n > 3+uint32(i) {
- for hdmx := f.hdmx[8:]; uint32(len(hdmx)) >= n; hdmx = hdmx[n:] {
- if int32(hdmx[0]) == scale>>6 {
- advanceWidth = int32(hdmx[2+i]) << 6
- break
- }
- }
- }
- }
- advanceWidth = (advanceWidth + 32) &^ 63
- }
- g.AdvanceWidth = advanceWidth
-
- // Set g.B to the 'control box', which is the bounding box of the Bézier
- // curves' control points. This is easier to calculate, no smaller than
- // and often equal to the tightest possible bounding box of the curves
- // themselves. This approach is what C Freetype does. We can't just scale
- // the nominal bounding box in the glyf data as the hinting process and
- // phantom point adjustment may move points outside of that box.
- if len(g.Point) == 0 {
- g.B = Bounds{}
- } else {
- p := g.Point[0]
- g.B.XMin = p.X
- g.B.XMax = p.X
- g.B.YMin = p.Y
- g.B.YMax = p.Y
- for _, p := range g.Point[1:] {
- if g.B.XMin > p.X {
- g.B.XMin = p.X
- } else if g.B.XMax < p.X {
- g.B.XMax = p.X
- }
- if g.B.YMin > p.Y {
- g.B.YMin = p.Y
- } else if g.B.YMax < p.Y {
- g.B.YMax = p.Y
- }
- }
- // Snap the box to the grid, if hinting is on.
- if h != NoHinting {
- g.B.XMin &^= 63
- g.B.YMin &^= 63
- g.B.XMax += 63
- g.B.XMax &^= 63
- g.B.YMax += 63
- g.B.YMax &^= 63
- }
- }
- return nil
-}
-
-func (g *GlyphBuf) load(recursion int32, i Index, useMyMetrics bool) (err error) {
- // The recursion limit here is arbitrary, but defends against malformed glyphs.
- if recursion >= 32 {
- return UnsupportedError("excessive compound glyph recursion")
- }
- // Find the relevant slice of g.font.glyf.
- var g0, g1 uint32
- if g.font.locaOffsetFormat == locaOffsetFormatShort {
- g0 = 2 * uint32(u16(g.font.loca, 2*int(i)))
- g1 = 2 * uint32(u16(g.font.loca, 2*int(i)+2))
- } else {
- g0 = u32(g.font.loca, 4*int(i))
- g1 = u32(g.font.loca, 4*int(i)+4)
- }
-
- // Decode the contour count and nominal bounding box, from the first
- // 10 bytes of the glyf data. boundsYMin and boundsXMax, at offsets 4
- // and 6, are unused.
- glyf, ne, boundsXMin, boundsYMax := []byte(nil), 0, int32(0), int32(0)
- if g0+10 <= g1 {
- glyf = g.font.glyf[g0:g1]
- ne = int(int16(u16(glyf, 0)))
- boundsXMin = int32(int16(u16(glyf, 2)))
- boundsYMax = int32(int16(u16(glyf, 8)))
- }
-
- // Create the phantom points.
- uhm, pp1x := g.font.unscaledHMetric(i), int32(0)
- uvm := g.font.unscaledVMetric(i, boundsYMax)
- g.phantomPoints = [4]Point{
- {X: boundsXMin - uhm.LeftSideBearing},
- {X: boundsXMin - uhm.LeftSideBearing + uhm.AdvanceWidth},
- {X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing},
- {X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing - uvm.AdvanceHeight},
- }
- if len(glyf) == 0 {
- g.addPhantomsAndScale(len(g.Point), len(g.Point), true, true)
- copy(g.phantomPoints[:], g.Point[len(g.Point)-4:])
- g.Point = g.Point[:len(g.Point)-4]
- return nil
- }
-
- // Load and hint the contours.
- if ne < 0 {
- if ne != -1 {
- // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html says that
- // "the values -2, -3, and so forth, are reserved for future use."
- return UnsupportedError("negative number of contours")
- }
- pp1x = g.font.scale(g.scale * (boundsXMin - uhm.LeftSideBearing))
- if err := g.loadCompound(recursion, uhm, i, glyf, useMyMetrics); err != nil {
- return err
- }
- } else {
- np0, ne0 := len(g.Point), len(g.End)
- program := g.loadSimple(glyf, ne)
- g.addPhantomsAndScale(np0, np0, true, true)
- pp1x = g.Point[len(g.Point)-4].X
- if g.hinting != NoHinting {
- if len(program) != 0 {
- err := g.hinter.run(
- program,
- g.Point[np0:],
- g.Unhinted[np0:],
- g.InFontUnits[np0:],
- g.End[ne0:],
- )
- if err != nil {
- return err
- }
- }
- // Drop the four phantom points.
- g.InFontUnits = g.InFontUnits[:len(g.InFontUnits)-4]
- g.Unhinted = g.Unhinted[:len(g.Unhinted)-4]
- }
- if useMyMetrics {
- copy(g.phantomPoints[:], g.Point[len(g.Point)-4:])
- }
- g.Point = g.Point[:len(g.Point)-4]
- if np0 != 0 {
- // The hinting program expects the []End values to be indexed relative
- // to the inner glyph, not the outer glyph, so we delay adding np0 until
- // after the hinting program (if any) has run.
- for i := ne0; i < len(g.End); i++ {
- g.End[i] += np0
- }
- }
- }
- if useMyMetrics && !g.metricsSet {
- g.metricsSet = true
- g.pp1x = pp1x
- }
- return nil
-}
-
-// loadOffset is the initial offset for loadSimple and loadCompound. The first
-// 10 bytes are the number of contours and the bounding box.
-const loadOffset = 10
-
-func (g *GlyphBuf) loadSimple(glyf []byte, ne int) (program []byte) {
- offset := loadOffset
- for i := 0; i < ne; i++ {
- g.End = append(g.End, 1+int(u16(glyf, offset)))
- offset += 2
- }
-
- // Note the TrueType hinting instructions.
- instrLen := int(u16(glyf, offset))
- offset += 2
- program = glyf[offset : offset+instrLen]
- offset += instrLen
-
- np0 := len(g.Point)
- np1 := np0 + int(g.End[len(g.End)-1])
-
- // Decode the flags.
- for i := np0; i < np1; {
- c := uint32(glyf[offset])
- offset++
- g.Point = append(g.Point, Point{Flags: c})
- i++
- if c&flagRepeat != 0 {
- count := glyf[offset]
- offset++
- for ; count > 0; count-- {
- g.Point = append(g.Point, Point{Flags: c})
- i++
- }
- }
- }
-
- // Decode the co-ordinates.
- var x int16
- for i := np0; i < np1; i++ {
- f := g.Point[i].Flags
- if f&flagXShortVector != 0 {
- dx := int16(glyf[offset])
- offset++
- if f&flagPositiveXShortVector == 0 {
- x -= dx
- } else {
- x += dx
- }
- } else if f&flagThisXIsSame == 0 {
- x += int16(u16(glyf, offset))
- offset += 2
- }
- g.Point[i].X = int32(x)
- }
- var y int16
- for i := np0; i < np1; i++ {
- f := g.Point[i].Flags
- if f&flagYShortVector != 0 {
- dy := int16(glyf[offset])
- offset++
- if f&flagPositiveYShortVector == 0 {
- y -= dy
- } else {
- y += dy
- }
- } else if f&flagThisYIsSame == 0 {
- y += int16(u16(glyf, offset))
- offset += 2
- }
- g.Point[i].Y = int32(y)
- }
-
- return program
-}
-
-func (g *GlyphBuf) loadCompound(recursion int32, uhm HMetric, i Index,
- glyf []byte, useMyMetrics bool) error {
-
- // Flags for decoding a compound glyph. These flags are documented at
- // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html.
- const (
- flagArg1And2AreWords = 1 << iota
- flagArgsAreXYValues
- flagRoundXYToGrid
- flagWeHaveAScale
- flagUnused
- flagMoreComponents
- flagWeHaveAnXAndYScale
- flagWeHaveATwoByTwo
- flagWeHaveInstructions
- flagUseMyMetrics
- flagOverlapCompound
- )
- np0, ne0 := len(g.Point), len(g.End)
- offset := loadOffset
- for {
- flags := u16(glyf, offset)
- component := Index(u16(glyf, offset+2))
- dx, dy, transform, hasTransform := int32(0), int32(0), [4]int32{}, false
- if flags&flagArg1And2AreWords != 0 {
- dx = int32(int16(u16(glyf, offset+4)))
- dy = int32(int16(u16(glyf, offset+6)))
- offset += 8
- } else {
- dx = int32(int16(int8(glyf[offset+4])))
- dy = int32(int16(int8(glyf[offset+5])))
- offset += 6
- }
- if flags&flagArgsAreXYValues == 0 {
- return UnsupportedError("compound glyph transform vector")
- }
- if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 {
- hasTransform = true
- switch {
- case flags&flagWeHaveAScale != 0:
- transform[0] = int32(int16(u16(glyf, offset+0)))
- transform[3] = transform[0]
- offset += 2
- case flags&flagWeHaveAnXAndYScale != 0:
- transform[0] = int32(int16(u16(glyf, offset+0)))
- transform[3] = int32(int16(u16(glyf, offset+2)))
- offset += 4
- case flags&flagWeHaveATwoByTwo != 0:
- transform[0] = int32(int16(u16(glyf, offset+0)))
- transform[1] = int32(int16(u16(glyf, offset+2)))
- transform[2] = int32(int16(u16(glyf, offset+4)))
- transform[3] = int32(int16(u16(glyf, offset+6)))
- offset += 8
- }
- }
- savedPP := g.phantomPoints
- np0 := len(g.Point)
- componentUMM := useMyMetrics && (flags&flagUseMyMetrics != 0)
- if err := g.load(recursion+1, component, componentUMM); err != nil {
- return err
- }
- if flags&flagUseMyMetrics == 0 {
- g.phantomPoints = savedPP
- }
- if hasTransform {
- for j := np0; j < len(g.Point); j++ {
- p := &g.Point[j]
- newX := int32((int64(p.X)*int64(transform[0])+1<<13)>>14) +
- int32((int64(p.Y)*int64(transform[2])+1<<13)>>14)
- newY := int32((int64(p.X)*int64(transform[1])+1<<13)>>14) +
- int32((int64(p.Y)*int64(transform[3])+1<<13)>>14)
- p.X, p.Y = newX, newY
- }
- }
- dx = g.font.scale(g.scale * dx)
- dy = g.font.scale(g.scale * dy)
- if flags&flagRoundXYToGrid != 0 {
- dx = (dx + 32) &^ 63
- dy = (dy + 32) &^ 63
- }
- for j := np0; j < len(g.Point); j++ {
- p := &g.Point[j]
- p.X += dx
- p.Y += dy
- }
- // TODO: also adjust g.InFontUnits and g.Unhinted?
- if flags&flagMoreComponents == 0 {
- break
- }
- }
-
- instrLen := 0
- if g.hinting != NoHinting && offset+2 <= len(glyf) {
- instrLen = int(u16(glyf, offset))
- offset += 2
- }
-
- g.addPhantomsAndScale(np0, len(g.Point), false, instrLen > 0)
- points, ends := g.Point[np0:], g.End[ne0:]
- g.Point = g.Point[:len(g.Point)-4]
- for j := range points {
- points[j].Flags &^= flagTouchedX | flagTouchedY
- }
-
- if instrLen == 0 {
- if !g.metricsSet {
- copy(g.phantomPoints[:], points[len(points)-4:])
- }
- return nil
- }
-
- // Hint the compound glyph.
- program := glyf[offset : offset+instrLen]
- // Temporarily adjust the ends to be relative to this compound glyph.
- if np0 != 0 {
- for i := range ends {
- ends[i] -= np0
- }
- }
- // Hinting instructions of a composite glyph completely refer to the
- // (already) hinted subglyphs.
- g.tmp = append(g.tmp[:0], points...)
- if err := g.hinter.run(program, points, g.tmp, g.tmp, ends); err != nil {
- return err
- }
- if np0 != 0 {
- for i := range ends {
- ends[i] += np0
- }
- }
- if !g.metricsSet {
- copy(g.phantomPoints[:], points[len(points)-4:])
- }
- return nil
-}
-
-func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) {
- // Add the four phantom points.
- g.Point = append(g.Point, g.phantomPoints[:]...)
- // Scale the points.
- if simple && g.hinting != NoHinting {
- g.InFontUnits = append(g.InFontUnits, g.Point[np1:]...)
- }
- for i := np1; i < len(g.Point); i++ {
- p := &g.Point[i]
- p.X = g.font.scale(g.scale * p.X)
- p.Y = g.font.scale(g.scale * p.Y)
- }
- if g.hinting == NoHinting {
- return
- }
- // Round the 1st phantom point to the grid, shifting all other points equally.
- // Note that "all other points" starts from np0, not np1.
- // TODO: delete this adjustment and the np0/np1 distinction, when
- // we update the compatibility tests to C Freetype 2.5.3.
- // See http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=05c786d990390a7ca18e62962641dac740bacb06
- if adjust {
- pp1x := g.Point[len(g.Point)-4].X
- if dx := ((pp1x + 32) &^ 63) - pp1x; dx != 0 {
- for i := np0; i < len(g.Point); i++ {
- g.Point[i].X += dx
- }
- }
- }
- if simple {
- g.Unhinted = append(g.Unhinted, g.Point[np1:]...)
- }
- // Round the 2nd and 4th phantom point to the grid.
- p := &g.Point[len(g.Point)-3]
- p.X = (p.X + 32) &^ 63
- p = &g.Point[len(g.Point)-1]
- p.Y = (p.Y + 32) &^ 63
-}
-
-// TODO: is this necessary? The zero-valued GlyphBuf is perfectly usable.
-
-// NewGlyphBuf returns a newly allocated GlyphBuf.
-func NewGlyphBuf() *GlyphBuf {
- return &GlyphBuf{
- Point: make([]Point, 0, 256),
- End: make([]int, 0, 32),
- }
-}