blob: 06d82914bb8b699d1eb3786e611ec40fefac03b4 [file] [log] [blame]
import DefaultTable
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval, num2binary, binary2num
from types import TupleType
# 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:
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
"""
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_1_addition = bigendian + OS2_format_1_addition
OS2_format_2_addition = bigendian + OS2_format_2_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)
# workarounds for buggy fonts (Apple, mona)
if not data:
self.version = 0
elif len(data) == sstruct.calcsize(OS2_format_1_addition):
self.version = 1
elif len(data) == sstruct.calcsize(OS2_format_2_addition):
if self.version not in (2, 3, 4):
self.version = 1
else:
from fontTools import ttLib
raise ttLib.TTLibError, "unknown format for OS/2 table (incorrect length): version %s" % (self.version, len(data))
if self.version == 1:
sstruct.unpack2(OS2_format_1_addition, data, self)
elif self.version in (2, 3, 4):
sstruct.unpack2(OS2_format_2_addition, data, self)
elif self.version <> 0:
from fontTools import ttLib
raise ttLib.TTLibError, "unknown format for OS/2 table: version %s" % self.version
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)
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
else:
format = OS2_format_0
formatstring, names, fixes = sstruct.getformat(format)
for name in names:
value = getattr(self, name)
if type(value) == type(0L):
value = int(value)
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 type(element) == TupleType:
panose.fromXML(element, 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"]))