Progress reading CFF tables

This commit is contained in:
Kovid Goyal 2012-11-08 14:07:14 +05:30
parent 85a427af83
commit 833a8ca4e2
3 changed files with 253 additions and 217 deletions

View File

@ -1,153 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from struct import unpack_from, unpack
from calibre.utils.fonts.sfnt import UnknownTable
from calibre.utils.fonts.sfnt.errors import UnsupportedFont
# Useful links
# http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
# http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5177.Type2.pdf
class CFF(object):
def __init__(self, raw):
(self.major_version, self.minor_version, self.header_size,
self.offset_size) = unpack_from(b'>4B', raw)
if (self.major_version, self.minor_version) != (1, 0):
raise UnsupportedFont('The CFF table has unknown version: '
'(%d, %d)'%(self.major_version, self.minor_version))
offset = self.header_size
# Read Names Index
self.font_names = Index(raw, offset)
offset = self.font_names.pos
if len(self.font_names) > 1:
raise UnsupportedFont('CFF table has more than one font.')
# Read Top Dict
self.top_index = Index(raw, offset)
offset = self.top_index.pos
# Read strings
self.strings = Strings(raw, offset)
offset = self.strings.pos
print (self.strings[len(cff_standard_strings):])
class Index(list):
def __init__(self, raw, offset):
list.__init__(self)
count = unpack_from(b'>H', raw, offset)[0]
offset += 2
self.pos = offset
if count > 0:
self.offset_size = unpack_from(b'>B', raw, offset)[0]
offset += 1
if self.offset_size == 3:
offsets = [unpack(b'>L', b'\0' + raw[i:i+3])[0]
for i in xrange(offset, 3*(count+2), 3)]
else:
fmt = {1:'B', 2:'H', 4:'L'}.get(self.offset_size)
fmt = ('>%d%s'%(count+1, fmt)).encode('ascii')
offsets = unpack_from(fmt, raw, offset)
offset += self.offset_size * (count+1) - 1
for i in xrange(len(offsets)-1):
off, noff = offsets[i:i+2]
obj = raw[offset+i:offset+noff]
self.append(obj)
self.pos = offset + offsets[-1]
class Strings(Index):
def __init__(self, raw, offset):
super(Strings, self).__init__(raw, offset)
for x in reversed(cff_standard_strings):
self.insert(0, x)
class CFFTable(UnknownTable):
def decompile(self):
self.cff = CFF(self.raw)
# cff_standard_strings {{{
# The 391 Standard Strings as used in the CFF format.
# from Adobe Technical None #5176, version 1.0, 18 March 1998
cff_standard_strings = [
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal',
'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft',
'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',
'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl',
'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 'bullet',
'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright',
'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex',
'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash',
'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe',
'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf',
'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',
'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply',
'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave',
'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave',
'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute',
'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute',
'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron',
'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',
'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall',
'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',
'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior',
'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior',
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall',
'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall',
'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall',
'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall',
'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'foursuperior',
'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall',
'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall',
'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall',
'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',
'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall',
'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall',
'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002',
'001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman',
'Semibold'
]
# }}}

View File

