func readTable(ttf []byte, offsetLength []byte) ([]byte, error) {
	offset := int(u32(offsetLength, 0))
	if offset < 0 {
		return nil, FontError(fmt.Sprintf("offset too large: %d", uint32(offset)))
	}
	length := int(u32(offsetLength, 4))
	if length < 0 {
		return nil, FontError(fmt.Sprintf("length too large: %d", uint32(length)))
	}
	end := offset + length
	if end < 0 || end > len(ttf) {
		return nil, FontError(fmt.Sprintf("offset + length too large: %d", uint32(offset)+uint32(length)))
	}
	return ttf[offset:end], nil
}
readTable returns a slice of the TTF data given by a table's directory entry.
package otf
import (
	"fmt"
	"io/ioutil"
	"math"
	"unicode/utf16"
)
type Font struct {
	FullName       string  
	PostscriptName string  
	UnitsPerEm             int      
	XMin, XMax, YMin, YMax int      
	Ascender               int      
	Descender              int      
	CapHeight              int      
	ItalicAngle            float32  
	cm          []cm
	hm          []HMetric
	cmapIndexes []byte
	nHMetric    int
	nGlyph      int
	nKern       int
	kernTable   []byte
	tables map[string][]byte
	liga      []Ligature
	kern      []Kerning
	classKern *classKerner
	smcpBefore, smcpAfter []Index
	full []byte  
	head []byte  
	name []byte  
	cff  []byte  
	os2  []byte  
	gpos []byte  
}
func Open(filename string) (*Font, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return Parse(data)
}
func Parse(data []byte) (*Font, error) {
	const (
		SigVer1 = 0x00010000
		SigOtto = 0x4f54544f
	)
	if len(data) < 12 {
		return nil, FontError("TTF data is too short")
	}
	offset := 0
	version, offset := u32(data, offset), offset+4
	if version != SigVer1 && version != SigOtto {
		return nil, FontError(fmt.Sprintf("bad version 0x%x", version))
	}
	n, offset := int(u16(data, offset)), offset+2
	if len(data) < 16*n+12 {
		return nil, FontError("TTF data is too short")
	}
	f := &Font{full: data, tables: make(map[string][]byte)}
	for i := 0; i < n; i++ {
		x := 16*i + 12
		name := string(data[x : x+4])
		table, err := readTable(data, data[x+8:x+16])
		if err != nil {
			return nil, err
		}
		f.tables[name] = table
	}
	f.head = f.tables["head"]
	f.name = f.tables["name"]
	f.gpos = f.tables["GPOS"]
	f.cff = f.tables["CFF "]
	f.os2 = f.tables["OS/2"]
	if err := f.parseHead(); err != nil {
		return nil, err
	}
	var err error
	if f.FullName, err = f.lookupName(4); err != nil {
		return nil, err
	}
	if f.PostscriptName, err = f.lookupName(6); err != nil {
		return nil, err
	}
	if err := f.parseCmap(f.tables["cmap"]); err != nil {
		return nil, err
	}
	if err := f.parseOS2(); err != nil {
		return nil, err
	}
	if err := f.parseHhea(f.tables["hhea"]); err != nil {
		return nil, err
	}
	if err := f.parseHmtx(f.tables["hmtx"]); err != nil {
		return nil, err
	}
	if err := f.parseMaxp(f.tables["maxp"]); err != nil {
		return nil, err
	}
	if err := f.parsePost(f.tables["post"]); err != nil {
		return nil, err
	}
	if err := f.parseGsub(); err != nil {
		return nil, err
	}
	if err := f.parseGsubSmcp(); err != nil {
		return nil, err
	}
	if err := f.parseGpos(); err != nil {
		return nil, err
	}
	return f, nil
}
func (f *Font) lookupName(name uint16) (string, error) {
	const (
		Unicode        uint16 = 0
		UnicodeEnglish uint16 = 0
		Windows        uint16 = 3
		WindowsUCS2    uint16 = 1
		WindowsEnglish uint16 = 0x409
	)
	if len(f.name) < 6 {
		return "", errorf("name block is too short (%d bytes)", len(f.name))
	}
	if format := u16(f.name, 0); format != 0 && format != 1 {
		return "", errorf("invalid name block format %d", format)
	}
	count, strOffset := int(u16(f.name, 2)), int(u16(f.name, 4))
	if 6+count*12 > len(f.name) {
		return "", errorf("name block is too short (%d bytes)", len(f.name))
	}
	found := -1
	for i := 0; i < count; i++ {
		entry := f.name[6+i*12 : 20+i*12]
		var (
			platformID = u16(entry, 0)
			specificID = u16(entry, 2)
			languageID = u16(entry, 4)
			nameID     = u16(entry, 6)
		)
		if nameID == name &&
			((platformID == Unicode && languageID == UnicodeEnglish) ||
				platformID == Windows && specificID == WindowsUCS2 && languageID == WindowsEnglish) {
			found = i
			break
		}
	}
	if found < 0 {
		return "", nil
	}
	length := int(u16(f.name, 14+found*12))
	offset := int(u16(f.name, 16+found*12)) + strOffset
	if offset+length > len(f.name) || length&1 != 0 {
		return "", errorf("invalid name entry offset or length")
	}
	runes := make([]uint16, length/2)
	for i := 0; i < len(runes); i++ {
		runes[i] = u16(f.name, offset+2*i)
	}
	return string(utf16.Decode(runes)), nil
}