from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval, num2binary, binary2num
from . import DefaultTable
import warnings
# panose classification
panoseFormat = """
bFamilyType: B
bSerifStyle: B
bWeight: B
bProportion: B
bContrast: B
bStrokeVariation: B
bArmStyle: B
bLetterForm: B
bMidline: B
bXHeight: B
"""
class Panose(object):
def toXML(self, writer, ttFont):
formatstring, names, fixes = sstruct.getformat(panoseFormat)
for name in names:
writer.simpletag(name, value=getattr(self, name))
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
setattr(self, name, safeEval(attrs["value"]))
# 'sfnt' OS/2 and Windows Metrics table - 'OS/2'
OS2_format_0 = """
> # big endian
version: H # version
xAvgCharWidth: h # average character width
usWeightClass: H # degree of thickness of strokes
usWidthClass: H # aspect ratio
fsType: h # type flags
ySubscriptXSize: h # subscript horizontal font size
ySubscriptYSize: h # subscript vertical font size
ySubscriptXOffset: h # subscript x offset
ySubscriptYOffset: h # subscript y offset
ySuperscriptXSize: h # superscript horizontal font size
ySuperscriptYSize: h # superscript vertical font size
ySuperscriptXOffset: h # superscript x offset
ySuperscriptYOffset: h # superscript y offset
yStrikeoutSize: h # strikeout size
yStrikeoutPosition: h # strikeout position
sFamilyClass: h # font family class and subclass
panose: 10s # panose classification number
ulUnicodeRange1: L # character range
ulUnicodeRange2: L # character range
ulUnicodeRange3: L # character range
ulUnicodeRange4: L # character range
achVendID: 4s # font vendor identification
fsSelection: H # font selection flags
fsFirstCharIndex: H # first unicode character index
fsLastCharIndex: H # last unicode character index
sTypoAscender: h # typographic ascender
sTypoDescender: h # typographic descender
sTypoLineGap: h # typographic line gap
usWinAscent: H # Windows ascender
usWinDescent: H # Windows descender
"""
OS2_format_1_addition = """
ulCodePageRange1: L
ulCodePageRange2: L
"""
OS2_format_2_addition = OS2_format_1_addition + """
sxHeight: h
sCapHeight: h
usDefaultChar: H
usBreakChar: H
usMaxContex: H
"""
OS2_format_5_addition = OS2_format_2_addition + """
usLowerOpticalPointSize: H
usUpperOpticalPointSize: H
"""
bigendian = " > # big endian\n"
OS2_format_1 = OS2_format_0 + OS2_format_1_addition
OS2_format_2 = OS2_format_0 + OS2_format_2_addition
OS2_format_5 = OS2_format_0 + OS2_format_5_addition
OS2_format_1_addition = bigendian + OS2_format_1_addition
OS2_format_2_addition = bigendian + OS2_format_2_addition
OS2_format_5_addition = bigendian + OS2_format_5_addition
class table_O_S_2f_2(DefaultTable.DefaultTable):
"""the OS/2 table"""
def decompile(self, data, ttFont):
dummy, data = sstruct.unpack2(OS2_format_0, data, self)
if self.version == 1:
dummy, data = sstruct.unpack2(OS2_format_1_addition, data, self)
elif self.version in (2, 3, 4):
dummy, data = sstruct.unpack2(OS2_format_2_addition, data, self)
elif self.version == 5:
dummy, data = sstruct.unpack2(OS2_format_5_addition, data, self)
self.usLowerOpticalPointSize /= 20
self.usUpperOpticalPointSize /= 20
elif self.version != 0:
from fontTools import ttLib
raise ttLib.TTLibError("unknown format for OS/2 table: version %s" % self.version)
if len(data):
warnings.warn("too much 'OS/2' table data")
self.panose = sstruct.unpack(panoseFormat, self.panose, Panose())
def compile(self, ttFont):
panose = self.panose
self.panose = sstruct.pack(panoseFormat, self.panose)
if self.version == 0:
data = sstruct.pack(OS2_format_0, self)
elif self.version == 1:
data = sstruct.pack(OS2_format_1, self)
elif self.version in (2, 3, 4):
data = sstruct.pack(OS2_format_2, self)
elif self.version == 5:
d = self.__dict__.copy()
d['usLowerOpticalPointSize'] = int(round(self.usLowerOpticalPointSize * 20))
d['usUpperOpticalPointSize'] = int(round(self.usUpperOpticalPointSize * 20))
data = sstruct.pack(OS2_format_5, d)
else:
from fontTools import ttLib
raise ttLib.TTLibError("unknown format for OS/2 table: version %s" % self.version)
self.panose = panose
return data
def toXML(self, writer, ttFont):
if self.version == 1:
format = OS2_format_1
elif self.version in (2, 3, 4):
format = OS2_format_2
elif self.version == 5:
format = OS2_format_5
else:
format = OS2_format_0
formatstring, names, fixes = sstruct.getformat(format)
for name in names:
value = getattr(self, name)
if name=="panose":
writer.begintag("panose")
writer.newline()
value.toXML(writer, ttFont)
writer.endtag("panose")
elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
"ulUnicodeRange3", "ulUnicodeRange4",
"ulCodePageRange1", "ulCodePageRange2"):
writer.simpletag(name, value=num2binary(value))
elif name in ("fsType", "fsSelection"):
writer.simpletag(name, value=num2binary(value, 16))
elif name == "achVendID":
writer.simpletag(name, value=repr(value)[1:-1])
else:
writer.simpletag(name, value=value)
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == "panose":
self.panose = panose = Panose()
for element in content:
if isinstance(element, tuple):
name, attrs, content = element
panose.fromXML(name, attrs, content, ttFont)
elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
"ulUnicodeRange3", "ulUnicodeRange4",
"ulCodePageRange1", "ulCodePageRange2",
"fsType", "fsSelection"):
setattr(self, name, binary2num(attrs["value"]))
elif name == "achVendID":
setattr(self, name, safeEval("'''" + attrs["value"] + "'''"))
else:
setattr(self, name, safeEval(attrs["value"]))