@ -28,17 +28,6 @@ cff_dict_operand_encoding[255] = "reserved"
real_nibbles = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'.', 'E', 'E-', None, '-']
class SimpleConverter(object):
def read(self, parent, value):
return value
def write(self, parent, value):
return value
class TODO(SimpleConverter):
pass
class Reader(dict):
def read_byte(self, b0, data, index):
@ -89,20 +78,13 @@ class Dict(Reader):
def __init__(self):
Reader.__init__(self)
table = self.TABLE[:]
for i in xrange(len(table)):
op, name, arg, default, conv = table[i]
if conv is not None:
continue
if arg in ("delta", "array", 'number', 'SID'):
conv = SimpleConverter()
else:
raise Exception('Should not happen')
table[i] = op, name, arg, default, conv
self.operators = {op:(name, arg) for op, name, arg, default in
self.TABLE}
self.defaults = {name:default for op, name, arg, default in self.TABLE}
self.operators = {op:(name, arg) for op, name, arg, default, conv in
table}
def safe_get(self, name):
return self.get(name, self.defaults[name])
def decompile(self, strings, global_subrs, data):
self.strings = strings
@ -162,40 +144,66 @@ class Dict(Reader):
class TopDict(Dict):
TABLE = [
#opcode name argument type default converter
((12, 30), 'ROS', ('SID','SID','number'), None, SimpleConverter()),
((12, 20), 'SyntheticBase', 'number', None, None),
(0, 'version', 'SID', None, None),
(1, 'Notice', 'SID', None, None),
((12, 0), 'Copyright', 'SID', None, None),
(2, 'FullName', 'SID', None, None),
((12, 38), 'FontName', 'SID', None, None),
(3, 'FamilyName', 'SID', None, None),
(4, 'Weight', 'SID', None, None),
((12, 1), 'isFixedPitch', 'number', 0, None),
((12, 2), 'ItalicAngle', 'number', 0, None),
((12, 3), 'UnderlinePosition', 'number', None, None),
((12, 4), 'UnderlineThickness', 'number', 50, None),
((12, 5), 'PaintType', 'number', 0, None),
((12, 6), 'CharstringType', 'number', 2, None),
((12, 7), 'FontMatrix', 'array', [0.001,0,0,0.001,0,0], None),
(13, 'UniqueID', 'number', None, None),
(5, 'FontBBox', 'array', [0,0,0,0], None),
((12, 8), 'StrokeWidth', 'number', 0, None),
(14, 'XUID', 'array', None, None),
((12, 21), 'PostScript', 'SID', None, None),
((12, 22), 'BaseFontName', 'SID', None, None),
((12, 23), 'BaseFontBlend', 'delta', None, None),
((12, 31), 'CIDFontVersion', 'number', 0, None),
((12, 32), 'CIDFontRevision', 'number', 0, None),
((12, 33), 'CIDFontType', 'number', 0, None),
((12, 34), 'CIDCount', 'number', 8720, None),
(15, 'charset', 'number', 0, TODO()),
((12, 35), 'UIDBase', 'number', None, None),
(16, 'Encoding', 'number', 0, TODO()),
(18, 'Private', ('number','number'), None, TODO()),
((12, 37), 'FDSelect', 'number', None, TODO()),
((12, 36), 'FDArray', 'number', None, TODO()),
(17, 'CharStrings', 'number', None, TODO()),
#opcode name argument type default
((12, 30), 'ROS', ('SID','SID','number'), None, ),
((12, 20), 'SyntheticBase', 'number', None, ),
(0, 'version', 'SID', None, ),
(1, 'Notice', 'SID', None, ),
((12, 0), 'Copyright', 'SID', None, ),
(2, 'FullName', 'SID', None, ),
((12, 38), 'FontName', 'SID', None, ),
(3, 'FamilyName', 'SID', None, ),
(4, 'Weight', 'SID', None, ),
((12, 1), 'isFixedPitch', 'number', 0, ),
((12, 2), 'ItalicAngle', 'number', 0, ),
((12, 3), 'UnderlinePosition', 'number', None, ),
((12, 4), 'UnderlineThickness', 'number', 50, ),
((12, 5), 'PaintType', 'number', 0, ),
((12, 6), 'CharstringType', 'number', 2, ),
((12, 7), 'FontMatrix', 'array', [0.001,0,0,0.001,0,0], ),
(13, 'UniqueID', 'number', None, ),
(5, 'FontBBox', 'array', [0,0,0,0], ),
((12, 8), 'StrokeWidth', 'number', 0, ),
(14, 'XUID', 'array', None, ),
((12, 21), 'PostScript', 'SID', None, ),
((12, 22), 'BaseFontName', 'SID', None, ),
((12, 23), 'BaseFontBlend', 'delta', None, ),
((12, 31), 'CIDFontVersion', 'number', 0, ),
((12, 32), 'CIDFontRevision', 'number', 0, ),
((12, 33), 'CIDFontType', 'number', 0, ),
((12, 34), 'CIDCount', 'number', 8720, ),
(15, 'charset', 'number', 0, ),
((12, 35), 'UIDBase', 'number', None, ),
(16, 'Encoding', 'number', 0, ),
(18, 'Private', ('number','number'), None, ),
((12, 37), 'FDSelect', 'number', None, ),
((12, 36), 'FDArray', 'number', None, ),
(17, 'CharStrings', 'number', None, ),
]
class PrivateDict(Dict):
TABLE = [
# opcode name argument type default
(6, 'BlueValues', 'delta', None, ),
(7, 'OtherBlues', 'delta', None, ),
(8, 'FamilyBlues', 'delta', None, ),
(9, 'FamilyOtherBlues', 'delta', None, ),
((12, 9), 'BlueScale', 'number', 0.039625, ),
((12, 10), 'BlueShift', 'number', 7, ),
((12, 11), 'BlueFuzz', 'number', 1, ),
(10, 'StdHW', 'number', None, ),
(11, 'StdVW', 'number', None, ),
((12, 12), 'StemSnapH', 'delta', None, ),
((12, 13), 'StemSnapV', 'delta', None, ),
((12, 14), 'ForceBold', 'number', 0, ),
((12, 15), 'ForceBoldThreshold', 'number', None, ), # deprecated
((12, 16), 'lenIV', 'number', None, ), # deprecated
((12, 17), 'LanguageGroup', 'number', 0, ),
((12, 18), 'ExpansionFactor', 'number', 0.06, ),
((12, 19), 'initialRandomSeed', 'number', 0, ),
(20, 'defaultWidthX', 'number', 0, ),
(21, 'nominalWidthX', 'number', 0, ),
(19, 'Subrs', 'number', None, ),
]

View File

@ -7,11 +7,12 @@ __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from struct import unpack_from, unpack
from struct import unpack_from, unpack, calcsize
from functools import partial
from calibre.utils.fonts.sfnt import UnknownTable
from calibre.utils.fonts.sfnt.errors import UnsupportedFont
from calibre.utils.fonts.sfnt.cff.dict_data import TopDict
from calibre.utils.fonts.sfnt.cff.dict_data import TopDict, PrivateDict
# Useful links
# http://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5176.CFF.pdf
@ -48,8 +49,36 @@ class CFF(object):
# Decompile Top Dict
self.top_dict.decompile(self.strings, self.global_subrs, self.top_index[0])
self.is_CID = 'ROS' in self.top_dict
# Read CharStrings (Glyph definitions)
try:
offset = self.top_dict['CharStrings']
except KeyError:
raise ValueError('This font has no CharStrings')
cs_type = self.top_dict.safe_get('CharstringType')
if cs_type != 2:
raise UnsupportedFont('This font has unsupported CharstringType: '
'%s'%cs_type)
self.char_strings = CharStringsIndex(raw, offset)
self.num_glyphs = len(self.char_strings)
# Read Private Dict
self.private_dict = None
pd = self.top_dict.safe_get('Private')
if pd:
size, offset = pd
self.private_dict = PrivateDict()
self.private_dict.decompile(self.strings, self.global_subrs,
raw[offset:offset+size])
# Read charset (Glyph names)
self.charset = Charset(raw, self.top_dict.safe_get('charset'),
self.strings, self.num_glyphs, self.is_CID)
import pprint
pprint.pprint(self.top_dict)
pprint.pprint(self.private_dict)
class Index(list):
@ -66,9 +95,9 @@ class Index(list):
offset += 1
if self.offset_size == 3:
offsets = [unpack(b'>L', b'\0' + raw[i:i+3])[0]
for i in xrange(offset, 3*(count+2), 3)]
for i in xrange(offset, offset+3*(count+2), 3)]
else:
fmt = {1:'B', 2:'H', 4:'L'}.get(self.offset_size)
fmt = {1:'B', 2:'H', 4:'L'}[self.offset_size]
fmt = ('>%d%s'%(count+1, fmt)).encode('ascii')
offsets = unpack_from(fmt, raw, offset)
offset += self.offset_size * (count+1) - 1
@ -78,16 +107,168 @@ class Index(list):
obj = raw[offset+off:offset+noff]
self.append(obj)
self.pos = offset + offsets[-1]
try:
self.pos = offset + offsets[-1]
except IndexError:
self.pos = offset
class Strings(Index):
def __init__(self, raw, offset):
super(Strings, self).__init__(raw, offset, prepend=cff_standard_strings)
super(Strings, self).__init__(raw, offset, prepend=[x.encode('ascii')
for x in cff_standard_strings])
class Charset(list):
STANDARD_CHARSETS = [ # {{{
# ISOAdobe
(".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
"percent", "ampersand", "quoteright", "parenleft", "parenright",
"asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"colon", "semicolon", "less", "equal", "greater", "question", "at",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"bracketleft", "backslash", "bracketright", "asciicircum",
"underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i",
"j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
"exclamdown", "cent", "sterling", "fraction", "yen", "florin",
"section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
"guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger",
"daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase",
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
"perthousand", "questiondown", "grave", "acute", "circumflex", "tilde",
"macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
"hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine",
"Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash",
"oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu",
"trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter",
"divide", "brokenbar", "degree", "thorn", "threequarters",
"twosuperior", "registered", "minus", "eth", "multiply",
"threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis",
"Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
"Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave",
"Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde",
"Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute",
"Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave",
"aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
"egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde",
"oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron",
"uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis",
"zcaron"),
# Expert
("notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle",
"dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior",
"parenrightsuperior", "twodotenleader", "onedotenleader", "comma",
"hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle",
"twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
"sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle",
"colon", "semicolon", "commasuperior", "threequartersemdash",
"periodsuperior", "questionsmall", "asuperior", "bsuperior",
"centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
"msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
"tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior",
"parenrightinferior", "Circumflexsmall", "hyphensuperior",
"Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall",
"Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall",
"Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall",
"Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
"colonmonetary", "onefitted", "rupiah", "Tildesmall",
"exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall",
"Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall",
"Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior",
"Ogoneksmall", "Ringsmall", "Cedillasmall", "onequarter", "onehalf",
"threequarters", "questiondownsmall", "oneeighth", "threeeighths",
"fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior",
"onesuperior", "twosuperior", "threesuperior", "foursuperior",
"fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
"ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
"threeinferior", "fourinferior", "fiveinferior", "sixinferior",
"seveninferior", "eightinferior", "nineinferior", "centinferior",
"dollarinferior", "periodinferior", "commainferior", "Agravesmall",
"Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
"Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
"Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
"Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
"Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
"Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall",
"Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall",
"Thornsmall", "Ydieresissmall"),
# Expert Subset
(".notdef", "space", "dollaroldstyle", "dollarsuperior",
"parenleftsuperior", "parenrightsuperior", "twodotenleader",
"onedotenleader", "comma", "hyphen", "period", "fraction",
"zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle",
"fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle",
"eightoldstyle", "nineoldstyle", "colon", "semicolon",
"commasuperior", "threequartersemdash", "periodsuperior",
"asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior",
"isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior",
"rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi",
"ffl", "parenleftinferior", "parenrightinferior", "hyphensuperior",
"colonmonetary", "onefitted", "rupiah", "centoldstyle",
"figuredash", "hypheninferior", "onequarter", "onehalf",
"threequarters", "oneeighth", "threeeighths", "fiveeighths",
"seveneighths", "onethird", "twothirds", "zerosuperior",
"onesuperior", "twosuperior", "threesuperior", "foursuperior",
"fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
"ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
"threeinferior", "fourinferior", "fiveinferior", "sixinferior",
"seveninferior", "eightinferior", "nineinferior", "centinferior",
"dollarinferior", "periodinferior", "commainferior"),
] # }}}
def __init__(self, raw, offset, strings, num_glyphs, is_CID):
super(Charset, self).__init__()
self.standard_charset = offset if offset in {0, 1, 2} else None
if is_CID and self.standard_charset is not None:
raise ValueError("CID font must not use a standard charset")
if self.standard_charset is None:
self.append(b'.notdef')
fmt = unpack_from(b'>B', raw, offset)[0]
offset += 1
f = {0:self.parse_fmt0, 1:self.parse_fmt1,
2:partial(self.parse_fmt1, is_two_byte=True)}.get(fmt, None)
if f is None:
raise UnsupportedFont('This font uses unsupported charset '
'table format: %d'%fmt)
f(raw, offset, strings, num_glyphs, is_CID)
def parse_fmt0(self, raw, offset, strings, num_glyphs, is_CID):
fmt = ('>%dH'%(num_glyphs-1)).encode('ascii')
ids = unpack_from(fmt, raw, offset)
if is_CID:
ids = ('cid%05d'%x for x in ids)
else:
ids = (strings[x] for x in ids)
self.extend(ids)
def parse_fmt1(self, raw, offset, strings, num_glyphs, is_CID,
is_two_byte=False):
fmt = b'>2H' if is_two_byte else b'>HB'
sz = calcsize(fmt)
count = 0
while count < num_glyphs - 1:
first, nleft = unpack_from(fmt, raw, offset)
offset += sz
count += nleft + 1
self.extend('cid%05d'%x if is_CID else strings[x] for x in
xrange(first, first + nleft+1))
def lookup(self, glyph_id):
if self.standard_charset is None:
return self[glyph_id]
return self.STANDARD_CHARSETS[self.standard_charset][glyph_id].encode('ascii')
class GlobalSubrs(Index):
pass
class CharStringsIndex(Index):
pass
class CFFTable(UnknownTable):
def decompile(self):