Home | History | Annotate | Download | only in tables
      1 from __future__ import print_function, division, absolute_import
      2 from fontTools.misc.py23 import *
      3 from fontTools.misc.textTools import safeEval
      4 from . import DefaultTable
      5 import sys
      6 import array
      7 import warnings
      8 
      9 
     10 class table__h_m_t_x(DefaultTable.DefaultTable):
     11 	
     12 	headerTag = 'hhea'
     13 	advanceName = 'width'
     14 	sideBearingName = 'lsb'
     15 	numberOfMetricsName = 'numberOfHMetrics'
     16 	
     17 	def decompile(self, data, ttFont):
     18 		numGlyphs = ttFont['maxp'].numGlyphs
     19 		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
     20 		if numberOfMetrics > numGlyphs:
     21 			numberOfMetrics = numGlyphs # We warn later.
     22 		# Note: advanceWidth is unsigned, but we read/write as signed.
     23 		metrics = array.array("h", data[:4 * numberOfMetrics])
     24 		if sys.byteorder != "big":
     25 			metrics.byteswap()
     26 		data = data[4 * numberOfMetrics:]
     27 		numberOfSideBearings = numGlyphs - numberOfMetrics
     28 		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
     29 		data = data[2 * numberOfSideBearings:]
     30 
     31 		if sys.byteorder != "big":
     32 			sideBearings.byteswap()
     33 		if data:
     34 			warnings.warn("too much 'hmtx'/'vmtx' table data")
     35 		self.metrics = {}
     36 		glyphOrder = ttFont.getGlyphOrder()
     37 		for i in range(numberOfMetrics):
     38 			glyphName = glyphOrder[i]
     39 			self.metrics[glyphName] = list(metrics[i*2:i*2+2])
     40 		lastAdvance = metrics[-2]
     41 		for i in range(numberOfSideBearings):
     42 			glyphName = glyphOrder[i + numberOfMetrics]
     43 			self.metrics[glyphName] = [lastAdvance, sideBearings[i]]
     44 	
     45 	def compile(self, ttFont):
     46 		metrics = []
     47 		for glyphName in ttFont.getGlyphOrder():
     48 			metrics.append(self.metrics[glyphName])
     49 		lastAdvance = metrics[-1][0]
     50 		lastIndex = len(metrics)
     51 		while metrics[lastIndex-2][0] == lastAdvance:
     52 			lastIndex -= 1
     53 			if lastIndex <= 1:
     54 				# all advances are equal
     55 				lastIndex = 1
     56 				break
     57 		additionalMetrics = metrics[lastIndex:]
     58 		additionalMetrics = [sb for advance, sb in additionalMetrics]
     59 		metrics = metrics[:lastIndex]
     60 		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
     61 		
     62 		allMetrics = []
     63 		for item in metrics:
     64 			allMetrics.extend(item)
     65 		allMetrics = array.array("h", allMetrics)
     66 		if sys.byteorder != "big":
     67 			allMetrics.byteswap()
     68 		data = allMetrics.tostring()
     69 		
     70 		additionalMetrics = array.array("h", additionalMetrics)
     71 		if sys.byteorder != "big":
     72 			additionalMetrics.byteswap()
     73 		data = data + additionalMetrics.tostring()
     74 		return data
     75 	
     76 	def toXML(self, writer, ttFont):
     77 		names = sorted(self.metrics.keys())
     78 		for glyphName in names:
     79 			advance, sb = self.metrics[glyphName]
     80 			writer.simpletag("mtx", [
     81 					("name", glyphName), 
     82 					(self.advanceName, advance), 
     83 					(self.sideBearingName, sb),
     84 					])
     85 			writer.newline()
     86 	
     87 	def fromXML(self, name, attrs, content, ttFont):
     88 		if not hasattr(self, "metrics"):
     89 			self.metrics = {}
     90 		if name == "mtx":
     91 			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]), 
     92 					safeEval(attrs[self.sideBearingName])]
     93 
     94 	def __delitem__(self, glyphName):
     95 		del self.metrics[glyphName]
     96 	
     97 	def __getitem__(self, glyphName):
     98 		return self.metrics[glyphName]
     99 	
    100 	def __setitem__(self, glyphName, advance_sb_pair):
    101 		self.metrics[glyphName] = tuple(advance_sb_pair)
    102 
    103