github.com/signintech/pdft@v0.5.0/minigopdf/fontmaker/core/ttfparser.go (about)

     1  package core
     2  
     3  import (
     4  	//"encoding/binary"
     5  	//"encoding/hex"
     6  	"bytes"
     7  	"encoding/binary"
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"regexp"
    14  	"strconv"
    15  	"strings"
    16  )
    17  
    18  var ERROR_NO_UNICODE_ENCODING_FOUND = errors.New("No Unicode encoding found")
    19  var ERROR_UNEXPECTED_SUBTABLE_FORMAT = errors.New("Unexpected subtable format")
    20  var ERROR_INCORRECT_MAGIC_NUMBER = errors.New("Incorrect magic number")
    21  var ERROR_POSTSCRIPT_NAME_NOT_FOUND = errors.New("PostScript name not found")
    22  
    23  // TTFParser true type font parser
    24  type TTFParser struct {
    25  	tables map[string]TableDirectoryEntry
    26  	//head
    27  	unitsPerEm       uint
    28  	xMin             int
    29  	yMin             int
    30  	xMax             int
    31  	yMax             int
    32  	indexToLocFormat int
    33  	//Hhea
    34  	numberOfHMetrics uint
    35  	ascender         int
    36  	descender        int
    37  	//end Hhea
    38  
    39  	numGlyphs      uint
    40  	widths         []uint
    41  	chars          map[int]uint
    42  	postScriptName string
    43  
    44  	//os2
    45  	os2Version    uint
    46  	Embeddable    bool
    47  	Bold          bool
    48  	typoAscender  int
    49  	typoDescender int
    50  	capHeight     int
    51  	sxHeight      int
    52  
    53  	//post
    54  	italicAngle        int
    55  	underlinePosition  int
    56  	underlineThickness int
    57  	isFixedPitch       bool
    58  	sTypoLineGap       int
    59  	usWinAscent        uint
    60  	usWinDescent       uint
    61  
    62  	//cmap
    63  	IsShortIndex  bool
    64  	LocaTable     []uint
    65  	SegCount      uint
    66  	StartCount    []uint
    67  	EndCount      []uint
    68  	IdRangeOffset []uint
    69  	IdDelta       []uint
    70  	GlyphIdArray  []uint
    71  	symbol        bool
    72  
    73  	//cmap format 12
    74  	groupingTables []CmapFormat12GroupingTable
    75  
    76  	//data of font
    77  	cahceFontData []byte
    78  
    79  	//kerning
    80  	useKerning bool //user config for use or not use kerning
    81  	kern       *KernTable
    82  }
    83  
    84  var Symbolic = 1 << 2
    85  var Nonsymbolic = (1 << 5)
    86  
    87  // Kern get KernTable
    88  func (t *TTFParser) Kern() *KernTable {
    89  	return t.kern
    90  }
    91  
    92  // UnderlinePosition postion of underline
    93  func (t *TTFParser) UnderlinePosition() int {
    94  	return t.underlinePosition
    95  }
    96  
    97  // GroupingTables get cmap format12 grouping table
    98  func (t *TTFParser) GroupingTables() []CmapFormat12GroupingTable {
    99  	return t.groupingTables
   100  }
   101  
   102  // UnderlineThickness thickness of underline
   103  func (t *TTFParser) UnderlineThickness() int {
   104  	return t.underlineThickness
   105  }
   106  
   107  func (t *TTFParser) XHeight() int {
   108  	if t.os2Version >= 2 && t.sxHeight != 0 {
   109  		return t.sxHeight
   110  	} else {
   111  		return int((0.66) * float64(t.ascender))
   112  	}
   113  }
   114  
   115  func (t *TTFParser) XMin() int {
   116  	return t.xMin
   117  }
   118  
   119  func (t *TTFParser) YMin() int {
   120  	return t.yMin
   121  }
   122  
   123  func (t *TTFParser) XMax() int {
   124  	return t.xMax
   125  }
   126  
   127  func (t *TTFParser) YMax() int {
   128  	return t.yMax
   129  }
   130  
   131  func (t *TTFParser) ItalicAngle() int {
   132  	return t.italicAngle
   133  }
   134  
   135  func (t *TTFParser) Flag() int {
   136  	flag := 0
   137  	if t.symbol {
   138  		flag |= Symbolic
   139  	} else {
   140  		flag |= Nonsymbolic
   141  	}
   142  	return flag
   143  }
   144  
   145  func (t *TTFParser) Ascender() int {
   146  	if t.typoAscender == 0 {
   147  		return t.ascender
   148  	}
   149  	return int(t.usWinAscent)
   150  }
   151  
   152  func (t *TTFParser) Descender() int {
   153  	if t.typoDescender == 0 {
   154  		return t.descender
   155  	}
   156  	descender := int(t.usWinDescent)
   157  	if t.descender < 0 {
   158  		descender = descender * (-1)
   159  	}
   160  	return descender
   161  }
   162  
   163  func (t *TTFParser) TypoAscender() int {
   164  	return t.typoAscender
   165  }
   166  
   167  func (t *TTFParser) TypoDescender() int {
   168  	return t.typoDescender
   169  }
   170  
   171  // CapHeight https://en.wikipedia.org/wiki/Cap_height
   172  func (t *TTFParser) CapHeight() int {
   173  	return t.capHeight
   174  }
   175  
   176  // NumGlyphs number of glyph
   177  func (t *TTFParser) NumGlyphs() uint {
   178  	return t.numGlyphs
   179  }
   180  
   181  func (t *TTFParser) UnitsPerEm() uint {
   182  	return t.unitsPerEm
   183  }
   184  
   185  func (t *TTFParser) NumberOfHMetrics() uint {
   186  	return t.numberOfHMetrics
   187  }
   188  
   189  func (t *TTFParser) Widths() []uint {
   190  	return t.widths
   191  }
   192  
   193  func (t *TTFParser) Chars() map[int]uint {
   194  	return t.chars
   195  }
   196  
   197  func (t *TTFParser) GetTables() map[string]TableDirectoryEntry {
   198  	return t.tables
   199  }
   200  
   201  // SetUseKerning set useKerning must set before Parse
   202  func (t *TTFParser) SetUseKerning(use bool) {
   203  	t.useKerning = use
   204  }
   205  
   206  // Parse parse
   207  func (t *TTFParser) Parse(filepath string) error {
   208  	data, err := ioutil.ReadFile(filepath)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	buff := bytes.NewBuffer(data)
   213  	return t.parse(buff)
   214  }
   215  
   216  // ParseByReader parse by io.reader
   217  func (t *TTFParser) ParseByReader(rd io.Reader) error {
   218  	return t.parse(rd)
   219  }
   220  
   221  func (t *TTFParser) parse(rd io.Reader) error {
   222  
   223  	fontdata, err := ioutil.ReadAll(rd)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	//t.cahceFontData = fontdata
   228  	fd := bytes.NewReader(fontdata)
   229  
   230  	version, err := t.Read(fd, 4)
   231  	if err != nil {
   232  		return err
   233  	}
   234  	if !t.CompareBytes(version, []byte{0x00, 0x01, 0x00, 0x00}) {
   235  		return errors.New("Unrecognized file (font) format")
   236  	}
   237  
   238  	i := uint(0)
   239  	numTables, err := t.ReadUShort(fd)
   240  	if err != nil {
   241  		return err
   242  	}
   243  	t.Skip(fd, 3*2) //searchRange, entrySelector, rangeShift
   244  	t.tables = make(map[string]TableDirectoryEntry)
   245  	for i < numTables {
   246  
   247  		tag, err := t.Read(fd, 4)
   248  		if err != nil {
   249  			return err
   250  		}
   251  
   252  		checksum, err := t.ReadULong(fd)
   253  		if err != nil {
   254  			return err
   255  		}
   256  
   257  		//fmt.Printf("offset\n")
   258  		offset, err := t.ReadULong(fd)
   259  		if err != nil {
   260  			return err
   261  		}
   262  
   263  		length, err := t.ReadULong(fd)
   264  		if err != nil {
   265  			return err
   266  		}
   267  		//fmt.Printf("\n\ntag=%s  \nOffset = %d\n", tag, offset)
   268  		var table TableDirectoryEntry
   269  		table.Offset = uint(offset)
   270  		table.CheckSum = checksum
   271  		table.Length = length
   272  		//fmt.Printf("\n\ntag=%s  \nOffset = %d\nPaddedLength =%d\n\n ", tag, table.Offset, table.PaddedLength())
   273  		t.tables[t.BytesToString(tag)] = table
   274  		i++
   275  	}
   276  
   277  	//fmt.Printf("%+v\n", me.tables)
   278  
   279  	err = t.ParseHead(fd)
   280  	if err != nil {
   281  		return err
   282  	}
   283  
   284  	err = t.ParseHhea(fd)
   285  	if err != nil {
   286  		return err
   287  	}
   288  
   289  	err = t.ParseMaxp(fd)
   290  	if err != nil {
   291  		return err
   292  	}
   293  	err = t.ParseHmtx(fd)
   294  	if err != nil {
   295  		return err
   296  	}
   297  	err = t.ParseCmap(fd)
   298  	if err != nil {
   299  		return err
   300  	}
   301  	err = t.ParseName(fd)
   302  	if err != nil {
   303  		return err
   304  	}
   305  	err = t.ParseOS2(fd)
   306  	if err != nil {
   307  		return err
   308  	}
   309  	err = t.ParsePost(fd)
   310  	if err != nil {
   311  		return err
   312  	}
   313  	err = t.ParseLoca(fd)
   314  	if err != nil {
   315  		return err
   316  	}
   317  
   318  	if t.useKerning {
   319  		err = t.Parsekern(fd)
   320  		if err != nil {
   321  			return err
   322  		}
   323  	}
   324  
   325  	//fmt.Printf("%#v\n", me.widths)
   326  	t.cahceFontData = fontdata //t.readFontData(fontpath)
   327  
   328  	return nil
   329  }
   330  
   331  func (t *TTFParser) FontData() []byte {
   332  	return t.cahceFontData
   333  }
   334  
   335  // ParseLoca parse loca table https://www.microsoft.com/typography/otspec/loca.htm
   336  func (t *TTFParser) ParseLoca(fd *bytes.Reader) error {
   337  
   338  	t.IsShortIndex = false
   339  	if t.indexToLocFormat == 0 {
   340  		t.IsShortIndex = true
   341  	}
   342  
   343  	//fmt.Printf("indexToLocFormat = %d\n", me.indexToLocFormat)
   344  	err := t.Seek(fd, "loca")
   345  	if err != nil {
   346  		return err
   347  	}
   348  	var locaTable []uint
   349  	table := t.tables["loca"]
   350  	if t.IsShortIndex {
   351  		//do ShortIndex
   352  		entries := table.Length / 2
   353  		i := uint(0)
   354  		for i < entries {
   355  			item, err := t.ReadUShort(fd)
   356  			if err != nil {
   357  				return err
   358  			}
   359  			locaTable = append(locaTable, item*2)
   360  			i++
   361  		}
   362  	} else {
   363  		entries := table.Length / 4
   364  		i := uint(0)
   365  		for i < entries {
   366  			item, err := t.ReadULong(fd)
   367  			if err != nil {
   368  				return err
   369  			}
   370  			locaTable = append(locaTable, item)
   371  			i++
   372  		}
   373  	}
   374  	t.LocaTable = locaTable
   375  	return nil
   376  }
   377  
   378  // ParsePost parse post table https://www.microsoft.com/typography/otspec/post.htm
   379  func (t *TTFParser) ParsePost(fd *bytes.Reader) error {
   380  
   381  	err := t.Seek(fd, "post")
   382  	if err != nil {
   383  		return err
   384  	}
   385  
   386  	err = t.Skip(fd, 4) // version
   387  	if err != nil {
   388  		return err
   389  	}
   390  
   391  	t.italicAngle, err = t.ReadShort(fd)
   392  	if err != nil {
   393  		return err
   394  	}
   395  
   396  	err = t.Skip(fd, 2) // Skip decimal part
   397  	if err != nil {
   398  		return err
   399  	}
   400  
   401  	t.underlinePosition, err = t.ReadShort(fd)
   402  	if err != nil {
   403  		return err
   404  	}
   405  
   406  	//fmt.Printf("start>>>>>>>\n")
   407  	t.underlineThickness, err = t.ReadShort(fd)
   408  	if err != nil {
   409  		return err
   410  	}
   411  	//fmt.Printf("underlineThickness=%d\n", t.underlineThickness)
   412  	//fmt.Printf(">>>>>>>%d\n", me.underlineThickness)
   413  
   414  	isFixedPitch, err := t.ReadULong(fd)
   415  	if err != nil {
   416  		return err
   417  	}
   418  	t.isFixedPitch = (isFixedPitch != 0)
   419  
   420  	return nil
   421  }
   422  
   423  // ParseOS2 parse OS2 table https://www.microsoft.com/typography/otspec/OS2.htm
   424  func (t *TTFParser) ParseOS2(fd *bytes.Reader) error {
   425  	err := t.Seek(fd, "OS/2")
   426  	if err != nil {
   427  		return err
   428  	}
   429  	version, err := t.ReadUShort(fd)
   430  	if err != nil {
   431  		return err
   432  	}
   433  	t.os2Version = version
   434  
   435  	err = t.Skip(fd, 3*2) // xAvgCharWidth, usWeightClass, usWidthClass
   436  	if err != nil {
   437  		return err
   438  	}
   439  	fsType, err := t.ReadUShort(fd)
   440  	if err != nil {
   441  		return err
   442  	}
   443  	t.Embeddable = (fsType != 2) && ((fsType & 0x200) == 0)
   444  
   445  	err = t.Skip(fd, (11*2)+10+(4*4)+4)
   446  	if err != nil {
   447  		return err
   448  	}
   449  	fsSelection, err := t.ReadUShort(fd)
   450  	if err != nil {
   451  		return err
   452  	}
   453  	t.Bold = ((fsSelection & 32) != 0)
   454  	err = t.Skip(fd, 2*2) // usFirstCharIndex, usLastCharIndex
   455  	if err != nil {
   456  		return err
   457  	}
   458  	t.typoAscender, err = t.ReadShort(fd)
   459  	if err != nil {
   460  		return err
   461  	}
   462  
   463  	t.typoDescender, err = t.ReadShort(fd)
   464  	if err != nil {
   465  		return err
   466  	}
   467  
   468  	t.sTypoLineGap, err = t.ReadShort(fd)
   469  	if err != nil {
   470  		return err
   471  	}
   472  
   473  	t.usWinAscent, err = t.ReadUShort(fd)
   474  	if err != nil {
   475  		return err
   476  	}
   477  
   478  	t.usWinDescent, err = t.ReadUShort(fd)
   479  	if err != nil {
   480  		return err
   481  	}
   482  
   483  	if version >= 2 {
   484  
   485  		err = t.Skip(fd, 2*4)
   486  		if err != nil {
   487  			return err
   488  		}
   489  
   490  		t.sxHeight, err = t.ReadShort(fd)
   491  		if err != nil {
   492  			return err
   493  		}
   494  
   495  		t.capHeight, err = t.ReadShort(fd)
   496  		if err != nil {
   497  			return err
   498  		}
   499  
   500  	} else {
   501  		t.capHeight = t.ascender
   502  	}
   503  
   504  	return nil
   505  }
   506  
   507  // ParseName parse name table https://www.microsoft.com/typography/otspec/name.htm
   508  func (t *TTFParser) ParseName(fd *bytes.Reader) error {
   509  
   510  	//$this->Seek('name');
   511  	err := t.Seek(fd, "name")
   512  	if err != nil {
   513  		return err
   514  	}
   515  
   516  	tableOffset, err := t.FTell(fd)
   517  	if err != nil {
   518  		return err
   519  	}
   520  
   521  	t.postScriptName = ""
   522  	err = t.Skip(fd, 2) // format
   523  	if err != nil {
   524  		return err
   525  	}
   526  
   527  	count, err := t.ReadUShort(fd)
   528  	if err != nil {
   529  		return err
   530  	}
   531  
   532  	stringOffset, err := t.ReadUShort(fd)
   533  	if err != nil {
   534  		return err
   535  	}
   536  
   537  	for i := 0; i < int(count); i++ {
   538  		err = t.Skip(fd, 3*2) // platformID, encodingID, languageID
   539  		if err != nil {
   540  			return err
   541  		}
   542  		nameID, err := t.ReadUShort(fd)
   543  		if err != nil {
   544  			return err
   545  		}
   546  		length, err := t.ReadUShort(fd)
   547  		if err != nil {
   548  			return err
   549  		}
   550  		offset, err := t.ReadUShort(fd)
   551  		if err != nil {
   552  			return err
   553  		}
   554  		if nameID == 6 {
   555  			// PostScript name
   556  			_, err = fd.Seek(int64(tableOffset+stringOffset+offset), 0)
   557  			if err != nil {
   558  				return err
   559  			}
   560  
   561  			stmp, err := t.Read(fd, int(length))
   562  			if err != nil {
   563  				return err
   564  			}
   565  
   566  			var tmpStmp []byte
   567  			for _, v := range stmp {
   568  				if v != 0 {
   569  					tmpStmp = append(tmpStmp, v)
   570  				}
   571  			}
   572  			s := fmt.Sprintf("%s", string(tmpStmp)) //strings(stmp)
   573  			s = strings.Replace(s, strconv.Itoa(0), "", -1)
   574  			s, err = t.PregReplace("|[ \\[\\](){}<>/%]|", "", s)
   575  			if err != nil {
   576  				return err
   577  			}
   578  			t.postScriptName = s
   579  			break
   580  		}
   581  	}
   582  
   583  	if t.postScriptName == "" {
   584  		return ERROR_POSTSCRIPT_NAME_NOT_FOUND
   585  	}
   586  
   587  	//fmt.Printf("%s\n", me.postScriptName)
   588  	return nil
   589  }
   590  
   591  func (t *TTFParser) PregReplace(pattern string, replacement string, subject string) (string, error) {
   592  
   593  	reg, err := regexp.Compile(pattern)
   594  	if err != nil {
   595  		return "", err
   596  	}
   597  	str := reg.ReplaceAllString(subject, replacement)
   598  	return str, nil
   599  }
   600  
   601  // ParseCmap parse cmap table format 4 https://www.microsoft.com/typography/otspec/cmap.htm
   602  func (t *TTFParser) ParseCmap(fd *bytes.Reader) error {
   603  	t.Seek(fd, "cmap")
   604  	t.Skip(fd, 2) // version
   605  	numTables, err := t.ReadUShort(fd)
   606  	if err != nil {
   607  		return err
   608  	}
   609  
   610  	offset31 := uint(0)
   611  	for i := 0; i < int(numTables); i++ {
   612  		platformID, err := t.ReadUShort(fd)
   613  		if err != nil {
   614  			return err
   615  		}
   616  		encodingID, err := t.ReadUShort(fd)
   617  		if err != nil {
   618  			return err
   619  		}
   620  		offset, err := t.ReadULong(fd)
   621  		if err != nil {
   622  			return err
   623  		}
   624  
   625  		t.symbol = false //init
   626  		if platformID == 3 && encodingID == 1 {
   627  			if encodingID == 0 {
   628  				t.symbol = true
   629  			}
   630  			offset31 = offset
   631  		}
   632  		//fmt.Printf("me.symbol=%d\n", me.symbol)
   633  	} //end for
   634  
   635  	if offset31 == 0 {
   636  		//No Unicode encoding found
   637  		return ERROR_NO_UNICODE_ENCODING_FOUND
   638  	}
   639  
   640  	var startCount, endCount, idDelta, idRangeOffset, glyphIDArray []uint
   641  
   642  	_, err = fd.Seek(int64(t.tables["cmap"].Offset+offset31), 0)
   643  	if err != nil {
   644  		return err
   645  	}
   646  
   647  	format, err := t.ReadUShort(fd)
   648  	if err != nil {
   649  		return err
   650  	}
   651  
   652  	if format != 4 {
   653  		//Unexpected subtable format
   654  		return ERROR_UNEXPECTED_SUBTABLE_FORMAT
   655  	}
   656  
   657  	length, err := t.ReadUShort(fd)
   658  	if err != nil {
   659  		return err
   660  	}
   661  	//fmt.Printf("\nlength=%d\n", length)
   662  
   663  	err = t.Skip(fd, 2) // language
   664  	if err != nil {
   665  		return err
   666  	}
   667  	segCount, err := t.ReadUShort(fd)
   668  	if err != nil {
   669  		return err
   670  	}
   671  	segCount = segCount / 2
   672  	t.SegCount = segCount
   673  	err = t.Skip(fd, 3*2) // searchRange, entrySelector, rangeShift
   674  	if err != nil {
   675  		return err
   676  	}
   677  
   678  	glyphCount := (length - (16 + 8*segCount)) / 2
   679  	//fmt.Printf("\nglyphCount=%d\n", glyphCount)
   680  
   681  	for i := 0; i < int(segCount); i++ {
   682  		tmp, err := t.ReadUShort(fd)
   683  		if err != nil {
   684  			return err
   685  		}
   686  		endCount = append(endCount, tmp)
   687  	}
   688  	t.EndCount = endCount
   689  
   690  	err = t.Skip(fd, 2) // reservedPad
   691  	if err != nil {
   692  		return err
   693  	}
   694  
   695  	for i := 0; i < int(segCount); i++ {
   696  		tmp, err := t.ReadUShort(fd)
   697  		if err != nil {
   698  			return err
   699  		}
   700  		startCount = append(startCount, tmp)
   701  	}
   702  	t.StartCount = startCount
   703  
   704  	for i := 0; i < int(segCount); i++ {
   705  		tmp, err := t.ReadUShort(fd)
   706  		if err != nil {
   707  			return err
   708  		}
   709  		idDelta = append(idDelta, tmp)
   710  	}
   711  	t.IdDelta = idDelta
   712  
   713  	offset, err := t.FTell(fd)
   714  	if err != nil {
   715  		return err
   716  	}
   717  	for i := 0; i < int(segCount); i++ {
   718  		tmp, err := t.ReadUShort(fd)
   719  		if err != nil {
   720  			return err
   721  		}
   722  		idRangeOffset = append(idRangeOffset, tmp)
   723  	}
   724  	t.IdRangeOffset = idRangeOffset
   725  	//_ = glyphIdArray
   726  	for i := 0; i < int(glyphCount); i++ {
   727  		tmp, err := t.ReadUShort(fd)
   728  		if err != nil {
   729  			return err
   730  		}
   731  		glyphIDArray = append(glyphIDArray, tmp)
   732  	}
   733  	t.GlyphIdArray = glyphIDArray
   734  
   735  	t.chars = make(map[int]uint)
   736  	for i := 0; i < int(segCount); i++ {
   737  		c1 := startCount[i]
   738  		c2 := endCount[i]
   739  		d := idDelta[i]
   740  		ro := idRangeOffset[i]
   741  		if ro > 0 {
   742  			_, err = fd.Seek(int64(offset+uint(2*i)+ro), 0)
   743  			if err != nil {
   744  				return err
   745  			}
   746  		}
   747  
   748  		for c := c1; c <= c2; c++ {
   749  			var gid uint
   750  			if c == 0xFFFF {
   751  				break
   752  			}
   753  			if ro > 0 {
   754  				gid, err = t.ReadUShort(fd)
   755  				if err != nil {
   756  					return err
   757  				}
   758  				if gid > 0 {
   759  					gid += d
   760  				}
   761  			} else {
   762  				gid = c + d
   763  			}
   764  
   765  			if gid >= 65536 {
   766  				gid -= 65536
   767  			}
   768  			if gid > 0 {
   769  				//fmt.Printf("%d gid = %d, ", int(c), gid)
   770  				t.chars[int(c)] = gid
   771  			}
   772  		}
   773  
   774  	}
   775  
   776  	_, err = t.ParseCmapFormat12(fd)
   777  	if err != nil {
   778  		return err
   779  	}
   780  
   781  	return nil
   782  }
   783  
   784  func (t *TTFParser) FTell(fd *bytes.Reader) (uint, error) {
   785  	offset, err := fd.Seek(0, os.SEEK_CUR)
   786  	return uint(offset), err
   787  }
   788  
   789  // ParseHmtx parse hmtx table  https://www.microsoft.com/typography/otspec/hmtx.htm
   790  func (t *TTFParser) ParseHmtx(fd *bytes.Reader) error {
   791  
   792  	t.Seek(fd, "hmtx")
   793  	i := uint(0)
   794  	for i < t.numberOfHMetrics {
   795  		advanceWidth, err := t.ReadUShort(fd)
   796  		if err != nil {
   797  			return err
   798  		}
   799  		err = t.Skip(fd, 2)
   800  		if err != nil {
   801  			return err
   802  		}
   803  		t.widths = append(t.widths, advanceWidth)
   804  		i++
   805  	}
   806  	if t.numberOfHMetrics < t.numGlyphs {
   807  		var err error
   808  		lastWidth := t.widths[t.numberOfHMetrics-1]
   809  		t.widths, err = t.ArrayPadUint(t.widths, t.numGlyphs, lastWidth)
   810  		if err != nil {
   811  			return err
   812  		}
   813  	}
   814  
   815  	return nil
   816  }
   817  
   818  func (t *TTFParser) ArrayPadUint(arr []uint, size uint, val uint) ([]uint, error) {
   819  	var result []uint
   820  	i := uint(0)
   821  	for i < size {
   822  		if int(i) < len(arr) {
   823  			result = append(result, arr[i])
   824  		} else {
   825  			result = append(result, val)
   826  		}
   827  		i++
   828  	}
   829  
   830  	return result, nil
   831  }
   832  
   833  // ParseHead parse head table  https://www.microsoft.com/typography/otspec/Head.htm
   834  func (t *TTFParser) ParseHead(fd *bytes.Reader) error {
   835  
   836  	//fmt.Printf("\nParseHead\n")
   837  	err := t.Seek(fd, "head")
   838  	if err != nil {
   839  		return err
   840  	}
   841  
   842  	err = t.Skip(fd, 3*4) // version, fontRevision, checkSumAdjustment
   843  	if err != nil {
   844  		return err
   845  	}
   846  	magicNumber, err := t.ReadULong(fd)
   847  	if err != nil {
   848  		return err
   849  	}
   850  
   851  	//fmt.Printf("\nmagicNumber = %d\n", magicNumber)
   852  	if magicNumber != 0x5F0F3CF5 {
   853  		return ERROR_INCORRECT_MAGIC_NUMBER
   854  	}
   855  
   856  	err = t.Skip(fd, 2)
   857  	if err != nil {
   858  		return err
   859  	}
   860  
   861  	t.unitsPerEm, err = t.ReadUShort(fd)
   862  	if err != nil {
   863  		return err
   864  	}
   865  
   866  	err = t.Skip(fd, 2*8) // created, modified
   867  	if err != nil {
   868  		return err
   869  	}
   870  
   871  	t.xMin, err = t.ReadShort(fd)
   872  	if err != nil {
   873  		return err
   874  	}
   875  
   876  	t.yMin, err = t.ReadShort(fd)
   877  	if err != nil {
   878  		return err
   879  	}
   880  
   881  	t.xMax, err = t.ReadShort(fd)
   882  	if err != nil {
   883  		return err
   884  	}
   885  
   886  	t.yMax, err = t.ReadShort(fd)
   887  	if err != nil {
   888  		return err
   889  	}
   890  
   891  	err = t.Skip(fd, 2*3) //skip macStyle,lowestRecPPEM,fontDirectionHint
   892  	if err != nil {
   893  		return err
   894  	}
   895  
   896  	t.indexToLocFormat, err = t.ReadShort(fd)
   897  	if err != nil {
   898  		return err
   899  	}
   900  
   901  	return nil
   902  }
   903  
   904  // ParseHhea parse hhea table  https://www.microsoft.com/typography/otspec/hhea.htm
   905  func (t *TTFParser) ParseHhea(fd *bytes.Reader) error {
   906  
   907  	err := t.Seek(fd, "hhea")
   908  	if err != nil {
   909  		return err
   910  	}
   911  
   912  	err = t.Skip(fd, 4) //skip version
   913  	if err != nil {
   914  		return err
   915  	}
   916  
   917  	t.ascender, err = t.ReadShort(fd)
   918  	if err != nil {
   919  		return err
   920  	}
   921  
   922  	t.descender, err = t.ReadShort(fd)
   923  	if err != nil {
   924  		return err
   925  	}
   926  
   927  	err = t.Skip(fd, 13*2)
   928  	if err != nil {
   929  		return err
   930  	}
   931  
   932  	t.numberOfHMetrics, err = t.ReadUShort(fd)
   933  	if err != nil {
   934  		return err
   935  	}
   936  
   937  	return nil
   938  }
   939  
   940  // ParseMaxp parse maxp table  https://www.microsoft.com/typography/otspec/Maxp.htm
   941  func (t *TTFParser) ParseMaxp(fd *bytes.Reader) error {
   942  	err := t.Seek(fd, "maxp")
   943  	if err != nil {
   944  		return err
   945  	}
   946  	err = t.Skip(fd, 4)
   947  	if err != nil {
   948  		return err
   949  	}
   950  	t.numGlyphs, err = t.ReadUShort(fd)
   951  	if err != nil {
   952  		return err
   953  	}
   954  	return nil
   955  }
   956  
   957  // ErrTableNotFound error table not found
   958  var ErrTableNotFound = errors.New("table not found")
   959  
   960  // Seek seek by tag
   961  func (t *TTFParser) Seek(fd *bytes.Reader, tag string) error {
   962  	table, ok := t.tables[tag]
   963  	if !ok {
   964  		return ErrTableNotFound
   965  	}
   966  	val := table.Offset
   967  	_, err := fd.Seek(int64(val), 0)
   968  	if err != nil {
   969  		return err
   970  	}
   971  	return nil
   972  }
   973  
   974  // BytesToString convert bytes to string
   975  func (t *TTFParser) BytesToString(b []byte) string {
   976  	return string(b) //strings.TrimSpace(string(b))
   977  }
   978  
   979  // ReadUShort read ushort
   980  func (t *TTFParser) ReadUShort(fd *bytes.Reader) (uint, error) {
   981  	buff, err := t.Read(fd, 2)
   982  	if err != nil {
   983  		return 0, err
   984  	}
   985  	n := binary.BigEndian.Uint16(buff)
   986  	return uint(n), nil
   987  }
   988  
   989  // ReadShort read short
   990  func (t *TTFParser) ReadShort(fd *bytes.Reader) (int, error) {
   991  	u, err := t.ReadUShort(fd)
   992  	if err != nil {
   993  		return 0, err
   994  	}
   995  
   996  	//fmt.Printf("%#v\n", buff)
   997  	var v int
   998  	if u >= 0x8000 {
   999  		v = int(u) - 65536
  1000  	} else {
  1001  		v = int(u)
  1002  	}
  1003  	return v, nil
  1004  }
  1005  
  1006  // ReadShortInt16 read short return int16
  1007  func (t *TTFParser) ReadShortInt16(fd *bytes.Reader) (int16, error) {
  1008  	n, err := t.ReadShort(fd)
  1009  	if err != nil {
  1010  		return 0, err
  1011  	}
  1012  	return int16(n), nil
  1013  }
  1014  
  1015  // ReadULong read ulong
  1016  func (t *TTFParser) ReadULong(fd *bytes.Reader) (uint, error) {
  1017  	buff, err := t.Read(fd, 4)
  1018  	//fmt.Printf("%#v\n", buff)
  1019  	if err != nil {
  1020  		return 0, err
  1021  	}
  1022  	n := binary.BigEndian.Uint32(buff)
  1023  	return uint(n), nil
  1024  }
  1025  
  1026  // Skip skip
  1027  func (t *TTFParser) Skip(fd *bytes.Reader, length int) error {
  1028  	_, err := fd.Seek(int64(length), 1)
  1029  	if err != nil {
  1030  		return err
  1031  	}
  1032  	return nil
  1033  }
  1034  
  1035  // Read read
  1036  func (t *TTFParser) Read(fd *bytes.Reader, length int) ([]byte, error) {
  1037  	buff := make([]byte, length)
  1038  	readlength, err := fd.Read(buff)
  1039  	if err != nil {
  1040  		return nil, err
  1041  	}
  1042  	if readlength != length {
  1043  		return nil, errors.New("file out of length")
  1044  	}
  1045  	//fmt.Printf("%d,%s\n", readlength, string(buff))
  1046  	return buff, nil
  1047  }
  1048  
  1049  // CompareBytes compare a and b
  1050  func (t *TTFParser) CompareBytes(a []byte, b []byte) bool {
  1051  
  1052  	if a == nil && b == nil {
  1053  		return true
  1054  	} else if a == nil && b != nil {
  1055  		return false
  1056  	} else if a != nil && b == nil {
  1057  		return false
  1058  	}
  1059  
  1060  	if len(a) != len(b) {
  1061  		return false
  1062  	}
  1063  
  1064  	i := 0
  1065  	length := len(a)
  1066  	for i < length {
  1067  		if a[i] != b[i] {
  1068  			return false
  1069  		}
  1070  		i++
  1071  	}
  1072  	return true
  1073  }