freetype: re-organize the freetype/truetype package into smaller files.
No code changes, just a copy/paste. R=bradfitz CC=golang-dev http://codereview.appspot.com/6201052
This commit is contained in:
parent
eaa4846c62
commit
a16d1037a1
2 changed files with 224 additions and 218 deletions
224
freetype/truetype/glyph.go
Normal file
224
freetype/truetype/glyph.go
Normal file
|
@ -0,0 +1,224 @@
|
|||
// 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
|
||||
|
||||
// A Point is a co-ordinate pair plus whether it is ``on'' a contour or an
|
||||
// ``off'' control point.
|
||||
type Point struct {
|
||||
X, Y int16
|
||||
// The Flags' LSB means whether or not this Point is ``on'' the contour.
|
||||
// Other bits are reserved for internal use.
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// The glyph's bounding box.
|
||||
B Bounds
|
||||
// Point contains all Points from all contours of the glyph.
|
||||
Point []Point
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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 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
|
||||
)
|
||||
|
||||
// decodeFlags decodes a glyph's run-length encoded flags,
|
||||
// and returns the remaining data.
|
||||
func (g *GlyphBuf) decodeFlags(d data, np0 int) data {
|
||||
for i := np0; i < len(g.Point); {
|
||||
c := d.u8()
|
||||
g.Point[i].Flags = c
|
||||
i++
|
||||
if c&flagRepeat != 0 {
|
||||
count := d.u8()
|
||||
for ; count > 0; count-- {
|
||||
g.Point[i].Flags = c
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// decodeCoords decodes a glyph's delta encoded co-ordinates.
|
||||
func (g *GlyphBuf) decodeCoords(d data, np0 int) {
|
||||
var x int16
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagXShortVector != 0 {
|
||||
dx := int16(d.u8())
|
||||
if f&flagPositiveXShortVector == 0 {
|
||||
x -= dx
|
||||
} else {
|
||||
x += dx
|
||||
}
|
||||
} else if f&flagThisXIsSame == 0 {
|
||||
x += int16(d.u16())
|
||||
}
|
||||
g.Point[i].X = x
|
||||
}
|
||||
var y int16
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagYShortVector != 0 {
|
||||
dy := int16(d.u8())
|
||||
if f&flagPositiveYShortVector == 0 {
|
||||
y -= dy
|
||||
} else {
|
||||
y += dy
|
||||
}
|
||||
} else if f&flagThisYIsSame == 0 {
|
||||
y += int16(d.u16())
|
||||
}
|
||||
g.Point[i].Y = y
|
||||
}
|
||||
}
|
||||
|
||||
// Load loads a glyph's contours from a Font, overwriting any previously
|
||||
// loaded contours for this GlyphBuf.
|
||||
func (g *GlyphBuf) Load(f *Font, i Index) error {
|
||||
// Reset the GlyphBuf.
|
||||
g.B = Bounds{}
|
||||
g.Point = g.Point[0:0]
|
||||
g.End = g.End[0:0]
|
||||
return g.load(f, i, 0)
|
||||
}
|
||||
|
||||
// loadCompound loads a glyph that is composed of other glyphs.
|
||||
func (g *GlyphBuf) loadCompound(f *Font, d data, recursion int) 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
|
||||
)
|
||||
for {
|
||||
flags := d.u16()
|
||||
component := d.u16()
|
||||
var dx, dy int16
|
||||
if flags&flagArg1And2AreWords != 0 {
|
||||
dx = int16(d.u16())
|
||||
dy = int16(d.u16())
|
||||
} else {
|
||||
dx = int16(int8(d.u8()))
|
||||
dy = int16(int8(d.u8()))
|
||||
}
|
||||
if flags&flagArgsAreXYValues == 0 {
|
||||
return UnsupportedError("compound glyph transform vector")
|
||||
}
|
||||
if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 {
|
||||
return UnsupportedError("compound glyph scale/transform")
|
||||
}
|
||||
b0, i0 := g.B, len(g.Point)
|
||||
g.load(f, Index(component), recursion+1)
|
||||
for i := i0; i < len(g.Point); i++ {
|
||||
g.Point[i].X += dx
|
||||
g.Point[i].Y += dy
|
||||
}
|
||||
if flags&flagUseMyMetrics == 0 {
|
||||
g.B = b0
|
||||
}
|
||||
if flags&flagMoreComponents == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load appends a glyph's contours to this GlyphBuf.
|
||||
func (g *GlyphBuf) load(f *Font, i Index, recursion int) error {
|
||||
if recursion >= 4 {
|
||||
return UnsupportedError("excessive compound glyph recursion")
|
||||
}
|
||||
// Find the relevant slice of f.glyf.
|
||||
var g0, g1 uint32
|
||||
if f.locaOffsetFormat == locaOffsetFormatShort {
|
||||
d := data(f.loca[2*int(i):])
|
||||
g0 = 2 * uint32(d.u16())
|
||||
g1 = 2 * uint32(d.u16())
|
||||
} else {
|
||||
d := data(f.loca[4*int(i):])
|
||||
g0 = d.u32()
|
||||
g1 = d.u32()
|
||||
}
|
||||
if g0 == g1 {
|
||||
return nil
|
||||
}
|
||||
d := data(f.glyf[g0:g1])
|
||||
// Decode the contour end indices.
|
||||
ne := int(int16(d.u16()))
|
||||
g.B.XMin = int16(d.u16())
|
||||
g.B.YMin = int16(d.u16())
|
||||
g.B.XMax = int16(d.u16())
|
||||
g.B.YMax = int16(d.u16())
|
||||
if ne == -1 {
|
||||
return g.loadCompound(f, d, recursion)
|
||||
} else if ne < 0 {
|
||||
// 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")
|
||||
}
|
||||
ne0, np0 := len(g.End), len(g.Point)
|
||||
ne += ne0
|
||||
if ne <= cap(g.End) {
|
||||
g.End = g.End[0:ne]
|
||||
} else {
|
||||
g.End = make([]int, ne, ne*2)
|
||||
}
|
||||
for i := ne0; i < ne; i++ {
|
||||
g.End[i] = 1 + np0 + int(d.u16())
|
||||
}
|
||||
// Skip the TrueType hinting instructions.
|
||||
instrLen := int(d.u16())
|
||||
d.skip(instrLen)
|
||||
// Decode the points.
|
||||
np := int(g.End[ne-1])
|
||||
if np <= cap(g.Point) {
|
||||
g.Point = g.Point[0:np]
|
||||
} else {
|
||||
g.Point = make([]Point, np, np*2)
|
||||
}
|
||||
d = g.decodeFlags(d, np0)
|
||||
g.decodeCoords(d, np0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewGlyphBuf returns a newly allocated GlyphBuf.
|
||||
func NewGlyphBuf() *GlyphBuf {
|
||||
g := new(GlyphBuf)
|
||||
g.Point = make([]Point, 0, 256)
|
||||
g.End = make([]int, 0, 32)
|
||||
return g
|
||||
}
|
|
@ -448,221 +448,3 @@ func parse(ttf []byte, offset int) (font *Font, err error) {
|
|||
font = f
|
||||
return
|
||||
}
|
||||
|
||||
// A Point is a co-ordinate pair plus whether it is ``on'' a contour or an
|
||||
// ``off'' control point.
|
||||
type Point struct {
|
||||
X, Y int16
|
||||
// The Flags' LSB means whether or not this Point is ``on'' the contour.
|
||||
// Other bits are reserved for internal use.
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// The glyph's bounding box.
|
||||
B Bounds
|
||||
// Point contains all Points from all contours of the glyph.
|
||||
Point []Point
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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 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
|
||||
)
|
||||
|
||||
// decodeFlags decodes a glyph's run-length encoded flags,
|
||||
// and returns the remaining data.
|
||||
func (g *GlyphBuf) decodeFlags(d data, np0 int) data {
|
||||
for i := np0; i < len(g.Point); {
|
||||
c := d.u8()
|
||||
g.Point[i].Flags = c
|
||||
i++
|
||||
if c&flagRepeat != 0 {
|
||||
count := d.u8()
|
||||
for ; count > 0; count-- {
|
||||
g.Point[i].Flags = c
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// decodeCoords decodes a glyph's delta encoded co-ordinates.
|
||||
func (g *GlyphBuf) decodeCoords(d data, np0 int) {
|
||||
var x int16
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagXShortVector != 0 {
|
||||
dx := int16(d.u8())
|
||||
if f&flagPositiveXShortVector == 0 {
|
||||
x -= dx
|
||||
} else {
|
||||
x += dx
|
||||
}
|
||||
} else if f&flagThisXIsSame == 0 {
|
||||
x += int16(d.u16())
|
||||
}
|
||||
g.Point[i].X = x
|
||||
}
|
||||
var y int16
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagYShortVector != 0 {
|
||||
dy := int16(d.u8())
|
||||
if f&flagPositiveYShortVector == 0 {
|
||||
y -= dy
|
||||
} else {
|
||||
y += dy
|
||||
}
|
||||
} else if f&flagThisYIsSame == 0 {
|
||||
y += int16(d.u16())
|
||||
}
|
||||
g.Point[i].Y = y
|
||||
}
|
||||
}
|
||||
|
||||
// Load loads a glyph's contours from a Font, overwriting any previously
|
||||
// loaded contours for this GlyphBuf.
|
||||
func (g *GlyphBuf) Load(f *Font, i Index) error {
|
||||
// Reset the GlyphBuf.
|
||||
g.B = Bounds{}
|
||||
g.Point = g.Point[0:0]
|
||||
g.End = g.End[0:0]
|
||||
return g.load(f, i, 0)
|
||||
}
|
||||
|
||||
// loadCompound loads a glyph that is composed of other glyphs.
|
||||
func (g *GlyphBuf) loadCompound(f *Font, d data, recursion int) 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
|
||||
)
|
||||
for {
|
||||
flags := d.u16()
|
||||
component := d.u16()
|
||||
var dx, dy int16
|
||||
if flags&flagArg1And2AreWords != 0 {
|
||||
dx = int16(d.u16())
|
||||
dy = int16(d.u16())
|
||||
} else {
|
||||
dx = int16(int8(d.u8()))
|
||||
dy = int16(int8(d.u8()))
|
||||
}
|
||||
if flags&flagArgsAreXYValues == 0 {
|
||||
return UnsupportedError("compound glyph transform vector")
|
||||
}
|
||||
if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 {
|
||||
return UnsupportedError("compound glyph scale/transform")
|
||||
}
|
||||
b0, i0 := g.B, len(g.Point)
|
||||
g.load(f, Index(component), recursion+1)
|
||||
for i := i0; i < len(g.Point); i++ {
|
||||
g.Point[i].X += dx
|
||||
g.Point[i].Y += dy
|
||||
}
|
||||
if flags&flagUseMyMetrics == 0 {
|
||||
g.B = b0
|
||||
}
|
||||
if flags&flagMoreComponents == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load appends a glyph's contours to this GlyphBuf.
|
||||
func (g *GlyphBuf) load(f *Font, i Index, recursion int) error {
|
||||
if recursion >= 4 {
|
||||
return UnsupportedError("excessive compound glyph recursion")
|
||||
}
|
||||
// Find the relevant slice of f.glyf.
|
||||
var g0, g1 uint32
|
||||
if f.locaOffsetFormat == locaOffsetFormatShort {
|
||||
d := data(f.loca[2*int(i):])
|
||||
g0 = 2 * uint32(d.u16())
|
||||
g1 = 2 * uint32(d.u16())
|
||||
} else {
|
||||
d := data(f.loca[4*int(i):])
|
||||
g0 = d.u32()
|
||||
g1 = d.u32()
|
||||
}
|
||||
if g0 == g1 {
|
||||
return nil
|
||||
}
|
||||
d := data(f.glyf[g0:g1])
|
||||
// Decode the contour end indices.
|
||||
ne := int(int16(d.u16()))
|
||||
g.B.XMin = int16(d.u16())
|
||||
g.B.YMin = int16(d.u16())
|
||||
g.B.XMax = int16(d.u16())
|
||||
g.B.YMax = int16(d.u16())
|
||||
if ne == -1 {
|
||||
return g.loadCompound(f, d, recursion)
|
||||
} else if ne < 0 {
|
||||
// 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")
|
||||
}
|
||||
ne0, np0 := len(g.End), len(g.Point)
|
||||
ne += ne0
|
||||
if ne <= cap(g.End) {
|
||||
g.End = g.End[0:ne]
|
||||
} else {
|
||||
g.End = make([]int, ne, ne*2)
|
||||
}
|
||||
for i := ne0; i < ne; i++ {
|
||||
g.End[i] = 1 + np0 + int(d.u16())
|
||||
}
|
||||
// Skip the TrueType hinting instructions.
|
||||
instrLen := int(d.u16())
|
||||
d.skip(instrLen)
|
||||
// Decode the points.
|
||||
np := int(g.End[ne-1])
|
||||
if np <= cap(g.Point) {
|
||||
g.Point = g.Point[0:np]
|
||||
} else {
|
||||
g.Point = make([]Point, np, np*2)
|
||||
}
|
||||
d = g.decodeFlags(d, np0)
|
||||
g.decodeCoords(d, np0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewGlyphBuf returns a newly allocated GlyphBuf.
|
||||
func NewGlyphBuf() *GlyphBuf {
|
||||
g := new(GlyphBuf)
|
||||
g.Point = make([]Point, 0, 256)
|
||||
g.End = make([]int, 0, 32)
|
||||
return g
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue