Apply remainder of #1675210: add support for TrueType Collection (TTC) files.

git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@564 4cde692c-a291-49d1-8350-778aa11640f8
This commit is contained in:
pabs3 2009-02-22 08:55:00 +00:00
parent d67cf25974
commit 7e91e776c9
3 changed files with 43 additions and 8 deletions

View File

@ -42,7 +42,7 @@ Dumping 'prep' table...
"""
#
# $Id: __init__.py,v 1.50 2008-03-01 11:43:00 jvr Exp $
# $Id: __init__.py,v 1.51 2009-02-22 08:55:00 pabs3 Exp $
#
import sys
@ -70,7 +70,8 @@ class TTFont:
def __init__(self, file=None, res_name_or_index=None,
sfntVersion="\000\001\000\000", checkChecksums=0,
verbose=0, recalcBBoxes=1, allowVID=0, ignoreDecompileErrors=False):
verbose=0, recalcBBoxes=1, allowVID=0, ignoreDecompileErrors=False,
fontNumber=-1):
"""The constructor can be called with a few different arguments.
When reading a font from disk, 'file' should be either a pathname
@ -152,7 +153,7 @@ class TTFont:
file = open(file, "rb")
else:
pass # assume "file" is a readable file object
self.reader = sfnt.SFNTReader(file, checkChecksums)
self.reader = sfnt.SFNTReader(file, checkChecksums, fontNumber=fontNumber)
self.sfntVersion = self.reader.sfntVersion
def close(self):

View File

@ -20,7 +20,7 @@ import os
class SFNTReader:
def __init__(self, file, checkChecksums=1):
def __init__(self, file, checkChecksums=1, fontNumber=-1):
self.file = file
self.checkChecksums = checkChecksums
data = self.file.read(sfntDirectorySize)
@ -28,6 +28,19 @@ class SFNTReader:
from fontTools import ttLib
raise ttLib.TTLibError, "Not a TrueType or OpenType font (not enough data)"
sstruct.unpack(sfntDirectoryFormat, data, self)
if self.sfntVersion == "ttcf":
assert ttcHeaderSize == sfntDirectorySize
sstruct.unpack(ttcHeaderFormat, data, self)
assert self.Version == 0x00010000 or self.Version == 0x00020000, "unrecognized TTC version 0x%08x" % self.Version
if not 0 <= fontNumber < self.numFonts:
from fontTools import ttLib
raise ttLib.TTLibError, "specify a font number between 0 and %d (inclusive)" % (self.numFonts - 1)
offsetTable = struct.unpack(">%dL" % self.numFonts, self.file.read(self.numFonts * 4))
if self.Version == 0x00020000:
pass # ignoring version 2.0 signatures
self.file.seek(offsetTable[fontNumber])
data = self.file.read(sfntDirectorySize)
sstruct.unpack(sfntDirectoryFormat, data, self)
if self.sfntVersion not in ("\000\001\000\000", "OTTO", "true"):
from fontTools import ttLib
raise ttLib.TTLibError, "Not a TrueType or OpenType font (bad sfntVersion)"
@ -165,6 +178,19 @@ class SFNTWriter:
# -- sfnt directory helpers and cruft
ttcHeaderFormat = """
> # big endian
TTCTag: 4s # "ttcf"
Version: L # 0x00010000 or 0x00020000
numFonts: L # number of fonts
# OffsetTable[numFonts]: L # array with offsets from beginning of file
# ulDsigTag: L # version 2.0 only
# ulDsigLength: L # version 2.0 only
# ulDsigOffset: L # version 2.0 only
"""
ttcHeaderSize = sstruct.calcsize(ttcHeaderFormat)
sfntDirectoryFormat = """
> # big endian
sfntVersion: 4s

View File

@ -41,6 +41,8 @@ usage: ttx [options] inputfile1 [... inputfileN]
file smaller.
-e Don't ignore decompilation errors, but show a full traceback
and abort.
-y <number> Select font number for TrueTrue Collection,
starting from 0.
Compile options:
-m Merge with TrueType-input-file: specify a TrueType or OpenType
@ -99,6 +101,7 @@ class Options:
def __init__(self, rawOptions, numFiles):
self.onlyTables = []
self.skipTables = []
self.fontNumber = -1
for option, value in rawOptions:
# general options
if option == "-h":
@ -122,6 +125,8 @@ class Options:
self.splitTables = 1
elif option == "-i":
self.disassembleInstructions = 0
elif option == "-y":
self.fontNumber = int(value)
# compile options
elif option == "-m":
self.mergeFile = value
@ -141,7 +146,7 @@ class Options:
def ttList(input, output, options):
import string
ttf = TTFont(input)
ttf = TTFont(input, fontNumber=options.fontNumber)
reader = ttf.reader
tags = reader.keys()
tags.sort()
@ -163,7 +168,8 @@ def ttList(input, output, options):
def ttDump(input, output, options):
print 'Dumping "%s" to "%s"...' % (input, output)
ttf = TTFont(input, 0, verbose=options.verbose, allowVID=options.allowVID,
ignoreDecompileErrors=options.ignoreDecompileErrors)
ignoreDecompileErrors=options.ignoreDecompileErrors,
fontNumber=options.fontNumber)
ttf.saveXML(output,
tables=options.onlyTables,
skipTables=options.skipTables,
@ -224,6 +230,8 @@ def guessFileType(fileName):
head = header[:4]
if head == "OTTO":
return "OTF"
elif head == "ttcf":
return "TTC"
elif head in ("\0\1\0\0", "true"):
return "TTF"
elif head.lower() == "<?xm":
@ -236,7 +244,7 @@ def guessFileType(fileName):
def parseOptions(args):
try:
rawOptions, files = getopt.getopt(args, "ld:vht:x:sim:bae")
rawOptions, files = getopt.getopt(args, "ld:vht:x:sim:baey:")
except getopt.GetoptError:
usage()
@ -248,7 +256,7 @@ def parseOptions(args):
for input in files:
tp = guessFileType(input)
if tp in ("OTF", "TTF"):
if tp in ("OTF", "TTF", "TTC"):
extension = ".ttx"
if options.listTables:
action = ttList