Merge pull request #50 from behdad/2and3
Fully functioning Python 2 and 3
diff --git a/Lib/fontTools/afmLib.py b/Lib/fontTools/afmLib.py
index aa303ad..ac31563 100644
--- a/Lib/fontTools/afmLib.py
+++ b/Lib/fontTools/afmLib.py
@@ -4,9 +4,9 @@
# It does not implement the full spec (Adobe Technote 5004, Adobe Font Metrics
# File Format Specification). Still, it should read most "common" AFM files.
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import re
-import string
-import types
__version__ = "$Id: afmLib.py,v 1.6 2003-05-24 12:50:47 jvr Exp $"
@@ -83,7 +83,7 @@
class error(Exception): pass
-class AFM:
+class AFM(object):
_attrs = None
@@ -112,15 +112,15 @@
def read(self, path):
lines = readlines(path)
for line in lines:
- if not string.strip(line):
+ if not line.strip():
continue
m = identifierRE.match(line)
if m is None:
- raise error, "syntax error in AFM file: " + `line`
+ raise error("syntax error in AFM file: " + repr(line))
pos = m.regs[1][1]
word = line[:pos]
- rest = string.strip(line[pos:])
+ rest = line[pos:].strip()
if word in self._keywords:
continue
if word == "C":
@@ -135,35 +135,35 @@
def parsechar(self, rest):
m = charRE.match(rest)
if m is None:
- raise error, "syntax error in AFM file: " + `rest`
+ raise error("syntax error in AFM file: " + repr(rest))
things = []
for fr, to in m.regs[1:]:
things.append(rest[fr:to])
charname = things[2]
del things[2]
- charnum, width, l, b, r, t = map(string.atoi, things)
+ charnum, width, l, b, r, t = (int(thing) for thing in things)
self._chars[charname] = charnum, width, (l, b, r, t)
def parsekernpair(self, rest):
m = kernRE.match(rest)
if m is None:
- raise error, "syntax error in AFM file: " + `rest`
+ raise error("syntax error in AFM file: " + repr(rest))
things = []
for fr, to in m.regs[1:]:
things.append(rest[fr:to])
leftchar, rightchar, value = things
- value = string.atoi(value)
+ value = int(value)
self._kerning[(leftchar, rightchar)] = value
def parseattr(self, word, rest):
if word == "FontBBox":
- l, b, r, t = map(string.atoi, string.split(rest))
+ l, b, r, t = [int(thing) for thing in rest.split()]
self._attrs[word] = l, b, r, t
elif word == "Comment":
self._comments.append(rest)
else:
try:
- value = string.atoi(rest)
+ value = int(rest)
except (ValueError, OverflowError):
self._attrs[word] = rest
else:
@@ -172,15 +172,15 @@
def parsecomposite(self, rest):
m = compositeRE.match(rest)
if m is None:
- raise error, "syntax error in AFM file: " + `rest`
+ raise error("syntax error in AFM file: " + repr(rest))
charname = m.group(1)
ncomponents = int(m.group(2))
rest = rest[m.regs[0][1]:]
components = []
- while 1:
+ while True:
m = componentRE.match(rest)
if m is None:
- raise error, "syntax error in AFM file: " + `rest`
+ raise error("syntax error in AFM file: " + repr(rest))
basechar = m.group(1)
xoffset = int(m.group(2))
yoffset = int(m.group(3))
@@ -195,7 +195,7 @@
import time
lines = [ "StartFontMetrics 2.0",
"Comment Generated by afmLib, version %s; at %s" %
- (string.split(__version__)[2],
+ (__version__.split()[2],
time.strftime("%m/%d/%Y %H:%M:%S",
time.localtime(time.time())))]
@@ -208,35 +208,30 @@
# a preferred order
attrs = self._attrs
for attr in preferredAttributeOrder:
- if attrs.has_key(attr):
+ if attr in attrs:
value = attrs[attr]
if attr == "FontBBox":
value = "%s %s %s %s" % value
lines.append(attr + " " + str(value))
# then write the attributes we don't know about,
# in alphabetical order
- items = attrs.items()
- items.sort()
+ items = sorted(attrs.items())
for attr, value in items:
if attr in preferredAttributeOrder:
continue
lines.append(attr + " " + str(value))
# write char metrics
- lines.append("StartCharMetrics " + `len(self._chars)`)
- items = map(lambda (charname, (charnum, width, box)):
- (charnum, (charname, width, box)),
- self._chars.items())
+ lines.append("StartCharMetrics " + repr(len(self._chars)))
+ items = [(charnum, (charname, width, box)) for charname, (charnum, width, box) in self._chars.items()]
- def myCmp(a, b):
- """Custom compare function to make sure unencoded chars (-1)
+ def myKey(a):
+ """Custom key function to make sure unencoded chars (-1)
end up at the end of the list after sorting."""
if a[0] == -1:
a = (0xffff,) + a[1:] # 0xffff is an arbitrary large number
- if b[0] == -1:
- b = (0xffff,) + b[1:]
- return cmp(a, b)
- items.sort(myCmp)
+ return a
+ items.sort(key=myKey)
for charnum, (charname, width, (l, b, r, t)) in items:
lines.append("C %d ; WX %d ; N %s ; B %d %d %d %d ;" %
@@ -245,17 +240,15 @@
# write kerning info
lines.append("StartKernData")
- lines.append("StartKernPairs " + `len(self._kerning)`)
- items = self._kerning.items()
- items.sort() # XXX is order important?
+ lines.append("StartKernPairs " + repr(len(self._kerning)))
+ items = sorted(self._kerning.items())
for (leftchar, rightchar), value in items:
lines.append("KPX %s %s %d" % (leftchar, rightchar, value))
lines.append("EndKernPairs")
lines.append("EndKernData")
if self._composites:
- composites = self._composites.items()
- composites.sort()
+ composites = sorted(self._composites.items())
lines.append("StartComposites %s" % len(self._composites))
for charname, components in composites:
line = "CC %s %s ;" % (charname, len(components))
@@ -269,16 +262,16 @@
writelines(path, lines, sep)
def has_kernpair(self, pair):
- return self._kerning.has_key(pair)
+ return pair in self._kerning
def kernpairs(self):
- return self._kerning.keys()
+ return list(self._kerning.keys())
def has_char(self, char):
- return self._chars.has_key(char)
+ return char in self._chars
def chars(self):
- return self._chars.keys()
+ return list(self._chars.keys())
def comments(self):
return self._comments
@@ -290,10 +283,10 @@
self._composites[glyphName] = components
def __getattr__(self, attr):
- if self._attrs.has_key(attr):
+ if attr in self._attrs:
return self._attrs[attr]
else:
- raise AttributeError, attr
+ raise AttributeError(attr)
def __setattr__(self, attr, value):
# all attrs *not* starting with "_" are consider to be AFM keywords
@@ -308,15 +301,15 @@
try:
del self.__dict__[attr]
except KeyError:
- raise AttributeError, attr
+ raise AttributeError(attr)
else:
try:
del self._attrs[attr]
except KeyError:
- raise AttributeError, attr
+ raise AttributeError(attr)
def __getitem__(self, key):
- if type(key) == types.TupleType:
+ if isinstance(key, tuple):
# key is a tuple, return the kernpair
return self._kerning[key]
else:
@@ -324,7 +317,7 @@
return self._chars[key]
def __setitem__(self, key, value):
- if type(key) == types.TupleType:
+ if isinstance(key, tuple):
# key is a tuple, set kernpair
self._kerning[key] = value
else:
@@ -332,7 +325,7 @@
self._chars[key] = value
def __delitem__(self, key):
- if type(key) == types.TupleType:
+ if isinstance(key, tuple):
# key is a tuple, del kernpair
del self._kerning[key]
else:
@@ -356,7 +349,7 @@
sep = sep + '\r' # mac or dos
if '\n' in data:
sep = sep + '\n' # unix or dos
- return string.split(data, sep)
+ return data.split(sep)
def writelines(path, lines, sep='\r'):
f = open(path, 'wb')
@@ -373,16 +366,16 @@
afm = AFM(path)
char = 'A'
if afm.has_char(char):
- print afm[char] # print charnum, width and boundingbox
+ print(afm[char]) # print charnum, width and boundingbox
pair = ('A', 'V')
if afm.has_kernpair(pair):
- print afm[pair] # print kerning value for pair
- print afm.Version # various other afm entries have become attributes
- print afm.Weight
+ print(afm[pair]) # print kerning value for pair
+ print(afm.Version) # various other afm entries have become attributes
+ print(afm.Weight)
# afm.comments() returns a list of all Comment lines found in the AFM
- print afm.comments()
+ print(afm.comments())
#print afm.chars()
#print afm.kernpairs()
- print afm
+ print(afm)
afm.write(path + ".muck")
diff --git a/Lib/fontTools/agl.py b/Lib/fontTools/agl.py
index c56ab81..597df7d 100644
--- a/Lib/fontTools/agl.py
+++ b/Lib/fontTools/agl.py
@@ -1,6 +1,9 @@
# The table below is taken from
# http://www.adobe.com/devnet/opentype/archives/aglfn.txt
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+
_aglText = """\
# -----------------------------------------------------------
# Copyright 2003, 2005-2008, 2010 Adobe Systems Incorporated.
@@ -719,12 +722,12 @@
continue
m = parseAGL_RE.match(line)
if not m:
- raise AGLError, "syntax error in glyphlist.txt: %s" % repr(line[:20])
+ raise AGLError("syntax error in glyphlist.txt: %s" % repr(line[:20]))
unicode = m.group(1)
assert len(unicode) == 4
unicode = int(unicode, 16)
glyphName = m.group(2)
- if AGL2UV.has_key(glyphName):
+ if glyphName in AGL2UV:
# the above table contains identical duplicates
assert AGL2UV[glyphName] == unicode
else:
diff --git a/Lib/fontTools/cffLib.py b/Lib/fontTools/cffLib.py
index 54c9cf2..9265ebc 100644
--- a/Lib/fontTools/cffLib.py
+++ b/Lib/fontTools/cffLib.py
@@ -4,11 +4,12 @@
# $Id: cffLib.py,v 1.34 2008-03-07 19:56:17 jvr Exp $
#
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import string
from fontTools.misc import psCharStrings
from fontTools.misc.textTools import safeEval
+import struct
DEBUG = 0
@@ -20,7 +21,7 @@
offSize: B
"""
-class CFFFontSet:
+class CFFFontSet(object):
def __init__(self):
pass
@@ -51,7 +52,7 @@
try:
index = self.fontNames.index(name)
except ValueError:
- raise KeyError, name
+ raise KeyError(name)
return self.topDictIndex[index]
def compile(self, file, otFont):
@@ -80,7 +81,7 @@
def toXML(self, xmlWriter, progress=None):
xmlWriter.newline()
for fontName in self.fontNames:
- xmlWriter.begintag("CFFFont", name=fontName)
+ xmlWriter.begintag("CFFFont", name=tostr(fontName))
xmlWriter.newline()
font = self[fontName]
font.toXML(xmlWriter, progress)
@@ -94,7 +95,7 @@
xmlWriter.newline()
xmlWriter.newline()
- def fromXML(self, (name, attrs, content)):
+ def fromXML(self, name, attrs, content):
if not hasattr(self, "GlobalSubrs"):
self.GlobalSubrs = GlobalSubrsIndex()
self.major = 1
@@ -113,18 +114,19 @@
for element in content:
if isinstance(element, basestring):
continue
- topDict.fromXML(element)
+ name, attrs, content = element
+ topDict.fromXML(name, attrs, content)
elif name == "GlobalSubrs":
for element in content:
if isinstance(element, basestring):
continue
name, attrs, content = element
subr = psCharStrings.T2CharString()
- subr.fromXML((name, attrs, content))
+ subr.fromXML(name, attrs, content)
self.GlobalSubrs.append(subr)
-class CFFWriter:
+class CFFWriter(object):
def __init__(self):
self.data = []
@@ -135,9 +137,9 @@
def toFile(self, file):
lastPosList = None
count = 1
- while 1:
+ while True:
if DEBUG:
- print "CFFWriter.toFile() iteration:", count
+ print("CFFWriter.toFile() iteration:", count)
count = count + 1
pos = 0
posList = [pos]
@@ -154,7 +156,7 @@
break
lastPosList = posList
if DEBUG:
- print "CFFWriter.toFile() writing to file."
+ print("CFFWriter.toFile() writing to file.")
begin = file.tell()
posList = [0]
for item in self.data:
@@ -178,7 +180,7 @@
return offSize
-class IndexCompiler:
+class IndexCompiler(object):
def __init__(self, items, strings, parent):
self.items = self.getItems(items, strings)
@@ -224,7 +226,7 @@
if hasattr(item, "toFile"):
item.toFile(file)
else:
- file.write(item)
+ file.write(tobytes(item))
class IndexedStringsCompiler(IndexCompiler):
@@ -301,7 +303,7 @@
self.parent.rawDict["CharStrings"] = pos
-class Index:
+class Index(object):
"""This class represents what the CFF spec calls an INDEX."""
@@ -313,7 +315,7 @@
self.items = []
return
if DEBUG:
- print "loading %s at %s" % (name, file.tell())
+ print("loading %s at %s" % (name, file.tell()))
self.file = file
count = readCard16(file)
self.count = count
@@ -323,10 +325,10 @@
return
offSize = readCard8(file)
if DEBUG:
- print " index count: %s offSize: %s" % (count, offSize)
+ print(" index count: %s offSize: %s" % (count, offSize))
assert offSize <= 4, "offSize too large: %s" % offSize
self.offsets = offsets = []
- pad = '\0' * (4 - offSize)
+ pad = b'\0' * (4 - offSize)
for index in range(count+1):
chunk = file.read(offSize)
chunk = pad + chunk
@@ -335,7 +337,7 @@
self.offsetBase = file.tell() - 1
file.seek(self.offsetBase + offsets[-1]) # pretend we've read the whole lot
if DEBUG:
- print " end of %s at %s" % (name, file.tell())
+ print(" end of %s at %s" % (name, file.tell()))
def __len__(self):
return len(self.items)
@@ -400,11 +402,11 @@
xmlWriter.endtag("CharString")
xmlWriter.newline()
- def fromXML(self, (name, attrs, content)):
- if name <> "CharString":
+ def fromXML(self, name, attrs, content):
+ if name != "CharString":
return
subr = psCharStrings.T2CharString()
- subr.fromXML((name, attrs, content))
+ subr.fromXML(name, attrs, content)
self.append(subr)
def getItemAndSelector(self, index):
@@ -440,14 +442,15 @@
compilerClass = FDArrayIndexCompiler
- def fromXML(self, (name, attrs, content)):
- if name <> "FontDict":
+ def fromXML(self, name, attrs, content):
+ if name != "FontDict":
return
fontDict = FontDict()
for element in content:
if isinstance(element, basestring):
continue
- fontDict.fromXML(element)
+ name, attrs, content = element
+ fontDict.fromXML(name, attrs, content)
self.append(fontDict)
@@ -497,7 +500,7 @@
self.gidArray.append(fdSelectValue)
-class CharStrings:
+class CharStrings(object):
def __init__(self, file, charset, globalSubrs, private, fdSelect, fdArray):
if file is not None:
@@ -517,16 +520,16 @@
self.fdArray = fdArray
def keys(self):
- return self.charStrings.keys()
+ return list(self.charStrings.keys())
def values(self):
if self.charStringsAreIndexed:
return self.charStringsIndex
else:
- return self.charStrings.values()
+ return list(self.charStrings.values())
def has_key(self, name):
- return self.charStrings.has_key(name)
+ return name in self.charStrings
def __len__(self):
return len(self.charStrings)
@@ -556,8 +559,7 @@
return self.charStrings[name], sel
def toXML(self, xmlWriter, progress):
- names = self.keys()
- names.sort()
+ names = sorted(self.keys())
i = 0
step = 10
numGlyphs = len(names)
@@ -578,15 +580,15 @@
xmlWriter.newline()
if not i % step and progress is not None:
progress.setLabel("Dumping 'CFF ' table... (%s)" % name)
- progress.increment(step / float(numGlyphs))
+ progress.increment(step / numGlyphs)
i = i + 1
- def fromXML(self, (name, attrs, content)):
+ def fromXML(self, name, attrs, content):
for element in content:
if isinstance(element, basestring):
continue
name, attrs, content = element
- if name <> "CharString":
+ if name != "CharString":
continue
fdID = -1
if hasattr(self, "fdArray"):
@@ -599,27 +601,27 @@
charString = psCharStrings.T2CharString(
private=private,
globalSubrs=self.globalSubrs)
- charString.fromXML((name, attrs, content))
+ charString.fromXML(name, attrs, content)
if fdID >= 0:
charString.fdSelectIndex = fdID
self[glyphName] = charString
def readCard8(file):
- return ord(file.read(1))
+ return byteord(file.read(1))
def readCard16(file):
value, = struct.unpack(">H", file.read(2))
return value
def writeCard8(file, value):
- file.write(chr(value))
+ file.write(bytechr(value))
def writeCard16(file, value):
file.write(struct.pack(">H", value))
def packCard8(value):
- return chr(value)
+ return bytechr(value)
def packCard16(value):
return struct.pack(">H", value)
@@ -634,9 +636,9 @@
d = {}
for op, name, arg, default, conv in table:
if isinstance(op, tuple):
- op = chr(op[0]) + chr(op[1])
+ op = bytechr(op[0]) + bytechr(op[1])
else:
- op = chr(op)
+ op = bytechr(op)
d[name] = (op, arg)
return d
@@ -660,7 +662,7 @@
return d
-class SimpleConverter:
+class SimpleConverter(object):
def read(self, parent, value):
return value
def write(self, parent, value):
@@ -668,18 +670,30 @@
def xmlWrite(self, xmlWriter, name, value, progress):
xmlWriter.simpletag(name, value=value)
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
return attrs["value"]
-class Latin1Converter(SimpleConverter):
+class ASCIIConverter(SimpleConverter):
+ def read(self, parent, value):
+ return tostr(value, encoding='ascii')
+ def write(self, parent, value):
+ return tobytes(value, encoding='ascii')
def xmlWrite(self, xmlWriter, name, value, progress):
- # Store as UTF-8
- value = unicode(value, "latin-1").encode("utf-8")
- xmlWriter.simpletag(name, value=value)
+ xmlWriter.simpletag(name, value=tostr(value, encoding="ascii"))
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
- s = unicode(attrs["value"], "utf-8")
- return s.encode("latin-1")
+ def xmlRead(self, name, attrs, content, parent):
+ return tobytes(attrs["value"], encoding=("ascii"))
+
+class Latin1Converter(SimpleConverter):
+ def read(self, parent, value):
+ return tostr(value, encoding='latin1')
+ def write(self, parent, value):
+ return tobytes(value, encoding='latin1')
+ def xmlWrite(self, xmlWriter, name, value, progress):
+ xmlWriter.simpletag(name, value=tostr(value, encoding="latin1"))
+ xmlWriter.newline()
+ def xmlRead(self, name, attrs, content, parent):
+ return tobytes(attrs["value"], encoding=("latin1"))
def parseNum(s):
@@ -690,17 +704,17 @@
return value
class NumberConverter(SimpleConverter):
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
return parseNum(attrs["value"])
class ArrayConverter(SimpleConverter):
def xmlWrite(self, xmlWriter, name, value, progress):
- value = map(str, value)
- xmlWriter.simpletag(name, value=" ".join(value))
+ value = " ".join(map(str, value))
+ xmlWriter.simpletag(name, value=value)
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
values = attrs["value"].split()
- return map(parseNum, values)
+ return [parseNum(value) for value in values]
class TableConverter(SimpleConverter):
def xmlWrite(self, xmlWriter, name, value, progress):
@@ -709,12 +723,13 @@
value.toXML(xmlWriter, progress)
xmlWriter.endtag(name)
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
ob = self.getClass()()
for element in content:
if isinstance(element, basestring):
continue
- ob.fromXML(element)
+ name, attrs, content = element
+ ob.fromXML(name, attrs, content)
return ob
class PrivateDictConverter(TableConverter):
@@ -757,7 +772,7 @@
return CharStrings(file, charset, globalSubrs, private, fdSelect, fdArray)
def write(self, parent, value):
return 0 # dummy value
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
if hasattr(parent, "ROS"):
# if it is a CID-keyed font, then the private Dict is extracted from the parent.FDArray
private, fdSelect, fdArray = None, parent.FDSelect, parent.FDArray
@@ -765,10 +780,10 @@
# if it is a name-keyed font, then the private dict is in the top dict, and there is no fdArray.
private, fdSelect, fdArray = parent.Private, None, None
charStrings = CharStrings(None, None, parent.GlobalSubrs, private, fdSelect, fdArray)
- charStrings.fromXML((name, attrs, content))
+ charStrings.fromXML(name, attrs, content)
return charStrings
-class CharsetConverter:
+class CharsetConverter(object):
def read(self, parent, value):
isCID = hasattr(parent, "ROS")
if value > 2:
@@ -776,7 +791,7 @@
file = parent.file
file.seek(value)
if DEBUG:
- print "loading charset at %s" % value
+ print("loading charset at %s" % value)
format = readCard8(file)
if format == 0:
charset = parseCharset0(numGlyphs, file, parent.strings, isCID)
@@ -786,9 +801,9 @@
raise NotImplementedError
assert len(charset) == numGlyphs
if DEBUG:
- print " charset end at %s" % file.tell()
+ print(" charset end at %s" % file.tell())
else: # offset == 0 -> no charset data.
- if isCID or not parent.rawDict.has_key("CharStrings"):
+ if isCID or "CharStrings" not in parent.rawDict:
assert value == 0 # We get here only when processing fontDicts from the FDArray of CFF-CID fonts. Only the real topDict references the chrset.
charset = None
elif value == 0:
@@ -807,12 +822,12 @@
##xmlWriter.simpletag("charset")
xmlWriter.comment("charset is dumped separately as the 'GlyphOrder' element")
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
if 0:
return safeEval(attrs["value"])
-class CharsetCompiler:
+class CharsetCompiler(object):
def __init__(self, strings, charset, parent):
assert charset[0] == '.notdef'
@@ -851,7 +866,7 @@
for name in charset[1:]:
data.append(packCard16(getNameID(name,strings)))
- return "".join(data)
+ return bytesjoin(data)
def packCharset(charset, isCID, strings):
@@ -868,7 +883,7 @@
SID = getNameID(name, strings)
if first is None:
first = SID
- elif end + 1 <> SID:
+ elif end + 1 != SID:
nLeft = end - first
if nLeft > 255:
format = 2
@@ -887,14 +902,14 @@
nLeftFunc = packCard16
for first, nLeft in ranges:
data.append(packCard16(first) + nLeftFunc(nLeft))
- return "".join(data)
+ return bytesjoin(data)
def parseCharset0(numGlyphs, file, strings, isCID):
charset = [".notdef"]
if isCID:
for i in range(numGlyphs - 1):
CID = readCard16(file)
- charset.append("cid" + string.zfill(str(CID), 5) )
+ charset.append("cid" + str(CID).zfill(5))
else:
for i in range(numGlyphs - 1):
SID = readCard16(file)
@@ -913,7 +928,7 @@
nLeft = nLeftFunc(file)
if isCID:
for CID in range(first, first+nLeft+1):
- charset.append("cid" + string.zfill(str(CID), 5) )
+ charset.append("cid" + str(CID).zfill(5))
else:
for SID in range(first, first+nLeft+1):
charset.append(strings[SID])
@@ -921,7 +936,7 @@
return charset
-class EncodingCompiler:
+class EncodingCompiler(object):
def __init__(self, strings, encoding, parent):
assert not isinstance(encoding, basestring)
@@ -955,11 +970,11 @@
file = parent.file
file.seek(value)
if DEBUG:
- print "loading Encoding at %s" % value
+ print("loading Encoding at %s" % value)
format = readCard8(file)
haveSupplement = format & 0x80
if haveSupplement:
- raise NotImplementedError, "Encoding supplements are not yet supported"
+ raise NotImplementedError("Encoding supplements are not yet supported")
format = format & 0x7f
if format == 0:
encoding = parseEncoding0(parent.charset, file, haveSupplement,
@@ -991,8 +1006,8 @@
xmlWriter.endtag(name)
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
- if attrs.has_key("name"):
+ def xmlRead(self, name, attrs, content, parent):
+ if "name" in attrs:
return attrs["name"]
encoding = [".notdef"] * 256
for element in content:
@@ -1047,7 +1062,7 @@
if code is None:
code = 0
data.append(packCard8(code))
- return "".join(data)
+ return bytesjoin(data)
def packEncoding1(charset, encoding, strings):
format = 1
@@ -1063,7 +1078,7 @@
code = m.get(name, -1)
if first is None:
first = code
- elif end + 1 <> code:
+ elif end + 1 != code:
nLeft = end - first
ranges.append((first, nLeft))
first = code
@@ -1080,7 +1095,7 @@
if first == -1: # unencoded
first = 0
data.append(packCard8(first) + packCard8(nLeft))
- return "".join(data)
+ return bytesjoin(data)
class FDArrayConverter(TableConverter):
@@ -1096,16 +1111,17 @@
def write(self, parent, value):
return 0 # dummy value
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
fdArray = FDArrayIndex()
for element in content:
if isinstance(element, basestring):
continue
- fdArray.fromXML(element)
+ name, attrs, content = element
+ fdArray.fromXML(name, attrs, content)
return fdArray
-class FDSelectConverter:
+class FDSelectConverter(object):
def read(self, parent, value):
file = parent.file
@@ -1122,7 +1138,7 @@
xmlWriter.simpletag(name, [('format', value.format)])
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
format = safeEval(attrs["format"])
file = None
numGlyphs = None
@@ -1135,7 +1151,7 @@
data = [packCard8(format)]
for index in fdSelectArray:
data.append(packCard8(index))
- return "".join(data)
+ return bytesjoin(data)
def packFDSelect3(fdSelectArray):
@@ -1158,10 +1174,10 @@
data.append(packCard16(fdRange[0]))
data.append(packCard8(fdRange[1]))
data.append(packCard16(sentinelGID))
- return "".join(data)
+ return bytesjoin(data)
-class FDSelectCompiler:
+class FDSelectCompiler(object):
def __init__(self, fdSelect, parent):
format = fdSelect.format
@@ -1197,11 +1213,11 @@
def xmlWrite(self, xmlWriter, name, value, progress):
registry, order, supplement = value
- xmlWriter.simpletag(name, [('Registry', registry), ('Order', order),
+ xmlWriter.simpletag(name, [('Registry', tostr(registry)), ('Order', tostr(order)),
('Supplement', supplement)])
xmlWriter.newline()
- def xmlRead(self, (name, attrs, content), parent):
+ def xmlRead(self, name, attrs, content, parent):
return (attrs['Registry'], attrs['Order'], safeEval(attrs['Supplement']))
@@ -1282,7 +1298,7 @@
elif arg == "number":
conv = NumberConverter()
elif arg == "SID":
- conv = SimpleConverter()
+ conv = ASCIIConverter()
else:
assert 0
table[i] = op, name, arg, default, conv
@@ -1299,7 +1315,7 @@
operators = buildOperatorDict(privateDictOperators)
-class DictCompiler:
+class DictCompiler(object):
def __init__(self, dictObj, strings, parent):
assert isinstance(strings, IndexedStrings)
@@ -1326,8 +1342,8 @@
def compile(self, reason):
if DEBUG:
- print "-- compiling %s for %s" % (self.__class__.__name__, reason)
- print "in baseDict: ", self
+ print("-- compiling %s for %s" % (self.__class__.__name__, reason))
+ print("in baseDict: ", self)
rawDict = self.rawDict
data = []
for name in self.dictObj.order:
@@ -1347,7 +1363,7 @@
arghandler = getattr(self, "arg_" + argType)
data.append(arghandler(value))
data.append(op)
- return "".join(data)
+ return bytesjoin(data)
def toFile(self, file):
file.write(self.compile("toFile"))
@@ -1360,7 +1376,7 @@
data = []
for num in value:
data.append(encodeNumber(num))
- return "".join(data)
+ return bytesjoin(data)
def arg_delta(self, value):
out = []
last = 0
@@ -1370,7 +1386,7 @@
data = []
for num in out:
data.append(encodeNumber(num))
- return "".join(data)
+ return bytesjoin(data)
def encodeNumber(num):
@@ -1455,12 +1471,12 @@
return children
-class BaseDict:
+class BaseDict(object):
def __init__(self, strings=None, file=None, offset=None):
self.rawDict = {}
if DEBUG:
- print "loading %s at %s" % (self.__class__.__name__, offset)
+ print("loading %s at %s" % (self.__class__.__name__, offset))
self.file = file
self.offset = offset
self.strings = strings
@@ -1468,7 +1484,7 @@
def decompile(self, data):
if DEBUG:
- print " length %s is %s" % (self.__class__.__name__, len(data))
+ print(" length %s is %s" % (self.__class__.__name__, len(data)))
dec = self.decompilerClass(self.strings)
dec.decompile(data)
self.rawDict = dec.getDict()
@@ -1485,7 +1501,7 @@
if value is None:
value = self.defaults.get(name)
if value is None:
- raise AttributeError, name
+ raise AttributeError(name)
conv = self.converters[name]
value = conv.read(self, value)
setattr(self, name, value)
@@ -1501,9 +1517,9 @@
conv = self.converters[name]
conv.xmlWrite(xmlWriter, name, value, progress)
- def fromXML(self, (name, attrs, content)):
+ def fromXML(self, name, attrs, content):
conv = self.converters[name]
- value = conv.xmlRead((name, attrs, content), self)
+ value = conv.xmlRead(name, attrs, content, self)
setattr(self, name, value)
@@ -1549,7 +1565,7 @@
try:
charString.decompile()
except:
- print "Error in charstring ", i
+ print("Error in charstring ", i)
import sys
type, value = sys. exc_info()[0:2]
raise type(value)
@@ -1587,7 +1603,7 @@
compilerClass = PrivateDictCompiler
-class IndexedStrings:
+class IndexedStrings(object):
"""SID -> string mapping."""
@@ -1595,7 +1611,7 @@
if file is None:
strings = []
else:
- strings = list(Index(file))
+ strings = [tostr(s) for s in Index(file)]
self.strings = strings
def getCompiler(self):
@@ -1613,9 +1629,9 @@
def getSID(self, s):
if not hasattr(self, "stringMapping"):
self.buildStringMapping()
- if cffStandardStringMapping.has_key(s):
+ if s in cffStandardStringMapping:
SID = cffStandardStringMapping[s]
- elif self.stringMapping.has_key(s):
+ elif s in self.stringMapping:
SID = self.stringMapping[s]
else:
SID = len(self.strings) + cffStandardStringCount
diff --git a/Lib/fontTools/fondLib.py b/Lib/fontTools/fondLib.py
index 74ae13b..c104d9e 100644
--- a/Lib/fontTools/fondLib.py
+++ b/Lib/fontTools/fondLib.py
@@ -1,11 +1,11 @@
-import os
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import string
try:
from Carbon import Res
except ImportError:
import Res
+import struct
error = "fondLib.error"
@@ -29,12 +29,12 @@
FONDheadersize = 52
-class FontFamily:
+class FontFamily(object):
def __init__(self, theRes, mode = 'r'):
self.ID, type, self.name = theRes.GetResInfo()
- if type <> 'FOND':
- raise ValueError, "FOND resource required"
+ if type != 'FOND':
+ raise ValueError("FOND resource required")
self.FOND = theRes
self.mode = mode
self.changed = 0
@@ -68,8 +68,8 @@
self.fondClass = flags
def save(self, destresfile = None):
- if self.mode <> 'w':
- raise error, "can't save font: no write permission"
+ if self.mode != 'w':
+ raise error("can't save font: no write permission")
self._buildfontassociationtable()
self._buildoffsettable()
self._buildboundingboxtable()
@@ -139,13 +139,13 @@
def _buildheader(self):
header = sstruct.pack(headerformat, self)
- header = header + apply(struct.pack, (">9h",) + self.ffProperty)
- header = header + apply(struct.pack, (">hh",) + self.ffIntl)
+ header = header + struct.pack(*(">9h",) + self.ffProperty)
+ header = header + struct.pack(*(">hh",) + self.ffIntl)
header = header + struct.pack(">h", self.ffVersion)
if DEBUG:
- print "header is the same?", self._rawheader == header and 'yes.' or 'no.'
- if self._rawheader <> header:
- print len(self._rawheader), len(header)
+ print("header is the same?", self._rawheader == header and 'yes.' or 'no.')
+ if self._rawheader != header:
+ print(len(self._rawheader), len(header))
self._rawheader = header
def _getfontassociationtable(self):
@@ -169,9 +169,9 @@
data = data + struct.pack(">3h", size, stype, ID)
if DEBUG:
- print "font association table is the same?", self._rawfontassociationtable == data and 'yes.' or 'no.'
- if self._rawfontassociationtable <> data:
- print len(self._rawfontassociationtable), len(data)
+ print("font association table is the same?", self._rawfontassociationtable == data and 'yes.' or 'no.')
+ if self._rawfontassociationtable != data:
+ print(len(self._rawfontassociationtable), len(data))
self._rawfontassociationtable = data
def _getoffsettable(self):
@@ -192,7 +192,7 @@
def _getboundingboxtable(self):
self.boundingBoxes = None
- if self._rawoffsettable[:6] <> '\0\0\0\0\0\6': # XXX ????
+ if self._rawoffsettable[:6] != '\0\0\0\0\0\6': # XXX ????
return
boxes = {}
data = self._rawoffsettable[6:]
@@ -206,8 +206,7 @@
def _buildboundingboxtable(self):
if self.boundingBoxes and self._rawoffsettable[:6] == '\0\0\0\0\0\6':
- boxes = self.boundingBoxes.items()
- boxes.sort()
+ boxes = sorted(self.boundingBoxes.items())
data = '\0\0\0\0\0\6' + struct.pack(">h", len(boxes) - 1)
for style, (l, b, r, t) in boxes:
data = data + struct.pack(">hhhhh", style, l, b, r, t)
@@ -241,16 +240,15 @@
return
numberofentries = len(self.widthTables)
data = struct.pack('>h', numberofentries - 1)
- tables = self.widthTables.items()
- tables.sort()
+ tables = sorted(self.widthTables.items())
for stylecode, table in tables:
data = data + struct.pack('>h', stylecode)
- if len(table) <> (3 + self.ffLastChar - self.ffFirstChar):
- raise error, "width table has wrong length"
+ if len(table) != (3 + self.ffLastChar - self.ffFirstChar):
+ raise error("width table has wrong length")
for width in table:
data = data + struct.pack('>h', width)
if DEBUG:
- print "glyph width table is the same?", self._rawglyphwidthtable == data and 'yes.' or 'no.'
+ print("glyph width table is the same?", self._rawglyphwidthtable == data and 'yes.' or 'no.')
self._rawglyphwidthtable = data
def _getkerningtables(self):
@@ -270,7 +268,7 @@
kerntable = self.kernTables[stylecode] = []
for j in range(numberofpairs):
firstchar, secondchar, kerndistance = struct.unpack(">cch", data[count:count+4])
- kerntable.append((ord(firstchar), ord(secondchar), kerndistance))
+ kerntable.append((byteord(firstchar), byteord(secondchar), kerndistance))
count = count + 4
if DEBUG:
@@ -284,20 +282,19 @@
return
numberofentries = len(self.kernTables)
data = [struct.pack('>h', numberofentries - 1)]
- tables = self.kernTables.items()
- tables.sort()
+ tables = sorted(self.kernTables.items())
for stylecode, table in tables:
data.append(struct.pack('>h', stylecode))
data.append(struct.pack('>h', len(table))) # numberofpairs
for firstchar, secondchar, kerndistance in table:
- data.append(struct.pack(">cch", chr(firstchar), chr(secondchar), kerndistance))
+ data.append(struct.pack(">cch", bytechr(firstchar), bytechr(secondchar), kerndistance))
- data = string.join(data, '')
+ data = bytesjoin(data)
if DEBUG:
- print "kerning table is the same?", self._rawkerningtables == data and 'yes.' or 'no.'
- if self._rawkerningtables <> data:
- print len(self._rawkerningtables), len(data)
+ print("kerning table is the same?", self._rawkerningtables == data and 'yes.' or 'no.')
+ if self._rawkerningtables != data:
+ print(len(self._rawkerningtables), len(data))
self._rawkerningtables = data
def _getstylemappingtable(self):
@@ -316,7 +313,7 @@
count = offset + 60
for i in range(stringcount):
- str_len = ord(data[count])
+ str_len = byteord(data[count])
self.styleStrings.append(data[count + 1:count + 1 + str_len])
count = count + 1 + str_len
@@ -337,18 +334,18 @@
self.styleMappingReserved)
self._packstylestrings()
- data = data + apply(struct.pack, (">48b",) + self.styleIndices)
+ data = data + struct.pack(*(">48b",) + self.styleIndices)
stringcount = len(self.styleStrings)
data = data + struct.pack(">h", stringcount)
for string in self.styleStrings:
- data = data + chr(len(string)) + string
+ data = data + bytechr(len(string)) + string
if len(data) % 2:
data = data + '\0'
if DEBUG:
- print "style mapping table is the same?", self._rawstylemappingtable == data and 'yes.' or 'no.'
+ print("style mapping table is the same?", self._rawstylemappingtable == data and 'yes.' or 'no.')
self._rawstylemappingtable = data
def _unpackstylestrings(self):
@@ -360,7 +357,7 @@
psNames[i] = self.styleStrings[0]
else:
style = self.styleStrings[0]
- codes = map(ord, self.styleStrings[index - 1])
+ codes = map(byteord, self.styleStrings[index - 1])
for code in codes:
style = style + self.styleStrings[code - 1]
psNames[i] = style
@@ -375,10 +372,8 @@
for part in split:
nameparts[part] = None
del nameparts[self.ffFamilyName]
- nameparts = nameparts.keys()
- nameparts.sort()
- items = splitnames.items()
- items.sort()
+ nameparts = sorted(nameparts.keys())
+ items = sorted(splitnames.items())
numindices = 0
for style, split in items:
if len(split) > 1:
@@ -391,7 +386,7 @@
continue
indices = ""
for part in split[1:]:
- indices = indices + chr(nameparts.index(part) + numindices + 2)
+ indices = indices + bytechr(nameparts.index(part) + numindices + 2)
styleStrings[self.styleIndices[style] - 1] = indices
self.styleStrings = styleStrings
@@ -415,9 +410,9 @@
numberofentries, = struct.unpack(">h", data[offset:offset+2])
count = offset + 2
for i in range(numberofentries):
- glyphcode = ord(data[count])
+ glyphcode = byteord(data[count])
count = count + 1
- strlen = ord(data[count])
+ strlen = byteord(data[count])
count = count + 1
glyphname = data[count:count+strlen]
glyphEncoding[glyphcode] = glyphname
@@ -433,10 +428,9 @@
return
numberofentries = len(self.glyphEncoding)
data = struct.pack(">h", numberofentries)
- items = self.glyphEncoding.items()
- items.sort()
+ items = sorted(self.glyphEncoding.items())
for glyphcode, glyphname in items:
- data = data + chr(glyphcode) + chr(len(glyphname)) + glyphname
+ data = data + bytechr(glyphcode) + bytechr(len(glyphname)) + glyphname
self._rawglyphencodingsubtable = data
@@ -445,8 +439,8 @@
def splitname(name, famname = None):
# XXX this goofs up MM font names: but how should it be done??
if famname:
- if name[:len(famname)] <> famname:
- raise error, "first part of name should be same as family name"
+ if name[:len(famname)] != famname:
+ raise error("first part of name should be same as family name")
name = name[len(famname):]
split = [famname]
else:
@@ -466,11 +460,11 @@
split = splitname(name)
lwfnname = split[0][:5]
for part in split[1:]:
- if part <> '-':
+ if part != '-':
lwfnname = lwfnname + part[:3]
return lwfnname
-class BitmapFontFile:
+class BitmapFontFile(object):
def __init__(self, path, mode='r'):
if mode == 'r':
@@ -478,7 +472,7 @@
elif mode == 'w':
permission = 3 # exclusive r/w
else:
- raise error, 'mode should be either "r" or "w"'
+ raise error('mode should be either "r" or "w"')
self.mode = mode
self.resref = Res.FSOpenResFile(path, permission)
Res.UseResFile(self.resref)
@@ -497,8 +491,7 @@
for fond in self.fonds:
fond.parse()
if hasattr(fond, "psNames") and fond.psNames:
- psNames = fond.psNames.values()
- psNames.sort()
+ psNames = sorted(fond.psNames.values())
self.fondsbyname[psNames[0]] = fond
def minimalparse(self):
@@ -506,7 +499,7 @@
fond.minimalparse()
def close(self):
- if self.resref <> None:
+ if self.resref != None:
try:
Res.CloseResFile(self.resref)
except Res.Error:
@@ -514,12 +507,12 @@
self.resref = None
-class FondSelector:
+class FondSelector(object):
def __init__(self, fondlist):
import W
if not fondlist:
- raise ValueError, "expected at least one FOND entry"
+ raise ValueError("expected at least one FOND entry")
if len(fondlist) == 1:
self.choice = 0
return
@@ -549,6 +542,6 @@
sel = self.w.l.getselection()
if not sel:
self.w.l.setselection([0])
- elif len(sel) <> 1:
+ elif len(sel) != 1:
self.w.l.setselection([sel[0]])
diff --git a/Lib/fontTools/inspect.py b/Lib/fontTools/inspect.py
index d273579..93186f0 100644
--- a/Lib/fontTools/inspect.py
+++ b/Lib/fontTools/inspect.py
@@ -5,13 +5,15 @@
"""GUI font inspector.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools import misc, ttLib, cffLib
import pygtk
pygtk.require('2.0')
import gtk
import sys
import array
-from fontTools import misc, ttLib, cffLib
class Row(object):
@@ -217,7 +219,7 @@
def on_iter_parent(self, rowref):
return rowref.get_parent()
-class Inspect:
+class Inspect(object):
def _delete_event(self, widget, event, data=None):
gtk.main_quit()
@@ -254,7 +256,7 @@
def main(args):
if len(args) < 1:
- print >>sys.stderr, "usage: pyftinspect font..."
+ print("usage: pyftinspect font...", file=sys.stderr)
sys.exit(1)
for arg in args:
Inspect(arg)
diff --git a/Lib/fontTools/misc/arrayTools.py b/Lib/fontTools/misc/arrayTools.py
index 3f39e7e..acbb02f 100644
--- a/Lib/fontTools/misc/arrayTools.py
+++ b/Lib/fontTools/misc/arrayTools.py
@@ -4,6 +4,8 @@
#
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import math
def calcBounds(array):
@@ -16,13 +18,15 @@
ys = [y for x, y in array]
return min(xs), min(ys), max(xs), max(ys)
-def updateBounds(bounds, (x, y), min=min, max=max):
+def updateBounds(bounds, p, min=min, max=max):
"""Return the bounding recangle of rectangle bounds and point (x, y)."""
+ (x, y) = p
xMin, yMin, xMax, yMax = bounds
return min(xMin, x), min(yMin, y), max(xMax, x), max(yMax, y)
-def pointInRect((x, y), rect):
+def pointInRect(p, rect):
"""Return True when point (x, y) is inside rect."""
+ (x, y) = p
xMin, yMin, xMax, yMax = rect
return (xMin <= x <= xMax) and (yMin <= y <= yMax)
@@ -45,52 +49,62 @@
return [int(math.floor(i+0.5)) for i in array]
-def normRect((xMin, yMin, xMax, yMax)):
+def normRect(rect):
"""Normalize the rectangle so that the following holds:
xMin <= xMax and yMin <= yMax
"""
+ (xMin, yMin, xMax, yMax) = rect
return min(xMin, xMax), min(yMin, yMax), max(xMin, xMax), max(yMin, yMax)
-def scaleRect((xMin, yMin, xMax, yMax), x, y):
+def scaleRect(rect, x, y):
"""Scale the rectangle by x, y."""
+ (xMin, yMin, xMax, yMax) = rect
return xMin * x, yMin * y, xMax * x, yMax * y
-def offsetRect((xMin, yMin, xMax, yMax), dx, dy):
+def offsetRect(rect, dx, dy):
"""Offset the rectangle by dx, dy."""
+ (xMin, yMin, xMax, yMax) = rect
return xMin+dx, yMin+dy, xMax+dx, yMax+dy
-def insetRect((xMin, yMin, xMax, yMax), dx, dy):
+def insetRect(rect, dx, dy):
"""Inset the rectangle by dx, dy on all sides."""
+ (xMin, yMin, xMax, yMax) = rect
return xMin+dx, yMin+dy, xMax-dx, yMax-dy
-def sectRect((xMin1, yMin1, xMax1, yMax1), (xMin2, yMin2, xMax2, yMax2)):
+def sectRect(rect1, rect2):
"""Return a boolean and a rectangle. If the input rectangles intersect, return
True and the intersecting rectangle. Return False and (0, 0, 0, 0) if the input
rectangles don't intersect.
"""
+ (xMin1, yMin1, xMax1, yMax1) = rect1
+ (xMin2, yMin2, xMax2, yMax2) = rect2
xMin, yMin, xMax, yMax = (max(xMin1, xMin2), max(yMin1, yMin2),
min(xMax1, xMax2), min(yMax1, yMax2))
if xMin >= xMax or yMin >= yMax:
return 0, (0, 0, 0, 0)
return 1, (xMin, yMin, xMax, yMax)
-def unionRect((xMin1, yMin1, xMax1, yMax1), (xMin2, yMin2, xMax2, yMax2)):
+def unionRect(rect1, rect2):
"""Return the smallest rectangle in which both input rectangles are fully
enclosed. In other words, return the total bounding rectangle of both input
rectangles.
"""
+ (xMin1, yMin1, xMax1, yMax1) = rect1
+ (xMin2, yMin2, xMax2, yMax2) = rect2
xMin, yMin, xMax, yMax = (min(xMin1, xMin2), min(yMin1, yMin2),
max(xMax1, xMax2), max(yMax1, yMax2))
return (xMin, yMin, xMax, yMax)
-def rectCenter((xMin, yMin, xMax, yMax)):
+def rectCenter(rect0):
"""Return the center of the rectangle as an (x, y) coordinate."""
+ (xMin, yMin, xMax, yMax) = rect0
return (xMin+xMax)/2, (yMin+yMax)/2
-def intRect((xMin, yMin, xMax, yMax)):
+def intRect(rect1):
"""Return the rectangle, rounded off to integer values, but guaranteeing that
the resulting rectangle is NOT smaller than the original.
"""
+ (xMin, yMin, xMax, yMax) = rect1
import math
xMin = int(math.floor(xMin))
yMin = int(math.floor(yMin))
@@ -147,9 +161,9 @@
>>> unionRect((0, 10, 20, 30), (0, 40, 20, 50))
(0, 10, 20, 50)
>>> rectCenter((0, 0, 100, 200))
- (50, 100)
+ (50.0, 100.0)
>>> rectCenter((0, 0, 100, 199.0))
- (50, 99.5)
+ (50.0, 99.5)
>>> intRect((0.9, 2.9, 3.1, 4.1))
(0, 2, 4, 5)
"""
diff --git a/Lib/fontTools/misc/bezierTools.py b/Lib/fontTools/misc/bezierTools.py
index 4c897d5..179ab3c 100644
--- a/Lib/fontTools/misc/bezierTools.py
+++ b/Lib/fontTools/misc/bezierTools.py
@@ -1,6 +1,8 @@
"""fontTools.misc.bezierTools.py -- tools for working with bezier path segments.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
__all__ = [
"calcQuadraticBounds",
@@ -98,7 +100,7 @@
if ax == 0:
return [(pt1, pt2)]
- t = float(where - (bx, by)[isHorizontal]) / ax
+ t = (where - (bx, by)[isHorizontal]) / ax
if 0 <= t < 1:
midPt = ax * t + bx, ay * t + by
return [(pt1, midPt), (midPt, pt2)]
@@ -132,8 +134,7 @@
a, b, c = calcQuadraticParameters(pt1, pt2, pt3)
solutions = solveQuadratic(a[isHorizontal], b[isHorizontal],
c[isHorizontal] - where)
- solutions = [t for t in solutions if 0 <= t < 1]
- solutions.sort()
+ solutions = sorted([t for t in solutions if 0 <= t < 1])
if not solutions:
return [(pt1, pt2, pt3)]
return _splitQuadraticAtT(a, b, c, *solutions)
@@ -157,8 +158,7 @@
a, b, c, d = calcCubicParameters(pt1, pt2, pt3, pt4)
solutions = solveCubic(a[isHorizontal], b[isHorizontal], c[isHorizontal],
d[isHorizontal] - where)
- solutions = [t for t in solutions if 0 <= t < 1]
- solutions.sort()
+ solutions = sorted([t for t in solutions if 0 <= t < 1])
if not solutions:
return [(pt1, pt2, pt3, pt4)]
return _splitCubicAtT(a, b, c, d, *solutions)
@@ -402,7 +402,7 @@
segments on a single line as a tuple.
"""
for segment in segments:
- print _segmentrepr(segment)
+ print(_segmentrepr(segment))
if __name__ == "__main__":
import doctest
diff --git a/Lib/fontTools/misc/eexec.py b/Lib/fontTools/misc/eexec.py
index ade0789..1264355 100644
--- a/Lib/fontTools/misc/eexec.py
+++ b/Lib/fontTools/misc/eexec.py
@@ -2,26 +2,27 @@
charstring encryption algorithm as used by PostScript Type 1 fonts.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+
# Warning: Although a Python implementation is provided here,
# all four public functions get overridden by the *much* faster
# C extension module eexecOp, if available.
-import string
-
error = "eexec.error"
def _decryptChar(cipher, R):
- cipher = ord(cipher)
+ cipher = byteord(cipher)
plain = ( (cipher ^ (R>>8)) ) & 0xFF
- R = ( (cipher + R) * 52845L + 22719L ) & 0xFFFF
- return chr(plain), R
+ R = ( (cipher + R) * 52845 + 22719 ) & 0xFFFF
+ return bytechr(plain), R
def _encryptChar(plain, R):
- plain = ord(plain)
+ plain = byteord(plain)
cipher = ( (plain ^ (R>>8)) ) & 0xFF
- R = ( (cipher + R) * 52845L + 22719L ) & 0xFFFF
- return chr(cipher), R
+ R = ( (cipher + R) * 52845 + 22719 ) & 0xFFFF
+ return bytechr(cipher), R
def decrypt(cipherstring, R):
@@ -31,7 +32,7 @@
for cipher in cipherstring:
plain, R = _decryptChar(cipher, R)
plainList.append(plain)
- plainstring = string.join(plainList, '')
+ plainstring = strjoin(plainList)
return plainstring, int(R)
def encrypt(plainstring, R):
@@ -39,7 +40,7 @@
for plain in plainstring:
cipher, R = _encryptChar(plain, R)
cipherList.append(cipher)
- cipherstring = string.join(cipherList, '')
+ cipherstring = strjoin(cipherList)
return cipherstring, int(R)
@@ -49,17 +50,17 @@
def deHexString(h):
import binascii
- h = "".join(h.split())
+ h = strjoin(h.split())
return binascii.unhexlify(h)
def _test():
import fontTools.misc.eexecOp as eexecOp
testStr = "\0\0asdadads asds\265"
- print decrypt, decrypt(testStr, 12321)
- print eexecOp.decrypt, eexecOp.decrypt(testStr, 12321)
- print encrypt, encrypt(testStr, 12321)
- print eexecOp.encrypt, eexecOp.encrypt(testStr, 12321)
+ print(decrypt, decrypt(testStr, 12321))
+ print(eexecOp.decrypt, eexecOp.decrypt(testStr, 12321))
+ print(encrypt, encrypt(testStr, 12321))
+ print(eexecOp.encrypt, eexecOp.encrypt(testStr, 12321))
if __name__ == "__main__":
diff --git a/Lib/fontTools/misc/fixedTools.py b/Lib/fontTools/misc/fixedTools.py
new file mode 100644
index 0000000..037a0e2
--- /dev/null
+++ b/Lib/fontTools/misc/fixedTools.py
@@ -0,0 +1,65 @@
+"""fontTools.misc.fixedTools.py -- tools for working with fixed numbers.
+"""
+
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+
+__all__ = [
+ "fixedToFloat",
+ "floatToFixed",
+]
+
+def fixedToFloat(value, precisionBits):
+ """Converts a fixed-point number to a float, choosing the float
+ that has the shortest decimal reprentation. Eg. to convert a
+ fixed number in a 2.14 format, use precisionBits=14. This is
+ pretty slow compared to a simple division. Use sporadically.
+
+ >>> fixedToFloat(13107, 14)
+ 0.8
+ >>> fixedToFloat(0, 14)
+ 0.0
+ >>> fixedToFloat(0x4000, 14)
+ 1.0
+ """
+
+ if not value: return 0.0
+
+ scale = 1 << precisionBits
+ value /= scale
+ eps = .5 / scale
+ digits = (precisionBits + 2) // 3
+ fmt = "%%.%df" % digits
+ lo = fmt % (value - eps)
+ hi = fmt % (value + eps)
+ out = []
+ length = min(len(lo), len(hi))
+ for i in range(length):
+ if lo[i] != hi[i]:
+ break;
+ out.append(lo[i])
+ outlen = len(out)
+ if outlen < length:
+ out.append(max(lo[outlen], hi[outlen]))
+ return float(strjoin(out))
+
+def floatToFixed(value, precisionBits):
+ """Converts a float to a fixed-point number given the number of
+ precisionBits. Ie. int(round(value * (1<<precisionBits))).
+
+ >>> floatToFixed(0.8, 14)
+ 13107
+ >>> floatToFixed(1.0, 14)
+ 16384
+ >>> floatToFixed(1, 14)
+ 16384
+ >>> floatToFixed(0, 14)
+ 0
+ """
+
+ return int(round(value * (1<<precisionBits)))
+
+
+if __name__ == "__main__":
+ import doctest
+ doctest.testmod()
diff --git a/Lib/fontTools/misc/homeResFile.py b/Lib/fontTools/misc/homeResFile.py
index b9463e4..dc61c2f 100644
--- a/Lib/fontTools/misc/homeResFile.py
+++ b/Lib/fontTools/misc/homeResFile.py
@@ -1,5 +1,7 @@
"""Mac-only module to find the home file of a resource."""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
import array
import calldll
@@ -49,7 +51,7 @@
ioFCBParID: l
"""
-class ParamBlock:
+class ParamBlock(object):
"""Wrapper for the very low level FCBPB record."""
@@ -70,14 +72,14 @@
ptr = buf.buffer_info()[0]
err = _getInfo(ptr)
if err:
- raise Res.Error, ("can't get file info", err)
+ raise Res.Error("can't get file info", err)
sstruct.unpack(_FCBPBFormat, buf.tostring(), self)
self.__haveInfo = 1
def getFileName(self):
self.getInfo()
data = self.__fileName.tostring()
- return data[1:ord(data[0])+1]
+ return data[1:byteord(data[0])+1]
def getFSSpec(self):
self.getInfo()
@@ -91,4 +93,4 @@
if __name__ == "__main__":
fond = Res.GetNamedResource("FOND", "Helvetica")
- print HomeResFile(fond)
+ print(HomeResFile(fond))
diff --git a/Lib/fontTools/misc/macCreatorType.py b/Lib/fontTools/misc/macCreatorType.py
index 57d158c..bcbc4cb 100644
--- a/Lib/fontTools/misc/macCreatorType.py
+++ b/Lib/fontTools/misc/macCreatorType.py
@@ -1,13 +1,16 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import sys
try:
import MacOS
except ImportError:
MacOS = None
+from .py23 import *
def _reverseString(s):
s = list(s)
s.reverse()
- return "".join(s)
+ return strjoin(s)
def getMacCreatorAndType(path):
diff --git a/Lib/fontTools/misc/psCharStrings.py b/Lib/fontTools/misc/psCharStrings.py
index 9b2105b..34ace23 100644
--- a/Lib/fontTools/misc/psCharStrings.py
+++ b/Lib/fontTools/misc/psCharStrings.py
@@ -2,9 +2,9 @@
CFF dictionary data and Type1/Type2 CharStrings.
"""
-import types
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import struct
-import string
DEBUG = 0
@@ -35,38 +35,35 @@
realNibblesDict[realNibbles[_i]] = _i
-class ByteCodeBase:
+class ByteCodeBase(object):
def read_byte(self, b0, data, index):
return b0 - 139, index
def read_smallInt1(self, b0, data, index):
- b1 = ord(data[index])
+ b1 = byteord(data[index])
return (b0-247)*256 + b1 + 108, index+1
def read_smallInt2(self, b0, data, index):
- b1 = ord(data[index])
+ b1 = byteord(data[index])
return -(b0-251)*256 - b1 - 108, index+1
def read_shortInt(self, b0, data, index):
- bin = data[index] + data[index+1]
- value, = struct.unpack(">h", bin)
+ value, = struct.unpack(">h", data[index:index+2])
return value, index+2
def read_longInt(self, b0, data, index):
- bin = data[index] + data[index+1] + data[index+2] + data[index+3]
- value, = struct.unpack(">l", bin)
+ value, = struct.unpack(">l", data[index:index+4])
return value, index+4
def read_fixed1616(self, b0, data, index):
- bin = data[index] + data[index+1] + data[index+2] + data[index+3]
- value, = struct.unpack(">l", bin)
- return value / 65536.0, index+4
+ value, = struct.unpack(">l", data[index:index+4])
+ return value / 65536, index+4
def read_realNumber(self, b0, data, index):
number = ''
- while 1:
- b = ord(data[index])
+ while True:
+ b = byteord(data[index])
index = index + 1
nibble0 = (b & 0xf0) >> 4
nibble1 = b & 0x0f
@@ -87,7 +84,7 @@
oper[item[0]] = item[1]
else:
oper[item[0]] = item[1:]
- if type(item[0]) == types.TupleType:
+ if isinstance(item[0], tuple):
opc[item[1]] = item[0]
else:
opc[item[1]] = (item[0],)
@@ -154,27 +151,27 @@
def getIntEncoder(format):
if format == "cff":
- fourByteOp = chr(29)
+ fourByteOp = bytechr(29)
elif format == "t1":
- fourByteOp = chr(255)
+ fourByteOp = bytechr(255)
else:
assert format == "t2"
fourByteOp = None
- def encodeInt(value, fourByteOp=fourByteOp, chr=chr,
+ def encodeInt(value, fourByteOp=fourByteOp, bytechr=bytechr,
pack=struct.pack, unpack=struct.unpack):
if -107 <= value <= 107:
- code = chr(value + 139)
+ code = bytechr(value + 139)
elif 108 <= value <= 1131:
value = value - 108
- code = chr((value >> 8) + 247) + chr(value & 0xFF)
+ code = bytechr((value >> 8) + 247) + bytechr(value & 0xFF)
elif -1131 <= value <= -108:
value = -value - 108
- code = chr((value >> 8) + 251) + chr(value & 0xFF)
+ code = bytechr((value >> 8) + 251) + bytechr(value & 0xFF)
elif fourByteOp is None:
# T2 only supports 2 byte ints
if -32768 <= value <= 32767:
- code = chr(28) + pack(">h", value)
+ code = bytechr(28) + pack(">h", value)
else:
# Backwards compatible hack: due to a previous bug in FontTools,
# 16.16 fixed numbers were written out as 4-byte ints. When
@@ -188,7 +185,7 @@
sys.stderr.write("Warning: 4-byte T2 number got passed to the "
"IntType handler. This should happen only when reading in "
"old XML files.\n")
- code = chr(255) + pack(">l", value)
+ code = bytechr(255) + pack(">l", value)
else:
code = fourByteOp + pack(">l", value)
return code
@@ -202,7 +199,7 @@
def encodeFixed(f, pack=struct.pack):
# For T2 only
- return "\xff" + pack(">l", int(round(f * 65536)))
+ return b"\xff" + pack(">l", int(round(f * 65536)))
def encodeFloat(f):
# For CFF only, used in cffLib
@@ -222,9 +219,9 @@
nibbles.append(0xf)
if len(nibbles) % 2:
nibbles.append(0xf)
- d = chr(30)
+ d = bytechr(30)
for i in range(0, len(nibbles), 2):
- d = d + chr(nibbles[i] << 4 | nibbles[i+1])
+ d = d + bytechr(nibbles[i] << 4 | nibbles[i+1])
return d
@@ -287,24 +284,24 @@
token = program[i]
i = i + 1
tp = type(token)
- if tp == types.StringType:
+ if issubclass(tp, basestring):
try:
- bytecode.extend(map(chr, opcodes[token]))
+ bytecode.extend(bytechr(b) for b in opcodes[token])
except KeyError:
- raise CharStringCompileError, "illegal operator: %s" % token
+ raise CharStringCompileError("illegal operator: %s" % token)
if token in ('hintmask', 'cntrmask'):
bytecode.append(program[i]) # hint mask
i = i + 1
- elif tp == types.IntType:
+ elif tp == int:
bytecode.append(encodeInt(token))
- elif tp == types.FloatType:
+ elif tp == float:
bytecode.append(encodeFixed(token))
else:
assert 0, "unsupported type: %s" % tp
try:
- bytecode = "".join(bytecode)
+ bytecode = bytesjoin(bytecode)
except TypeError:
- print bytecode
+ print(bytecode)
raise
self.setBytecode(bytecode)
@@ -320,11 +317,11 @@
self.program = None
def getToken(self, index,
- len=len, ord=ord, getattr=getattr, type=type, StringType=types.StringType):
+ len=len, byteord=byteord, getattr=getattr, type=type, StringType=str):
if self.bytecode is not None:
if index >= len(self.bytecode):
return None, 0, 0
- b0 = ord(self.bytecode[index])
+ b0 = byteord(self.bytecode[index])
index = index + 1
code = self.operandEncoding[b0]
handler = getattr(self, code)
@@ -334,7 +331,7 @@
return None, 0, 0
token = self.program[index]
index = index + 1
- isOperator = type(token) == StringType
+ isOperator = isinstance(token, StringType)
return token, isOperator, index
def getBytes(self, index, nBytes):
@@ -350,7 +347,7 @@
def do_operator(self, b0, data, index):
if b0 == 12:
- op = (b0, ord(data[index]))
+ op = (b0, byteord(data[index]))
index = index+1
else:
op = b0
@@ -364,33 +361,33 @@
else:
index = 0
args = []
- while 1:
+ while True:
token, isOperator, index = self.getToken(index)
if token is None:
break
if isOperator:
- args = map(str, args)
+ args = [str(arg) for arg in args]
if token in ('hintmask', 'cntrmask'):
hintMask, isOperator, index = self.getToken(index)
bits = []
for byte in hintMask:
- bits.append(num2binary(ord(byte), 8))
- hintMask = string.join(bits, "")
- line = string.join(args + [token, hintMask], " ")
+ bits.append(num2binary(byteord(byte), 8))
+ hintMask = strjoin(bits)
+ line = ' '.join(args + [token, hintMask])
else:
- line = string.join(args + [token], " ")
+ line = ' '.join(args + [token])
xmlWriter.write(line)
xmlWriter.newline()
args = []
else:
args.append(token)
- def fromXML(self, (name, attrs, content)):
+ def fromXML(self, name, attrs, content):
from fontTools.misc.textTools import binary2num, readHex
if attrs.get("raw"):
self.setBytecode(readHex(content))
return
- content = "".join(content)
+ content = strjoin(content)
content = content.split()
program = []
end = len(content)
@@ -407,9 +404,9 @@
program.append(token)
if token in ('hintmask', 'cntrmask'):
mask = content[i]
- maskBytes = ""
+ maskBytes = b""
for j in range(0, len(mask), 8):
- maskBytes = maskBytes + chr(binary2num(mask[j:j+8]))
+ maskBytes = maskBytes + bytechr(binary2num(mask[j:j+8]))
program.append(maskBytes)
i = i + 1
else:
@@ -472,7 +469,7 @@
return
program = []
index = 0
- while 1:
+ while True:
token, isOperator, index = self.getToken(index)
if token is None:
break
@@ -485,7 +482,7 @@
self.width = extractor.width
-class SimpleT2Decompiler:
+class SimpleT2Decompiler(object):
def __init__(self, localSubrs, globalSubrs):
self.localSubrs = localSubrs
@@ -510,7 +507,7 @@
pushToProgram = lambda x: None
pushToStack = self.operandStack.append
index = 0
- while 1:
+ while True:
token, isOperator, index = charString.getToken(index)
if token is None:
break # we're done!
@@ -579,7 +576,7 @@
def op_hintmask(self, index):
if not self.hintMaskBytes:
self.countHints()
- self.hintMaskBytes = (self.hintCount + 7) / 8
+ self.hintMaskBytes = (self.hintCount + 7) // 8
hintMaskBytes, index = self.callingStack[-1].getBytes(index, self.hintMaskBytes)
return hintMaskBytes, index
@@ -587,7 +584,7 @@
def countHints(self):
args = self.popall()
- self.hintCount = self.hintCount + len(args) / 2
+ self.hintCount = self.hintCount + len(args) // 2
# misc
def op_and(self, index):
@@ -695,7 +692,7 @@
def countHints(self):
args = self.popallWidth()
- self.hintCount = self.hintCount + len(args) / 2
+ self.hintCount = self.hintCount + len(args) // 2
#
# hint operators
@@ -882,8 +879,8 @@
def op_div(self, index):
num2 = self.pop()
num1 = self.pop()
- d1 = num1/num2
- d2 = float(num1)/num2
+ d1 = num1//num2
+ d2 = num1/num2
if d1 == d2:
self.push(d1)
else:
@@ -1114,7 +1111,7 @@
lenData = len(data)
push = self.stack.append
while index < lenData:
- b0 = ord(data[index])
+ b0 = byteord(data[index])
index = index + 1
code = self.operandEncoding[b0]
handler = getattr(self, code)
@@ -1134,7 +1131,7 @@
def do_operator(self, b0, data, index):
if b0 == 12:
- op = (b0, ord(data[index]))
+ op = (b0, byteord(data[index]))
index = index+1
else:
op = b0
@@ -1143,7 +1140,7 @@
return None, index
def handle_operator(self, operator, argType):
- if type(argType) == type(()):
+ if isinstance(argType, type(())):
value = ()
for i in range(len(argType)-1, -1, -1):
arg = argType[i]
diff --git a/Lib/fontTools/misc/py23.py b/Lib/fontTools/misc/py23.py
new file mode 100644
index 0000000..2842840
--- /dev/null
+++ b/Lib/fontTools/misc/py23.py
@@ -0,0 +1,84 @@
+"""Python 2/3 compat layer."""
+
+from __future__ import print_function, division
+
+try:
+ basestring
+except NameError:
+ basestring = str
+
+try:
+ unicode
+except NameError:
+ unicode = str
+
+try:
+ unichr
+ bytechr = chr
+ byteord = ord
+except:
+ unichr = chr
+ def bytechr(n):
+ return bytes([n])
+ def byteord(c):
+ return c if isinstance(c, int) else ord(c)
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ try:
+ from StringIO import StringIO
+ except ImportError:
+ from io import BytesIO as StringIO
+
+def strjoin(iterable):
+ return ''.join(iterable)
+if str == bytes:
+ class Tag(str):
+ def tobytes(self):
+ if isinstance(self, bytes):
+ return self
+ else:
+ return self.encode('latin1')
+
+ def tostr(s, encoding='ascii'):
+ if not isinstance(s, str):
+ return s.encode(encoding)
+ else:
+ return s
+ tobytes = tostr
+
+ bytesjoin = strjoin
+else:
+ class Tag(str):
+
+ @staticmethod
+ def transcode(blob):
+ if not isinstance(blob, str):
+ blob = blob.decode('latin-1')
+ return blob
+
+ def __new__(self, content):
+ return str.__new__(self, self.transcode(content))
+ def __eq__(self, other):
+ return str.__eq__(self, self.transcode(other))
+
+ def __hash__(self):
+ return str.__hash__(self)
+
+ def tobytes(self):
+ return self.encode('latin-1')
+
+ def tostr(s, encoding='ascii'):
+ if not isinstance(s, str):
+ return s.decode(encoding)
+ else:
+ return s
+ def tobytes(s, encoding='ascii'):
+ if not isinstance(s, bytes):
+ return s.encode(encoding)
+ else:
+ return s
+
+ def bytesjoin(iterable):
+ return b''.join(tobytes(item) for item in iterable)
diff --git a/Lib/fontTools/misc/sstruct.py b/Lib/fontTools/misc/sstruct.py
index 7bc4772..ecf495b 100644
--- a/Lib/fontTools/misc/sstruct.py
+++ b/Lib/fontTools/misc/sstruct.py
@@ -46,50 +46,57 @@
it returns the size of the data in bytes.
"""
-# XXX I would like to support pascal strings, too, but I'm not
-# sure if that's wise. Would be nice if struct supported them
-# "properly", but that would certainly break calcsize()...
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc.fixedTools import fixedToFloat as fi2fl, floatToFixed as fl2fi
+import struct
+import re
__version__ = "1.2"
__copyright__ = "Copyright 1998, Just van Rossum <just@letterror.com>"
-import struct
-import re
-import types
-
-error = "sstruct.error"
+class Error(Exception):
+ pass
def pack(format, object):
formatstring, names, fixes = getformat(format)
elements = []
- if type(object) is not types.DictType:
+ if not isinstance(object, dict):
object = object.__dict__
for name in names:
value = object[name]
- if fixes.has_key(name):
+ if name in fixes:
# fixed point conversion
- value = int(round(value*fixes[name]))
+ value = fl2fi(value, fixes[name])
+ elif isinstance(value, basestring):
+ value = tobytes(value)
elements.append(value)
- data = apply(struct.pack, (formatstring,) + tuple(elements))
+ data = struct.pack(*(formatstring,) + tuple(elements))
return data
def unpack(format, data, object=None):
if object is None:
object = {}
+ data = tobytes(data)
formatstring, names, fixes = getformat(format)
- if type(object) is types.DictType:
- dict = object
+ if isinstance(object, dict):
+ d = object
else:
- dict = object.__dict__
+ d = object.__dict__
elements = struct.unpack(formatstring, data)
for i in range(len(names)):
name = names[i]
value = elements[i]
- if fixes.has_key(name):
+ if name in fixes:
# fixed point conversion
- value = value / fixes[name]
- dict[name] = value
+ value = fi2fl(value, fixes[name])
+ elif isinstance(value, bytes):
+ try:
+ value = tostr(value)
+ except UnicodeDecodeError:
+ pass
+ d[name] = value
return object
def unpack2(format, data, object=None):
@@ -139,12 +146,12 @@
m = _extraRE.match(line)
if m:
formatchar = m.group(1)
- if formatchar <> 'x' and formatstring:
- raise error, "a special format char must be first"
+ if formatchar != 'x' and formatstring:
+ raise Error("a special format char must be first")
else:
m = _elementRE.match(line)
if not m:
- raise error, "syntax error in format: '%s'" % line
+ raise Error("syntax error in format: '%s'" % line)
name = m.group(1)
names.append(name)
formatchar = m.group(2)
@@ -154,10 +161,10 @@
after = int(m.group(4))
bits = before + after
if bits not in [8, 16, 32]:
- raise error, "fixed point must be 8, 16 or 32 bits long"
+ raise Error("fixed point must be 8, 16 or 32 bits long")
formatchar = _fixedpointmappings[bits]
assert m.group(5) == "F"
- fixes[name] = float(1 << after)
+ fixes[name] = after
formatstring = formatstring + formatchar
_formatcache[format] = formatstring, names, fixes
return formatstring, names, fixes
@@ -177,9 +184,9 @@
afixed: 16.16F
"""
- print 'size:', calcsize(format)
+ print('size:', calcsize(format))
- class foo:
+ class foo(object):
pass
i = foo()
@@ -194,11 +201,11 @@
i.afixed = 1.5
data = pack(format, i)
- print 'data:', `data`
- print unpack(format, data)
+ print('data:', repr(data))
+ print(unpack(format, data))
i2 = foo()
unpack(format, data, i2)
- print vars(i2)
+ print(vars(i2))
if __name__ == "__main__":
_test()
diff --git a/Lib/fontTools/misc/textTools.py b/Lib/fontTools/misc/textTools.py
index d461b25..f4fe07c 100644
--- a/Lib/fontTools/misc/textTools.py
+++ b/Lib/fontTools/misc/textTools.py
@@ -1,6 +1,8 @@
"""fontTools.misc.textTools.py -- miscelaneous routines."""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import string
@@ -11,18 +13,17 @@
def readHex(content):
"""Convert a list of hex strings to binary data."""
- return deHexStr(''.join([ chunk for chunk in content if isinstance(chunk,str) ]))
+ return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, basestring)))
def deHexStr(hexdata):
"""Convert a hex string to binary data."""
- parts = string.split(hexdata)
- hexdata = string.join(parts, "")
+ hexdata = strjoin(hexdata.split())
if len(hexdata) % 2:
hexdata = hexdata + "0"
data = []
for i in range(0, len(hexdata), 2):
- data.append(chr(string.atoi(hexdata[i:i+2], 16)))
- return "".join(data)
+ data.append(bytechr(int(hexdata[i:i+2], 16)))
+ return bytesjoin(data)
def hexStr(data):
@@ -30,7 +31,7 @@
h = string.hexdigits
r = ''
for c in data:
- i = ord(c)
+ i = byteord(c)
r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
return r
@@ -51,15 +52,15 @@
all.append(bin)
all.reverse()
assert l in (0, -1), "number doesn't fit in number of bits"
- return string.join(all, " ")
+ return ' '.join(all)
def binary2num(bin):
- bin = string.join(string.split(bin), "")
+ bin = strjoin(bin.split())
l = 0
for digit in bin:
l = l << 1
- if digit <> "0":
+ if digit != "0":
l = l | 0x1
return l
@@ -70,19 +71,7 @@
"""
try:
- # turn ['FOO', 'aaBc', 'ABcD'] into
- # [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')],
- # but only if all elements are strings
- tupledlist = map(lambda item, lower = string.lower:
- (lower(item), item), alist)
+ return sorted(alist, key=lambda a: (a.lower(), a))
except TypeError:
- # at least one element in alist is not a string, proceed the normal way...
- alist = alist[:]
- alist.sort()
- return alist
- else:
- tupledlist.sort()
- # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into
- # ['aaBc', 'ABcD', 'FOO']
- return map(lambda x: x[1], tupledlist)
+ return sorted(alist)
diff --git a/Lib/fontTools/misc/transform.py b/Lib/fontTools/misc/transform.py
index 769475f..531b288 100644
--- a/Lib/fontTools/misc/transform.py
+++ b/Lib/fontTools/misc/transform.py
@@ -45,6 +45,8 @@
>>>
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
__all__ = ["Transform", "Identity", "Offset", "Scale"]
@@ -64,7 +66,7 @@
return v
-class Transform:
+class Transform(object):
"""2x2 transformation matrix plus offset, a.k.a. Affine transform.
Transform instances are immutable: all transforming methods, eg.
@@ -96,7 +98,7 @@
"""
self.__affine = xx, xy, yx, yy, dx, dy
- def transformPoint(self, (x, y)):
+ def transformPoint(self, p):
"""Transform a point.
Example:
@@ -105,6 +107,7 @@
>>> t.transformPoint((100, 100))
(250.0, 550.0)
"""
+ (x, y) = p
xx, xy, yx, yy, dx, dy = self.__affine
return (xx*x + yx*y + dx, xy*x + yy*y + dy)
@@ -233,7 +236,7 @@
if self.__affine == (1, 0, 0, 1, 0, 0):
return self
xx, xy, yx, yy, dx, dy = self.__affine
- det = float(xx*yy - yx*xy)
+ det = xx*yy - yx*xy
xx, xy, yx, yy = yy/det, -xy/det, -yx/det, xx/det
dx, dy = -xx*dx - yx*dy, -xy*dx - yy*dy
return self.__class__(xx, xy, yx, yy, dx, dy)
@@ -265,19 +268,7 @@
"""
return self.__affine[index]
- def __getslice__(self, i, j):
- """Transform instances also behave like sequences and even support
- slicing:
- >>> t = Offset(100, 200)
- >>> t
- <Transform [1 0 0 1 100 200]>
- >>> t[4:]
- (100, 200)
- >>>
- """
- return self.__affine[i:j]
-
- def __cmp__(self, other):
+ def __lt__(self, other):
"""Transform instances are comparable:
>>> t1 = Identity.scale(2, 3).translate(4, 6)
>>> t2 = Identity.translate(8, 18).scale(2, 3)
@@ -298,8 +289,32 @@
"""
xx1, xy1, yx1, yy1, dx1, dy1 = self.__affine
xx2, xy2, yx2, yy2, dx2, dy2 = other
- return cmp((xx1, xy1, yx1, yy1, dx1, dy1),
- (xx2, xy2, yx2, yy2, dx2, dy2))
+ return (xx1, xy1, yx1, yy1, dx1, dy1) < \
+ (xx2, xy2, yx2, yy2, dx2, dy2)
+
+ def __eq__(self, other):
+ """Transform instances are comparable:
+ >>> t1 = Identity.scale(2, 3).translate(4, 6)
+ >>> t2 = Identity.translate(8, 18).scale(2, 3)
+ >>> t1 == t2
+ 1
+ >>>
+
+ But beware of floating point rounding errors:
+ >>> t1 = Identity.scale(0.2, 0.3).translate(0.4, 0.6)
+ >>> t2 = Identity.translate(0.08, 0.18).scale(0.2, 0.3)
+ >>> t1
+ <Transform [0.2 0.0 0.0 0.3 0.08 0.18]>
+ >>> t2
+ <Transform [0.2 0.0 0.0 0.3 0.08 0.18]>
+ >>> t1 == t2
+ 0
+ >>>
+ """
+ xx1, xy1, yx1, yy1, dx1, dy1 = self.__affine
+ xx2, xy2, yx2, yy2, dx2, dy2 = other
+ return (xx1, xy1, yx1, yy1, dx1, dy1) == \
+ (xx2, xy2, yx2, yy2, dx2, dy2)
def __hash__(self):
"""Transform instances are hashable, meaning you can use them as
@@ -328,7 +343,7 @@
return hash(self.__affine)
def __repr__(self):
- return "<%s [%s %s %s %s %s %s]>" % ((self.__class__.__name__,)
+ return "<%s [%s %s %s %s %s %s]>" % ((self.__class__.__name__,) \
+ tuple(map(str, self.__affine)))
diff --git a/Lib/fontTools/misc/xmlReader.py b/Lib/fontTools/misc/xmlReader.py
index f01dbcf..085e057 100644
--- a/Lib/fontTools/misc/xmlReader.py
+++ b/Lib/fontTools/misc/xmlReader.py
@@ -1,3 +1,5 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools import ttLib
from fontTools.misc.textTools import safeEval
from fontTools.ttLib.tables.DefaultTable import DefaultTable
@@ -9,7 +11,7 @@
BUFSIZE = 0x4000
-class XMLReader:
+class XMLReader(object):
def __init__(self, fileName, ttFont, progress=None, quiet=False):
self.ttFont = ttFont
@@ -23,7 +25,7 @@
def read(self):
if self.progress:
import stat
- self.progress.set(0, os.stat(fileName)[stat.ST_SIZE] / 100 or 1)
+ self.progress.set(0, os.stat(fileName)[stat.ST_SIZE] // 100 or 1)
file = open(self.fileName)
self._parseFile(file)
file.close()
@@ -31,31 +33,30 @@
def _parseFile(self, file):
from xml.parsers.expat import ParserCreate
parser = ParserCreate()
- parser.returns_unicode = 0
parser.StartElementHandler = self._startElementHandler
parser.EndElementHandler = self._endElementHandler
parser.CharacterDataHandler = self._characterDataHandler
pos = 0
- while 1:
+ while True:
chunk = file.read(BUFSIZE)
if not chunk:
parser.Parse(chunk, 1)
break
pos = pos + len(chunk)
if self.progress:
- self.progress.set(pos / 100)
+ self.progress.set(pos // 100)
parser.Parse(chunk, 0)
def _startElementHandler(self, name, attrs):
stackSize = self.stackSize
self.stackSize = stackSize + 1
if not stackSize:
- if name <> "ttFont":
- raise TTXParseError, "illegal root tag: %s" % name
+ if name != "ttFont":
+ raise TTXParseError("illegal root tag: %s" % name)
sfntVersion = attrs.get("sfntVersion")
if sfntVersion is not None:
- if len(sfntVersion) <> 4:
+ if len(sfntVersion) != 4:
sfntVersion = safeEval('"' + sfntVersion + '"')
self.ttFont.sfntVersion = sfntVersion
self.contentStack.append([])
@@ -75,16 +76,16 @@
ttLib.debugmsg(msg)
else:
if not self.quiet:
- print msg
+ print(msg)
if tag == "GlyphOrder":
tableClass = ttLib.GlyphOrder
- elif attrs.has_key("ERROR"):
+ elif "ERROR" in attrs:
tableClass = DefaultTable
else:
tableClass = ttLib.getTableClass(tag)
if tableClass is None:
tableClass = DefaultTable
- if tag == 'loca' and self.ttFont.has_key(tag):
+ if tag == 'loca' and tag in self.ttFont:
# Special-case the 'loca' table as we need the
# original if the 'glyf' table isn't recompiled.
self.currentTable = self.ttFont[tag]
@@ -110,14 +111,15 @@
if self.stackSize == 1:
self.root = None
elif self.stackSize == 2:
- self.currentTable.fromXML(self.root, self.ttFont)
+ name, attrs, content = self.root
+ self.currentTable.fromXML(name, attrs, content, self.ttFont)
self.root = None
-class ProgressPrinter:
+class ProgressPrinter(object):
def __init__(self, title, maxval=100):
- print title
+ print(title)
def set(self, val, maxval=None):
pass
@@ -126,5 +128,5 @@
pass
def setLabel(self, text):
- print text
+ print(text)
diff --git a/Lib/fontTools/misc/xmlWriter.py b/Lib/fontTools/misc/xmlWriter.py
index aa70f13..6862e91 100644
--- a/Lib/fontTools/misc/xmlWriter.py
+++ b/Lib/fontTools/misc/xmlWriter.py
@@ -1,17 +1,23 @@
"""xmlWriter.py -- Simple XML authoring class"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+import sys
import string
import struct
-import os
INDENT = " "
-class XMLWriter:
+class XMLWriter(object):
- def __init__(self, fileOrPath, indentwhite=INDENT, idlefunc=None, encoding="utf-8"):
+ def __init__(self, fileOrPath, indentwhite=INDENT, idlefunc=None):
if not hasattr(fileOrPath, "write"):
- self.file = open(fileOrPath, "w")
+ try:
+ # Python3 has encoding support.
+ self.file = open(fileOrPath, "w")
+ except TypeError:
+ self.file = open(fileOrPath, "w", encoding="utf-8")
else:
# assume writable file object
self.file = fileOrPath
@@ -21,32 +27,43 @@
self.needindent = 1
self.idlefunc = idlefunc
self.idlecounter = 0
- if encoding:
- self.writeraw('<?xml version="1.0" encoding="%s"?>' % encoding)
- else:
- self.writeraw('<?xml version="1.0"?>')
+ self._writeraw('<?xml version="1.0" encoding="utf-8"?>')
self.newline()
def close(self):
self.file.close()
- def write(self, data):
- self.writeraw(escape(data))
+ def write(self, string, indent=True):
+ """Writes text."""
+ self._writeraw(escape(string), indent=indent)
+
+ def writecdata(self, string):
+ """Writes text in a CDATA section."""
+ self._writeraw("<![CDATA[" + string + "]]>")
+
+ def write8bit(self, data, strip=False):
+ """Writes a bytes() sequence into the XML, escaping
+ non-ASCII bytes. When this is read in xmlReader,
+ the original bytes can be recovered by encoding to
+ 'latin-1'."""
+ self._writeraw(escape8bit(data), strip=strip)
+
+ def write16bit(self, data, strip=False):
+ self._writeraw(escape16bit(data), strip=strip)
- def write_noindent(self, data):
- self.file.write(escape(data))
+ def write_noindent(self, string):
+ """Writes text without indentation."""
+ self._writeraw(escape(string), indent=False)
- def write8bit(self, data):
- self.writeraw(escape8bit(data))
-
- def write16bit(self, data):
- self.writeraw(escape16bit(data))
-
- def writeraw(self, data):
- if self.needindent:
+ def _writeraw(self, data, indent=True, strip=False):
+ """Writes bytes, possibly indented."""
+ if indent and self.needindent:
self.file.write(self.indentlevel * self.indentwhite)
self.needindent = 0
- self.file.write(data)
+ s = tostr(data, encoding="utf-8")
+ if (strip):
+ s = s.strip()
+ self.file.write(s)
def newline(self):
self.file.write("\n")
@@ -58,22 +75,22 @@
def comment(self, data):
data = escape(data)
- lines = string.split(data, "\n")
- self.writeraw("<!-- " + lines[0])
+ lines = data.split("\n")
+ self._writeraw("<!-- " + lines[0])
for line in lines[1:]:
self.newline()
- self.writeraw(" " + line)
- self.writeraw(" -->")
+ self._writeraw(" " + line)
+ self._writeraw(" -->")
def simpletag(self, _TAG_, *args, **kwargs):
- attrdata = apply(self.stringifyattrs, args, kwargs)
+ attrdata = self.stringifyattrs(*args, **kwargs)
data = "<%s%s/>" % (_TAG_, attrdata)
- self.writeraw(data)
+ self._writeraw(data)
def begintag(self, _TAG_, *args, **kwargs):
- attrdata = apply(self.stringifyattrs, args, kwargs)
+ attrdata = self.stringifyattrs(*args, **kwargs)
data = "<%s%s>" % (_TAG_, attrdata)
- self.writeraw(data)
+ self._writeraw(data)
self.stack.append(_TAG_)
self.indent()
@@ -82,7 +99,7 @@
del self.stack[-1]
self.dedent()
data = "</%s>" % _TAG_
- self.writeraw(data)
+ self._writeraw(data)
def dumphex(self, data):
linelength = 16
@@ -95,7 +112,7 @@
for j in range(0, hexlinelength, chunksize):
line = line + white + hexline[j:j+chunksize]
white = " "
- self.writeraw(line)
+ self._writeraw(line)
self.newline()
def indent(self):
@@ -108,8 +125,7 @@
def stringifyattrs(self, *args, **kwargs):
if kwargs:
assert not args
- attributes = kwargs.items()
- attributes.sort()
+ attributes = sorted(kwargs.items())
elif args:
assert len(args) == 1
attributes = args[0]
@@ -122,39 +138,34 @@
def escape(data):
- data = string.replace(data, "&", "&")
- data = string.replace(data, "<", "<")
+ data = tostr(data, 'utf-8')
+ data = data.replace("&", "&")
+ data = data.replace("<", "<")
+ data = data.replace(">", ">")
return data
def escapeattr(data):
- data = string.replace(data, "&", "&")
- data = string.replace(data, "<", "<")
- data = string.replace(data, '"', """)
+ data = escape(data)
+ data = data.replace('"', """)
return data
def escape8bit(data):
+ """Input is Unicode string."""
def escapechar(c):
n = ord(c)
- if c in "<&":
- if c == "&":
- return "&"
- else:
- return "<"
- elif 32 <= n <= 127:
+ if 32 <= n <= 127 and c not in "<&>":
return c
else:
- return "&#" + `n` + ";"
- return string.join(map(escapechar, data), "")
-
-needswap = struct.pack("h", 1) == "\001\000"
+ return "&#" + repr(n) + ";"
+ return strjoin(map(escapechar, data.decode('latin-1')))
def escape16bit(data):
import array
a = array.array("H")
a.fromstring(data)
- if needswap:
+ if sys.byteorder != "big":
a.byteswap()
- def escapenum(n, amp=ord("&"), lt=ord("<")):
+ def escapenum(n, amp=byteord("&"), lt=byteord("<")):
if n == amp:
return "&"
elif n == lt:
@@ -162,15 +173,14 @@
elif 32 <= n <= 127:
return chr(n)
else:
- return "&#" + `n` + ";"
- return string.join(map(escapenum, a), "")
+ return "&#" + repr(n) + ";"
+ return strjoin(map(escapenum, a))
def hexStr(s):
h = string.hexdigits
r = ''
for c in s:
- i = ord(c)
+ i = byteord(c)
r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
return r
-
diff --git a/Lib/fontTools/nfntLib.py b/Lib/fontTools/nfntLib.py
index c834fc5..ea2c9ee 100644
--- a/Lib/fontTools/nfntLib.py
+++ b/Lib/fontTools/nfntLib.py
@@ -1,7 +1,7 @@
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import string
-import types
+import struct
# FontRec header
@@ -25,7 +25,7 @@
assert headerSize == 26
-class NFNT:
+class NFNT(object):
def __init__(self, data=None):
if data is not None:
@@ -44,23 +44,23 @@
self.bits = data[headerSize:headerSize + bitmapSize]
# XXX deal with self.nDescent being a positive number
- assert (headerSize + bitmapSize + tableSize - 16) / 2 == self.owTLoc # ugh...
+ assert (headerSize + bitmapSize + tableSize - 16) // 2 == self.owTLoc # ugh...
locTable = data[headerSize + bitmapSize:headerSize + bitmapSize + tableSize]
- if len(locTable) <> tableSize:
- raise ValueError, 'invalid NFNT format'
+ if len(locTable) != tableSize:
+ raise ValueError('invalid NFNT format')
owTable = data[headerSize + bitmapSize + tableSize:headerSize + bitmapSize + 2 * tableSize]
- if len(owTable) <> tableSize:
- raise ValueError, 'invalid NFNT format'
+ if len(owTable) != tableSize:
+ raise ValueError('invalid NFNT format')
# fill tables
self.offsetTable = []
self.widthTable = []
self.locTable = []
for i in range(0, tableSize, 2):
- self.offsetTable.append(ord(owTable[i]))
- self.widthTable.append(ord(owTable[i+1]))
+ self.offsetTable.append(byteord(owTable[i]))
+ self.widthTable.append(byteord(owTable[i+1]))
loc, = struct.unpack("h", locTable[i:i+2])
self.locTable.append(loc)
@@ -70,10 +70,10 @@
owTable = [None] * nEntries
locTable = [None] * nEntries
for i in range(nEntries):
- owTable[i] = chr(self.offsetTable[i]) + chr(self.widthTable[i])
+ owTable[i] = bytechr(self.offsetTable[i]) + bytechr(self.widthTable[i])
locTable[i] = struct.pack("h", self.locTable[i])
- owTable = string.join(owTable, "")
- locTable = string.join(locTable, "")
+ owTable = bytesjoin(owTable)
+ locTable = bytesjoin(locTable)
assert len(locTable) == len(owTable) == 2 * (self.lastChar - self.firstChar + 3)
return header + self.bits + locTable + owTable
@@ -93,7 +93,7 @@
byte = bits[y * rowBytes + xByte]
for xBit in range(8):
x = 8 * xByte + xBit
- bit = (ord(byte) >> (7 - xBit)) & 0x01
+ bit = (byteord(byte) >> (7 - xBit)) & 0x01
bitImage[x, y] = bit
for i in range(nGlyphs):
@@ -128,9 +128,9 @@
fRectWidth = max(fRectWidth, glyph.pixels.shape[0] + glyph.offset)
fRectWidth = fRectWidth - kernMax
- imageWidth = 16 * ((imageWidth - 1) / 16 + 1)
- rowBytes = imageWidth / 8
- rowWords = rowBytes / 2
+ imageWidth = 16 * ((imageWidth - 1) // 16 + 1)
+ rowBytes = imageWidth // 8
+ rowWords = rowBytes // 2
bitImage = numpy.zeros((imageWidth, imageHeight), numpy.int8)
locTable = []
widthTable = []
@@ -158,8 +158,8 @@
byte = 0
for x in range(8):
byte = byte | ((bitImage[8 * xByte + x, y] & 0x01) << (7 - x))
- bits.append(chr(byte))
- bits = string.join(bits, "")
+ bits.append(bytechr(byte))
+ bits = bytesjoin(bits)
# assign values
self.fontType = 0x9000
@@ -173,7 +173,7 @@
self.rowWords = rowWords
tableSize = 2 * (self.lastChar - self.firstChar + 3)
- self.owTLoc = (headerSize + len(bits) + tableSize - 16) / 2
+ self.owTLoc = (headerSize + len(bits) + tableSize - 16) // 2
self.bits = bits
self.locTable = locTable
@@ -185,7 +185,7 @@
def __getitem__(self, charNum):
if charNum > self.lastChar or charNum < 0:
- raise IndexError, "no such character"
+ raise IndexError("no such character")
index = charNum - self.firstChar
if index < 0:
return None
@@ -193,10 +193,10 @@
def __setitem__(self, charNum, glyph):
if charNum > self.lastChar or charNum < 0:
- raise IndexError, "no such character"
+ raise IndexError("no such character")
index = charNum - self.firstChar
if index < 0:
- raise IndexError, "no such character"
+ raise IndexError("no such character")
self.glyphs[index] = glyph
def __len__(self):
@@ -231,14 +231,14 @@
return width
def charwidth(self, ch):
- cindex = ord(ch) - self.firstChar
+ cindex = byteord(ch) - self.firstChar
if cindex > self.lastChar or \
(self.offsetTable[cindex] == 255 and self.widthTable[cindex] == 255):
cindex = -2 # missing char
return self.widthTable[cindex]
def getcharbounds(self, ch):
- cindex = ord(ch) - self.firstChar
+ cindex = byteord(ch) - self.firstChar
if cindex > self.lastChar or \
(self.offsetTable[cindex] == 255 and self.widthTable[cindex] == 255):
return self.getcharboundsindex(-2) # missing char
@@ -248,7 +248,7 @@
offset = self.offsetTable[cindex]
width = self.widthTable[cindex]
if offset == 255 and width == 255:
- raise ValueError, "character not defined"
+ raise ValueError("character not defined")
location0 = self.locTable[cindex]
location1 = self.locTable[cindex + 1]
srcbounds = (location0, 0, location1, self.fRectHeight)
@@ -259,7 +259,7 @@
return width, srcbounds, destbounds
-class Glyph:
+class Glyph(object):
def __init__(self, width, offset, pixels=None, pixelDepth=1):
self.width = width
@@ -276,7 +276,7 @@
if not nameOrID:
# just take the first in the file
res = Res.Get1IndResource(resType, 1)
- elif type(nameOrID) == types.IntType:
+ elif isinstance(nameOrID, int):
res = Res.Get1Resource(resType, nameOrID)
else:
res = Res.Get1NamedResource(resType, nameOrID)
@@ -301,4 +301,4 @@
font.unpackGlyphs()
font.packGlyphs()
data2 = font.compile()
- print "xxxxx", data == data2, len(data) == len(data2)
+ print("xxxxx", data == data2, len(data) == len(data2))
diff --git a/Lib/fontTools/pens/basePen.py b/Lib/fontTools/pens/basePen.py
index 04da75a..0ad866c 100644
--- a/Lib/fontTools/pens/basePen.py
+++ b/Lib/fontTools/pens/basePen.py
@@ -36,6 +36,8 @@
sequence of length 2 will do.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
__all__ = ["AbstractPen", "NullPen", "BasePen",
"decomposeSuperBezierSegment", "decomposeQuadraticSegment"]
@@ -248,7 +250,7 @@
elif n == 0:
self.lineTo(points[0])
else:
- raise AssertionError, "can't get there from here"
+ raise AssertionError("can't get there from here")
def qCurveTo(self, *points):
n = len(points) - 1 # 'n' is the number of control points
@@ -296,9 +298,8 @@
for i in range(2, n+1):
# calculate points in between control points.
nDivisions = min(i, 3, n-i+2)
- d = float(nDivisions)
for j in range(1, nDivisions):
- factor = j / d
+ factor = j / nDivisions
temp1 = points[i-1]
temp2 = points[i-2]
temp = (temp2[0] + factor * (temp1[0] - temp2[0]),
@@ -339,14 +340,14 @@
class _TestPen(BasePen):
"""Test class that prints PostScript to stdout."""
def _moveTo(self, pt):
- print "%s %s moveto" % (pt[0], pt[1])
+ print("%s %s moveto" % (pt[0], pt[1]))
def _lineTo(self, pt):
- print "%s %s lineto" % (pt[0], pt[1])
+ print("%s %s lineto" % (pt[0], pt[1]))
def _curveToOne(self, bcp1, bcp2, pt):
- print "%s %s %s %s %s %s curveto" % (bcp1[0], bcp1[1],
- bcp2[0], bcp2[1], pt[0], pt[1])
+ print("%s %s %s %s %s %s curveto" % (bcp1[0], bcp1[1],
+ bcp2[0], bcp2[1], pt[0], pt[1]))
def _closePath(self):
- print "closepath"
+ print("closepath")
if __name__ == "__main__":
diff --git a/Lib/fontTools/pens/boundsPen.py b/Lib/fontTools/pens/boundsPen.py
index 3fde6e3..144acc4 100644
--- a/Lib/fontTools/pens/boundsPen.py
+++ b/Lib/fontTools/pens/boundsPen.py
@@ -1,6 +1,8 @@
-from fontTools.pens.basePen import BasePen
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
+from fontTools.pens.basePen import BasePen
__all__ = ["BoundsPen", "ControlBoundsPen"]
@@ -86,8 +88,8 @@
pen = ControlBoundsPen(None)
draw(pen)
- print pen.bounds
+ print(pen.bounds)
pen = BoundsPen(None)
draw(pen)
- print pen.bounds
+ print(pen.bounds)
diff --git a/Lib/fontTools/pens/cocoaPen.py b/Lib/fontTools/pens/cocoaPen.py
index ef3bf03..59a4c81 100644
--- a/Lib/fontTools/pens/cocoaPen.py
+++ b/Lib/fontTools/pens/cocoaPen.py
@@ -1,3 +1,5 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.pens.basePen import BasePen
@@ -13,14 +15,14 @@
path = NSBezierPath.bezierPath()
self.path = path
- def _moveTo(self, (x, y)):
- self.path.moveToPoint_((x, y))
+ def _moveTo(self, p):
+ self.path.moveToPoint_(p)
- def _lineTo(self, (x, y)):
- self.path.lineToPoint_((x, y))
+ def _lineTo(self, p):
+ self.path.lineToPoint_(p)
- def _curveToOne(self, (x1, y1), (x2, y2), (x3, y3)):
- self.path.curveToPoint_controlPoint1_controlPoint2_((x3, y3), (x1, y1), (x2, y2))
+ def _curveToOne(self, p1, p2, p3):
+ self.path.curveToPoint_controlPoint1_controlPoint2_(p3, p1, p2)
def _closePath(self):
self.path.closePath()
diff --git a/Lib/fontTools/pens/pointInsidePen.py b/Lib/fontTools/pens/pointInsidePen.py
index 131c75f..4966815 100644
--- a/Lib/fontTools/pens/pointInsidePen.py
+++ b/Lib/fontTools/pens/pointInsidePen.py
@@ -2,6 +2,8 @@
for shapes.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.pens.basePen import BasePen
from fontTools.misc.bezierTools import solveQuadratic, solveCubic
@@ -96,7 +98,7 @@
dx = x2 - x1
dy = y2 - y1
- t = float(y - y1) / dy
+ t = (y - y1) / dy
ix = dx * t + x1
if ix < x:
return
@@ -120,8 +122,7 @@
cy = (y2 - dy) * 3.0
by = (y3 - y2) * 3.0 - cy
ay = y4 - dy - cy - by
- solutions = solveCubic(ay, by, cy, dy - y)
- solutions.sort()
+ solutions = sorted(solveCubic(ay, by, cy, dy - y))
solutions = [t for t in solutions if ZERO_MINUS_EPSILON <= t <= ONE_PLUS_EPSILON]
if not solutions:
return
@@ -176,8 +177,7 @@
c = y1
b = (y2 - c) * 2.0
a = y3 - c - b
- solutions = solveQuadratic(a, b, c - y)
- solutions.sort()
+ solutions = sorted(solveQuadratic(a, b, c - y))
solutions = [t for t in solutions if ZERO_MINUS_EPSILON <= t <= ONE_PLUS_EPSILON]
if not solutions:
return
diff --git a/Lib/fontTools/pens/reportLabPen.py b/Lib/fontTools/pens/reportLabPen.py
index 1c3fcf8..c1c394e 100644
--- a/Lib/fontTools/pens/reportLabPen.py
+++ b/Lib/fontTools/pens/reportLabPen.py
@@ -1,3 +1,5 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.pens.basePen import BasePen
@@ -12,13 +14,18 @@
path = Path()
self.path = path
- def _moveTo(self, (x,y)):
+ def _moveTo(self, p):
+ (x,y) = p
self.path.moveTo(x,y)
- def _lineTo(self, (x,y)):
+ def _lineTo(self, p):
+ (x,y) = p
self.path.lineTo(x,y)
- def _curveToOne(self, (x1,y1), (x2,y2), (x3,y3)):
+ def _curveToOne(self, p1, p2, p3):
+ (x1,y1) = p1
+ (x2,y2) = p2
+ (x3,y3) = p3
self.path.curveTo(x1, y1, x2, y2, x3, y3)
def _closePath(self):
@@ -28,10 +35,10 @@
if __name__=="__main__":
import sys
if len(sys.argv) < 3:
- print "Usage: reportLabPen.py <OTF/TTF font> <glyphname> [<image file to create>]"
- print " If no image file name is created, by default <glyphname>.png is created."
- print " example: reportLabPen.py Arial.TTF R test.png"
- print " (The file format will be PNG, regardless of the image file name supplied)"
+ print("Usage: reportLabPen.py <OTF/TTF font> <glyphname> [<image file to create>]")
+ print(" If no image file name is created, by default <glyphname>.png is created.")
+ print(" example: reportLabPen.py Arial.TTF R test.png")
+ print(" (The file format will be PNG, regardless of the image file name supplied)")
sys.exit(0)
from fontTools.ttLib import TTFont
diff --git a/Lib/fontTools/pens/transformPen.py b/Lib/fontTools/pens/transformPen.py
index 63c9323..8069ecd 100644
--- a/Lib/fontTools/pens/transformPen.py
+++ b/Lib/fontTools/pens/transformPen.py
@@ -1,3 +1,5 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.pens.basePen import AbstractPen
diff --git a/Lib/fontTools/subset.py b/Lib/fontTools/subset.py
index 20d2b7c..1a1601d 100644
--- a/Lib/fontTools/subset.py
+++ b/Lib/fontTools/subset.py
@@ -7,15 +7,16 @@
Later grown into full OpenType subsetter, supporting all standard tables.
"""
-import sys
-import struct
-import time
-import array
-
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools import ttLib
from fontTools.ttLib.tables import otTables
from fontTools.misc import psCharStrings
from fontTools.pens import basePen
+import sys
+import struct
+import time
+import array
def _add_method(*clazzes):
@@ -24,10 +25,10 @@
def wrapper(method):
for clazz in clazzes:
assert clazz.__name__ != 'DefaultTable', 'Oops, table class not found.'
- assert not hasattr(clazz, method.func_name), \
+ assert not hasattr(clazz, method.__name__), \
"Oops, class '%s' has method '%s'." % (clazz.__name__,
- method.func_name)
- setattr(clazz, method.func_name, method)
+ method.__name__)
+ setattr(clazz, method.__name__, method)
return None
return wrapper
@@ -68,25 +69,25 @@
"Returns ascending list of matching class values."
return _uniq_sort(
([0] if any(g not in self.classDefs for g in glyphs) else []) +
- [v for g,v in self.classDefs.iteritems() if g in glyphs])
+ [v for g,v in self.classDefs.items() if g in glyphs])
@_add_method(otTables.ClassDef)
def intersect_class(self, glyphs, klass):
"Returns set of glyphs matching class."
if klass == 0:
return set(g for g in glyphs if g not in self.classDefs)
- return set(g for g,v in self.classDefs.iteritems()
+ return set(g for g,v in self.classDefs.items()
if v == klass and g in glyphs)
@_add_method(otTables.ClassDef)
def subset(self, glyphs, remap=False):
"Returns ascending list of remaining classes."
- self.classDefs = dict((g,v) for g,v in self.classDefs.iteritems() if g in glyphs)
+ self.classDefs = dict((g,v) for g,v in self.classDefs.items() if g in glyphs)
# Note: while class 0 has the special meaning of "not matched",
# if no glyph will ever /not match/, we can optimize class 0 out too.
indices = _uniq_sort(
([0] if any(g not in self.classDefs for g in glyphs) else []) +
- self.classDefs.values())
+ list(self.classDefs.values()))
if remap:
self.remap(indices)
return indices
@@ -95,20 +96,20 @@
def remap(self, class_map):
"Remaps classes."
self.classDefs = dict((g,class_map.index(v))
- for g,v in self.classDefs.iteritems())
+ for g,v in self.classDefs.items())
@_add_method(otTables.SingleSubst)
def closure_glyphs(self, s, cur_glyphs=None):
if cur_glyphs == None: cur_glyphs = s.glyphs
if self.Format in [1, 2]:
- s.glyphs.update(v for g,v in self.mapping.iteritems() if g in cur_glyphs)
+ s.glyphs.update(v for g,v in self.mapping.items() if g in cur_glyphs)
else:
assert 0, "unknown format: %s" % self.Format
@_add_method(otTables.SingleSubst)
def subset_glyphs(self, s):
if self.Format in [1, 2]:
- self.mapping = dict((g,v) for g,v in self.mapping.iteritems()
+ self.mapping = dict((g,v) for g,v in self.mapping.items()
if g in s.glyphs and v in s.glyphs)
return bool(self.mapping)
else:
@@ -142,7 +143,7 @@
def closure_glyphs(self, s, cur_glyphs=None):
if cur_glyphs == None: cur_glyphs = s.glyphs
if self.Format == 1:
- _set_update(s.glyphs, *(vlist for g,vlist in self.alternates.iteritems()
+ _set_update(s.glyphs, *(vlist for g,vlist in self.alternates.items()
if g in cur_glyphs))
else:
assert 0, "unknown format: %s" % self.Format
@@ -151,7 +152,7 @@
def subset_glyphs(self, s):
if self.Format == 1:
self.alternates = dict((g,vlist)
- for g,vlist in self.alternates.iteritems()
+ for g,vlist in self.alternates.items()
if g in s.glyphs and
all(v in s.glyphs for v in vlist))
return bool(self.alternates)
@@ -164,7 +165,7 @@
if self.Format == 1:
_set_update(s.glyphs, *([seq.LigGlyph for seq in seqs
if all(c in s.glyphs for c in seq.Component)]
- for g,seqs in self.ligatures.iteritems()
+ for g,seqs in self.ligatures.items()
if g in cur_glyphs))
else:
assert 0, "unknown format: %s" % self.Format
@@ -172,13 +173,13 @@
@_add_method(otTables.LigatureSubst)
def subset_glyphs(self, s):
if self.Format == 1:
- self.ligatures = dict((g,v) for g,v in self.ligatures.iteritems()
+ self.ligatures = dict((g,v) for g,v in self.ligatures.items()
if g in s.glyphs)
self.ligatures = dict((g,[seq for seq in seqs
if seq.LigGlyph in s.glyphs and
all(c in s.glyphs for c in seq.Component)])
- for g,seqs in self.ligatures.iteritems())
- self.ligatures = dict((g,v) for g,v in self.ligatures.iteritems() if v)
+ for g,seqs in self.ligatures.items())
+ self.ligatures = dict((g,v) for g,v in self.ligatures.items() if v)
return bool(self.ligatures)
else:
assert 0, "unknown format: %s" % self.Format
@@ -1091,12 +1092,12 @@
if table.MarkAttachClassDef:
table.MarkAttachClassDef.classDefs = dict((g,v) for g,v in
table.MarkAttachClassDef.
- classDefs.iteritems()
+ classDefs.items()
if g in glyphs)
if table.GlyphClassDef:
table.GlyphClassDef.classDefs = dict((g,v) for g,v in
table.GlyphClassDef.
- classDefs.iteritems()
+ classDefs.items()
if g in glyphs)
if table.AttachList:
indices = table.AttachList.Coverage.subset(glyphs)
@@ -1126,13 +1127,13 @@
table.AttachList = None
if hasattr(table, "MarkGlyphSetsDef") and table.MarkGlyphSetsDef and not table.MarkGlyphSetsDef.Coverage:
table.MarkGlyphSetsDef = None
- if table.Version == float(0x00010002)/0x10000:
+ if table.Version == 0x00010002/0x10000:
table.Version = 1.0
return bool(table.LigCaretList or
table.MarkAttachClassDef or
table.GlyphClassDef or
table.AttachList or
- (table.Version >= float(0x00010002)/0x10000 and table.MarkGlyphSetsDef))
+ (table.Version >= 0x00010002/0x10000 and table.MarkGlyphSetsDef))
@_add_method(ttLib.getTableClass('kern'))
def prune_pre_subset(self, options):
@@ -1144,30 +1145,30 @@
def subset_glyphs(self, s):
glyphs = s.glyphs_gsubed
for t in self.kernTables:
- t.kernTable = dict(((a,b),v) for (a,b),v in t.kernTable.iteritems()
+ t.kernTable = dict(((a,b),v) for (a,b),v in t.kernTable.items()
if a in glyphs and b in glyphs)
self.kernTables = [t for t in self.kernTables if t.kernTable]
return bool(self.kernTables)
@_add_method(ttLib.getTableClass('vmtx'))
def subset_glyphs(self, s):
- self.metrics = dict((g,v) for g,v in self.metrics.iteritems() if g in s.glyphs)
+ self.metrics = dict((g,v) for g,v in self.metrics.items() if g in s.glyphs)
return bool(self.metrics)
@_add_method(ttLib.getTableClass('hmtx'))
def subset_glyphs(self, s):
- self.metrics = dict((g,v) for g,v in self.metrics.iteritems() if g in s.glyphs)
+ self.metrics = dict((g,v) for g,v in self.metrics.items() if g in s.glyphs)
return True # Required table
@_add_method(ttLib.getTableClass('hdmx'))
def subset_glyphs(self, s):
- self.hdmx = dict((sz,dict((g,v) for g,v in l.iteritems() if g in s.glyphs))
- for sz,l in self.hdmx.iteritems())
+ self.hdmx = dict((sz,dict((g,v) for g,v in l.items() if g in s.glyphs))
+ for sz,l in self.hdmx.items())
return bool(self.hdmx)
@_add_method(ttLib.getTableClass('VORG'))
def subset_glyphs(self, s):
- self.VOriginRecords = dict((g,v) for g,v in self.VOriginRecords.iteritems()
+ self.VOriginRecords = dict((g,v) for g,v in self.VOriginRecords.items()
if g in s.glyphs)
self.numVertOriginYMetrics = len(self.VOriginRecords)
return True # Never drop; has default metrics
@@ -1238,9 +1239,9 @@
@_add_method(ttLib.getTableClass('glyf'))
def subset_glyphs(self, s):
- self.glyphs = dict((g,v) for g,v in self.glyphs.iteritems() if g in s.glyphs)
+ self.glyphs = dict((g,v) for g,v in self.glyphs.items() if g in s.glyphs)
indices = [i for i,g in enumerate(self.glyphOrder) if g in s.glyphs]
- for v in self.glyphs.itervalues():
+ for v in self.glyphs.values():
if hasattr(v, "data"):
v.remapComponentsFast(indices)
else:
@@ -1252,7 +1253,7 @@
@_add_method(ttLib.getTableClass('glyf'))
def prune_post_subset(self, options):
if not options.hinting:
- for v in self.glyphs.itervalues():
+ for v in self.glyphs.values():
v.removeHinting()
return True
@@ -1295,11 +1296,11 @@
sel.format = None
sel.gidArray = [sel.gidArray[i] for i in indices]
cs.charStrings = dict((g,indices.index(v))
- for g,v in cs.charStrings.iteritems()
+ for g,v in cs.charStrings.items()
if g in s.glyphs)
else:
cs.charStrings = dict((g,v)
- for g,v in cs.charStrings.iteritems()
+ for g,v in cs.charStrings.items()
if g in s.glyphs)
font.charset = [g for g in font.charset if g in s.glyphs]
font.numGlyphs = len(font.charset)
@@ -1310,12 +1311,12 @@
def subset_subroutines(self, subrs, gsubrs):
p = self.program
assert len(p)
- for i in xrange(1, len(p)):
+ for i in range(1, len(p)):
if p[i] == 'callsubr':
- assert type(p[i-1]) is int
+ assert isinstance(p[i-1], int)
p[i-1] = subrs._used.index(p[i-1] + subrs._old_bias) - subrs._new_bias
elif p[i] == 'callgsubr':
- assert type(p[i-1]) is int
+ assert isinstance(p[i-1], int)
p[i-1] = gsubrs._used.index(p[i-1] + gsubrs._old_bias) - gsubrs._new_bias
@_add_method(psCharStrings.T2CharString)
@@ -1365,7 +1366,7 @@
class _DehintingT2Decompiler(psCharStrings.SimpleT2Decompiler):
- class Hints:
+ class Hints(object):
def __init__(self):
# Whether calling this charstring produces any hint stems
self.has_hint = False
@@ -1402,8 +1403,8 @@
if hints.status != 2:
# Check from last_check, make sure we didn't have any operators.
- for i in xrange(hints.last_checked, len(charString.program) - 1):
- if type(charString.program[i]) == str:
+ for i in range(hints.last_checked, len(charString.program) - 1):
+ if isinstance(charString.program[i], str):
hints.status = 2
break;
else:
@@ -1448,8 +1449,8 @@
hints.has_hintmask = True
if hints.status != 2 and hints.has_hint:
# Check from last_check, see if we may be an implicit vstem
- for i in xrange(hints.last_checked, index - 1):
- if type(cs.program[i]) == str:
+ for i in range(hints.last_checked, index - 1):
+ if isinstance(cs.program[i], str):
hints.status = 2
break;
if hints.status != 2:
@@ -1491,8 +1492,8 @@
if hints.status != 2:
# Check from last_check, make sure we didn't have
# any operators.
- for i in xrange(hints.last_checked, index - 1):
- if type(cs.program[i]) == str:
+ for i in range(hints.last_checked, index - 1):
+ if isinstance(cs.program[i], str):
hints.status = 2
break;
hints.last_checked = index
@@ -1622,7 +1623,7 @@
if hasattr(subrs, 'offsets'):
del subrs.offsets
- for i in xrange (subrs.count):
+ for i in range (subrs.count):
subrs[i].subset_subroutines (local_subrs, font.GlobalSubrs)
# Cleanup
@@ -1673,10 +1674,10 @@
if t.format == 14:
# TODO(behdad) XXX We drop all the default-UVS mappings(g==None).
t.uvsDict = dict((v,[(u,g) for u,g in l if g in s.glyphs])
- for v,l in t.uvsDict.iteritems())
- t.uvsDict = dict((v,l) for v,l in t.uvsDict.iteritems() if l)
+ for v,l in t.uvsDict.items())
+ t.uvsDict = dict((v,l) for v,l in t.uvsDict.items() if l)
else:
- t.cmap = dict((u,g) for u,g in t.cmap.iteritems()
+ t.cmap = dict((u,g) for u,g in t.cmap.items()
if g in s.glyphs_requested or u in s.unicodes_requested)
self.tables = [t for t in self.tables
if (t.cmap if t.format != 14 else t.uvsDict)]
@@ -1740,7 +1741,7 @@
'abvs', 'blws', 'psts', 'haln', 'dist', 'abvm', 'blwm'],
}
_layout_features_default = _uniq_sort(sum(
- _layout_features_groups.itervalues(), []))
+ iter(_layout_features_groups.values()), []))
drop_tables = _drop_tables_default
no_subset_tables = _no_subset_tables_default
@@ -1765,7 +1766,7 @@
self.set(**kwargs)
def set(self, **kwargs):
- for k,v in kwargs.iteritems():
+ for k,v in kwargs.items():
if not hasattr(self, k):
raise self.UnknownOptionError("Unknown option '%s'" % k)
setattr(self, k, v)
@@ -1848,7 +1849,7 @@
def populate(self, glyphs=[], unicodes=[], text=""):
self.unicodes_requested.update(unicodes)
- if isinstance(text, str):
+ if isinstance(text, bytes):
text = text.decode("utf8")
for u in text:
self.unicodes_requested.add(ord(u))
@@ -1996,14 +1997,14 @@
def __call__(self, *things):
if not self.verbose:
return
- print ' '.join(str(x) for x in things)
+ print(' '.join(str(x) for x in things))
def lapse(self, *things):
if not self.timing:
return
new_time = time.time()
- print "Took %0.3fs to %s" %(new_time - self.last_time,
- ' '.join(str(x) for x in things))
+ print("Took %0.3fs to %s" %(new_time - self.last_time,
+ ' '.join(str(x) for x in things)))
self.last_time = new_time
def glyphs(self, glyphs, font=None):
@@ -2070,7 +2071,7 @@
args = options.parse_opts(args, ignore_unknown=['text'])
if len(args) < 2:
- print >>sys.stderr, "usage: pyftsubset font-file glyph... [--text=ABC]... [--option=value]..."
+ print("usage: pyftsubset font-file glyph... [--text=ABC]... [--option=value]...", file=sys.stderr)
sys.exit(1)
fontfile = args[0]
diff --git a/Lib/fontTools/t1Lib.py b/Lib/fontTools/t1Lib.py
index 42d95c2..1a81a99 100644
--- a/Lib/fontTools/t1Lib.py
+++ b/Lib/fontTools/t1Lib.py
@@ -15,17 +15,17 @@
part should be written as hexadecimal or binary, but only if kind
is 'LWFN' or 'PFB'.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc import eexec
+from fontTools.misc.macCreatorType import getMacCreatorAndType
+import os
+import re
__author__ = "jvr"
__version__ = "1.0b2"
DEBUG = 0
-from fontTools.misc import eexec
-from fontTools.misc.macCreatorType import getMacCreatorAndType
-import string
-import re
-import os
-
try:
try:
@@ -42,7 +42,7 @@
class T1Error(Exception): pass
-class T1Font:
+class T1Font(object):
"""Type 1 font class.
@@ -102,7 +102,7 @@
def read(path, onlyHeader=0):
"""reads any Type 1 font file, returns raw data"""
- normpath = string.lower(path)
+ normpath = path.lower()
creator, type = getMacCreatorAndType(path)
if type == 'LWFN':
return readLWFN(path, onlyHeader), 'LWFN'
@@ -113,7 +113,7 @@
def write(path, data, kind='OTHER', dohex=0):
assertType1(data)
- kind = string.upper(kind)
+ kind = kind.upper()
try:
os.remove(path)
except os.error:
@@ -150,9 +150,9 @@
data = []
for i in range(501, 501 + n):
res = Res.Get1Resource('POST', i)
- code = ord(res.data[0])
- if ord(res.data[1]) <> 0:
- raise T1Error, 'corrupt LWFN file'
+ code = byteord(res.data[0])
+ if byteord(res.data[1]) != 0:
+ raise T1Error('corrupt LWFN file')
if code in [1, 2]:
if onlyHeader and code == 2:
break
@@ -166,10 +166,10 @@
elif code == 0:
pass # comment, ignore
else:
- raise T1Error, 'bad chunk code: ' + `code`
+ raise T1Error('bad chunk code: ' + repr(code))
finally:
Res.CloseResFile(resRef)
- data = string.join(data, '')
+ data = bytesjoin(data)
assertType1(data)
return data
@@ -177,10 +177,10 @@
"""reads a PFB font file, returns raw data"""
f = open(path, "rb")
data = []
- while 1:
- if f.read(1) <> chr(128):
- raise T1Error, 'corrupt PFB file'
- code = ord(f.read(1))
+ while True:
+ if f.read(1) != bytechr(128):
+ raise T1Error('corrupt PFB file')
+ code = byteord(f.read(1))
if code in [1, 2]:
chunklen = stringToLong(f.read(4))
chunk = f.read(chunklen)
@@ -189,11 +189,11 @@
elif code == 3:
break
else:
- raise T1Error, 'bad chunk code: ' + `code`
+ raise T1Error('bad chunk code: ' + repr(code))
if onlyHeader:
break
f.close()
- data = string.join(data, '')
+ data = bytesjoin(data)
assertType1(data)
return data
@@ -211,7 +211,7 @@
data.append(deHexString(chunk))
else:
data.append(chunk)
- return string.join(data, '')
+ return bytesjoin(data)
# file writing tools
@@ -228,11 +228,11 @@
else:
code = 1
while chunk:
- res = Res.Resource(chr(code) + '\0' + chunk[:LWFNCHUNKSIZE - 2])
+ res = Res.Resource(bytechr(code) + '\0' + chunk[:LWFNCHUNKSIZE - 2])
res.AddResource('POST', resID, '')
chunk = chunk[LWFNCHUNKSIZE - 2:]
resID = resID + 1
- res = Res.Resource(chr(5) + '\0')
+ res = Res.Resource(bytechr(5) + '\0')
res.AddResource('POST', resID, '')
finally:
Res.CloseResFile(resRef)
@@ -246,10 +246,10 @@
code = 2
else:
code = 1
- f.write(chr(128) + chr(code))
+ f.write(bytechr(128) + bytechr(code))
f.write(longToString(len(chunk)))
f.write(chunk)
- f.write(chr(128) + chr(3))
+ f.write(bytechr(128) + bytechr(3))
finally:
f.close()
@@ -257,7 +257,7 @@
chunks = findEncryptedChunks(data)
f = open(path, "wb")
try:
- hexlinelen = HEXLINELENGTH / 2
+ hexlinelen = HEXLINELENGTH // 2
for isEncrypted, chunk in chunks:
if isEncrypted:
code = 2
@@ -297,9 +297,9 @@
chunk = deHexString(chunk)
decrypted, R = eexec.decrypt(chunk, 55665)
decrypted = decrypted[4:]
- if decrypted[-len(EEXECINTERNALEND)-1:-1] <> EEXECINTERNALEND \
- and decrypted[-len(EEXECINTERNALEND)-2:-2] <> EEXECINTERNALEND:
- raise T1Error, "invalid end of eexec part"
+ if decrypted[-len(EEXECINTERNALEND)-1:-1] != EEXECINTERNALEND \
+ and decrypted[-len(EEXECINTERNALEND)-2:-2] != EEXECINTERNALEND:
+ raise T1Error("invalid end of eexec part")
decrypted = decrypted[:-len(EEXECINTERNALEND)-2] + '\r'
data.append(EEXECBEGINMARKER + decrypted + EEXECENDMARKER)
else:
@@ -307,25 +307,25 @@
data.append(chunk[:-len(EEXECBEGIN)-1])
else:
data.append(chunk)
- return string.join(data, '')
+ return bytesjoin(data)
def findEncryptedChunks(data):
chunks = []
- while 1:
- eBegin = string.find(data, EEXECBEGIN)
+ while True:
+ eBegin = data.find(EEXECBEGIN)
if eBegin < 0:
break
eBegin = eBegin + len(EEXECBEGIN) + 1
- eEnd = string.find(data, EEXECEND, eBegin)
+ eEnd = data.find(EEXECEND, eBegin)
if eEnd < 0:
- raise T1Error, "can't find end of eexec part"
+ raise T1Error("can't find end of eexec part")
cypherText = data[eBegin:eEnd + 2]
if isHex(cypherText[:4]):
cypherText = deHexString(cypherText)
plainText, R = eexec.decrypt(cypherText, 55665)
- eEndLocal = string.find(plainText, EEXECINTERNALEND)
+ eEndLocal = plainText.find(EEXECINTERNALEND)
if eEndLocal < 0:
- raise T1Error, "can't find end of eexec part"
+ raise T1Error("can't find end of eexec part")
chunks.append((0, data[:eBegin]))
chunks.append((1, cypherText[:eEndLocal + len(EEXECINTERNALEND) + 1]))
data = data[eEnd:]
@@ -333,7 +333,7 @@
return chunks
def deHexString(hexstring):
- return eexec.deHexString(string.join(string.split(hexstring), ""))
+ return eexec.deHexString(strjoin(hexstring.split()))
# Type 1 assertion
@@ -345,11 +345,11 @@
if data[:len(head)] == head:
break
else:
- raise T1Error, "not a PostScript font"
+ raise T1Error("not a PostScript font")
if not _fontType1RE.search(data):
- raise T1Error, "not a Type 1 font"
- if string.find(data, "currentfile eexec") < 0:
- raise T1Error, "not an encrypted Type 1 font"
+ raise T1Error("not a Type 1 font")
+ if data.find("currentfile eexec") < 0:
+ raise T1Error("not an encrypted Type 1 font")
# XXX what else?
return data
@@ -359,14 +359,14 @@
def longToString(long):
str = ""
for i in range(4):
- str = str + chr((long & (0xff << (i * 8))) >> i * 8)
+ str = str + bytechr((long & (0xff << (i * 8))) >> i * 8)
return str
def stringToLong(str):
- if len(str) <> 4:
- raise ValueError, 'string must be 4 bytes long'
+ if len(str) != 4:
+ raise ValueError('string must be 4 bytes long')
long = 0
for i in range(4):
- long = long + (ord(str[i]) << (i * 8))
+ long = long + (byteord(str[i]) << (i * 8))
return long
diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py
index 54abed1..bb9f262 100644
--- a/Lib/fontTools/ttLib/__init__.py
+++ b/Lib/fontTools/ttLib/__init__.py
@@ -45,9 +45,10 @@
# $Id: __init__.py,v 1.51 2009-02-22 08:55:00 pabs3 Exp $
#
-import sys
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import os
-import string
+import sys
haveMacSupport = 0
if sys.platform == "mac":
@@ -60,7 +61,7 @@
class TTLibError(Exception): pass
-class TTFont:
+class TTFont(object):
"""The main font object. It manages file input and output, and offers
a convenient way of accessing tables.
@@ -148,7 +149,7 @@
# assume file is a string
if haveMacSupport and res_name_or_index is not None:
# on the mac, we deal with sfnt resources as well as flat files
- import macUtils
+ from . import macUtils
if res_name_or_index == 0:
if macUtils.getSFNTResIndices(file):
# get the first available sfnt font.
@@ -183,7 +184,7 @@
if not hasattr(file, "write"):
closeStream = 1
if os.name == "mac" and makeSuitcase:
- import macUtils
+ from . import macUtils
file = macUtils.SFNTResourceWriter(file, self)
else:
file = open(file, "wb")
@@ -194,7 +195,7 @@
# assume "file" is a writable file object
closeStream = 0
- tags = self.keys()
+ tags = list(self.keys())
if "GlyphOrder" in tags:
tags.remove("GlyphOrder")
numTables = len(tags)
@@ -236,7 +237,7 @@
self.disassembleInstructions = disassembleInstructions
self.bitmapGlyphDataFormat = bitmapGlyphDataFormat
if not tables:
- tables = self.keys()
+ tables = list(self.keys())
if "GlyphOrder" not in tables:
tables = ["GlyphOrder"] + tables
if skipTables:
@@ -251,7 +252,7 @@
idlefunc = None
writer = xmlWriter.XMLWriter(fileOrPath, idlefunc=idlefunc)
- writer.begintag("ttFont", sfntVersion=`self.sfntVersion`[1:-1],
+ writer.begintag("ttFont", sfntVersion=repr(self.sfntVersion)[1:-1],
ttLibVersion=version)
writer.newline()
@@ -290,7 +291,7 @@
debugmsg("Done dumping TTX")
def _tableToXML(self, writer, tag, progress, quiet):
- if self.has_key(tag):
+ if tag in self:
table = self[tag]
report = "Dumping '%s' table..." % tag
else:
@@ -301,8 +302,8 @@
debugmsg(report)
else:
if not quiet:
- print report
- if not self.has_key(tag):
+ print(report)
+ if tag not in self:
return
xmlTag = tagToXML(tag)
if hasattr(table, "ERROR"):
@@ -322,7 +323,7 @@
"""Import a TTX file (an XML-based text format), so as to recreate
a font object.
"""
- if self.has_key("maxp") and self.has_key("post"):
+ if "maxp" in self and "post" in self:
# Make sure the glyph order is loaded, as it otherwise gets
# lost if the XML doesn't contain the glyph order, yet does
# contain the table which was originally used to extract the
@@ -337,12 +338,12 @@
def isLoaded(self, tag):
"""Return true if the table identified by 'tag' has been
decompiled and loaded into memory."""
- return self.tables.has_key(tag)
+ return tag in self.tables
def has_key(self, tag):
if self.isLoaded(tag):
return 1
- elif self.reader and self.reader.has_key(tag):
+ elif self.reader and tag in self.reader:
return 1
elif tag == "GlyphOrder":
return 1
@@ -352,9 +353,9 @@
__contains__ = has_key
def keys(self):
- keys = self.tables.keys()
+ keys = list(self.tables.keys())
if self.reader:
- for key in self.reader.keys():
+ for key in list(self.reader.keys()):
if key not in keys:
keys.append(key)
@@ -364,9 +365,10 @@
return ["GlyphOrder"] + keys
def __len__(self):
- return len(self.keys())
+ return len(list(self.keys()))
def __getitem__(self, tag):
+ tag = Tag(tag)
try:
return self.tables[tag]
except KeyError:
@@ -390,10 +392,9 @@
if not self.ignoreDecompileErrors:
raise
# fall back to DefaultTable, retaining the binary table data
- print "An exception occurred during the decompilation of the '%s' table" % tag
- from tables.DefaultTable import DefaultTable
- import StringIO
- file = StringIO.StringIO()
+ print("An exception occurred during the decompilation of the '%s' table" % tag)
+ from .tables.DefaultTable import DefaultTable
+ file = StringIO()
traceback.print_exc(file=file)
table = DefaultTable(tag)
table.ERROR = file.getvalue()
@@ -401,17 +402,17 @@
table.decompile(data, self)
return table
else:
- raise KeyError, "'%s' table not found" % tag
+ raise KeyError("'%s' table not found" % tag)
def __setitem__(self, tag, table):
- self.tables[tag] = table
+ self.tables[Tag(tag)] = table
def __delitem__(self, tag):
- if not self.has_key(tag):
- raise KeyError, "'%s' table not found" % tag
- if self.tables.has_key(tag):
+ if tag not in self:
+ raise KeyError("'%s' table not found" % tag)
+ if tag in self.tables:
del self.tables[tag]
- if self.reader and self.reader.has_key(tag):
+ if self.reader and tag in self.reader:
del self.reader[tag]
def setGlyphOrder(self, glyphOrder):
@@ -422,10 +423,10 @@
return self.glyphOrder
except AttributeError:
pass
- if self.has_key('CFF '):
+ if 'CFF ' in self:
cff = self['CFF ']
self.glyphOrder = cff.getGlyphOrder()
- elif self.has_key('post'):
+ elif 'post' in self:
# TrueType font
glyphOrder = self['post'].getGlyphOrder()
if glyphOrder is None:
@@ -485,24 +486,23 @@
cmap = tempcmap.cmap
# create a reverse cmap dict
reversecmap = {}
- for unicode, name in cmap.items():
+ for unicode, name in list(cmap.items()):
reversecmap[name] = unicode
allNames = {}
for i in range(numGlyphs):
tempName = glyphOrder[i]
- if reversecmap.has_key(tempName):
+ if tempName in reversecmap:
unicode = reversecmap[tempName]
- if agl.UV2AGL.has_key(unicode):
+ if unicode in agl.UV2AGL:
# get name from the Adobe Glyph List
glyphName = agl.UV2AGL[unicode]
else:
# create uni<CODE> name
- glyphName = "uni" + string.upper(string.zfill(
- hex(unicode)[2:], 4))
+ glyphName = "uni%04X" % unicode
tempName = glyphName
n = 1
- while allNames.has_key(tempName):
- tempName = glyphName + "#" + `n`
+ while tempName in allNames:
+ tempName = glyphName + "#" + repr(n)
n = n + 1
glyphOrder[i] = tempName
allNames[tempName] = 1
@@ -519,8 +519,7 @@
def getGlyphNames(self):
"""Get a list of glyph names, sorted alphabetically."""
- glyphNames = self.getGlyphOrder()[:]
- glyphNames.sort()
+ glyphNames = sorted(self.getGlyphOrder()[:])
return glyphNames
def getGlyphNames2(self):
@@ -554,13 +553,13 @@
self._buildReverseGlyphOrderDict()
glyphOrder = self.getGlyphOrder()
d = self._reverseGlyphOrderDict
- if not d.has_key(glyphName):
+ if glyphName not in d:
if glyphName in glyphOrder:
self._buildReverseGlyphOrderDict()
return self.getGlyphID(glyphName)
else:
if requireReal or not self.allowVID:
- raise KeyError, glyphName
+ raise KeyError(glyphName)
else:
# user intends virtual GID support
try:
@@ -580,7 +579,7 @@
return glyphID
glyphID = d[glyphName]
- if glyphName <> glyphOrder[glyphID]:
+ if glyphName != glyphOrder[glyphID]:
self._buildReverseGlyphOrderDict()
return self.getGlyphID(glyphName)
return glyphID
@@ -605,7 +604,7 @@
tableClass = getTableClass(tag)
for masterTable in tableClass.dependencies:
if masterTable not in done:
- if self.has_key(masterTable):
+ if masterTable in self:
self._writeTable(masterTable, writer, done)
else:
done.append(masterTable)
@@ -618,16 +617,17 @@
def getTableData(self, tag):
"""Returns raw table data, whether compiled or directly read from disk.
"""
+ tag = Tag(tag)
if self.isLoaded(tag):
if self.verbose:
debugmsg("compiling '%s' table" % tag)
return self.tables[tag].compile(self)
- elif self.reader and self.reader.has_key(tag):
+ elif self.reader and tag in self.reader:
if self.verbose:
debugmsg("Reading '%s' table from disk" % tag)
return self.reader[tag]
else:
- raise KeyError, tag
+ raise KeyError(tag)
def getGlyphSet(self, preferCFF=1):
"""Return a generic GlyphSet, which is a dict-like object
@@ -641,16 +641,16 @@
If the font contains both a 'CFF ' and a 'glyf' table, you can use
the 'preferCFF' argument to specify which one should be taken.
"""
- if preferCFF and self.has_key("CFF "):
- return self["CFF "].cff.values()[0].CharStrings
- if self.has_key("glyf"):
+ if preferCFF and "CFF " in self:
+ return list(self["CFF "].cff.values())[0].CharStrings
+ if "glyf" in self:
return _TTGlyphSet(self)
- if self.has_key("CFF "):
- return self["CFF "].cff.values()[0].CharStrings
- raise TTLibError, "Font contains no outlines"
+ if "CFF " in self:
+ return list(self["CFF "].cff.values())[0].CharStrings
+ raise TTLibError("Font contains no outlines")
-class _TTGlyphSet:
+class _TTGlyphSet(object):
"""Generic dict-like GlyphSet class, meant as a TrueType counterpart
to CFF's CharString dict. See TTFont.getGlyphSet().
@@ -664,10 +664,10 @@
self._ttFont = ttFont
def keys(self):
- return self._ttFont["glyf"].keys()
+ return list(self._ttFont["glyf"].keys())
def has_key(self, glyphName):
- return self._ttFont["glyf"].has_key(glyphName)
+ return glyphName in self._ttFont["glyf"]
__contains__ = has_key
@@ -681,7 +681,7 @@
return default
-class _TTGlyph:
+class _TTGlyph(object):
"""Wrapper for a TrueType glyph that supports the Pen protocol, meaning
that it has a .draw() method that takes a pen object as its only
@@ -742,7 +742,7 @@
pen.closePath()
-class GlyphOrder:
+class GlyphOrder(object):
"""A pseudo table. The glyph order isn't in the font as a separate
table, but it's nice to present it as such in the TTX format.
@@ -761,7 +761,7 @@
writer.simpletag("GlyphID", id=i, name=glyphName)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "glyphOrder"):
self.glyphOrder = []
ttFont.setGlyphOrder(self.glyphOrder)
@@ -773,11 +773,11 @@
"""Fetch the packer/unpacker module for a table.
Return None when no module is found.
"""
- import tables
+ from . import tables
pyTag = tagToIdentifier(tag)
try:
__import__("fontTools.ttLib.tables." + pyTag)
- except ImportError, err:
+ except ImportError as err:
# If pyTag is found in the ImportError message,
# means table is not implemented. If it's not
# there, then some other module is missing, don't
@@ -796,7 +796,7 @@
"""
module = getTableModule(tag)
if module is None:
- from tables.DefaultTable import DefaultTable
+ from .tables.DefaultTable import DefaultTable
return DefaultTable
pyTag = tagToIdentifier(tag)
tableClass = getattr(module, "table_" + pyTag)
@@ -817,7 +817,7 @@
elif re.match("[A-Z]", c):
return c + "_"
else:
- return hex(ord(c))[2:]
+ return hex(byteord(c))[2:]
def tagToIdentifier(tag):
@@ -834,6 +834,7 @@
'OS/2' -> 'O_S_2f_2'
"""
import re
+ tag = Tag(tag)
if tag == "GlyphOrder":
return tag
assert len(tag) == 4, "tag should be 4 characters long"
@@ -862,10 +863,10 @@
tag = tag + ident[i]
else:
# assume hex
- tag = tag + chr(int(ident[i:i+2], 16))
+ tag = tag + bytechr(int(ident[i:i+2], 16))
# append trailing spaces
tag = tag + (4 - len(tag)) * ' '
- return tag
+ return Tag(tag)
def tagToXML(tag):
@@ -874,12 +875,13 @@
case sensitive, this is a fairly simple/readable translation.
"""
import re
+ tag = Tag(tag)
if tag == "OS/2":
return "OS_2"
elif tag == "GlyphOrder":
return tag
if re.match("[A-Za-z_][A-Za-z_0-9]* *$", tag):
- return string.strip(tag)
+ return tag.strip()
else:
return tagToIdentifier(tag)
@@ -892,12 +894,12 @@
return identifierToTag(tag)
else:
return tag + " " * (4 - len(tag))
- return tag
+ return Tag(tag)
def debugmsg(msg):
import time
- print msg + time.strftime(" (%H:%M:%S)", time.localtime(time.time()))
+ print(msg + time.strftime(" (%H:%M:%S)", time.localtime(time.time())))
# Table order as recommended in the OpenType specification 1.4
@@ -913,8 +915,7 @@
specification, or according to a custom tableOrder. If given and not
None, tableOrder needs to be a list of tag names.
"""
- tagList = list(tagList)
- tagList.sort()
+ tagList = sorted(tagList)
if tableOrder is None:
if "DSIG" in tagList:
# DSIG should be last (XXX spec reference?)
@@ -940,7 +941,7 @@
from fontTools.ttLib.sfnt import SFNTReader, SFNTWriter
reader = SFNTReader(inFile, checkChecksums=checkChecksums)
writer = SFNTWriter(outFile, len(reader.tables), reader.sfntVersion, reader.flavor, reader.flavorData)
- tables = reader.keys()
+ tables = list(reader.keys())
for tag in sortedTagList(tables, tableOrder):
writer[tag] = reader[tag]
writer.close()
diff --git a/Lib/fontTools/ttLib/macUtils.py b/Lib/fontTools/ttLib/macUtils.py
index 2d5aedb..c7c261d 100644
--- a/Lib/fontTools/ttLib/macUtils.py
+++ b/Lib/fontTools/ttLib/macUtils.py
@@ -1,24 +1,25 @@
"""ttLib.macUtils.py -- Various Mac-specific stuff."""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
import sys
import os
if sys.platform not in ("mac", "darwin"):
- raise ImportError, "This module is Mac-only!"
-
-import cStringIO
+ raise ImportError("This module is Mac-only!")
try:
from Carbon import Res
except ImportError:
import Res
+
def MyOpenResFile(path):
mode = 1 # read only
try:
resref = Res.FSOpenResFile(path, mode)
except Res.Error:
# try data fork
- resref = Res.FSOpenResourceFile(path, u'', mode)
+ resref = Res.FSOpenResourceFile(path, unicode(), mode)
return resref
@@ -31,7 +32,7 @@
Res.UseResFile(resref)
numSFNTs = Res.Count1Resources('sfnt')
Res.CloseResFile(resref)
- return range(1, numSFNTs + 1)
+ return list(range(1, numSFNTs + 1))
def openTTFonts(path):
@@ -49,22 +50,22 @@
for index in sfnts:
fonts.append(ttLib.TTFont(path, index))
if not fonts:
- raise ttLib.TTLibError, "no fonts found in file '%s'" % path
+ raise ttLib.TTLibError("no fonts found in file '%s'" % path)
return fonts
-class SFNTResourceReader:
+class SFNTResourceReader(object):
"""Simple (Mac-only) read-only file wrapper for 'sfnt' resources."""
def __init__(self, path, res_name_or_index):
resref = MyOpenResFile(path)
Res.UseResFile(resref)
- if type(res_name_or_index) == type(""):
+ if isinstance(res_name_or_index, basestring):
res = Res.Get1NamedResource('sfnt', res_name_or_index)
else:
res = Res.Get1IndResource('sfnt', res_name_or_index)
- self.file = cStringIO.StringIO(res.data)
+ self.file = StringIO(res.data)
Res.CloseResFile(resref)
self.name = path
@@ -73,12 +74,12 @@
return getattr(self.file, attr)
-class SFNTResourceWriter:
+class SFNTResourceWriter(object):
"""Simple (Mac-only) file wrapper for 'sfnt' resources."""
def __init__(self, path, ttFont, res_id=None):
- self.file = cStringIO.StringIO()
+ self.file = StringIO()
self.name = path
self.closed = 0
fullname = ttFont['name'].getName(4, 1, 0) # Full name, mac, default encoding
@@ -86,15 +87,15 @@
psname = ttFont['name'].getName(6, 1, 0) # PostScript name, etc.
if fullname is None or fullname is None or psname is None:
from fontTools import ttLib
- raise ttLib.TTLibError, "can't make 'sfnt' resource, no Macintosh 'name' table found"
+ raise ttLib.TTLibError("can't make 'sfnt' resource, no Macintosh 'name' table found")
self.fullname = fullname.string
self.familyname = familyname.string
self.psname = psname.string
- if self.familyname <> self.psname[:len(self.familyname)]:
+ if self.familyname != self.psname[:len(self.familyname)]:
# ugh. force fam name to be the same as first part of ps name,
# fondLib otherwise barfs.
for i in range(min(len(self.psname), len(self.familyname))):
- if self.familyname[i] <> self.psname[i]:
+ if self.familyname[i] != self.psname[i]:
break
self.familyname = self.psname[:i]
@@ -157,7 +158,7 @@
fond.styleMappingReserved = 0
# calc:
- scale = 4096.0 / self.ttFont['head'].unitsPerEm
+ scale = 4096 / self.ttFont['head'].unitsPerEm
fond.ffAscent = scale * self.ttFont['hhea'].ascent
fond.ffDescent = scale * self.ttFont['hhea'].descent
fond.ffWidMax = scale * self.ttFont['hhea'].advanceWidthMax
@@ -172,20 +173,20 @@
names = {}
for code, name in cmap.cmap.items():
names[name] = code
- if self.ttFont.has_key('kern'):
+ if 'kern' in self.ttFont:
kern = self.ttFont['kern'].getkern(0)
if kern:
fondkerning = []
for (left, right), value in kern.kernTable.items():
- if names.has_key(left) and names.has_key(right):
+ if left in names and right in names:
fondkerning.append((names[left], names[right], scale * value))
fondkerning.sort()
fond.kernTables = {0: fondkerning}
- if self.ttFont.has_key('hmtx'):
+ if 'hmtx' in self.ttFont:
hmtx = self.ttFont['hmtx']
fondwidths = [2048] * 256 + [0, 0] # default width, + plus two zeros.
for name, (width, lsb) in hmtx.metrics.items():
- if names.has_key(name):
+ if name in names:
fondwidths[names[name]] = scale * width
fond.widthTables = {0: fondwidths}
fond.save()
diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py
index 82e3e04..da5c79d 100644
--- a/Lib/fontTools/ttLib/sfnt.py
+++ b/Lib/fontTools/ttLib/sfnt.py
@@ -12,13 +12,13 @@
a table's length chages you need to rewrite the whole file anyway.
"""
-import sys
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import os
+import struct
-class SFNTReader:
+class SFNTReader(object):
def __init__(self, file, checkChecksums=1, fontNumber=-1):
self.file = file
@@ -29,33 +29,34 @@
self.DirectoryEntry = SFNTDirectoryEntry
self.sfntVersion = self.file.read(4)
self.file.seek(0)
- if self.sfntVersion == "ttcf":
+ if self.sfntVersion == b"ttcf":
sstruct.unpack(ttcHeaderFormat, self.file.read(ttcHeaderSize), 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)
+ 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])
sstruct.unpack(sfntDirectoryFormat, self.file.read(sfntDirectorySize), self)
- elif self.sfntVersion == "wOFF":
+ elif self.sfntVersion == b"wOFF":
self.flavor = "woff"
self.DirectoryEntry = WOFFDirectoryEntry
sstruct.unpack(woffDirectoryFormat, self.file.read(woffDirectorySize), self)
else:
sstruct.unpack(sfntDirectoryFormat, self.file.read(sfntDirectorySize), self)
+ self.sfntVersion = Tag(self.sfntVersion)
- if self.sfntVersion not in ("\000\001\000\000", "OTTO", "true"):
+ if self.sfntVersion not in ("\x00\x01\x00\x00", "OTTO", "true"):
from fontTools import ttLib
- raise ttLib.TTLibError, "Not a TrueType or OpenType font (bad sfntVersion)"
+ raise ttLib.TTLibError("Not a TrueType or OpenType font (bad sfntVersion)")
self.tables = {}
for i in range(self.numTables):
entry = self.DirectoryEntry()
entry.fromFile(self.file)
if entry.length > 0:
- self.tables[entry.tag] = entry
+ self.tables[Tag(entry.tag)] = entry
else:
# Ignore zero-length tables. This doesn't seem to be documented,
# yet it's apparently how the Windows TT rasterizer behaves.
@@ -68,43 +69,45 @@
self.flavorData = WOFFFlavorData(self)
def has_key(self, tag):
- return self.tables.has_key(tag)
+ return tag in self.tables
+
+ __contains__ = has_key
def keys(self):
return self.tables.keys()
def __getitem__(self, tag):
"""Fetch the raw table data."""
- entry = self.tables[tag]
+ entry = self.tables[Tag(tag)]
data = entry.loadData (self.file)
if self.checkChecksums:
if tag == 'head':
# Beh: we have to special-case the 'head' table.
- checksum = calcChecksum(data[:8] + '\0\0\0\0' + data[12:])
+ checksum = calcChecksum(data[:8] + b'\0\0\0\0' + data[12:])
else:
checksum = calcChecksum(data)
if self.checkChecksums > 1:
# Be obnoxious, and barf when it's wrong
assert checksum == entry.checksum, "bad checksum for '%s' table" % tag
- elif checksum <> entry.checkSum:
+ elif checksum != entry.checkSum:
# Be friendly, and just print a warning.
- print "bad checksum for '%s' table" % tag
+ print("bad checksum for '%s' table" % tag)
return data
def __delitem__(self, tag):
- del self.tables[tag]
+ del self.tables[Tag(tag)]
def close(self):
self.file.close()
-class SFNTWriter:
+class SFNTWriter(object):
def __init__(self, file, numTables, sfntVersion="\000\001\000\000",
flavor=None, flavorData=None):
self.file = file
self.numTables = numTables
- self.sfntVersion = sfntVersion
+ self.sfntVersion = Tag(sfntVersion)
self.flavor = flavor
self.flavorData = flavorData
@@ -126,27 +129,27 @@
# clear out directory area
self.file.seek(self.nextTableOffset)
# make sure we're actually where we want to be. (old cStringIO bug)
- self.file.write('\0' * (self.nextTableOffset - self.file.tell()))
+ self.file.write(b'\0' * (self.nextTableOffset - self.file.tell()))
self.tables = {}
def __setitem__(self, tag, data):
"""Write raw table data to disk."""
reuse = False
- if self.tables.has_key(tag):
+ if tag in self.tables:
# We've written this table to file before. If the length
# of the data is still the same, we allow overwriting it.
entry = self.tables[tag]
assert not hasattr(entry.__class__, 'encodeData')
- if len(data) <> entry.length:
+ if len(data) != entry.length:
from fontTools import ttLib
- raise ttLib.TTLibError, "cannot rewrite '%s' table: length does not match directory entry" % tag
+ raise ttLib.TTLibError("cannot rewrite '%s' table: length does not match directory entry" % tag)
reuse = True
else:
entry = self.DirectoryEntry()
entry.tag = tag
if tag == 'head':
- entry.checkSum = calcChecksum(data[:8] + '\0\0\0\0' + data[12:])
+ entry.checkSum = calcChecksum(data[:8] + b'\0\0\0\0' + data[12:])
self.headTable = data
entry.uncompressed = True
else:
@@ -162,7 +165,7 @@
# Don't depend on f.seek() as we need to add the padding even if no
# subsequent write follows (seek is lazy), ie. after the final table
# in the font.
- self.file.write('\0' * (self.nextTableOffset - self.file.tell()))
+ self.file.write(b'\0' * (self.nextTableOffset - self.file.tell()))
assert self.nextTableOffset == self.file.tell()
self.tables[tag] = entry
@@ -171,14 +174,13 @@
"""All tables must have been written to disk. Now write the
directory.
"""
- tables = self.tables.items()
- tables.sort()
- if len(tables) <> self.numTables:
+ tables = sorted(self.tables.items())
+ if len(tables) != self.numTables:
from fontTools import ttLib
- raise ttLib.TTLibError, "wrong number of tables; expected %d, found %d" % (self.numTables, len(tables))
+ raise ttLib.TTLibError("wrong number of tables; expected %d, found %d" % (self.numTables, len(tables)))
if self.flavor == "woff":
- self.signature = "wOFF"
+ self.signature = b"wOFF"
self.reserved = 0
self.totalSfntSize = 12
@@ -237,7 +239,7 @@
def _calcMasterChecksum(self, directory):
# calculate checkSumAdjustment
- tags = self.tables.keys()
+ tags = list(self.tables.keys())
checksums = []
for i in range(len(tags)):
checksums.append(self.tables[tags[i]].checkSum)
@@ -248,8 +250,7 @@
# Create a SFNT directory for checksum calculation purposes
self.searchRange, self.entrySelector, self.rangeShift = getSearchRange(self.numTables)
directory = sstruct.pack(sfntDirectoryFormat, self)
- tables = self.tables.items()
- tables.sort()
+ tables = sorted(self.tables.items())
for tag, entry in tables:
sfntEntry = SFNTDirectoryEntry()
for item in ['tag', 'checkSum', 'offset', 'length']:
@@ -339,7 +340,7 @@
woffDirectoryEntrySize = sstruct.calcsize(woffDirectoryEntryFormat)
-class DirectoryEntry:
+class DirectoryEntry(object):
def __init__(self):
self.uncompressed = False # if True, always embed entry raw
@@ -450,18 +451,18 @@
If the data length is not a multiple of four, it assumes
it is to be padded with null byte.
- >>> print calcChecksum("abcd")
+ >>> print calcChecksum(b"abcd")
1633837924
- >>> print calcChecksum("abcdxyz")
+ >>> print calcChecksum(b"abcdxyz")
3655064932
"""
remainder = len(data) % 4
if remainder:
- data += "\0" * (4 - remainder)
+ data += b"\0" * (4 - remainder)
value = 0
blockSize = 4096
assert blockSize % 4 == 0
- for i in xrange(0, len(data), blockSize):
+ for i in range(0, len(data), blockSize):
block = data[i:i+blockSize]
longs = struct.unpack(">%dL" % (len(block) // 4), block)
value = (value + sum(longs)) & 0xffffffff
diff --git a/Lib/fontTools/ttLib/tables/B_A_S_E_.py b/Lib/fontTools/ttLib/tables/B_A_S_E_.py
index 53975c8..9551e2c 100644
--- a/Lib/fontTools/ttLib/tables/B_A_S_E_.py
+++ b/Lib/fontTools/ttLib/tables/B_A_S_E_.py
@@ -1,4 +1,4 @@
-from otBase import BaseTTXConverter
+from .otBase import BaseTTXConverter
class table_B_A_S_E_(BaseTTXConverter):
diff --git a/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py b/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py
index 71514e1..6e5e1f0 100644
--- a/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py
+++ b/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py
@@ -1,7 +1,8 @@
# Since bitmap glyph metrics are shared between EBLC and EBDT
# this class gets its own python file.
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-from types import TupleType
from fontTools.misc.textTools import safeEval
@@ -26,7 +27,7 @@
Advance: B
"""
-class BitmapGlyphMetrics:
+class BitmapGlyphMetrics(object):
def toXML(self, writer, ttFont):
writer.begintag(self.__class__.__name__)
@@ -37,17 +38,17 @@
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
metricNames = set(sstruct.getformat(self.__class__.binaryFormat)[1])
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
# Make sure this is a metric that is needed by GlyphMetrics.
if name in metricNames:
vars(self)[name] = safeEval(attrs['value'])
else:
- print "Warning: unknown name '%s' being ignored in %s." % name, self.__class__.__name__
+ print("Warning: unknown name '%s' being ignored in %s." % name, self.__class__.__name__)
class BigGlyphMetrics(BitmapGlyphMetrics):
diff --git a/Lib/fontTools/ttLib/tables/C_B_D_T_.py b/Lib/fontTools/ttLib/tables/C_B_D_T_.py
index 2289594..cd2a975 100644
--- a/Lib/fontTools/ttLib/tables/C_B_D_T_.py
+++ b/Lib/fontTools/ttLib/tables/C_B_D_T_.py
@@ -3,12 +3,13 @@
# Google Author(s): Matt Fontaine
-import E_B_D_T_
-import string
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-from BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
-from E_B_D_T_ import BitmapGlyph, BitmapPlusSmallMetricsMixin, BitmapPlusBigMetricsMixin
+from . import E_B_D_T_
+from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+from .E_B_D_T_ import BitmapGlyph, BitmapPlusSmallMetricsMixin, BitmapPlusBigMetricsMixin
+import struct
class table_C_B_D_T_(E_B_D_T_.table_E_B_D_T_):
@@ -51,7 +52,7 @@
dataList.append(sstruct.pack(smallGlyphMetricsFormat, self.metrics))
dataList.append(struct.pack(">L", len(self.imageData)))
dataList.append(self.imageData)
- return string.join(dataList, "")
+ return bytesjoin(dataList)
class cbdt_bitmap_format_18(BitmapPlusBigMetricsMixin, ColorBitmapGlyph):
@@ -70,7 +71,7 @@
dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
dataList.append(struct.pack(">L", len(self.imageData)))
dataList.append(self.imageData)
- return string.join(dataList, "")
+ return bytesjoin(dataList)
class cbdt_bitmap_format_19(ColorBitmapGlyph):
diff --git a/Lib/fontTools/ttLib/tables/C_B_L_C_.py b/Lib/fontTools/ttLib/tables/C_B_L_C_.py
index 886f50c..2f78571 100644
--- a/Lib/fontTools/ttLib/tables/C_B_L_C_.py
+++ b/Lib/fontTools/ttLib/tables/C_B_L_C_.py
@@ -2,7 +2,7 @@
#
# Google Author(s): Matt Fontaine
-import E_B_L_C_
+from . import E_B_L_C_
class table_C_B_L_C_(E_B_L_C_.table_E_B_L_C_):
diff --git a/Lib/fontTools/ttLib/tables/C_F_F_.py b/Lib/fontTools/ttLib/tables/C_F_F_.py
index 6a083c3..eb48f75 100644
--- a/Lib/fontTools/ttLib/tables/C_F_F_.py
+++ b/Lib/fontTools/ttLib/tables/C_F_F_.py
@@ -1,5 +1,7 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools import cffLib
+from . import DefaultTable
class table_C_F_F_(DefaultTable.DefaultTable):
@@ -10,12 +12,10 @@
self._gaveGlyphOrder = 0
def decompile(self, data, otFont):
- from cStringIO import StringIO
self.cff.decompile(StringIO(data), otFont)
assert len(self.cff) == 1, "can't deal with multi-font CFF tables."
def compile(self, otFont):
- from cStringIO import StringIO
f = StringIO()
self.cff.compile(f, otFont)
return f.getvalue()
@@ -29,7 +29,7 @@
def getGlyphOrder(self):
if self._gaveGlyphOrder:
from fontTools import ttLib
- raise ttLib.TTLibError, "illegal use of getGlyphOrder()"
+ raise ttLib.TTLibError("illegal use of getGlyphOrder()")
self._gaveGlyphOrder = 1
return self.cff[self.cff.fontNames[0]].getGlyphOrder()
@@ -41,8 +41,8 @@
def toXML(self, writer, otFont, progress=None):
self.cff.toXML(writer, progress)
- def fromXML(self, (name, attrs, content), otFont):
+ def fromXML(self, name, attrs, content, otFont):
if not hasattr(self, "cff"):
self.cff = cffLib.CFFFontSet()
- self.cff.fromXML((name, attrs, content))
+ self.cff.fromXML(name, attrs, content)
diff --git a/Lib/fontTools/ttLib/tables/C_O_L_R_.py b/Lib/fontTools/ttLib/tables/C_O_L_R_.py
index b39a4a0..31ef729 100644
--- a/Lib/fontTools/ttLib/tables/C_O_L_R_.py
+++ b/Lib/fontTools/ttLib/tables/C_O_L_R_.py
@@ -2,12 +2,12 @@
#
# Google Author(s): Behdad Esfahbod
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc.textTools import safeEval
+from . import DefaultTable
import operator
-import DefaultTable
import struct
-from fontTools.ttLib import sfnt
-from fontTools.misc.textTools import safeEval, readHex
-from types import IntType, StringType
class table_C_O_L_R_(DefaultTable.DefaultTable):
@@ -44,12 +44,12 @@
self.ColorLayers = colorLayerLists = {}
try:
- names = map(operator.getitem, [glyphOrder]*numBaseGlyphRecords, gids)
+ names = list(map(operator.getitem, [glyphOrder]*numBaseGlyphRecords, gids))
except IndexError:
getGlyphName = self.getGlyphName
- names = map(getGlyphName, gids )
+ names = list(map(getGlyphName, gids ))
- map(operator.setitem, [colorLayerLists]*numBaseGlyphRecords, names, layerLists)
+ list(map(operator.setitem, [colorLayerLists]*numBaseGlyphRecords, names, layerLists))
def compile(self, ttFont):
@@ -74,7 +74,7 @@
dataList = [struct.pack(">HHLLH", self.version, len(glyphMap), 14, 14+6*len(glyphMap), len(layerMap))]
dataList.extend(glyphMap)
dataList.extend(layerMap)
- data = "".join(dataList)
+ data = bytesjoin(dataList)
return data
def toXML(self, writer, ttFont):
@@ -97,49 +97,48 @@
writer.endtag("ColorGlyph")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "ColorLayers"):
self.ColorLayers = {}
self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID
if name == "ColorGlyph":
glyphName = attrs["name"]
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
layers = []
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
layer = LayerRecord()
- layer.fromXML(element, ttFont)
+ layer.fromXML(element[0], element[1], element[2], ttFont)
layers.append (layer)
operator.setitem(self, glyphName, layers)
- elif attrs.has_key("value"):
- value = safeEval(attrs["value"])
- setattr(self, name, value)
+ elif "value" in attrs:
+ setattr(self, name, safeEval(attrs["value"]))
def __getitem__(self, glyphSelector):
- if type(glyphSelector) == IntType:
+ if isinstance(glyphSelector, int):
# its a gid, convert to glyph name
glyphSelector = self.getGlyphName(glyphSelector)
- if not self.ColorLayers.has_key(glyphSelector):
+ if glyphSelector not in self.ColorLayers:
return None
return self.ColorLayers[glyphSelector]
def __setitem__(self, glyphSelector, value):
- if type(glyphSelector) == IntType:
+ if isinstance(glyphSelector, int):
# its a gid, convert to glyph name
glyphSelector = self.getGlyphName(glyphSelector)
if value:
self.ColorLayers[glyphSelector] = value
- elif self.ColorLayers.has_key(glyphSelector):
+ elif glyphSelector in self.ColorLayers:
del self.ColorLayers[glyphSelector]
-class LayerRecord:
+class LayerRecord(object):
def __init__(self, name = None, colorID = None):
self.name = name
@@ -149,15 +148,11 @@
writer.simpletag("layer", name=self.name, colorID=self.colorID)
writer.newline()
- def fromXML(self, (eltname, attrs, content), ttFont):
+ def fromXML(self, eltname, attrs, content, ttFont):
for (name, value) in attrs.items():
if name == "name":
- if type(value) == IntType:
+ if isinstance(value, int):
value = ttFont.getGlyphName(value)
setattr(self, name, value)
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
diff --git a/Lib/fontTools/ttLib/tables/C_P_A_L_.py b/Lib/fontTools/ttLib/tables/C_P_A_L_.py
index 1e5a878..fc96caa 100644
--- a/Lib/fontTools/ttLib/tables/C_P_A_L_.py
+++ b/Lib/fontTools/ttLib/tables/C_P_A_L_.py
@@ -2,12 +2,11 @@
#
# Google Author(s): Behdad Esfahbod
-import operator
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc.textTools import safeEval
+from . import DefaultTable
import struct
-from fontTools.ttLib import sfnt
-from fontTools.misc.textTools import safeEval, readHex
-from types import IntType, StringType
class table_C_P_A_L_(DefaultTable.DefaultTable):
@@ -36,7 +35,7 @@
assert(len(palette) == self.numPaletteEntries)
for color in palette:
dataList.append(struct.pack(">BBBB", color.blue,color.green,color.red,color.alpha))
- data = "".join(dataList)
+ data = bytesjoin(dataList)
return data
def toXML(self, writer, ttFont):
@@ -53,27 +52,27 @@
writer.endtag("palette")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "palettes"):
self.palettes = []
if name == "palette":
palette = []
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
palette = []
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
color = Color()
- color.fromXML(element, ttFont)
+ color.fromXML(element[0], element[1], element[2], ttFont)
palette.append (color)
self.palettes.append(palette)
- elif attrs.has_key("value"):
+ elif "value" in attrs:
value = safeEval(attrs["value"])
setattr(self, name, value)
-class Color:
+class Color(object):
def __init__(self, blue=None, green=None, red=None, alpha=None):
self.blue = blue
@@ -91,7 +90,7 @@
writer.simpletag("color", value=self.hex(), index=index)
writer.newline()
- def fromXML(self, (eltname, attrs, content), ttFont):
+ def fromXML(self, eltname, attrs, content, ttFont):
value = attrs["value"]
if value[0] == '#':
value = value[1:]
diff --git a/Lib/fontTools/ttLib/tables/D_S_I_G_.py b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
index 995069d..20f14ee 100644
--- a/Lib/fontTools/ttLib/tables/D_S_I_G_.py
+++ b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
@@ -1,6 +1,9 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
from fontTools.misc import sstruct
+from . import DefaultTable
+import base64
DSIG_HeaderFormat = """
> # big endian
@@ -69,7 +72,10 @@
sigrec.ulOffset = offset
headers.append(sstruct.pack(DSIG_SignatureFormat, sigrec))
offset += sigrec.ulLength
- return ''.join(headers+data)
+ if offset % 2:
+ # Pad to even bytes
+ data.append(b'\0')
+ return bytesjoin(headers+data)
def toXML(self, xmlWriter, ttFont):
xmlWriter.comment("note that the Digital Signature will be invalid after recompilation!")
@@ -80,7 +86,7 @@
sigrec.toXML(xmlWriter, ttFont)
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "tableHeader":
self.signatureRecords = []
self.ulVersion = safeEval(attrs["version"])
@@ -89,14 +95,24 @@
return
if name == "SignatureRecord":
sigrec = SignatureRecord()
- sigrec.fromXML((name, attrs, content), ttFont)
+ sigrec.fromXML(name, attrs, content, ttFont)
self.signatureRecords.append(sigrec)
pem_spam = lambda l, spam = {
"-----BEGIN PKCS7-----": True, "-----END PKCS7-----": True, "": True
}: not spam.get(l.strip())
-class SignatureRecord:
+def b64encode(b):
+ s = base64.b64encode(b)
+ # Line-break at 76 chars.
+ items = []
+ while s:
+ items.append(tostr(s[:76]))
+ items.append('\n')
+ s = s[76:]
+ return strjoin(items)
+
+class SignatureRecord(object):
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.__dict__)
@@ -104,12 +120,12 @@
writer.begintag(self.__class__.__name__, format=self.ulFormat)
writer.newline()
writer.write_noindent("-----BEGIN PKCS7-----\n")
- writer.write_noindent(self.pkcs7.encode('base64'))
+ writer.write_noindent(b64encode(self.pkcs7))
writer.write_noindent("-----END PKCS7-----\n")
writer.endtag(self.__class__.__name__)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.ulFormat = safeEval(attrs["format"])
self.usReserved1 = safeEval(attrs.get("reserved1", "0"))
self.usReserved2 = safeEval(attrs.get("reserved2", "0"))
- self.pkcs7 = "".join(filter(pem_spam, content)).decode('base64')
+ self.pkcs7 = base64.b64decode(tobytes(strjoin(filter(pem_spam, content))))
diff --git a/Lib/fontTools/ttLib/tables/DefaultTable.py b/Lib/fontTools/ttLib/tables/DefaultTable.py
index 8d68ec0..5951a0b 100644
--- a/Lib/fontTools/ttLib/tables/DefaultTable.py
+++ b/Lib/fontTools/ttLib/tables/DefaultTable.py
@@ -1,12 +1,12 @@
-import string
-import sys
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
-class DefaultTable:
+class DefaultTable(object):
dependencies = []
def __init__(self, tag):
- self.tableTag = tag
+ self.tableTag = Tag(tag)
def decompile(self, data, ttFont):
self.data = data
@@ -26,19 +26,17 @@
writer.endtag("hexdata")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
from fontTools.misc.textTools import readHex
from fontTools import ttLib
- if name <> "hexdata":
- raise ttLib.TTLibError, "can't handle '%s' element" % name
+ if name != "hexdata":
+ raise ttLib.TTLibError("can't handle '%s' element" % name)
self.decompile(readHex(content), ttFont)
def __repr__(self):
return "<'%s' table at %x>" % (self.tableTag, id(self))
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.__dict__, other.__dict__)
-
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self.__dict__ == other.__dict__
diff --git a/Lib/fontTools/ttLib/tables/E_B_D_T_.py b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
index 4b033ec..ab2b8f4 100644
--- a/Lib/fontTools/ttLib/tables/E_B_D_T_.py
+++ b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
@@ -1,13 +1,12 @@
-
-import DefaultTable
-import os
-import string
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import itertools
-from types import TupleType
from fontTools.misc.textTools import safeEval, readHex, hexStr, deHexStr
-from BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+from . import DefaultTable
+import itertools
+import os
+import struct
ebdtTableVersionFormat = """
> # big endian
@@ -52,7 +51,7 @@
bitmapGlyphDict = {}
self.strikeData.append(bitmapGlyphDict)
for indexSubTable in curStrike.indexSubTables:
- dataIter = itertools.izip(indexSubTable.names, indexSubTable.locations)
+ dataIter = zip(indexSubTable.names, indexSubTable.locations)
for curName, curLoc in dataIter:
# Don't create duplicate data entries for the same glyphs.
# Instead just use the structures that already exist if they exist.
@@ -82,7 +81,7 @@
# recalculation is defered to the EblcIndexSubTable class and just
# pass what is known about bitmap glyphs from this particular table.
locator = ttFont[self.__class__.locatorName]
- for curStrike, curGlyphDict in itertools.izip(locator.strikes, self.strikeData):
+ for curStrike, curGlyphDict in zip(locator.strikes, self.strikeData):
for curIndexSubTable in curStrike.indexSubTables:
dataLocations = []
for curName in curIndexSubTable.names:
@@ -114,7 +113,7 @@
# of any of the problems in the convertion that may arise.
curIndexSubTable.locations = dataLocations
- return string.join(dataList, "")
+ return bytesjoin(dataList)
def toXML(self, writer, ttFont):
# When exporting to XML if one of the data export formats
@@ -122,7 +121,7 @@
# In this case populate the bitmaps with "export metrics".
if ttFont.bitmapGlyphDataFormat in ('row', 'bitwise'):
locator = ttFont[self.__class__.locatorName]
- for curStrike, curGlyphDict in itertools.izip(locator.strikes, self.strikeData):
+ for curStrike, curGlyphDict in zip(locator.strikes, self.strikeData):
for curIndexSubTable in curStrike.indexSubTables:
for curName in curIndexSubTable.names:
glyph = curGlyphDict[curName]
@@ -145,7 +144,7 @@
writer.endtag('strikedata')
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == 'header':
self.version = safeEval(attrs['version'])
elif name == 'strikedata':
@@ -155,7 +154,7 @@
bitmapGlyphDict = {}
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name[4:].startswith(_bitmapGlyphSubclassPrefix[4:]):
@@ -163,11 +162,11 @@
glyphName = attrs['name']
imageFormatClass = self.getImageFormatClass(imageFormat)
curGlyph = imageFormatClass(None, None)
- curGlyph.fromXML(element, ttFont)
+ curGlyph.fromXML(name, attrs, content, ttFont)
assert glyphName not in bitmapGlyphDict, "Duplicate glyphs with the same name '%s' in the same strike." % glyphName
bitmapGlyphDict[glyphName] = curGlyph
else:
- print "Warning: %s being ignored by %s", name, self.__class__.__name__
+ print("Warning: %s being ignored by %s", name, self.__class__.__name__)
# Grow the strike data array to the appropriate size. The XML
# format allows the strike index value to be out of order.
@@ -176,7 +175,7 @@
assert self.strikeData[strikeIndex] == None, "Duplicate strike EBDT indices."
self.strikeData[strikeIndex] = bitmapGlyphDict
-class EbdtComponent:
+class EbdtComponent(object):
def toXML(self, writer, ttFont):
writer.begintag('ebdtComponent', [('name', self.name)])
@@ -187,45 +186,45 @@
writer.endtag('ebdtComponent')
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.name = attrs['name']
componentNames = set(sstruct.getformat(ebdtComponentFormat)[1][1:])
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name in componentNames:
vars(self)[name] = safeEval(attrs['value'])
else:
- print "Warning: unknown name '%s' being ignored by EbdtComponent." % name
+ print("Warning: unknown name '%s' being ignored by EbdtComponent." % name)
# Helper functions for dealing with binary.
def _data2binary(data, numBits):
binaryList = []
for curByte in data:
- value = ord(curByte)
+ value = byteord(curByte)
numBitsCut = min(8, numBits)
- for i in xrange(numBitsCut):
+ for i in range(numBitsCut):
if value & 0x1:
binaryList.append('1')
else:
binaryList.append('0')
value = value >> 1
numBits -= numBitsCut
- return string.join(binaryList, "")
+ return strjoin(binaryList)
def _binary2data(binary):
byteList = []
- for bitLoc in xrange(0, len(binary), 8):
+ for bitLoc in range(0, len(binary), 8):
byteString = binary[bitLoc:bitLoc+8]
curByte = 0
for curBit in reversed(byteString):
curByte = curByte << 1
if curBit == '1':
curByte |= 1
- byteList.append(chr(curByte))
- return string.join(byteList, "")
+ byteList.append(bytechr(curByte))
+ return bytesjoin(byteList)
def _memoize(f):
class memodict(dict):
@@ -243,14 +242,14 @@
@_memoize
def _reverseBytes(data):
if len(data) != 1:
- return string.join(map(_reverseBytes, data), "")
- byte = ord(data)
+ return bytesjoin(map(_reverseBytes, data))
+ byte = byteord(data)
result = 0
- for i in xrange(8):
+ for i in range(8):
result = result << 1
result |= byte & 1
byte = byte >> 1
- return chr(result)
+ return bytechr(result)
# This section of code is for reading and writing image data to/from XML.
@@ -261,7 +260,7 @@
writer.endtag('rawimagedata')
writer.newline()
-def _readRawImageData(bitmapObject, (name, attrs, content), ttFont):
+def _readRawImageData(bitmapObject, name, attrs, content, ttFont):
bitmapObject.imageData = readHex(content)
def _writeRowImageData(strikeIndex, glyphName, bitmapObject, writer, ttFont):
@@ -272,14 +271,14 @@
writer.begintag('rowimagedata', bitDepth=bitDepth, width=metrics.width, height=metrics.height)
writer.newline()
- for curRow in xrange(metrics.height):
+ for curRow in range(metrics.height):
rowData = bitmapObject.getRow(curRow, bitDepth=bitDepth, metrics=metrics)
writer.simpletag('row', value=hexStr(rowData))
writer.newline()
writer.endtag('rowimagedata')
writer.newline()
-def _readRowImageData(bitmapObject, (name, attrs, content), ttFont):
+def _readRowImageData(bitmapObject, name, attrs, content, ttFont):
bitDepth = safeEval(attrs['bitDepth'])
metrics = SmallGlyphMetrics()
metrics.width = safeEval(attrs['width'])
@@ -287,7 +286,7 @@
dataRows = []
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attr, content = element
# Chop off 'imagedata' from the tag to get just the option.
@@ -306,17 +305,17 @@
writer.begintag('bitwiseimagedata', bitDepth=bitDepth, width=metrics.width, height=metrics.height)
writer.newline()
- for curRow in xrange(metrics.height):
+ for curRow in range(metrics.height):
rowData = bitmapObject.getRow(curRow, bitDepth=1, metrics=metrics, reverseBytes=True)
rowData = _data2binary(rowData, metrics.width)
# Make the output a readable ASCII art form.
- rowData = string.join(map(binaryConv.get, rowData), "")
+ rowData = strjoin(map(binaryConv.get, rowData))
writer.simpletag('row', value=rowData)
writer.newline()
writer.endtag('bitwiseimagedata')
writer.newline()
-def _readBitwiseImageData(bitmapObject, (name, attrs, content), ttFont):
+def _readBitwiseImageData(bitmapObject, name, attrs, content, ttFont):
bitDepth = safeEval(attrs['bitDepth'])
metrics = SmallGlyphMetrics()
metrics.width = safeEval(attrs['width'])
@@ -328,12 +327,12 @@
dataRows = []
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attr, content = element
if name == 'row':
- mapParams = itertools.izip(attr['value'], itertools.repeat('1'))
- rowData = string.join(itertools.starmap(binaryConv.get, mapParams), "")
+ mapParams = zip(attr['value'], itertools.repeat('1'))
+ rowData = strjoin(itertools.starmap(binaryConv.get, mapParams))
dataRows.append(_binary2data(rowData))
bitmapObject.setRows(dataRows, bitDepth=bitDepth, metrics=metrics, reverseBytes=True)
@@ -354,7 +353,7 @@
with open(fullPath, "wb") as file:
file.write(bitmapObject.imageData)
-def _readExtFileImageData(bitmapObject, (name, attrs, content), ttFont):
+def _readExtFileImageData(bitmapObject, name, attrs, content, ttFont):
fullPath = attrs['value']
with open(fullPath, "rb") as file:
bitmapObject.imageData = file.read()
@@ -365,7 +364,7 @@
# in XML.
_bitmapGlyphSubclassPrefix = 'ebdt_bitmap_format_'
-class BitmapGlyph:
+class BitmapGlyph(object):
# For the external file format. This can be changed in subclasses. This way
# when the extfile option is turned on files have the form: glyphName.ext
@@ -383,16 +382,17 @@
def __init__(self, data, ttFont):
self.data = data
self.ttFont = ttFont
- if not ttFont.lazy:
- self.decompile()
- del self.data
+ # TODO Currently non-lazy decompilation is untested here...
+ #if not ttFont.lazy:
+ # self.decompile()
+ # del self.data
def __getattr__(self, attr):
# Allow lazy decompile.
if attr[:2] == '__':
- raise AttributeError, attr
+ raise AttributeError(attr)
if not hasattr(self, "data"):
- raise AttributeError, attr
+ raise AttributeError(attr)
self.decompile()
del self.data
return getattr(self, attr)
@@ -412,16 +412,18 @@
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- self.readMetrics((name, attrs, content), ttFont)
+ def fromXML(self, name, attrs, content, ttFont):
+ self.readMetrics(name, attrs, content, ttFont)
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attr, content = element
+ if not name.endswith('imagedata'):
+ continue
# Chop off 'imagedata' from the tag to get just the option.
option = name[:-len('imagedata')]
- if option in self.__class__.xmlDataFunctions:
- self.readData(element, ttFont)
+ assert option in self.__class__.xmlDataFunctions
+ self.readData(name, attrs, content, ttFont)
# Some of the glyphs have the metrics. This allows for metrics to be
# added if the glyph format has them. Default behavior is to do nothing.
@@ -429,7 +431,7 @@
pass
# The opposite of write metrics.
- def readMetrics(self, (name, attrs, content), ttFont):
+ def readMetrics(self, name, attrs, content, ttFont):
pass
def writeData(self, strikeIndex, glyphName, writer, ttFont):
@@ -439,11 +441,11 @@
writeFunc = _writeRawImageData
writeFunc(strikeIndex, glyphName, self, writer, ttFont)
- def readData(self, (name, attrs, content), ttFont):
+ def readData(self, name, attrs, content, ttFont):
# Chop off 'imagedata' from the tag to get just the option.
option = name[:-len('imagedata')]
writeFunc, readFunc = self.__class__.xmlDataFunctions[option]
- readFunc(self, (name, attrs, content), ttFont)
+ readFunc(self, name, attrs, content, ttFont)
# A closure for creating a mixin for the two types of metrics handling.
@@ -457,21 +459,21 @@
metricsId = metricStrings.index(curMetricsName)
oppositeMetricsName = metricStrings[1-metricsId]
- class BitmapPlusMetricsMixin:
+ class BitmapPlusMetricsMixin(object):
def writeMetrics(self, writer, ttFont):
self.metrics.toXML(writer, ttFont)
- def readMetrics(self, (name, attrs, content), ttFont):
+ def readMetrics(self, name, attrs, content, ttFont):
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == curMetricsName:
self.metrics = metricsClass()
- self.metrics.fromXML(element, ttFont)
+ self.metrics.fromXML(name, attrs, content, ttFont)
elif name == oppositeMetricsName:
- print "Warning: %s being ignored in format %d." % oppositeMetricsName, self.getFormat()
+ print("Warning: %s being ignored in format %d." % oppositeMetricsName, self.getFormat())
return BitmapPlusMetricsMixin
@@ -482,7 +484,7 @@
# Data that is bit aligned can be tricky to deal with. These classes implement
# helper functionality for dealing with the data and getting a particular row
# of bitwise data. Also helps implement fancy data export/import in XML.
-class BitAlignedBitmapMixin:
+class BitAlignedBitmapMixin(object):
def _getBitRange(self, row, bitDepth, metrics):
rowBits = (bitDepth * metrics.width)
@@ -512,28 +514,28 @@
dataList = []
bitRange = self._getBitRange(row, bitDepth, metrics)
stepRange = bitRange + (8,)
- for curBit in xrange(*stepRange):
+ for curBit in range(*stepRange):
endBit = min(curBit+8, bitRange[1])
numBits = endBit - curBit
cutPoint = curBit % 8
- firstByteLoc = curBit / 8
- secondByteLoc = endBit / 8
+ firstByteLoc = curBit // 8
+ secondByteLoc = endBit // 8
if firstByteLoc < secondByteLoc:
numBitsCut = 8 - cutPoint
else:
numBitsCut = endBit - curBit
curByte = _reverseBytes(self.imageData[firstByteLoc])
- firstHalf = ord(curByte) >> cutPoint
+ firstHalf = byteord(curByte) >> cutPoint
firstHalf = ((1<<numBitsCut)-1) & firstHalf
newByte = firstHalf
if firstByteLoc < secondByteLoc and secondByteLoc < len(self.imageData):
curByte = _reverseBytes(self.imageData[secondByteLoc])
- secondHalf = ord(curByte) << numBitsCut
+ secondHalf = byteord(curByte) << numBitsCut
newByte = (firstHalf | secondHalf) & ((1<<numBits)-1)
- dataList.append(chr(newByte))
+ dataList.append(bytechr(newByte))
# The way the data is kept is opposite the algorithm used.
- data = string.join(dataList, "")
+ data = bytesjoin(dataList)
if not reverseBytes:
data = _reverseBytes(data)
return data
@@ -542,25 +544,25 @@
if metrics == None:
metrics = self.metrics
if not reverseBytes:
- dataRows = map(_reverseBytes, dataRows)
+ dataRows = list(map(_reverseBytes, dataRows))
# Keep track of a list of ordinal values as they are easier to modify
# than a list of strings. Map to actual strings later.
- numBytes = (self._getBitRange(len(dataRows), bitDepth, metrics)[0] + 7) / 8
+ numBytes = (self._getBitRange(len(dataRows), bitDepth, metrics)[0] + 7) // 8
ordDataList = [0] * numBytes
for row, data in enumerate(dataRows):
bitRange = self._getBitRange(row, bitDepth, metrics)
stepRange = bitRange + (8,)
- for curBit, curByte in itertools.izip(xrange(*stepRange), data):
+ for curBit, curByte in zip(range(*stepRange), data):
endBit = min(curBit+8, bitRange[1])
cutPoint = curBit % 8
- firstByteLoc = curBit / 8
- secondByteLoc = endBit / 8
+ firstByteLoc = curBit // 8
+ secondByteLoc = endBit // 8
if firstByteLoc < secondByteLoc:
numBitsCut = 8 - cutPoint
else:
numBitsCut = endBit - curBit
- curByte = ord(curByte)
+ curByte = byteord(curByte)
firstByte = curByte & ((1<<numBitsCut)-1)
ordDataList[firstByteLoc] |= (firstByte << cutPoint)
if firstByteLoc < secondByteLoc and secondByteLoc < numBytes:
@@ -568,12 +570,12 @@
ordDataList[secondByteLoc] |= secondByte
# Save the image data with the bits going the correct way.
- self.imageData = _reverseBytes(string.join(map(chr, ordDataList), ""))
+ self.imageData = _reverseBytes(bytesjoin(map(bytechr, ordDataList)))
-class ByteAlignedBitmapMixin:
+class ByteAlignedBitmapMixin(object):
def _getByteRange(self, row, bitDepth, metrics):
- rowBytes = (bitDepth * metrics.width + 7) / 8
+ rowBytes = (bitDepth * metrics.width + 7) // 8
byteOffset = row * rowBytes
return (byteOffset, byteOffset+rowBytes)
@@ -592,7 +594,7 @@
metrics = self.metrics
if reverseBytes:
dataRows = map(_reverseBytes, dataRows)
- self.imageData = string.join(dataRows, "")
+ self.imageData = bytesjoin(dataRows)
class ebdt_bitmap_format_1(ByteAlignedBitmapMixin, BitmapPlusSmallMetricsMixin, BitmapGlyph):
@@ -668,24 +670,24 @@
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- self.readMetrics((name, attrs, content), ttFont)
+ def fromXML(self, name, attrs, content, ttFont):
+ self.readMetrics(name, attrs, content, ttFont)
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attr, content = element
if name == 'components':
self.componentArray = []
for compElement in content:
- if type(compElement) != TupleType:
+ if not isinstance(compElement, tuple):
continue
- name, attr, content = compElement
+ name, attrs, content = compElement
if name == 'ebdtComponent':
curComponent = EbdtComponent()
- curComponent.fromXML(compElement, ttFont)
+ curComponent.fromXML(name, attrs, content, ttFont)
self.componentArray.append(curComponent)
else:
- print "Warning: '%s' being ignored in component array." % name
+ print("Warning: '%s' being ignored in component array." % name)
class ebdt_bitmap_format_8(BitmapPlusSmallMetricsMixin, ComponentBitmapGlyph):
@@ -698,7 +700,7 @@
(numComponents,) = struct.unpack(">H", data[:2])
data = data[2:]
self.componentArray = []
- for i in xrange(numComponents):
+ for i in range(numComponents):
curComponent = EbdtComponent()
dummy, data = sstruct.unpack2(ebdtComponentFormat, data, curComponent)
curComponent.name = self.ttFont.getGlyphName(curComponent.glyphCode)
@@ -707,12 +709,12 @@
def compile(self, ttFont):
dataList = []
dataList.append(sstruct.pack(smallGlyphMetricsFormat, self.metrics))
- dataList.append('\0')
+ dataList.append(b'\0')
dataList.append(struct.pack(">H", len(self.componentArray)))
for curComponent in self.componentArray:
curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
- return string.join(dataList, "")
+ return bytesjoin(dataList)
class ebdt_bitmap_format_9(BitmapPlusBigMetricsMixin, ComponentBitmapGlyph):
@@ -723,7 +725,7 @@
(numComponents,) = struct.unpack(">H", data[:2])
data = data[2:]
self.componentArray = []
- for i in xrange(numComponents):
+ for i in range(numComponents):
curComponent = EbdtComponent()
dummy, data = sstruct.unpack2(ebdtComponentFormat, data, curComponent)
curComponent.name = self.ttFont.getGlyphName(curComponent.glyphCode)
@@ -736,7 +738,7 @@
for curComponent in self.componentArray:
curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
- return string.join(dataList, "")
+ return bytesjoin(dataList)
# Dictionary of bitmap formats to the class representing that format
diff --git a/Lib/fontTools/ttLib/tables/E_B_L_C_.py b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
index c7e2f89..1856fd7 100644
--- a/Lib/fontTools/ttLib/tables/E_B_L_C_.py
+++ b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
@@ -1,13 +1,12 @@
-
-import DefaultTable
-import string
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import itertools
-from types import TupleType
-from collections import deque
+from . import DefaultTable
from fontTools.misc.textTools import safeEval
-from BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+import struct
+import itertools
+from collections import deque
eblcHeaderFormat = """
> # big endian
@@ -76,7 +75,7 @@
dummy, data = sstruct.unpack2(eblcHeaderFormat, data, self)
self.strikes = []
- for curStrikeIndex in xrange(self.numSizes):
+ for curStrikeIndex in range(self.numSizes):
curStrike = Strike()
self.strikes.append(curStrike)
curTable = curStrike.bitmapSizeTable
@@ -89,7 +88,7 @@
for curStrike in self.strikes:
curTable = curStrike.bitmapSizeTable
- for subtableIndex in xrange(curTable.numberOfIndexSubTables):
+ for subtableIndex in range(curTable.numberOfIndexSubTables):
lowerBound = curTable.indexSubTableArrayOffset + subtableIndex * indexSubTableArraySize
upperBound = lowerBound + indexSubTableArraySize
data = origData[lowerBound:upperBound]
@@ -171,7 +170,7 @@
indexSubTableDataList = []
for indexSubTable in curStrike.indexSubTables:
indexSubTable.additionalOffsetToIndexSubtable = dataSize - curTable.indexSubTableArrayOffset
- glyphIds = map(ttFont.getGlyphID, indexSubTable.names)
+ glyphIds = list(map(ttFont.getGlyphID, indexSubTable.names))
indexSubTable.firstGlyphIndex = min(glyphIds)
indexSubTable.lastGlyphIndex = max(glyphIds)
data = indexSubTable.compile(ttFont)
@@ -198,7 +197,7 @@
dataList.append(data)
dataList.extend(indexSubTablePairDataList)
- return string.join(dataList, "")
+ return bytesjoin(dataList)
def toXML(self, writer, ttFont):
writer.simpletag('header', [('version', self.version)])
@@ -206,7 +205,7 @@
for curIndex, curStrike in enumerate(self.strikes):
curStrike.toXML(curIndex, writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == 'header':
self.version = safeEval(attrs['version'])
elif name == 'strike':
@@ -214,7 +213,7 @@
self.strikes = []
strikeIndex = safeEval(attrs['index'])
curStrike = Strike()
- curStrike.fromXML((name, attrs, content), ttFont, self)
+ curStrike.fromXML(name, attrs, content, ttFont, self)
# Grow the strike array to the appropriate size. The XML format
# allows for the strike index value to be out of order.
@@ -223,7 +222,7 @@
assert self.strikes[strikeIndex] == None, "Duplicate strike EBLC indices."
self.strikes[strikeIndex] = curStrike
-class Strike:
+class Strike(object):
def __init__(self):
self.bitmapSizeTable = BitmapSizeTable()
@@ -240,23 +239,23 @@
writer.endtag('strike')
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont, locator):
+ def fromXML(self, name, attrs, content, ttFont, locator):
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == 'bitmapSizeTable':
- self.bitmapSizeTable.fromXML(element, ttFont)
+ self.bitmapSizeTable.fromXML(name, attrs, content, ttFont)
elif name.startswith(_indexSubTableSubclassPrefix):
indexFormat = safeEval(name[len(_indexSubTableSubclassPrefix):])
indexFormatClass = locator.getIndexFormatClass(indexFormat)
indexSubTable = indexFormatClass(None, None)
indexSubTable.indexFormat = indexFormat
- indexSubTable.fromXML(element, ttFont)
+ indexSubTable.fromXML(name, attrs, content, ttFont)
self.indexSubTables.append(indexSubTable)
-class BitmapSizeTable:
+class BitmapSizeTable(object):
# Returns all the simple metric names that bitmap size table
# cares about in terms of XML creation.
@@ -277,27 +276,27 @@
writer.endtag('bitmapSizeTable')
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
# Create a lookup for all the simple names that make sense to
# bitmap size table. Only read the information from these names.
dataNames = set(self._getXMLMetricNames())
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == 'sbitLineMetrics':
direction = attrs['direction']
assert direction in ('hori', 'vert'), "SbitLineMetrics direction specified invalid."
metricObj = SbitLineMetrics()
- metricObj.fromXML(element, ttFont)
+ metricObj.fromXML(name, attrs, content, ttFont)
vars(self)[direction] = metricObj
elif name in dataNames:
vars(self)[name] = safeEval(attrs['value'])
else:
- print "Warning: unknown name '%s' being ignored in BitmapSizeTable." % name
+ print("Warning: unknown name '%s' being ignored in BitmapSizeTable." % name)
-class SbitLineMetrics:
+class SbitLineMetrics(object):
def toXML(self, name, writer, ttFont):
writer.begintag('sbitLineMetrics', [('direction', name)])
@@ -308,10 +307,10 @@
writer.endtag('sbitLineMetrics')
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
metricNames = set(sstruct.getformat(sbitLineMetricsFormat)[1])
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name in metricNames:
@@ -320,21 +319,22 @@
# Important information about the naming scheme. Used for identifying subtables.
_indexSubTableSubclassPrefix = 'eblc_index_sub_table_'
-class EblcIndexSubTable:
+class EblcIndexSubTable(object):
def __init__(self, data, ttFont):
self.data = data
self.ttFont = ttFont
- if not ttFont.lazy:
- self.decompile()
- del self.data, self.ttFont
+ # TODO Currently non-lazy decompiling doesn't work for this class...
+ #if not ttFont.lazy:
+ # self.decompile()
+ # del self.data, self.ttFont
def __getattr__(self, attr):
# Allow lazy decompile.
if attr[:2] == '__':
- raise AttributeError, attr
+ raise AttributeError(attr)
if not hasattr(self, "data"):
- raise AttributeError, attr
+ raise AttributeError(attr)
self.decompile()
del self.data, self.ttFont
return getattr(self, attr)
@@ -360,13 +360,13 @@
# For font debugging of consecutive formats the ids are also written.
# The ids are not read when moving from the XML format.
glyphIds = map(ttFont.getGlyphID, self.names)
- for glyphName, glyphId in itertools.izip(self.names, glyphIds):
+ for glyphName, glyphId in zip(self.names, glyphIds):
writer.simpletag('glyphLoc', name=glyphName, id=glyphId)
writer.newline()
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
# Read all the attributes. Even though the glyph indices are
# recalculated, they are still read in case there needs to
# be an immediate export of the data.
@@ -374,11 +374,11 @@
self.firstGlyphIndex = safeEval(attrs['firstGlyphIndex'])
self.lastGlyphIndex = safeEval(attrs['lastGlyphIndex'])
- self.readMetrics((name, attrs, content), ttFont)
+ self.readMetrics(name, attrs, content, ttFont)
self.names = []
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == 'glyphLoc':
@@ -391,7 +391,7 @@
pass
# A helper method that is the inverse of writeMetrics.
- def readMetrics(self, (name, attrs, content), ttFont):
+ def readMetrics(self, name, attrs, content, ttFont):
pass
# This method is for fixed glyph data sizes. There are formats where
@@ -408,11 +408,12 @@
def removeSkipGlyphs(self):
# Determines if a name, location pair is a valid data location.
# Skip glyphs are marked when the size is equal to zero.
- def isValidLocation((name, (startByte, endByte))):
+ def isValidLocation(args):
+ (name, (startByte, endByte)) = args
return startByte < endByte
# Remove all skip glyphs.
- dataPairs = filter(isValidLocation, zip(self.names, self.locations))
- self.names, self.locations = map(list, zip(*dataPairs))
+ dataPairs = list(filter(isValidLocation, zip(self.names, self.locations)))
+ self.names, self.locations = list(map(list, zip(*dataPairs)))
# A closure for creating a custom mixin. This is done because formats 1 and 3
# are very similar. The only difference between them is the size per offset
@@ -423,37 +424,37 @@
dataFormat = '>'+formatStringForDataType
offsetDataSize = struct.calcsize(dataFormat)
- class OffsetArrayIndexSubTableMixin:
+ class OffsetArrayIndexSubTableMixin(object):
def decompile(self):
numGlyphs = self.lastGlyphIndex - self.firstGlyphIndex + 1
- indexingOffsets = [glyphIndex * offsetDataSize for glyphIndex in xrange(numGlyphs+2)]
+ indexingOffsets = [glyphIndex * offsetDataSize for glyphIndex in range(numGlyphs+2)]
indexingLocations = zip(indexingOffsets, indexingOffsets[1:])
offsetArray = [struct.unpack(dataFormat, self.data[slice(*loc)])[0] for loc in indexingLocations]
- glyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
+ glyphIds = list(range(self.firstGlyphIndex, self.lastGlyphIndex+1))
modifiedOffsets = [offset + self.imageDataOffset for offset in offsetArray]
- self.locations = zip(modifiedOffsets, modifiedOffsets[1:])
+ self.locations = list(zip(modifiedOffsets, modifiedOffsets[1:]))
- self.names = map(self.ttFont.getGlyphName, glyphIds)
+ self.names = list(map(self.ttFont.getGlyphName, glyphIds))
self.removeSkipGlyphs()
def compile(self, ttFont):
# First make sure that all the data lines up properly. Formats 1 and 3
# must have all its data lined up consecutively. If not this will fail.
- for curLoc, nxtLoc in itertools.izip(self.locations, self.locations[1:]):
+ for curLoc, nxtLoc in zip(self.locations, self.locations[1:]):
assert curLoc[1] == nxtLoc[0], "Data must be consecutive in indexSubTable offset formats"
- glyphIds = map(ttFont.getGlyphID, self.names)
+ glyphIds = list(map(ttFont.getGlyphID, self.names))
# Make sure that all ids are sorted strictly increasing.
- assert all(glyphIds[i] < glyphIds[i+1] for i in xrange(len(glyphIds)-1))
+ assert all(glyphIds[i] < glyphIds[i+1] for i in range(len(glyphIds)-1))
# Run a simple algorithm to add skip glyphs to the data locations at
# the places where an id is not present.
idQueue = deque(glyphIds)
locQueue = deque(self.locations)
- allGlyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
+ allGlyphIds = list(range(self.firstGlyphIndex, self.lastGlyphIndex+1))
allLocations = []
for curId in allGlyphIds:
if curId != idQueue[0]:
@@ -477,38 +478,38 @@
# Take care of any padding issues. Only occurs in format 3.
if offsetDataSize * len(dataList) % 4 != 0:
dataList.append(struct.pack(dataFormat, 0))
- return string.join(dataList, "")
+ return bytesjoin(dataList)
return OffsetArrayIndexSubTableMixin
# A Mixin for functionality shared between the different kinds
# of fixed sized data handling. Both kinds have big metrics so
# that kind of special processing is also handled in this mixin.
-class FixedSizeIndexSubTableMixin:
+class FixedSizeIndexSubTableMixin(object):
def writeMetrics(self, writer, ttFont):
writer.simpletag('imageSize', value=self.imageSize)
writer.newline()
self.metrics.toXML(writer, ttFont)
- def readMetrics(self, (name, attrs, content), ttFont):
+ def readMetrics(self, name, attrs, content, ttFont):
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == 'imageSize':
self.imageSize = safeEval(attrs['value'])
elif name == BigGlyphMetrics.__name__:
self.metrics = BigGlyphMetrics()
- self.metrics.fromXML(element, ttFont)
+ self.metrics.fromXML(name, attrs, content, ttFont)
elif name == SmallGlyphMetrics.__name__:
- print "Warning: SmallGlyphMetrics being ignored in format %d." % self.indexFormat
+ print("Warning: SmallGlyphMetrics being ignored in format %d." % self.indexFormat)
def padBitmapData(self, data):
# Make sure that the data isn't bigger than the fixed size.
assert len(data) <= self.imageSize, "Data in indexSubTable format %d must be less than the fixed size." % self.indexFormat
# Pad the data so that it matches the fixed size.
- pad = (self.imageSize - len(data)) * '\0'
+ pad = (self.imageSize - len(data)) * b'\0'
return data + pad
class eblc_index_sub_table_1(_createOffsetArrayIndexSubTableMixin('L'), EblcIndexSubTable):
@@ -520,21 +521,21 @@
(self.imageSize,) = struct.unpack(">L", self.data[:4])
self.metrics = BigGlyphMetrics()
sstruct.unpack2(bigGlyphMetricsFormat, self.data[4:], self.metrics)
- glyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
- offsets = [self.imageSize * i + self.imageDataOffset for i in xrange(len(glyphIds)+1)]
- self.locations = zip(offsets, offsets[1:])
- self.names = map(self.ttFont.getGlyphName, glyphIds)
+ glyphIds = list(range(self.firstGlyphIndex, self.lastGlyphIndex+1))
+ offsets = [self.imageSize * i + self.imageDataOffset for i in range(len(glyphIds)+1)]
+ self.locations = list(zip(offsets, offsets[1:]))
+ self.names = list(map(self.ttFont.getGlyphName, glyphIds))
def compile(self, ttFont):
- glyphIds = map(ttFont.getGlyphID, self.names)
+ glyphIds = list(map(ttFont.getGlyphID, self.names))
# Make sure all the ids are consecutive. This is required by Format 2.
- assert glyphIds == range(self.firstGlyphIndex, self.lastGlyphIndex+1), "Format 2 ids must be consecutive."
+ assert glyphIds == list(range(self.firstGlyphIndex, self.lastGlyphIndex+1)), "Format 2 ids must be consecutive."
self.imageDataOffset = min(zip(*self.locations)[0])
dataList = [EblcIndexSubTable.compile(self, ttFont)]
dataList.append(struct.pack(">L", self.imageSize))
dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
- return string.join(dataList, "")
+ return bytesjoin(dataList)
class eblc_index_sub_table_3(_createOffsetArrayIndexSubTableMixin('H'), EblcIndexSubTable):
pass
@@ -545,21 +546,21 @@
(numGlyphs,) = struct.unpack(">L", self.data[:4])
data = self.data[4:]
- indexingOffsets = [glyphIndex * codeOffsetPairSize for glyphIndex in xrange(numGlyphs+2)]
+ indexingOffsets = [glyphIndex * codeOffsetPairSize for glyphIndex in range(numGlyphs+2)]
indexingLocations = zip(indexingOffsets, indexingOffsets[1:])
glyphArray = [struct.unpack(codeOffsetPairFormat, data[slice(*loc)]) for loc in indexingLocations]
- glyphIds, offsets = map(list, zip(*glyphArray))
+ glyphIds, offsets = list(map(list, zip(*glyphArray)))
# There are one too many glyph ids. Get rid of the last one.
glyphIds.pop()
offsets = [offset + self.imageDataOffset for offset in offsets]
- self.locations = zip(offsets, offsets[1:])
- self.names = map(self.ttFont.getGlyphName, glyphIds)
+ self.locations = list(zip(offsets, offsets[1:]))
+ self.names = list(map(self.ttFont.getGlyphName, glyphIds))
def compile(self, ttFont):
# First make sure that all the data lines up properly. Format 4
# must have all its data lined up consecutively. If not this will fail.
- for curLoc, nxtLoc in itertools.izip(self.locations, self.locations[1:]):
+ for curLoc, nxtLoc in zip(self.locations, self.locations[1:]):
assert curLoc[1] == nxtLoc[0], "Data must be consecutive in indexSubTable format 4"
offsets = list(self.locations[0]) + [loc[1] for loc in self.locations[1:]]
@@ -568,15 +569,15 @@
# and allows imageDataOffset to not be required to be in the XML version.
self.imageDataOffset = min(offsets)
offsets = [offset - self.imageDataOffset for offset in offsets]
- glyphIds = map(ttFont.getGlyphID, self.names)
+ glyphIds = list(map(ttFont.getGlyphID, self.names))
# Create an iterator over the ids plus a padding value.
idsPlusPad = list(itertools.chain(glyphIds, [0]))
dataList = [EblcIndexSubTable.compile(self, ttFont)]
dataList.append(struct.pack(">L", len(glyphIds)))
- tmp = [struct.pack(codeOffsetPairFormat, *cop) for cop in itertools.izip(idsPlusPad, offsets)]
+ tmp = [struct.pack(codeOffsetPairFormat, *cop) for cop in zip(idsPlusPad, offsets)]
dataList += tmp
- data = string.join(dataList, "")
+ data = bytesjoin(dataList)
return data
class eblc_index_sub_table_5(FixedSizeIndexSubTableMixin, EblcIndexSubTable):
@@ -588,23 +589,23 @@
self.metrics, data = sstruct.unpack2(bigGlyphMetricsFormat, data, BigGlyphMetrics())
(numGlyphs,) = struct.unpack(">L", data[:4])
data = data[4:]
- glyphIds = [struct.unpack(">H", data[2*i:2*(i+1)])[0] for i in xrange(numGlyphs)]
+ glyphIds = [struct.unpack(">H", data[2*i:2*(i+1)])[0] for i in range(numGlyphs)]
- offsets = [self.imageSize * i + self.imageDataOffset for i in xrange(len(glyphIds)+1)]
- self.locations = zip(offsets, offsets[1:])
- self.names = map(self.ttFont.getGlyphName, glyphIds)
+ offsets = [self.imageSize * i + self.imageDataOffset for i in range(len(glyphIds)+1)]
+ self.locations = list(zip(offsets, offsets[1:]))
+ self.names = list(map(self.ttFont.getGlyphName, glyphIds))
def compile(self, ttFont):
self.imageDataOffset = min(zip(*self.locations)[0])
dataList = [EblcIndexSubTable.compile(self, ttFont)]
dataList.append(struct.pack(">L", self.imageSize))
dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
- glyphIds = map(ttFont.getGlyphID, self.names)
+ glyphIds = list(map(ttFont.getGlyphID, self.names))
dataList.append(struct.pack(">L", len(glyphIds)))
dataList += [struct.pack(">H", curId) for curId in glyphIds]
if len(glyphIds) % 2 == 1:
dataList.append(struct.pack(">H", 0))
- return string.join(dataList, "")
+ return bytesjoin(dataList)
# Dictionary of indexFormat to the class representing that format.
eblc_sub_table_classes = {
diff --git a/Lib/fontTools/ttLib/tables/G_D_E_F_.py b/Lib/fontTools/ttLib/tables/G_D_E_F_.py
index d763a5d..d4a5741 100644
--- a/Lib/fontTools/ttLib/tables/G_D_E_F_.py
+++ b/Lib/fontTools/ttLib/tables/G_D_E_F_.py
@@ -1,4 +1,4 @@
-from otBase import BaseTTXConverter
+from .otBase import BaseTTXConverter
class table_G_D_E_F_(BaseTTXConverter):
diff --git a/Lib/fontTools/ttLib/tables/G_M_A_P_.py b/Lib/fontTools/ttLib/tables/G_M_A_P_.py
index c4f64f9..6e8b322 100644
--- a/Lib/fontTools/ttLib/tables/G_M_A_P_.py
+++ b/Lib/fontTools/ttLib/tables/G_M_A_P_.py
@@ -1,7 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-from types import StringType
-from fontTools.misc.textTools import safeEval, num2binary, binary2num
+from fontTools.misc.textTools import safeEval
+from . import DefaultTable
GMAPFormat = """
> # big endian
@@ -26,7 +27,7 @@
-class GMAPRecord:
+class GMAPRecord(object):
def __init__(self, uv = 0, cid = 0, gid = 0, ggid = 0, name = ""):
self.UV = uv
self.cid = cid
@@ -51,16 +52,12 @@
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
value = attrs["value"]
if name == "GlyphletName":
self.name = value
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
def compile(self, ttFont):
@@ -82,7 +79,7 @@
def decompile(self, data, ttFont):
dummy, newData = sstruct.unpack2(GMAPFormat, data, self)
- self.psFontName = newData[:self.fontNameLength]
+ self.psFontName = tostr(newData[:self.fontNameLength])
assert (self.recordsOffset % 4) == 0, "GMAP error: recordsOffset is not 32 bit aligned."
newData = data[self.recordsOffset:]
self.gmapRecords = []
@@ -95,10 +92,10 @@
def compile(self, ttFont):
self.recordsCount = len(self.gmapRecords)
self.fontNameLength = len(self.psFontName)
- self.recordsOffset = 4 *(((self.fontNameLength + 12) + 3) /4)
+ self.recordsOffset = 4 *(((self.fontNameLength + 12) + 3) // 4)
data = sstruct.pack(GMAPFormat, self)
- data = data + self.psFontName
- data = data + "\0" * (self.recordsOffset - len(data))
+ data = data + tobytes(self.psFontName)
+ data = data + b"\0" * (self.recordsOffset - len(data))
for record in self.gmapRecords:
data = data + record.compile(ttFont)
return data
@@ -117,23 +114,20 @@
for gmapRecord in self.gmapRecords:
gmapRecord.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "GMAPRecord":
if not hasattr(self, "gmapRecords"):
self.gmapRecords = []
gmapRecord = GMAPRecord()
self.gmapRecords.append(gmapRecord)
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
- gmapRecord.fromXML(element, ttFont)
+ name, attrs, content = element
+ gmapRecord.fromXML(name, attrs, content, ttFont)
else:
value = attrs["value"]
if name == "PSFontName":
self.psFontName = value
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
diff --git a/Lib/fontTools/ttLib/tables/G_P_K_G_.py b/Lib/fontTools/ttLib/tables/G_P_K_G_.py
index 6321093..4acccaa 100644
--- a/Lib/fontTools/ttLib/tables/G_P_K_G_.py
+++ b/Lib/fontTools/ttLib/tables/G_P_K_G_.py
@@ -1,10 +1,10 @@
-import sys
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import array
-from types import StringType
from fontTools.misc.textTools import safeEval, readHex
-from fontTools import ttLib
+from . import DefaultTable
+import sys
+import array
GPKGFormat = """
> # big endian
@@ -25,7 +25,7 @@
GMAPoffsets = array.array("I")
endPos = (self.numGMAPs+1) * 4
GMAPoffsets.fromstring(newData[:endPos])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
GMAPoffsets.byteswap()
self.GMAPs = []
for i in range(self.numGMAPs):
@@ -36,7 +36,7 @@
endPos = pos + (self.numGlyplets + 1)*4
glyphletOffsets = array.array("I")
glyphletOffsets.fromstring(newData[pos:endPos])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
glyphletOffsets.byteswap()
self.glyphlets = []
for i in range(self.numGlyplets):
@@ -59,7 +59,7 @@
pos += len(self.GMAPs[i-1])
GMAPoffsets[i] = pos
gmapArray = array.array("I", GMAPoffsets)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
gmapArray.byteswap()
dataList.append(gmapArray.tostring())
@@ -68,12 +68,12 @@
pos += len(self.glyphlets[i-1])
glyphletOffsets[i] = pos
glyphletArray = array.array("I", glyphletOffsets)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
glyphletArray.byteswap()
dataList.append(glyphletArray.tostring())
dataList += self.GMAPs
dataList += self.glyphlets
- data = "".join(dataList)
+ data = bytesjoin(dataList)
return data
def toXML(self, writer, ttFont):
@@ -107,12 +107,12 @@
writer.endtag("glyphlets")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "GMAPs":
if not hasattr(self, "GMAPs"):
self.GMAPs = []
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
itemName, itemAttrs, itemContent = element
if itemName == "hexdata":
@@ -121,15 +121,10 @@
if not hasattr(self, "glyphlets"):
self.glyphlets = []
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
itemName, itemAttrs, itemContent = element
if itemName == "hexdata":
self.glyphlets.append(readHex(itemContent))
else:
- value = attrs["value"]
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
diff --git a/Lib/fontTools/ttLib/tables/G_P_O_S_.py b/Lib/fontTools/ttLib/tables/G_P_O_S_.py
index 52f44d4..013c820 100644
--- a/Lib/fontTools/ttLib/tables/G_P_O_S_.py
+++ b/Lib/fontTools/ttLib/tables/G_P_O_S_.py
@@ -1,4 +1,4 @@
-from otBase import BaseTTXConverter
+from .otBase import BaseTTXConverter
class table_G_P_O_S_(BaseTTXConverter):
diff --git a/Lib/fontTools/ttLib/tables/G_S_U_B_.py b/Lib/fontTools/ttLib/tables/G_S_U_B_.py
index a523c59..4403649 100644
--- a/Lib/fontTools/ttLib/tables/G_S_U_B_.py
+++ b/Lib/fontTools/ttLib/tables/G_S_U_B_.py
@@ -1,4 +1,4 @@
-from otBase import BaseTTXConverter
+from .otBase import BaseTTXConverter
class table_G_S_U_B_(BaseTTXConverter):
diff --git a/Lib/fontTools/ttLib/tables/J_S_T_F_.py b/Lib/fontTools/ttLib/tables/J_S_T_F_.py
index 8ff395e..ddf5405 100644
--- a/Lib/fontTools/ttLib/tables/J_S_T_F_.py
+++ b/Lib/fontTools/ttLib/tables/J_S_T_F_.py
@@ -1,4 +1,4 @@
-from otBase import BaseTTXConverter
+from .otBase import BaseTTXConverter
class table_J_S_T_F_(BaseTTXConverter):
diff --git a/Lib/fontTools/ttLib/tables/L_T_S_H_.py b/Lib/fontTools/ttLib/tables/L_T_S_H_.py
index 6cd5aad..453f08b 100644
--- a/Lib/fontTools/ttLib/tables/L_T_S_H_.py
+++ b/Lib/fontTools/ttLib/tables/L_T_S_H_.py
@@ -1,7 +1,9 @@
-import DefaultTable
-import array
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
+import struct
+import array
# XXX I've lowered the strictness, to make sure Apple's own Chicago
# XXX gets through. They're looking into it, I hope to raise the standards
@@ -24,7 +26,7 @@
def compile(self, ttFont):
version = 0
- names = self.yPels.keys()
+ names = list(self.yPels.keys())
numGlyphs = len(names)
yPels = [0] * numGlyphs
# ouch: the assertion is not true in Chicago!
@@ -35,16 +37,15 @@
return struct.pack(">HH", version, numGlyphs) + yPels.tostring()
def toXML(self, writer, ttFont):
- names = self.yPels.keys()
- names.sort()
+ names = sorted(self.yPels.keys())
for name in names:
writer.simpletag("yPel", name=name, value=self.yPels[name])
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "yPels"):
self.yPels = {}
- if name <> "yPel":
+ if name != "yPel":
return # ignore unknown tags
self.yPels[attrs["name"]] = safeEval(attrs["value"])
diff --git a/Lib/fontTools/ttLib/tables/M_E_T_A_.py b/Lib/fontTools/ttLib/tables/M_E_T_A_.py
index b8fb640..0a3a708 100644
--- a/Lib/fontTools/ttLib/tables/M_E_T_A_.py
+++ b/Lib/fontTools/ttLib/tables/M_E_T_A_.py
@@ -1,10 +1,11 @@
-import DefaultTable
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
-import string
-from types import FloatType, ListType, StringType, TupleType
-import sys
+from . import DefaultTable
+import struct
+
+
METAHeaderFormat = """
> # big endian
tableVersionMajor: H
@@ -166,28 +167,24 @@
for glyphRec in self.glyphRecords:
glyphRec.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "GlyphRecord":
if not hasattr(self, "glyphRecords"):
self.glyphRecords = []
glyphRec = GlyphRecord()
self.glyphRecords.append(glyphRec)
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
- glyphRec.fromXML(element, ttFont)
+ name, attrs, content = element
+ glyphRec.fromXML(name, attrs, content, ttFont)
glyphRec.offset = -1
glyphRec.nMetaEntry = len(glyphRec.stringRecs)
else:
- value = attrs["value"]
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(attrs["value"]))
-class GlyphRecord:
+class GlyphRecord(object):
def __init__(self):
self.glyphID = -1
self.nMetaEntry = -1
@@ -207,22 +204,17 @@
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "StringRecord":
stringRec = StringRecord()
self.stringRecs.append(stringRec)
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
- stringRec.fromXML(element, ttFont)
+ stringRec.fromXML(name, attrs, content, ttFont)
stringRec.stringLen = len(stringRec.string)
else:
- value = attrs["value"]
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(attrs["value"]))
def compile(self, parentTable):
data = sstruct.pack(METAGlyphRecordFormat, self)
@@ -232,23 +224,14 @@
datum = struct.pack(">L", self.offset)
data = data + datum
return data
-
-
- def __cmp__(self, other):
- """Compare method, so a list of NameRecords can be sorted
- according to the spec by just sorting it..."""
-
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.glyphID, other.glyphID)
def __repr__(self):
return "GlyphRecord[ glyphID: " + str(self.glyphID) + ", nMetaEntry: " + str(self.nMetaEntry) + ", offset: " + str(self.offset) + " ]"
+# XXX The following two functions are really broken around UTF-8 vs Unicode
def mapXMLToUTF8(string):
- uString = u""
+ uString = unicode()
strLen = len(string)
i = 0
while i < strLen:
@@ -266,7 +249,7 @@
uString = uString + unichr(eval('0x' + valStr))
else:
- uString = uString + unichr(ord(string[i]))
+ uString = uString + unichr(byteord(string[i]))
i = i +1
return uString.encode('utf8')
@@ -278,18 +261,13 @@
for uChar in uString:
i = ord(uChar)
if (i < 0x80) and (i > 0x1F):
- string = string + chr(i)
+ string = string + uChar
else:
string = string + "&#x" + hex(i)[2:] + ";"
return string
-class StringRecord:
- def __init__(self):
- self.labelID = -1
- self.string = ""
- self.stringLen = -1
- self.offset = -1
+class StringRecord(object):
def toXML(self, writer, ttFont):
writer.begintag("StringRecord")
@@ -303,16 +281,16 @@
writer.endtag("StringRecord")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- value = attrs["value"]
- if name == "string":
- self.string = mapXMLToUTF8(value)
- else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ def fromXML(self, name, attrs, content, ttFont):
+ for element in content:
+ if isinstance(element, basestring):
+ continue
+ name, attrs, content = element
+ value = attrs["value"]
+ if name == "string":
+ self.string = mapXMLToUTF8(value)
+ else:
+ setattr(self, name, safeEval(value))
def compile(self, parentTable):
data = sstruct.pack(METAStringRecordFormat, self)
@@ -322,15 +300,6 @@
datum = struct.pack(">L", self.offset)
data = data + datum
return data
-
- def __cmp__(self, other):
- """Compare method, so a list of NameRecords can be sorted
- according to the spec by just sorting it..."""
-
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.labelID, other.labelID)
def __repr__(self):
return "StringRecord [ labelID: " + str(self.labelID) + " aka " + getLabelString(self.labelID) \
diff --git a/Lib/fontTools/ttLib/tables/O_S_2f_2.py b/Lib/fontTools/ttLib/tables/O_S_2f_2.py
index eb3cb01..f678c17 100644
--- a/Lib/fontTools/ttLib/tables/O_S_2f_2.py
+++ b/Lib/fontTools/ttLib/tables/O_S_2f_2.py
@@ -1,7 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval, num2binary, binary2num
-from types import TupleType
+from . import DefaultTable
import warnings
@@ -20,7 +21,7 @@
bXHeight: B
"""
-class Panose:
+class Panose(object):
def toXML(self, writer, ttFont):
formatstring, names, fixes = sstruct.getformat(panoseFormat)
@@ -28,7 +29,7 @@
writer.simpletag(name, value=getattr(self, name))
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
setattr(self, name, safeEval(attrs["value"]))
@@ -109,11 +110,11 @@
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:
+ 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
+ raise ttLib.TTLibError("unknown format for OS/2 table: version %s" % self.version)
if len(data):
warnings.warn("too much 'OS/2' table data")
@@ -135,7 +136,7 @@
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
+ raise ttLib.TTLibError("unknown format for OS/2 table: version %s" % self.version)
self.panose = panose
return data
@@ -151,8 +152,6 @@
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()
@@ -170,12 +169,13 @@
writer.simpletag(name, value=value)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ 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)
+ if isinstance(element, tuple):
+ name, attrs, content = element
+ panose.fromXML(name, attrs, content, ttFont)
elif name in ("ulUnicodeRange1", "ulUnicodeRange2",
"ulUnicodeRange3", "ulUnicodeRange4",
"ulCodePageRange1", "ulCodePageRange2",
diff --git a/Lib/fontTools/ttLib/tables/S_I_N_G_.py b/Lib/fontTools/ttLib/tables/S_I_N_G_.py
index 3f76c93..6d9a412 100644
--- a/Lib/fontTools/ttLib/tables/S_I_N_G_.py
+++ b/Lib/fontTools/ttLib/tables/S_I_N_G_.py
@@ -1,9 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import struct
-import time
-import string
-from fontTools.misc.textTools import safeEval, num2binary, binary2num
+from fontTools.misc.textTools import safeEval
+from . import DefaultTable
SINGFormat = """
> # big endian
@@ -30,52 +29,53 @@
def decompile(self, data, ttFont):
dummy, rest = sstruct.unpack2(SINGFormat, data, self)
self.uniqueName = self.decompileUniqueName(self.uniqueName)
- self.nameLength = ord(self.nameLength)
+ self.nameLength = byteord(self.nameLength)
assert len(rest) == self.nameLength
- self.baseGlyphName = rest
+ self.baseGlyphName = tostr(rest)
rawMETAMD5 = self.METAMD5
- self.METAMD5 = "[" + hex(ord(self.METAMD5[0]))
+ self.METAMD5 = "[" + hex(byteord(self.METAMD5[0]))
for char in rawMETAMD5[1:]:
- self.METAMD5 = self.METAMD5 + ", " + hex(ord(char))
+ self.METAMD5 = self.METAMD5 + ", " + hex(byteord(char))
self.METAMD5 = self.METAMD5 + "]"
def decompileUniqueName(self, data):
name = ""
for char in data:
- val = ord(char)
+ val = byteord(char)
if val == 0:
break
if (val > 31) or (val < 128):
- name = name + char
+ name += chr(val)
else:
octString = oct(val)
if len(octString) > 3:
octString = octString[1:] # chop off that leading zero.
elif len(octString) < 3:
octString.zfill(3)
- name = name + "\\" + octString
+ name += "\\" + octString
return name
def compile(self, ttFont):
- self.nameLength = chr(len(self.baseGlyphName))
- self.uniqueName = self.compilecompileUniqueName(self.uniqueName, 28)
+ d = self.__dict__.copy()
+ d["nameLength"] = bytechr(len(self.baseGlyphName))
+ d["uniqueName"] = self.compilecompileUniqueName(self.uniqueName, 28)
METAMD5List = eval(self.METAMD5)
- self.METAMD5 = ""
+ d["METAMD5"] = b""
for val in METAMD5List:
- self.METAMD5 = self.METAMD5 + chr(val)
- assert (len(self.METAMD5) == 16), "Failed to pack 16 byte MD5 hash in SING table"
- data = sstruct.pack(SINGFormat, self)
- data = data + self.baseGlyphName
+ d["METAMD5"] += bytechr(val)
+ assert (len(d["METAMD5"]) == 16), "Failed to pack 16 byte MD5 hash in SING table"
+ data = sstruct.pack(SINGFormat, d)
+ data = data + tobytes(self.baseGlyphName)
return data
def compilecompileUniqueName(self, name, length):
nameLen = len(name)
if length <= nameLen:
- name[:length-1] + "\000"
+ name = name[:length-1] + "\000"
else:
- name.join( (nameLen - length)* "\000")
+ name += (nameLen - length) * "\000"
return name
@@ -90,13 +90,9 @@
writer.simpletag("baseGlyphName", value=self.baseGlyphName)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
value = attrs["value"]
if name in ["uniqueName", "METAMD5", "baseGlyphName"]:
setattr(self, name, value)
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
diff --git a/Lib/fontTools/ttLib/tables/S_V_G_.py b/Lib/fontTools/ttLib/tables/S_V_G_.py
index 84e77ad..8d04811 100644
--- a/Lib/fontTools/ttLib/tables/S_V_G_.py
+++ b/Lib/fontTools/ttLib/tables/S_V_G_.py
@@ -1,3 +1,14 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc import sstruct
+from . import DefaultTable
+try:
+ import xml.etree.cElementTree as ET
+except ImportError:
+ import xml.etree.ElementTree as ET
+import struct
+import re
+
__doc__="""
Compiles/decompiles version 0 and 1 SVG tables from/to XML.
@@ -42,18 +53,6 @@
"""
-import DefaultTable
-import struct
-from fontTools.misc import sstruct
-from fontTools.misc.textTools import safeEval
-try:
- import xml.etree.cElementTree as ET
-except ImportError:
- import xml.etree.ElementTree as ET
-import string
-import types
-import re
-
XML = ET.XML
XMLElement = ET.Element
xmlToString = ET.tostring
@@ -105,7 +104,7 @@
self.decompile_format_1(data, ttFont)
else:
if self.version != 0:
- print "Unknown SVG table version '%s'. Decompiling as version 0." % (self.version)
+ print("Unknown SVG table version '%s'. Decompiling as version 0." % (self.version))
self.decompile_format_0(data, ttFont)
@@ -172,7 +171,7 @@
for entry in entries:
start = entry.svgDocOffset + subTableStart
end = start + entry.svgDocLength
- doc = data[start:end]
+ doc = tostr(data[start:end], "utf-8")
self.docList.append( [doc, entry.startGlyphID, entry.endGlyphID] )
def compile(self, ttFont):
@@ -196,11 +195,11 @@
docOffset = curOffset
docLength = len(doc)
curOffset += docLength
- entry = struct.pack(">HHLL", startGlyphID, endGlyphID, docOffset, docLength)
- entryList.append(entry)
- docList.append(doc)
+ entry = struct.pack(">HHLL", startGlyphID, endGlyphID, docOffset, docLength)
+ entryList.append(entry)
+ docList.append(tobytes(doc, encoding="utf-8"))
entryList.extend(docList)
- svgDocData = "".join(entryList)
+ svgDocData = bytesjoin(entryList)
# get colorpalette info.
if self.colorPalettes == None:
@@ -224,11 +223,11 @@
for colorRecord in colorPalette.paletteColors:
data = struct.pack(">BBBB", colorRecord.red, colorRecord.green, colorRecord.blue, colorRecord.alpha)
dataList.append(data)
- palettesData = "".join(dataList)
+ palettesData = bytesjoin(dataList)
header = struct.pack(">HLL", version, offsetToSVGDocIndex, offsetToColorPalettes)
data = [header, svgDocData, palettesData]
- data = "".join(data)
+ data = bytesjoin(data)
return data
def compileFormat1(self, ttFont):
@@ -242,11 +241,11 @@
docOffset = curOffset
docLength = len(doc)
curOffset += docLength
- entry = struct.pack(">HHLL", startGlyphID, endGlyphID, docOffset, docLength)
- dataList.append(entry)
- docList.append(doc)
+ entry = struct.pack(">HHLL", startGlyphID, endGlyphID, docOffset, docLength)
+ dataList.append(entry)
+ docList.append(tobytes(doc, encoding="utf-8"))
dataList.extend(docList)
- data = "".join(dataList)
+ data = bytesjoin(dataList)
return data
def toXML(self, writer, ttFont):
@@ -254,7 +253,7 @@
for doc, startGID, endGID in self.docList:
writer.begintag("svgDoc", startGlyphID=startGID, endGlyphID=endGID)
writer.newline()
- writer.writeraw("<![CDATA["+ doc + "]]>")
+ writer.writecdata(doc)
writer.newline()
writer.endtag("svgDoc")
writer.newline()
@@ -290,25 +289,25 @@
writer.endtag("colorPalettes")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
import re
if name == "svgDoc":
if not hasattr(self, "docList"):
self.docList = []
- doc = "".join(content)
+ doc = strjoin(content)
doc = doc.strip()
startGID = int(attrs["startGlyphID"])
endGID = int(attrs["endGlyphID"])
self.docList.append( [doc, startGID, endGID] )
elif name == "colorPalettes":
self.colorPalettes = ColorPalettes()
- self.colorPalettes.fromXML((name, attrs, content), ttFont)
+ self.colorPalettes.fromXML(name, attrs, content, ttFont)
if self.colorPalettes.numColorParams == 0:
self.colorPalettes = None
else:
- print "Unknown", name, content
+ print("Unknown", name, content)
-class DocumentIndexEntry:
+class DocumentIndexEntry(object):
def __init__(self):
self.startGlyphID = None # USHORT
self.endGlyphID = None # USHORT
@@ -318,16 +317,16 @@
def __repr__(self):
return "startGlyphID: %s, endGlyphID: %s, svgDocOffset: %s, svgDocLength: %s" % (self.startGlyphID, self.endGlyphID, self.svgDocOffset, self.svgDocLength)
-class ColorPalettes:
+class ColorPalettes(object):
def __init__(self):
self.numColorParams = None # USHORT
self.colorParamUINameIDs = [] # list of name table name ID values that provide UI description of each color palette.
self.numColorPalettes = None # USHORT
self.colorPaletteList = [] # list of ColorPalette records
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
for element in content:
- if type(element) == type(""):
+ if isinstance(element, type("")):
continue
name, attrib, content = element
if name == "colorParamUINameID":
@@ -344,15 +343,15 @@
if len(colorPalette.paletteColors) != self.numColorParams:
raise ValueError("Number of color records in a colorPalette ('%s') does not match the number of colorParamUINameIDs elements ('%s')." % (len(colorPalette.paletteColors), self.numColorParams))
-class ColorPalette:
+class ColorPalette(object):
def __init__(self):
self.uiNameID = None # USHORT. name table ID that describes user interface strings associated with this color palette.
self.paletteColors = [] # list of ColorRecords
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.uiNameID = int(attrs["uiNameID"])
for element in content:
- if type(element) == type(""):
+ if isinstance(element, type("")):
continue
name, attrib, content = element
if name == "colorRecord":
@@ -363,7 +362,7 @@
colorRecord.blue = eval(attrib["blue"])
colorRecord.alpha = eval(attrib["alpha"])
-class ColorRecord:
+class ColorRecord(object):
def __init__(self):
self.red = 255 # all are one byte values.
self.green = 255
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_B_.py b/Lib/fontTools/ttLib/tables/T_S_I_B_.py
index 31608f8..5cc54e2 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_B_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_B_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_B_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_D_.py b/Lib/fontTools/ttLib/tables/T_S_I_D_.py
index 0388405..8228f8a 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_D_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_D_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_D_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_J_.py b/Lib/fontTools/ttLib/tables/T_S_I_J_.py
index 8f6ed8b..0983b57 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_J_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_J_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_J_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_P_.py b/Lib/fontTools/ttLib/tables/T_S_I_P_.py
index f0de28d..e34a18c 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_P_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_P_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_P_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_S_.py b/Lib/fontTools/ttLib/tables/T_S_I_S_.py
index fc98317..56373e6 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_S_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_S_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_S_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I_V_.py b/Lib/fontTools/ttLib/tables/T_S_I_V_.py
index 928b7ce..a87e3f7 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I_V_.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I_V_.py
@@ -1,4 +1,4 @@
-import asciiTable
+from . import asciiTable
class table_T_S_I_V_(asciiTable.asciiTable):
pass
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__0.py b/Lib/fontTools/ttLib/tables/T_S_I__0.py
index c527818..44214f7 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I__0.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I__0.py
@@ -1,9 +1,11 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from . import DefaultTable
import struct
tsi0Format = '>HHl'
-def fixlongs((glyphID, textLength, textOffset)):
+def fixlongs(glyphID, textLength, textOffset):
return int(glyphID), int(textLength), textOffset
@@ -16,7 +18,7 @@
indices = []
size = struct.calcsize(tsi0Format)
for i in range(numGlyphs + 5):
- glyphID, textLength, textOffset = fixlongs(struct.unpack(tsi0Format, data[:size]))
+ glyphID, textLength, textOffset = fixlongs(*struct.unpack(tsi0Format, data[:size]))
indices.append((glyphID, textLength, textOffset))
data = data[size:]
assert len(data) == 0
@@ -29,7 +31,7 @@
# We have no corresponging table (TSI1 or TSI3); let's return
# no data, which effectively means "ignore us".
return ""
- data = ""
+ data = b""
for index, textLength, textOffset in self.indices:
data = data + struct.pack(tsi0Format, index, textLength, textOffset)
data = data + struct.pack(tsi0Format, 0XFFFE, 0, -1409540300) # 0xABFC1F34
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__1.py b/Lib/fontTools/ttLib/tables/T_S_I__1.py
index fa6f7fe..bcb4049 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I__1.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I__1.py
@@ -1,5 +1,6 @@
-import DefaultTable
-import string
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from . import DefaultTable
class table_T_S_I__1(DefaultTable.DefaultTable):
@@ -39,19 +40,19 @@
if not hasattr(self, "glyphPrograms"):
self.glyphPrograms = {}
self.extraPrograms = {}
- data = ''
+ data = b''
indextable = ttFont[self.indextable]
glyphNames = ttFont.getGlyphOrder()
indices = []
for i in range(len(glyphNames)):
if len(data) % 2:
- data = data + "\015" # align on 2-byte boundaries, fill with return chars. Yum.
+ data = data + b"\015" # align on 2-byte boundaries, fill with return chars. Yum.
name = glyphNames[i]
- if self.glyphPrograms.has_key(name):
+ if name in self.glyphPrograms:
text = self.glyphPrograms[name]
else:
- text = ""
+ text = b""
textLength = len(text)
if textLength >= 0x8000:
textLength = 0x8000 # XXX ???
@@ -59,16 +60,15 @@
data = data + text
extra_indices = []
- codes = self.extras.items()
- codes.sort()
+ codes = sorted(self.extras.items())
for i in range(len(codes)):
if len(data) % 2:
- data = data + "\015" # align on 2-byte boundaries, fill with return chars.
+ data = data + b"\015" # align on 2-byte boundaries, fill with return chars.
code, name = codes[i]
- if self.extraPrograms.has_key(name):
+ if name in self.extraPrograms:
text = self.extraPrograms[name]
else:
- text = ""
+ text = b""
textLength = len(text)
if textLength >= 0x8000:
textLength = 0x8000 # XXX ???
@@ -78,8 +78,7 @@
return data
def toXML(self, writer, ttFont):
- names = self.glyphPrograms.keys()
- names.sort()
+ names = sorted(self.glyphPrograms.keys())
writer.newline()
for name in names:
text = self.glyphPrograms[name]
@@ -87,31 +86,30 @@
continue
writer.begintag("glyphProgram", name=name)
writer.newline()
- writer.write_noindent(string.replace(text, "\r", "\n"))
+ writer.write_noindent(text.replace("\r", "\n"))
writer.newline()
writer.endtag("glyphProgram")
writer.newline()
writer.newline()
- extra_names = self.extraPrograms.keys()
- extra_names.sort()
+ extra_names = sorted(self.extraPrograms.keys())
for name in extra_names:
text = self.extraPrograms[name]
if not text:
continue
writer.begintag("extraProgram", name=name)
writer.newline()
- writer.write_noindent(string.replace(text, "\r", "\n"))
+ writer.write_noindent(text.replace("\r", "\n"))
writer.newline()
writer.endtag("extraProgram")
writer.newline()
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "glyphPrograms"):
self.glyphPrograms = {}
self.extraPrograms = {}
- lines = string.split(string.replace(string.join(content, ""), "\r", "\n"), "\n")
- text = string.join(lines[1:-1], "\r")
+ lines = strjoin(content).replace("\r", "\n").split("\n")
+ text = '\r'.join(lines[1:-1])
if name == "glyphProgram":
self.glyphPrograms[attrs["name"]] = text
elif name == "extraProgram":
diff --git a/Lib/fontTools/ttLib/tables/T_S_I__5.py b/Lib/fontTools/ttLib/tables/T_S_I__5.py
index f714b82..9d9c3c3 100644
--- a/Lib/fontTools/ttLib/tables/T_S_I__5.py
+++ b/Lib/fontTools/ttLib/tables/T_S_I__5.py
@@ -1,8 +1,9 @@
-import sys
-import DefaultTable
-import array
-from fontTools import ttLib
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
+import sys
+import array
class table_T_S_I__5(DefaultTable.DefaultTable):
@@ -12,7 +13,7 @@
assert len(data) == 2 * numGlyphs
a = array.array("H")
a.fromstring(data)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
a.byteswap()
self.glyphGrouping = {}
for i in range(numGlyphs):
@@ -23,21 +24,20 @@
a = array.array("H")
for i in range(len(glyphNames)):
a.append(self.glyphGrouping[glyphNames[i]])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
a.byteswap()
return a.tostring()
def toXML(self, writer, ttFont):
- names = self.glyphGrouping.keys()
- names.sort()
+ names = sorted(self.glyphGrouping.keys())
for glyphName in names:
writer.simpletag("glyphgroup", name=glyphName, value=self.glyphGrouping[glyphName])
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "glyphGrouping"):
self.glyphGrouping = {}
- if name <> "glyphgroup":
+ if name != "glyphgroup":
return
self.glyphGrouping[attrs["name"]] = safeEval(attrs["value"])
diff --git a/Lib/fontTools/ttLib/tables/V_O_R_G_.py b/Lib/fontTools/ttLib/tables/V_O_R_G_.py
index f817048..5f29eb1 100644
--- a/Lib/fontTools/ttLib/tables/V_O_R_G_.py
+++ b/Lib/fontTools/ttLib/tables/V_O_R_G_.py
@@ -1,9 +1,9 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc.textTools import safeEval
+from . import DefaultTable
import operator
-import DefaultTable
import struct
-from fontTools.ttLib import sfnt
-from fontTools.misc.textTools import safeEval, readHex
-from types import IntType, StringType
class table_V_O_R_G_(DefaultTable.DefaultTable):
@@ -30,17 +30,17 @@
self.VOriginRecords = vOrig = {}
glyphOrder = ttFont.getGlyphOrder()
try:
- names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids )
+ names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids)
except IndexError:
getGlyphName = self.getGlyphName
names = map(getGlyphName, gids )
- map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids)
+ list(map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids))
def compile(self, ttFont):
- vorgs = self.VOriginRecords.values()
- names = self.VOriginRecords.keys()
+ vorgs = list(self.VOriginRecords.values())
+ names = list(self.VOriginRecords.keys())
nameMap = ttFont.getReverseGlyphMap()
lenRecords = len(vorgs)
try:
@@ -48,13 +48,13 @@
except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=1)
gids = map(operator.getitem, [nameMap]*lenRecords, names)
- vOriginTable = map(None, gids, vorgs)
+ vOriginTable = list(zip(gids, vorgs))
self.numVertOriginYMetrics = lenRecords
vOriginTable.sort() # must be in ascending GID order
dataList = [ struct.pack(">Hh", rec[0], rec[1]) for rec in vOriginTable]
header = struct.pack(">HHhH", self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics)
dataList.insert(0, header)
- data = "".join(dataList)
+ data = bytesjoin(dataList)
return data
def toXML(self, writer, ttFont):
@@ -79,46 +79,43 @@
vOriginRec = VOriginRecord(entry[1], entry[2])
vOriginRec.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "VOriginRecords"):
self.VOriginRecords = {}
self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID
if name == "VOriginRecord":
- for element in content:
- if isinstance(element, StringType):
- continue
vOriginRec = VOriginRecord()
for element in content:
- if isinstance(element, StringType):
+ if isinstance(element, basestring):
continue
- vOriginRec.fromXML(element, ttFont)
+ name, attrs, content = element
+ vOriginRec.fromXML(name, attrs, content, ttFont)
self.VOriginRecords[vOriginRec.glyphName] = vOriginRec.vOrigin
- elif attrs.has_key("value"):
- value = safeEval(attrs["value"])
- setattr(self, name, value)
+ elif "value" in attrs:
+ setattr(self, name, safeEval(attrs["value"]))
def __getitem__(self, glyphSelector):
- if type(glyphSelector) == IntType:
+ if isinstance(glyphSelector, int):
# its a gid, convert to glyph name
glyphSelector = self.getGlyphName(glyphSelector)
- if not self.VOriginRecords.has_key(glyphSelector):
+ if glyphSelector not in self.VOriginRecords:
return self.defaultVertOriginY
return self.VOriginRecords[glyphSelector]
def __setitem__(self, glyphSelector, value):
- if type(glyphSelector) == IntType:
+ if isinstance(glyphSelector, int):
# its a gid, convert to glyph name
glyphSelector = self.getGlyphName(glyphSelector)
if value != self.defaultVertOriginY:
self.VOriginRecords[glyphSelector] = value
- elif self.VOriginRecords.has_key(glyphSelector):
+ elif glyphSelector in self.VOriginRecords:
del self.VOriginRecords[glyphSelector]
-class VOriginRecord:
+class VOriginRecord(object):
def __init__(self, name = None, vOrigin = None):
self.glyphName = name
@@ -134,13 +131,9 @@
writer.endtag("VOriginRecord")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
value = attrs["value"]
if name == "glyphName":
setattr(self, name, value)
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
- setattr(self, name, value)
+ setattr(self, name, safeEval(value))
diff --git a/Lib/fontTools/ttLib/tables/__init__.py b/Lib/fontTools/ttLib/tables/__init__.py
index 205af81..108aed1 100644
--- a/Lib/fontTools/ttLib/tables/__init__.py
+++ b/Lib/fontTools/ttLib/tables/__init__.py
@@ -3,52 +3,52 @@
"""Dummy function to let modulefinder know what tables may be
dynamically imported. Generated by MetaTools/buildTableList.py.
"""
- import B_A_S_E_
- import C_B_D_T_
- import C_B_L_C_
- import C_F_F_
- import C_O_L_R_
- import C_P_A_L_
- import D_S_I_G_
- import E_B_D_T_
- import E_B_L_C_
- import G_D_E_F_
- import G_M_A_P_
- import G_P_K_G_
- import G_P_O_S_
- import G_S_U_B_
- import J_S_T_F_
- import L_T_S_H_
- import M_E_T_A_
- import O_S_2f_2
- import S_I_N_G_
- import S_V_G_
- import T_S_I_B_
- import T_S_I_D_
- import T_S_I_J_
- import T_S_I_P_
- import T_S_I_S_
- import T_S_I_V_
- import T_S_I__0
- import T_S_I__1
- import T_S_I__2
- import T_S_I__3
- import T_S_I__5
- import V_O_R_G_
- import _c_m_a_p
- import _c_v_t
- import _f_p_g_m
- import _g_a_s_p
- import _g_l_y_f
- import _h_d_m_x
- import _h_e_a_d
- import _h_h_e_a
- import _h_m_t_x
- import _k_e_r_n
- import _l_o_c_a
- import _m_a_x_p
- import _n_a_m_e
- import _p_o_s_t
- import _p_r_e_p
- import _v_h_e_a
- import _v_m_t_x
+ from . import B_A_S_E_
+ from . import C_B_D_T_
+ from . import C_B_L_C_
+ from . import C_F_F_
+ from . import C_O_L_R_
+ from . import C_P_A_L_
+ from . import D_S_I_G_
+ from . import E_B_D_T_
+ from . import E_B_L_C_
+ from . import G_D_E_F_
+ from . import G_M_A_P_
+ from . import G_P_K_G_
+ from . import G_P_O_S_
+ from . import G_S_U_B_
+ from . import J_S_T_F_
+ from . import L_T_S_H_
+ from . import M_E_T_A_
+ from . import O_S_2f_2
+ from . import S_I_N_G_
+ from . import S_V_G_
+ from . import T_S_I_B_
+ from . import T_S_I_D_
+ from . import T_S_I_J_
+ from . import T_S_I_P_
+ from . import T_S_I_S_
+ from . import T_S_I_V_
+ from . import T_S_I__0
+ from . import T_S_I__1
+ from . import T_S_I__2
+ from . import T_S_I__3
+ from . import T_S_I__5
+ from . import V_O_R_G_
+ from . import _c_m_a_p
+ from . import _c_v_t
+ from . import _f_p_g_m
+ from . import _g_a_s_p
+ from . import _g_l_y_f
+ from . import _h_d_m_x
+ from . import _h_e_a_d
+ from . import _h_h_e_a
+ from . import _h_m_t_x
+ from . import _k_e_r_n
+ from . import _l_o_c_a
+ from . import _m_a_x_p
+ from . import _n_a_m_e
+ from . import _p_o_s_t
+ from . import _p_r_e_p
+ from . import _v_h_e_a
+ from . import _v_m_t_x
diff --git a/Lib/fontTools/ttLib/tables/_c_m_a_p.py b/Lib/fontTools/ttLib/tables/_c_m_a_p.py
index 9ae7987..b08c1ff 100644
--- a/Lib/fontTools/ttLib/tables/_c_m_a_p.py
+++ b/Lib/fontTools/ttLib/tables/_c_m_a_p.py
@@ -1,11 +1,11 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc.textTools import safeEval, readHex
+from . import DefaultTable
import sys
-import DefaultTable
import struct
import array
import operator
-from fontTools import ttLib
-from fontTools.misc.textTools import safeEval, readHex
-from types import TupleType
class table__c_m_a_p(DefaultTable.DefaultTable):
@@ -33,9 +33,9 @@
format, length = struct.unpack(">HL", data[offset:offset+6])
if not length:
- print "Error: cmap subtable is reported as having zero length: platformID %s, platEncID %s, format %s offset %s. Skipping table." % (platformID, platEncID,format, offset)
+ print("Error: cmap subtable is reported as having zero length: platformID %s, platEncID %s, format %s offset %s. Skipping table." % (platformID, platEncID,format, offset))
continue
- if not cmap_classes.has_key(format):
+ if format not in cmap_classes:
table = cmap_format_unknown(format)
else:
table = cmap_classes[format](format)
@@ -45,18 +45,18 @@
# any other data gets decompiled only when an attribute of the
# subtable is referenced.
table.decompileHeader(data[offset:offset+int(length)], ttFont)
- if seenOffsets.has_key(offset):
+ if offset in seenOffsets:
table.cmap = tables[seenOffsets[offset]].cmap
else:
seenOffsets[offset] = i
tables.append(table)
def compile(self, ttFont):
- self.tables.sort() # sort according to the spec; see CmapSubtable.__cmp__()
+ self.tables.sort() # sort according to the spec; see CmapSubtable.__lt__()
numSubTables = len(self.tables)
totalOffset = 4 + 8 * numSubTables
data = struct.pack(">HH", self.tableVersion, numSubTables)
- tableData = ""
+ tableData = b""
seen = {} # Some tables are the same object reference. Don't compile them twice.
done = {} # Some tables are different objects, but compile to the same data chunk
for table in self.tables:
@@ -64,7 +64,7 @@
offset = seen[id(table.cmap)]
except KeyError:
chunk = table.compile(ttFont)
- if done.has_key(chunk):
+ if chunk in done:
offset = done[chunk]
else:
offset = seen[id(table.cmap)] = done[chunk] = totalOffset + len(tableData)
@@ -78,26 +78,26 @@
for table in self.tables:
table.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "tableVersion":
self.tableVersion = safeEval(attrs["version"])
return
- if name[:12] <> "cmap_format_":
+ if name[:12] != "cmap_format_":
return
if not hasattr(self, "tables"):
self.tables = []
format = safeEval(name[12:])
- if not cmap_classes.has_key(format):
+ if format not in cmap_classes:
table = cmap_format_unknown(format)
else:
table = cmap_classes[format](format)
table.platformID = safeEval(attrs["platformID"])
table.platEncID = safeEval(attrs["platEncID"])
- table.fromXML((name, attrs, content), ttFont)
+ table.fromXML(name, attrs, content, ttFont)
self.tables.append(table)
-class CmapSubtable:
+class CmapSubtable(object):
def __init__(self, format):
self.format = format
@@ -107,9 +107,9 @@
def __getattr__(self, attr):
# allow lazy decompilation of subtables.
if attr[:2] == '__': # don't handle requests for member functions like '__lt__'
- raise AttributeError, attr
+ raise AttributeError(attr)
if self.data == None:
- raise AttributeError, attr
+ raise AttributeError(attr)
self.decompile(None, None) # use saved data.
self.data = None # Once this table has been decompiled, make sure we don't
# just return the original data. Also avoids recursion when
@@ -132,8 +132,7 @@
("language", self.language),
])
writer.newline()
- codes = self.cmap.items()
- codes.sort()
+ codes = sorted(self.cmap.items())
self._writeCodes(codes, writer)
writer.endtag(self.__class__.__name__)
writer.newline()
@@ -150,10 +149,11 @@
writer.comment(Unicode[code])
writer.newline()
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
+ def __lt__(self, other):
+ if not isinstance(other, CmapSubtable):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
- # implemented so that list.sort() sorts according to the cmap spec.
+ # implemented so that list.sort() sorts according to the spec.
selfTuple = (
getattr(self, "platformID", None),
getattr(self, "platEncID", None),
@@ -164,7 +164,7 @@
getattr(other, "platEncID", None),
getattr(other, "language", None),
other.__dict__)
- return cmp(selfTuple, otherTuple)
+ return selfTuple < otherTuple
class cmap_format_0(CmapSubtable):
@@ -182,20 +182,19 @@
glyphIdArray.fromstring(self.data)
self.cmap = cmap = {}
lenArray = len(glyphIdArray)
- charCodes = range(lenArray)
+ charCodes = list(range(lenArray))
names = map(self.ttFont.getGlyphName, glyphIdArray)
- map(operator.setitem, [cmap]*lenArray, charCodes, names)
+ list(map(operator.setitem, [cmap]*lenArray, charCodes, names))
def compile(self, ttFont):
if self.data:
return struct.pack(">HHH", 0, 262, self.language) + self.data
- charCodeList = self.cmap.items()
- charCodeList.sort()
+ charCodeList = sorted(self.cmap.items())
charCodes = [entry[0] for entry in charCodeList]
valueList = [entry[1] for entry in charCodeList]
- assert charCodes == range(256)
+ assert charCodes == list(range(256))
valueList = map(ttFont.getGlyphID, valueList)
glyphIdArray = array.array("B", valueList)
@@ -203,22 +202,22 @@
assert len(data) == 262
return data
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.language = safeEval(attrs["language"])
if not hasattr(self, "cmap"):
self.cmap = {}
cmap = self.cmap
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "map":
+ if name != "map":
continue
cmap[safeEval(attrs["code"])] = attrs["name"]
subHeaderFormat = ">HHhH"
-class SubHeader:
+class SubHeader(object):
def __init__(self):
self.firstCode = None
self.entryCount = None
@@ -272,9 +271,9 @@
allKeys = array.array("H")
allKeys.fromstring(data[:512])
data = data[512:]
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
allKeys.byteswap()
- subHeaderKeys = [ key/8 for key in allKeys]
+ subHeaderKeys = [ key//8 for key in allKeys]
maxSubHeaderindex = max(subHeaderKeys)
#Load subHeaders
@@ -288,7 +287,7 @@
giDataPos = pos + subHeader.idRangeOffset-2
giList = array.array("H")
giList.fromstring(data[giDataPos:giDataPos + subHeader.entryCount*2])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
giList.byteswap()
subHeader.glyphIndexArray = giList
subHeaderList.append(subHeader)
@@ -329,7 +328,7 @@
# add it to the glyphID to get the final glyphIndex
# value. In this case the final glyph index = 3+ 42 -> 45 for the final glyphIndex. Whew!
- self.data = ""
+ self.data = b""
self.cmap = cmap = {}
notdefGI = 0
for firstByte in range(256):
@@ -363,15 +362,15 @@
# same as mapping it to .notdef.
# cmap values are GID's.
glyphOrder = self.ttFont.getGlyphOrder()
- gids = cmap.values()
- charCodes = cmap.keys()
+ gids = list(cmap.values())
+ charCodes = list(cmap.keys())
lenCmap = len(gids)
try:
- names = map(operator.getitem, [glyphOrder]*lenCmap, gids )
+ names = list(map(operator.getitem, [glyphOrder]*lenCmap, gids ))
except IndexError:
getGlyphName = self.ttFont.getGlyphName
- names = map(getGlyphName, gids )
- map(operator.setitem, [cmap]*lenCmap, charCodes, names)
+ names = list(map(getGlyphName, gids ))
+ list(map(operator.setitem, [cmap]*lenCmap, charCodes, names))
def compile(self, ttFont):
@@ -380,18 +379,17 @@
kEmptyTwoCharCodeRange = -1
notdefGI = 0
- items = self.cmap.items()
- items.sort()
+ items = sorted(self.cmap.items())
charCodes = [item[0] for item in items]
names = [item[1] for item in items]
nameMap = ttFont.getReverseGlyphMap()
lenCharCodes = len(charCodes)
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=1)
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
# allow virtual GIDs in format 2 tables
gids = []
@@ -517,22 +515,22 @@
for subhead in subHeaderList[:-1]:
for gi in subhead.glyphIndexArray:
dataList.append(struct.pack(">H", gi))
- data = "".join(dataList)
+ data = bytesjoin(dataList)
assert (len(data) == length), "Error: cmap format 2 is not same length as calculated! actual: " + str(len(data))+ " calc : " + str(length)
return data
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.language = safeEval(attrs["language"])
if not hasattr(self, "cmap"):
self.cmap = {}
cmap = self.cmap
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "map":
+ if name != "map":
continue
cmap[safeEval(attrs["code"])] = attrs["name"]
@@ -639,13 +637,13 @@
(segCountX2, searchRange, entrySelector, rangeShift) = \
struct.unpack(">4H", data[:8])
data = data[8:]
- segCount = segCountX2 / 2
+ segCount = segCountX2 // 2
allCodes = array.array("H")
allCodes.fromstring(data)
self.data = data = None
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
allCodes.byteswap()
# divide the data
@@ -663,7 +661,7 @@
charCodes = []
gids = []
for i in range(len(startCode) - 1): # don't do 0xffff!
- rangeCharCodes = range(startCode[i], endCode[i] + 1)
+ rangeCharCodes = list(range(startCode[i], endCode[i] + 1))
charCodes = charCodes + rangeCharCodes
for charCode in rangeCharCodes:
rangeOffset = idRangeOffset[i]
@@ -671,9 +669,9 @@
glyphID = charCode + idDelta[i]
else:
# *someone* needs to get killed.
- index = idRangeOffset[i] / 2 + (charCode - startCode[i]) + i - len(idRangeOffset)
+ index = idRangeOffset[i] // 2 + (charCode - startCode[i]) + i - len(idRangeOffset)
assert (index < lenGIArray), "In format 4 cmap, range (%d), the calculated index (%d) into the glyph index array is not less than the length of the array (%d) !" % (i, index, lenGIArray)
- if glyphIndexArray[index] <> 0: # if not missing glyph
+ if glyphIndexArray[index] != 0: # if not missing glyph
glyphID = glyphIndexArray[index] + idDelta[i]
else:
glyphID = 0 # missing glyph
@@ -683,11 +681,11 @@
lenCmap = len(gids)
glyphOrder = self.ttFont.getGlyphOrder()
try:
- names = map(operator.getitem, [glyphOrder]*lenCmap, gids )
+ names = list(map(operator.getitem, [glyphOrder]*lenCmap, gids ))
except IndexError:
getGlyphName = self.ttFont.getGlyphName
- names = map(getGlyphName, gids )
- map(operator.setitem, [cmap]*lenCmap, charCodes, names)
+ names = list(map(getGlyphName, gids ))
+ list(map(operator.setitem, [cmap]*lenCmap, charCodes, names))
@@ -718,21 +716,21 @@
from fontTools.ttLib.sfnt import maxPowerOfTwo
- charCodes = self.cmap.keys()
+ charCodes = list(self.cmap.keys())
lenCharCodes = len(charCodes)
if lenCharCodes == 0:
startCode = [0xffff]
endCode = [0xffff]
else:
charCodes.sort()
- names = map(operator.getitem, [self.cmap]*lenCharCodes, charCodes)
+ names = list(map(operator.getitem, [self.cmap]*lenCharCodes, charCodes))
nameMap = ttFont.getReverseGlyphMap()
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=1)
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
# allow virtual GIDs in format 4 tables
gids = []
@@ -750,7 +748,7 @@
gids.append(gid)
cmap = {} # code:glyphID mapping
- map(operator.setitem, [cmap]*len(charCodes), charCodes, gids)
+ list(map(operator.setitem, [cmap]*len(charCodes), charCodes, gids))
# Build startCode and endCode lists.
# Split the char codes in ranges of consecutive char codes, then split
@@ -780,7 +778,7 @@
indices = []
for charCode in range(startCode[i], endCode[i] + 1):
indices.append(cmap[charCode])
- if (indices == range(indices[0], indices[0] + len(indices))):
+ if (indices == list(range(indices[0], indices[0] + len(indices)))):
idDeltaTemp = self.setIDDelta(indices[0] - startCode[i])
idDelta.append( idDeltaTemp)
idRangeOffset.append(0)
@@ -803,7 +801,7 @@
charCodeArray = array.array("H", endCode + [0] + startCode)
idDeltaeArray = array.array("h", idDelta)
restArray = array.array("H", idRangeOffset + glyphIndexArray)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
charCodeArray.byteswap()
idDeltaeArray.byteswap()
restArray.byteswap()
@@ -814,17 +812,17 @@
segCountX2, searchRange, entrySelector, rangeShift)
return header + data
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.language = safeEval(attrs["language"])
if not hasattr(self, "cmap"):
self.cmap = {}
cmap = self.cmap
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
nameMap, attrsMap, dummyContent = element
- if nameMap <> "map":
+ if nameMap != "map":
assert 0, "Unrecognized keyword in cmap subtable"
cmap[safeEval(attrsMap["code"])] = attrsMap["name"]
@@ -846,54 +844,54 @@
#assert len(data) == 2 * entryCount # XXX not true in Apple's Helvetica!!!
glyphIndexArray = array.array("H")
glyphIndexArray.fromstring(data[:2 * int(entryCount)])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
glyphIndexArray.byteswap()
self.data = data = None
self.cmap = cmap = {}
lenArray = len(glyphIndexArray)
- charCodes = range(firstCode, firstCode + lenArray )
+ charCodes = list(range(firstCode, firstCode + lenArray))
glyphOrder = self.ttFont.getGlyphOrder()
try:
- names = map(operator.getitem, [glyphOrder]*lenArray, glyphIndexArray )
+ names = list(map(operator.getitem, [glyphOrder]*lenArray, glyphIndexArray ))
except IndexError:
getGlyphName = self.ttFont.getGlyphName
- names = map(getGlyphName, glyphIndexArray )
- map(operator.setitem, [cmap]*lenArray, charCodes, names)
+ names = list(map(getGlyphName, glyphIndexArray ))
+ list(map(operator.setitem, [cmap]*lenArray, charCodes, names))
def compile(self, ttFont):
if self.data:
return struct.pack(">HHH", self.format, self.length, self.language) + self.data
cmap = self.cmap
- codes = cmap.keys()
+ codes = list(cmap.keys())
if codes: # yes, there are empty cmap tables.
- codes = range(codes[0], codes[-1] + 1)
+ codes = list(range(codes[0], codes[-1] + 1))
firstCode = codes[0]
valueList = [cmap.get(code, ".notdef") for code in codes]
valueList = map(ttFont.getGlyphID, valueList)
glyphIndexArray = array.array("H", valueList)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
glyphIndexArray.byteswap()
data = glyphIndexArray.tostring()
else:
- data = ""
+ data = b""
firstCode = 0
header = struct.pack(">HHHHH",
6, len(data) + 10, self.language, firstCode, len(codes))
return header + data
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.language = safeEval(attrs["language"])
if not hasattr(self, "cmap"):
self.cmap = {}
cmap = self.cmap
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "map":
+ if name != "map":
continue
cmap[safeEval(attrs["code"])] = attrs["name"]
@@ -933,32 +931,32 @@
startCharCode, endCharCode, glyphID = struct.unpack(">LLL",data[pos:pos+12] )
pos += 12
lenGroup = 1 + endCharCode - startCharCode
- charCodes += range(startCharCode, endCharCode +1)
+ charCodes += list(range(startCharCode, endCharCode +1))
gids += self._computeGIDs(glyphID, lenGroup)
self.data = data = None
self.cmap = cmap = {}
lenCmap = len(gids)
glyphOrder = self.ttFont.getGlyphOrder()
try:
- names = map(operator.getitem, [glyphOrder]*lenCmap, gids )
+ names = list(map(operator.getitem, [glyphOrder]*lenCmap, gids ))
except IndexError:
getGlyphName = self.ttFont.getGlyphName
- names = map(getGlyphName, gids )
- map(operator.setitem, [cmap]*lenCmap, charCodes, names)
+ names = list(map(getGlyphName, gids ))
+ list(map(operator.setitem, [cmap]*lenCmap, charCodes, names))
def compile(self, ttFont):
if self.data:
return struct.pack(">HHLLL", self.format, self.reserved, self.length, self.language, self.nGroups) + self.data
- charCodes = self.cmap.keys()
+ charCodes = list(self.cmap.keys())
lenCharCodes = len(charCodes)
- names = self.cmap.values()
+ names = list(self.cmap.values())
nameMap = ttFont.getReverseGlyphMap()
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=1)
try:
- gids = map(operator.getitem, [nameMap]*lenCharCodes, names)
+ gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names))
except KeyError:
# allow virtual GIDs in format 12 tables
gids = []
@@ -977,7 +975,7 @@
gids.append(gid)
cmap = {} # code:glyphID mapping
- map(operator.setitem, [cmap]*len(charCodes), charCodes, gids)
+ list(map(operator.setitem, [cmap]*len(charCodes), charCodes, gids))
charCodes.sort()
index = 0
@@ -1000,7 +998,7 @@
lastCharCode = charCode
dataList.append(struct.pack(">LLL", startCharCode, lastCharCode, startGlyphID))
nGroups = nGroups + 1
- data = "".join(dataList)
+ data = bytesjoin(dataList)
lengthSubtable = len(data) +16
assert len(data) == (nGroups*12) == (lengthSubtable-16)
return struct.pack(">HHLLL", self.format, self.reserved , lengthSubtable, self.language, nGroups) + data
@@ -1016,13 +1014,12 @@
("nGroups", self.nGroups),
])
writer.newline()
- codes = self.cmap.items()
- codes.sort()
+ codes = sorted(self.cmap.items())
self._writeCodes(codes, writer)
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.format = safeEval(attrs["format"])
self.reserved = safeEval(attrs["reserved"])
self.length = safeEval(attrs["length"])
@@ -1033,10 +1030,10 @@
cmap = self.cmap
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "map":
+ if name != "map":
continue
cmap[safeEval(attrs["code"])] = attrs["name"]
@@ -1047,7 +1044,7 @@
self._format_step = 1
def _computeGIDs(self, startingGlyph, numberOfGlyphs):
- return range(startingGlyph, startingGlyph + numberOfGlyphs)
+ return list(range(startingGlyph, startingGlyph + numberOfGlyphs))
def _IsInSameRun(self, glyphID, lastGlyphID, charCode, lastCharCode):
return (glyphID == 1 + lastGlyphID) and (charCode == 1 + lastCharCode)
@@ -1066,35 +1063,16 @@
def cvtToUVS(threeByteString):
- if sys.byteorder <> "big":
- data = "\0" +threeByteString
- else:
- data = threeByteString + "\0"
+ data = b"\0" + threeByteString
val, = struct.unpack(">L", data)
return val
def cvtFromUVS(val):
- if sys.byteorder <> "big":
- threeByteString = struct.pack(">L", val)[1:]
- else:
- threeByteString = struct.pack(">L", val)[:3]
- return threeByteString
+ assert 0 <= val < 0x1000000
+ fourByteString = struct.pack(">L", val)
+ return fourByteString[1:]
-def cmpUVSListEntry(first, second):
- uv1, glyphName1 = first
- uv2, glyphName2 = second
-
- if (glyphName1 == None) and (glyphName2 != None):
- return -1
- elif (glyphName2 == None) and (glyphName1 != None):
- return 1
-
- ret = cmp(uv1, uv2)
- if ret:
- return ret
- return cmp(glyphName1, glyphName2)
-
-
+
class cmap_format_14(CmapSubtable):
def decompileHeader(self, data, ttFont):
@@ -1128,13 +1106,13 @@
startOffset += 4
firstBaseUV = cvtToUVS(uv)
cnt = addtlCnt+1
- baseUVList = range(firstBaseUV, firstBaseUV+cnt)
+ baseUVList = list(range(firstBaseUV, firstBaseUV+cnt))
glyphList = [None]*cnt
localUVList = zip(baseUVList, glyphList)
try:
uvsDict[varUVS].extend(localUVList)
except KeyError:
- uvsDict[varUVS] = localUVList
+ uvsDict[varUVS] = list(localUVList)
if nonDefUVSOffset:
startOffset = nonDefUVSOffset - 10
@@ -1164,11 +1142,10 @@
])
writer.newline()
uvsDict = self.uvsDict
- uvsList = uvsDict.keys()
- uvsList.sort()
+ uvsList = sorted(uvsDict.keys())
for uvs in uvsList:
uvList = uvsDict[uvs]
- uvList.sort(cmpUVSListEntry)
+ uvList.sort(key=lambda item: (item[1] != None, item[0], item[1]))
for uv, gname in uvList:
if gname == None:
gname = "None"
@@ -1178,11 +1155,11 @@
writer.endtag(self.__class__.__name__)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.format = safeEval(attrs["format"])
self.length = safeEval(attrs["length"])
self.numVarSelectorRecords = safeEval(attrs["numVarSelectorRecords"])
- self.language = 0xFF # provide a value so that CmapSubtable.__cmp__() won't fail
+ self.language = 0xFF # provide a value so that CmapSubtable.__lt__() won't fail
if not hasattr(self, "cmap"):
self.cmap = {} # so that clients that expect this to exist in a cmap table won't fail.
if not hasattr(self, "uvsDict"):
@@ -1190,10 +1167,10 @@
uvsDict = self.uvsDict
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "map":
+ if name != "map":
continue
uvs = safeEval(attrs["uvs"])
uv = safeEval(attrs["uv"])
@@ -1211,8 +1188,7 @@
return struct.pack(">HLL", self.format, self.length , self.numVarSelectorRecords) + self.data
uvsDict = self.uvsDict
- uvsList = uvsDict.keys()
- uvsList.sort()
+ uvsList = sorted(uvsDict.keys())
self.numVarSelectorRecords = len(uvsList)
offset = 10 + self.numVarSelectorRecords*11 # current value is end of VarSelectorRecords block.
data = []
@@ -1220,9 +1196,9 @@
for uvs in uvsList:
entryList = uvsDict[uvs]
- defList = filter(lambda entry: entry[1] == None, entryList)
+ defList = [entry for entry in entryList if entry[1] == None]
if defList:
- defList = map(lambda entry: entry[0], defList)
+ defList = [entry[0] for entry in defList]
defOVSOffset = offset
defList.sort()
@@ -1247,7 +1223,7 @@
else:
defOVSOffset = 0
- ndefList = filter(lambda entry: entry[1] != None, entryList)
+ ndefList = [entry for entry in entryList if entry[1] != None]
if ndefList:
nonDefUVSOffset = offset
ndefList.sort()
@@ -1265,7 +1241,7 @@
vrec = struct.pack(">3sLL", cvtFromUVS(uvs), defOVSOffset, nonDefUVSOffset)
varSelectorRecords.append(vrec)
- data = "".join(varSelectorRecords) + "".join(data)
+ data = bytesjoin(varSelectorRecords) + bytesjoin(data)
self.length = 10 + len(data)
headerdata = struct.pack(">HLL", self.format, self.length , self.numVarSelectorRecords)
self.data = headerdata + data
@@ -1286,7 +1262,7 @@
writer.endtag(cmapName)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.data = readHex(content)
self.cmap = {}
diff --git a/Lib/fontTools/ttLib/tables/_c_v_t.py b/Lib/fontTools/ttLib/tables/_c_v_t.py
index be08ca3..fc0ceb7 100644
--- a/Lib/fontTools/ttLib/tables/_c_v_t.py
+++ b/Lib/fontTools/ttLib/tables/_c_v_t.py
@@ -1,21 +1,22 @@
-import sys
-import DefaultTable
-import array
-from fontTools import ttLib
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
+import sys
+import array
class table__c_v_t(DefaultTable.DefaultTable):
def decompile(self, data, ttFont):
values = array.array("h")
values.fromstring(data)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
values.byteswap()
self.values = values
def compile(self, ttFont):
values = self.values[:]
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
values.byteswap()
return values.tostring()
@@ -25,7 +26,7 @@
writer.simpletag("cv", value=value, index=i)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "values"):
self.values = array.array("h")
if name == "cv":
diff --git a/Lib/fontTools/ttLib/tables/_f_p_g_m.py b/Lib/fontTools/ttLib/tables/_f_p_g_m.py
index 6f7beee..a6cebae 100644
--- a/Lib/fontTools/ttLib/tables/_f_p_g_m.py
+++ b/Lib/fontTools/ttLib/tables/_f_p_g_m.py
@@ -1,6 +1,7 @@
-import DefaultTable
-import array
-import ttProgram
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from . import DefaultTable
+from . import ttProgram
class table__f_p_g_m(DefaultTable.DefaultTable):
@@ -16,9 +17,9 @@
self.program.toXML(writer, ttFont)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
program = ttProgram.Program()
- program.fromXML((name, attrs, content), ttFont)
+ program.fromXML(name, attrs, content, ttFont)
self.program = program
def __len__(self):
diff --git a/Lib/fontTools/ttLib/tables/_g_a_s_p.py b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
index 43f513f..5097a08 100644
--- a/Lib/fontTools/ttLib/tables/_g_a_s_p.py
+++ b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
@@ -1,6 +1,8 @@
-import DefaultTable
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
+import struct
GASP_SYMMETRIC_GRIDFIT = 0x0004
@@ -24,9 +26,8 @@
def compile(self, ttFont):
version = 0 # ignore self.version
numRanges = len(self.gaspRange)
- data = ""
- items = self.gaspRange.items()
- items.sort()
+ data = b""
+ items = sorted(self.gaspRange.items())
for rangeMaxPPEM, rangeGaspBehavior in items:
data = data + struct.pack(">HH", rangeMaxPPEM, rangeGaspBehavior)
if rangeGaspBehavior & ~(GASP_GRIDFIT | GASP_DOGRAY):
@@ -35,16 +36,15 @@
return data
def toXML(self, writer, ttFont):
- items = self.gaspRange.items()
- items.sort()
+ items = sorted(self.gaspRange.items())
for rangeMaxPPEM, rangeGaspBehavior in items:
writer.simpletag("gaspRange", [
("rangeMaxPPEM", rangeMaxPPEM),
("rangeGaspBehavior", rangeGaspBehavior)])
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- if name <> "gaspRange":
+ def fromXML(self, name, attrs, content, ttFont):
+ if name != "gaspRange":
return
if not hasattr(self, "gaspRange"):
self.gaspRange = {}
diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
index 838c5d1..fc47903 100644
--- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py
+++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
@@ -1,6 +1,20 @@
"""_g_l_y_f.py -- Converter classes for the 'glyf' table."""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from fontTools.misc import sstruct
+from fontTools import ttLib
+from fontTools.misc.textTools import safeEval
+from fontTools.misc.arrayTools import calcBounds
+from fontTools.misc.fixedTools import fixedToFloat as fi2fl, floatToFixed as fl2fi
+from . import DefaultTable
+from . import ttProgram
+import sys
+import struct
+import array
+import warnings
+
#
# The Apple and MS rasterizers behave differently for
# scaled composite components: one does scale first and then translate
@@ -14,18 +28,6 @@
SCALE_COMPONENT_OFFSET_DEFAULT = 0 # 0 == MS, 1 == Apple
-import sys
-import struct
-from fontTools.misc import sstruct
-import DefaultTable
-from fontTools import ttLib
-from fontTools.misc.textTools import safeEval, readHex
-from fontTools.misc.arrayTools import calcBounds
-import ttProgram
-import array
-from types import StringType, TupleType
-import warnings
-
class table__g_l_y_f(DefaultTable.DefaultTable):
def decompile(self, data, ttFont):
@@ -42,8 +44,8 @@
glyphName = 'ttxautoglyph%s' % i
next = int(loca[i+1])
glyphdata = data[last:next]
- if len(glyphdata) <> (next - last):
- raise ttLib.TTLibError, "not enough 'glyf' table data"
+ if len(glyphdata) != (next - last):
+ raise ttLib.TTLibError("not enough 'glyf' table data")
glyph = Glyph(glyphdata)
self.glyphs[glyphName] = glyph
last = next
@@ -58,7 +60,6 @@
def compile(self, ttFont):
if not hasattr(self, "glyphOrder"):
self.glyphOrder = ttFont.getGlyphOrder()
- import string
locations = []
currentLocation = 0
dataList = []
@@ -70,7 +71,7 @@
currentLocation = currentLocation + len(glyphData)
dataList.append(glyphData)
locations.append(currentLocation)
- data = string.join(dataList, "")
+ data = bytesjoin(dataList)
if 'loca' in ttFont:
ttFont['loca'].set(locations)
ttFont['maxp'].numGlyphs = len(self.glyphs)
@@ -88,7 +89,7 @@
for glyphName in glyphNames:
if not counter % progressStep and progress is not None:
progress.setLabel("Dumping 'glyf' table... (%s)" % glyphName)
- progress.increment(progressStep / float(numGlyphs))
+ progress.increment(progressStep / numGlyphs)
counter = counter + 1
glyph = self[glyphName]
if glyph.numberOfContours:
@@ -109,8 +110,8 @@
writer.newline()
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- if name <> "TTGlyph":
+ def fromXML(self, name, attrs, content, ttFont):
+ if name != "TTGlyph":
return
if not hasattr(self, "glyphs"):
self.glyphs = {}
@@ -124,9 +125,10 @@
setattr(glyph, attr, safeEval(attrs.get(attr, '0')))
self.glyphs[glyphName] = glyph
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
- glyph.fromXML(element, ttFont)
+ name, attrs, content = element
+ glyph.fromXML(name, attrs, content, ttFont)
if not ttFont.recalcBBoxes:
glyph.compact(self, 0)
@@ -144,7 +146,7 @@
return self.glyphs.keys()
def has_key(self, glyphName):
- return self.glyphs.has_key(glyphName)
+ return glyphName in self.glyphs
__contains__ = has_key
@@ -202,7 +204,7 @@
UNSCALED_COMPONENT_OFFSET = 0x1000 # composite designed not to have the component offset scaled (designed for MS)
-class Glyph:
+class Glyph(object):
def __init__(self, data=""):
if not data:
@@ -249,7 +251,7 @@
if len(data) % 4:
# add pad bytes
nPadBytes = 4 - (len(data) % 4)
- data = data + "\0" * nPadBytes
+ data = data + b"\0" * nPadBytes
return data
def toXML(self, writer, ttFont):
@@ -281,18 +283,18 @@
writer.endtag("instructions")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "contour":
if self.numberOfContours < 0:
- raise ttLib.TTLibError, "can't mix composites and contours in glyph"
+ raise ttLib.TTLibError("can't mix composites and contours in glyph")
self.numberOfContours = self.numberOfContours + 1
coordinates = GlyphCoordinates()
flags = []
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
- if name <> "pt":
+ if name != "pt":
continue # ignore anything but "pt"
coordinates.append((safeEval(attrs["x"]), safeEval(attrs["y"])))
flags.append(not not safeEval(attrs["on"]))
@@ -307,19 +309,20 @@
self.endPtsOfContours.append(len(self.coordinates)-1)
elif name == "component":
if self.numberOfContours > 0:
- raise ttLib.TTLibError, "can't mix composites and contours in glyph"
+ raise ttLib.TTLibError("can't mix composites and contours in glyph")
self.numberOfContours = -1
if not hasattr(self, "components"):
self.components = []
component = GlyphComponent()
self.components.append(component)
- component.fromXML((name, attrs, content), ttFont)
+ component.fromXML(name, attrs, content, ttFont)
elif name == "instructions":
self.program = ttProgram.Program()
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
- self.program.fromXML(element, ttFont)
+ name, attrs, content = element
+ self.program.fromXML(name, attrs, content, ttFont)
def getCompositeMaxpValues(self, glyfTable, maxComponentDepth=1):
assert self.isComposite()
@@ -362,7 +365,7 @@
def decompileCoordinates(self, data):
endPtsOfContours = array.array("h")
endPtsOfContours.fromstring(data[:2*self.numberOfContours])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
endPtsOfContours.byteswap()
self.endPtsOfContours = endPtsOfContours.tolist()
@@ -423,12 +426,12 @@
xFormat = ">" # big endian
yFormat = ">" # big endian
i = j = 0
- while 1:
- flag = ord(data[i])
+ while True:
+ flag = byteord(data[i])
i = i + 1
repeat = 1
if flag & flagRepeat:
- repeat = ord(data[i]) + 1
+ repeat = byteord(data[i]) + 1
i = i + 1
for k in range(repeat):
if flag & flagXShort:
@@ -455,7 +458,7 @@
return flags, xCoordinates, yCoordinates
def compileComponents(self, glyfTable):
- data = ""
+ data = b""
lastcomponent = len(self.components) - 1
more = 1
haveInstructions = 0
@@ -473,9 +476,9 @@
def compileCoordinates(self):
assert len(self.coordinates) == len(self.flags)
- data = ""
+ data = b""
endPtsOfContours = array.array("h", self.endPtsOfContours)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
endPtsOfContours.byteswap()
data = data + endPtsOfContours.tostring()
instructions = self.program.getBytecode()
@@ -537,10 +540,10 @@
compressedflags.append(flag)
lastflag = flag
data = data + array.array("B", compressedflags).tostring()
- xPoints = map(int, xPoints) # work around struct >= 2.5 bug
- yPoints = map(int, yPoints)
- data = data + apply(struct.pack, (xFormat,)+tuple(xPoints))
- data = data + apply(struct.pack, (yFormat,)+tuple(yPoints))
+ xPoints = list(map(int, xPoints)) # work around struct >= 2.5 bug
+ yPoints = list(map(int, yPoints))
+ data = data + struct.pack(*(xFormat,)+tuple(xPoints))
+ data = data + struct.pack(*(yFormat,)+tuple(yPoints))
return data
def recalcBounds(self, glyfTable):
@@ -559,7 +562,7 @@
def __getitem__(self, componentIndex):
if not self.isComposite():
- raise ttLib.TTLibError, "can't use glyph as sequence"
+ raise ttLib.TTLibError("can't use glyph as sequence")
return self.components[componentIndex]
def getCoordinates(self, glyfTable):
@@ -641,7 +644,7 @@
def removeHinting(self):
if not hasattr(self, "data"):
- self.program = ttLib.tables.ttProgram.Program()
+ self.program = ttProgram.Program()
self.program.fromBytecode([])
return
@@ -670,7 +673,7 @@
# padding.
coordBytes = 0
j = 0
- while 1:
+ while True:
flag = data[i]
i = i + 1
repeat = 1
@@ -718,18 +721,17 @@
if len(data) % 4:
# add pad bytes
nPadBytes = 4 - (len(data) % 4)
- data = data + "\0" * nPadBytes
+ data = data + b"\0" * nPadBytes
self.data = data
-
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
- return cmp(self.__dict__, other.__dict__)
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self.__dict__ == other.__dict__
-class GlyphComponent:
+class GlyphComponent(object):
def __init__(self):
pass
@@ -755,7 +757,6 @@
self.glyphName = glyfTable.getGlyphName(int(glyphID))
#print ">>", reprflag(self.flags)
data = data[4:]
- x4000 = float(0x4000)
if self.flags & ARG_1_AND_2_ARE_WORDS:
if self.flags & ARGS_ARE_XY_VALUES:
@@ -774,17 +775,17 @@
if self.flags & WE_HAVE_A_SCALE:
scale, = struct.unpack(">h", data[:2])
- self.transform = [[scale/x4000, 0], [0, scale/x4000]] # fixed 2.14
+ self.transform = [[fi2fl(scale,14), 0], [0, fi2fl(scale,14)]] # fixed 2.14
data = data[2:]
elif self.flags & WE_HAVE_AN_X_AND_Y_SCALE:
xscale, yscale = struct.unpack(">hh", data[:4])
- self.transform = [[xscale/x4000, 0], [0, yscale/x4000]] # fixed 2.14
+ self.transform = [[fi2fl(xscale,14), 0], [0, fi2fl(yscale,14)]] # fixed 2.14
data = data[4:]
elif self.flags & WE_HAVE_A_TWO_BY_TWO:
(xscale, scale01,
scale10, yscale) = struct.unpack(">hhhh", data[:8])
- self.transform = [[xscale/x4000, scale01/x4000],
- [scale10/x4000, yscale/x4000]] # fixed 2.14
+ self.transform = [[fi2fl(xscale,14), fi2fl(scale01,14)],
+ [fi2fl(scale10,14), fi2fl(yscale,14)]] # fixed 2.14
data = data[8:]
more = self.flags & MORE_COMPONENTS
haveInstructions = self.flags & WE_HAVE_INSTRUCTIONS
@@ -794,7 +795,7 @@
return more, haveInstructions, data
def compile(self, more, haveInstructions, glyfTable):
- data = ""
+ data = b""
# reset all flags we will calculate ourselves
flags = self.flags & (ROUND_XY_TO_GRID | USE_MY_METRICS |
@@ -820,13 +821,13 @@
flags = flags | ARG_1_AND_2_ARE_WORDS
if hasattr(self, "transform"):
- transform = [[int(x * 0x4000 + .5) for x in row] for row in self.transform]
+ transform = [[fl2fi(x,14) for x in row] for row in self.transform]
if transform[0][1] or transform[1][0]:
flags = flags | WE_HAVE_A_TWO_BY_TWO
data = data + struct.pack(">hhhh",
transform[0][0], transform[0][1],
transform[1][0], transform[1][1])
- elif transform[0][0] <> transform[1][1]:
+ elif transform[0][0] != transform[1][1]:
flags = flags | WE_HAVE_AN_X_AND_Y_SCALE
data = data + struct.pack(">hh",
transform[0][0], transform[1][1])
@@ -852,7 +853,7 @@
("scalex", transform[0][0]), ("scale01", transform[0][1]),
("scale10", transform[1][0]), ("scaley", transform[1][1]),
]
- elif transform[0][0] <> transform[1][1]:
+ elif transform[0][0] != transform[1][1]:
attrs = attrs + [
("scalex", transform[0][0]), ("scaley", transform[1][1]),
]
@@ -862,36 +863,35 @@
writer.simpletag("component", attrs)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.glyphName = attrs["glyphName"]
- if attrs.has_key("firstPt"):
+ if "firstPt" in attrs:
self.firstPt = safeEval(attrs["firstPt"])
self.secondPt = safeEval(attrs["secondPt"])
else:
self.x = safeEval(attrs["x"])
self.y = safeEval(attrs["y"])
- if attrs.has_key("scale01"):
+ if "scale01" in attrs:
scalex = safeEval(attrs["scalex"])
scale01 = safeEval(attrs["scale01"])
scale10 = safeEval(attrs["scale10"])
scaley = safeEval(attrs["scaley"])
self.transform = [[scalex, scale01], [scale10, scaley]]
- elif attrs.has_key("scalex"):
+ elif "scalex" in attrs:
scalex = safeEval(attrs["scalex"])
scaley = safeEval(attrs["scaley"])
self.transform = [[scalex, 0], [0, scaley]]
- elif attrs.has_key("scale"):
+ elif "scale" in attrs:
scale = safeEval(attrs["scale"])
self.transform = [[scale, 0], [0, scale]]
self.flags = safeEval(attrs["flags"])
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self.__dict__ == other.__dict__
- return cmp(self.__dict__, other.__dict__)
-
-class GlyphCoordinates:
+class GlyphCoordinates(object):
def __init__(self, iterable=[]):
self._a = array.array("h")
@@ -907,17 +907,17 @@
return c
def __len__(self):
- return len(self._a) / 2
+ return len(self._a) // 2
def __getitem__(self, k):
if isinstance(k, slice):
- indices = xrange(*k.indices(len(self)))
+ indices = range(*k.indices(len(self)))
return [self[i] for i in indices]
return self._a[2*k],self._a[2*k+1]
def __setitem__(self, k, v):
if isinstance(k, slice):
- indices = xrange(*k.indices(len(self)))
+ indices = range(*k.indices(len(self)))
for j,i in enumerate(indices):
self[i] = v[j]
return
@@ -926,8 +926,8 @@
def __repr__(self):
return 'GlyphCoordinates(['+','.join(str(c) for c in self)+'])'
- def append(self, (x,y)):
- self._a.extend((x,y))
+ def append(self, p):
+ self._a.extend(tuple(p))
def extend(self, iterable):
for x,y in iterable:
@@ -936,14 +936,14 @@
def relativeToAbsolute(self):
a = self._a
x,y = 0,0
- for i in range(len(a) / 2):
+ for i in range(len(a) // 2):
a[2*i ] = x = a[2*i ] + x
a[2*i+1] = y = a[2*i+1] + y
def absoluteToRelative(self):
a = self._a
x,y = 0,0
- for i in range(len(a) / 2):
+ for i in range(len(a) // 2):
dx = a[2*i ] - x
dy = a[2*i+1] - y
x = a[2*i ]
@@ -951,25 +951,31 @@
a[2*i ] = dx
a[2*i+1] = dy
- def translate(self, (x,y)):
+ def translate(self, p):
+ (x,y) = p
a = self._a
- for i in range(len(a) / 2):
+ for i in range(len(a) // 2):
a[2*i ] += x
a[2*i+1] += y
def transform(self, t):
a = self._a
- for i in range(len(a) / 2):
+ for i in range(len(a) // 2):
x = a[2*i ]
y = a[2*i+1]
a[2*i ] = int(.5 + x * t[0][0] + y * t[1][0])
a[2*i+1] = int(.5 + x * t[0][1] + y * t[1][1])
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self._a == other._a
+
def reprflag(flag):
bin = ""
- if type(flag) == StringType:
- flag = ord(flag)
+ if isinstance(flag, str):
+ flag = byteord(flag)
while flag:
if flag & 0x01:
bin = "1" + bin
diff --git a/Lib/fontTools/ttLib/tables/_h_d_m_x.py b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
index 592f426..f9fd557 100644
--- a/Lib/fontTools/ttLib/tables/_h_d_m_x.py
+++ b/Lib/fontTools/ttLib/tables/_h_d_m_x.py
@@ -1,6 +1,7 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import string
+from . import DefaultTable
hdmxHeaderFormat = """
> # big endian!
@@ -17,11 +18,11 @@
dummy, data = sstruct.unpack2(hdmxHeaderFormat, data, self)
self.hdmx = {}
for i in range(self.numRecords):
- ppem = ord(data[0])
- maxSize = ord(data[1])
+ ppem = byteord(data[0])
+ maxSize = byteord(data[1])
widths = {}
for glyphID in range(numGlyphs):
- widths[glyphOrder[glyphID]] = ord(data[glyphID+2])
+ widths[glyphOrder[glyphID]] = byteord(data[glyphID+2])
self.hdmx[ppem] = widths
data = data[self.recordSize:]
assert len(data) == 0, "too much hdmx data"
@@ -30,25 +31,23 @@
self.version = 0
numGlyphs = ttFont['maxp'].numGlyphs
glyphOrder = ttFont.getGlyphOrder()
- self.recordSize = 4 * ((2 + numGlyphs + 3) / 4)
- pad = (self.recordSize - 2 - numGlyphs) * "\0"
+ self.recordSize = 4 * ((2 + numGlyphs + 3) // 4)
+ pad = (self.recordSize - 2 - numGlyphs) * b"\0"
self.numRecords = len(self.hdmx)
data = sstruct.pack(hdmxHeaderFormat, self)
- items = self.hdmx.items()
- items.sort()
+ items = sorted(self.hdmx.items())
for ppem, widths in items:
- data = data + chr(ppem) + chr(max(widths.values()))
+ data = data + bytechr(ppem) + bytechr(max(widths.values()))
for glyphID in range(len(glyphOrder)):
width = widths[glyphOrder[glyphID]]
- data = data + chr(width)
+ data = data + bytechr(width)
data = data + pad
return data
def toXML(self, writer, ttFont):
writer.begintag("hdmxData")
writer.newline()
- ppems = self.hdmx.keys()
- ppems.sort()
+ ppems = sorted(self.hdmx.keys())
records = []
format = ""
for ppem in ppems:
@@ -58,7 +57,7 @@
glyphNames = ttFont.getGlyphOrder()[:]
glyphNames.sort()
maxNameLen = max(map(len, glyphNames))
- format = "%" + `maxNameLen` + 's:' + format + ' ;'
+ format = "%" + repr(maxNameLen) + 's:' + format + ' ;'
writer.write(format % (("ppem",) + tuple(ppems)))
writer.newline()
writer.newline()
@@ -74,18 +73,18 @@
writer.endtag("hdmxData")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- if name <> "hdmxData":
+ def fromXML(self, name, attrs, content, ttFont):
+ if name != "hdmxData":
return
- content = string.join(content, "")
- lines = string.split(content, ";")
- topRow = string.split(lines[0])
+ content = strjoin(content)
+ lines = content.split(";")
+ topRow = lines[0].split()
assert topRow[0] == "ppem:", "illegal hdmx format"
- ppems = map(int, topRow[1:])
+ ppems = list(map(int, topRow[1:]))
self.hdmx = hdmx = {}
for ppem in ppems:
hdmx[ppem] = {}
- lines = map(string.split, lines[1:])
+ lines = (line.split() for line in lines[1:])
for line in lines:
if not line:
continue
@@ -94,7 +93,7 @@
if "\\" in glyphName:
from fontTools.misc.textTools import safeEval
glyphName = safeEval('"""' + glyphName + '"""')
- line = map(int, line[1:])
+ line = list(map(int, line[1:]))
assert len(line) == len(ppems), "illegal hdmx format"
for i in range(len(ppems)):
hdmx[ppems[i]][glyphName] = line[i]
diff --git a/Lib/fontTools/ttLib/tables/_h_e_a_d.py b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
index 61d9a16..182f328 100644
--- a/Lib/fontTools/ttLib/tables/_h_e_a_d.py
+++ b/Lib/fontTools/ttLib/tables/_h_e_a_d.py
@@ -1,8 +1,9 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
-import time
-import string
from fontTools.misc.textTools import safeEval, num2binary, binary2num
+from . import DefaultTable
+import time
headFormat = """
@@ -35,12 +36,12 @@
if rest:
# this is quite illegal, but there seem to be fonts out there that do this
assert rest == "\0\0"
- self.unitsPerEm = int(self.unitsPerEm)
- self.flags = int(self.flags)
+ self.unitsPerEm = self.unitsPerEm
+ self.flags = self.flags
self.strings2dates()
def compile(self, ttFont):
- self.modified = long(time.time() - mac_epoch_diff)
+ self.modified = int(time.time() - mac_epoch_diff)
self.dates2strings()
data = sstruct.pack(headFormat, self)
self.strings2dates()
@@ -67,7 +68,7 @@
value = time.asctime(time.gmtime(0))
if name in ("magicNumber", "checkSumAdjustment"):
if value < 0:
- value = value + 0x100000000L
+ value = value + 0x100000000
value = hex(value)
if value[-1:] == "L":
value = value[:-1]
@@ -76,31 +77,15 @@
writer.simpletag(name, value=value)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
value = attrs["value"]
if name in ("created", "modified"):
value = parse_date(value) - mac_epoch_diff
elif name in ("macStyle", "flags"):
value = binary2num(value)
else:
- try:
- value = safeEval(value)
- except OverflowError:
- value = long(value)
+ value = safeEval(value)
setattr(self, name, value)
-
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- selfdict = self.__dict__.copy()
- otherdict = other.__dict__.copy()
- # for testing purposes, compare without the modified and checkSumAdjustment
- # fields, since they are allowed to be different.
- for key in ["modified", "checkSumAdjustment"]:
- del selfdict[key]
- del otherdict[key]
- return cmp(selfdict, otherdict)
def calc_mac_epoch_diff():
@@ -112,7 +97,7 @@
# This assert fails in certain time zones, with certain daylight settings
#assert time.gmtime(safe_epoch)[:6] == safe_epoch_t[:6]
seconds1904to1972 = 60 * 60 * 24 * (365 * (1972-1904) + 17) # thanks, Laurence!
- return long(safe_epoch - seconds1904to1972)
+ return int(safe_epoch - seconds1904to1972)
mac_epoch_diff = calc_mac_epoch_diff()
@@ -122,34 +107,31 @@
_weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
def parse_date(datestring):
- datestring = string.lower(datestring)
- weekday, month, day, tim, year = string.split(datestring)
+ datestring = datestring.lower()
+ weekday, month, day, tim, year = datestring.split()
weekday = _weekdays.index(weekday)
month = _months.index(month)
year = int(year)
day = int(day)
- hour, minute, second = map(int, string.split(tim, ":"))
+ hour, minute, second = [int(item) for item in tim.split(":")]
t = (year, month, day, hour, minute, second, weekday, 0, 0)
- try:
- return long(time.mktime(t) - time.timezone)
- except OverflowError:
- return 0L
+ return int(time.mktime(t) - time.timezone)
def bin2long(data):
# thanks </F>!
- v = 0L
- for i in map(ord, data):
+ v = 0
+ for i in map(byteord, data):
v = v<<8 | i
return v
def long2bin(v, bytes=8):
- mask = long("FF" * bytes, 16)
- data = ""
+ mask = int("FF" * bytes, 16)
+ data = b""
while v:
- data = chr(v & 0xff) + data
+ data = bytechr(v & 0xff) + data
v = (v >> 8) & mask
- data = (bytes - len(data)) * "\0" + data
+ data = (bytes - len(data)) * b"\0" + data
assert len(data) == 8, "long too long"
return data
diff --git a/Lib/fontTools/ttLib/tables/_h_h_e_a.py b/Lib/fontTools/ttLib/tables/_h_h_e_a.py
index cf2919e..0f0dfbc 100644
--- a/Lib/fontTools/ttLib/tables/_h_h_e_a.py
+++ b/Lib/fontTools/ttLib/tables/_h_h_e_a.py
@@ -1,6 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
hheaFormat = """
@@ -39,7 +41,7 @@
def recalc(self, ttFont):
hmtxTable = ttFont['hmtx']
- if ttFont.has_key('glyf'):
+ if 'glyf' in ttFont:
glyfTable = ttFont['glyf']
INFINITY = 100000
advanceWidthMax = 0
@@ -81,11 +83,9 @@
formatstring, names, fixes = sstruct.getformat(hheaFormat)
for name in names:
value = getattr(self, name)
- if type(value) == type(0L):
- value = int(value)
writer.simpletag(name, value=value)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
setattr(self, name, safeEval(attrs["value"]))
diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
index 1b1e200..f7ea1e6 100644
--- a/Lib/fontTools/ttLib/tables/_h_m_t_x.py
+++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
@@ -1,8 +1,9 @@
-import sys
-import DefaultTable
-import array
-from fontTools import ttLib
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
+import sys
+import array
import warnings
@@ -20,14 +21,14 @@
numberOfMetrics = numGlyphs # We warn later.
# Note: advanceWidth is unsigned, but we read/write as signed.
metrics = array.array("h", data[:4 * numberOfMetrics])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
metrics.byteswap()
data = data[4 * numberOfMetrics:]
numberOfSideBearings = numGlyphs - numberOfMetrics
sideBearings = array.array("h", data[:2 * numberOfSideBearings])
data = data[2 * numberOfSideBearings:]
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
sideBearings.byteswap()
if data:
sys.stderr.write("too much data for hmtx/vmtx table\n")
@@ -61,19 +62,18 @@
for item in metrics:
allMetrics.extend(item)
allMetrics = array.array("h", allMetrics)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
allMetrics.byteswap()
data = allMetrics.tostring()
additionalMetrics = array.array("h", additionalMetrics)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
additionalMetrics.byteswap()
data = data + additionalMetrics.tostring()
return data
def toXML(self, writer, ttFont):
- names = self.metrics.keys()
- names.sort()
+ names = sorted(self.metrics.keys())
for glyphName in names:
advance, sb = self.metrics[glyphName]
writer.simpletag("mtx", [
@@ -83,7 +83,7 @@
])
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if not hasattr(self, "metrics"):
self.metrics = {}
if name == "mtx":
@@ -93,6 +93,6 @@
def __getitem__(self, glyphName):
return self.metrics[glyphName]
- def __setitem__(self, glyphName, (advance, sb)):
- self.metrics[glyphName] = advance, sb
+ def __setitem__(self, glyphName, advance_sb_pair):
+ self.metrics[glyphName] = tuple(advance_sb_pair)
diff --git a/Lib/fontTools/ttLib/tables/_k_e_r_n.py b/Lib/fontTools/ttLib/tables/_k_e_r_n.py
index 22c5552..4ee9fc4 100644
--- a/Lib/fontTools/ttLib/tables/_k_e_r_n.py
+++ b/Lib/fontTools/ttLib/tables/_k_e_r_n.py
@@ -1,8 +1,10 @@
-import DefaultTable
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.ttLib import sfnt
from fontTools.misc.textTools import safeEval, readHex
-from types import TupleType
+from fontTools.misc.fixedTools import fixedToFloat as fi2fl, floatToFixed as fl2fi
+from . import DefaultTable
+import struct
import warnings
@@ -20,7 +22,7 @@
if (len(data) >= 8) and (version == 1):
# AAT Apple's "new" format. Hm.
version, nTables = struct.unpack(">LL", data[:8])
- self.version = version / float(0x10000)
+ self.version = fi2fl(version, 16)
data = data[8:]
apple = True
else:
@@ -36,7 +38,7 @@
else:
version, length = struct.unpack(">HH", data[:4])
length = int(length)
- if not kern_classes.has_key(version):
+ if version not in kern_classes:
subtable = KernTable_format_unkown(version)
else:
subtable = kern_classes[version]()
@@ -52,7 +54,7 @@
nTables = 0
if self.version == 1.0:
# AAT Apple's "new" format.
- data = struct.pack(">ll", self.version * 0x10000, nTables)
+ data = struct.pack(">ll", fl2fi(self.version, 16), nTables)
else:
data = struct.pack(">HH", self.version, nTables)
if hasattr(self, "kernTables"):
@@ -66,24 +68,24 @@
for subtable in self.kernTables:
subtable.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "version":
self.version = safeEval(attrs["value"])
return
- if name <> "kernsubtable":
+ if name != "kernsubtable":
return
if not hasattr(self, "kernTables"):
self.kernTables = []
format = safeEval(attrs["format"])
- if not kern_classes.has_key(format):
+ if format not in kern_classes:
subtable = KernTable_format_unkown(format)
else:
subtable = kern_classes[format]()
self.kernTables.append(subtable)
- subtable.fromXML((name, attrs, content), ttFont)
+ subtable.fromXML(name, attrs, content, ttFont)
-class KernTable_format_0:
+class KernTable_format_0(object):
def decompile(self, data, ttFont):
version, length, coverage = (0,0,0)
@@ -103,7 +105,7 @@
for k in range(nPairs):
if len(data) < 6:
# buggy kern table
- data = ""
+ data = b""
break
left, right, value = struct.unpack(">HHh", data[:6])
data = data[6:]
@@ -120,10 +122,8 @@
data = struct.pack(">HHHH", nPairs, searchRange, entrySelector, rangeShift)
# yeehee! (I mean, turn names into indices)
- kernTable = map(lambda ((left, right), value), getGlyphID=ttFont.getGlyphID:
- (getGlyphID(left), getGlyphID(right), value),
- self.kernTable.items())
- kernTable.sort()
+ getGlyphID = ttFont.getGlyphID
+ kernTable = sorted((getGlyphID(left), getGlyphID(right), value) for ((left,right),value) in self.kernTable.items())
for left, right, value in kernTable:
data = data + struct.pack(">HHh", left, right, value)
return struct.pack(">HHH", self.version, len(data) + 6, self.coverage) + data
@@ -131,8 +131,7 @@
def toXML(self, writer, ttFont):
writer.begintag("kernsubtable", coverage=self.coverage, format=0)
writer.newline()
- items = self.kernTable.items()
- items.sort()
+ items = sorted(self.kernTable.items())
for (left, right), value in items:
writer.simpletag("pair", [
("l", left),
@@ -143,13 +142,13 @@
writer.endtag("kernsubtable")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.coverage = safeEval(attrs["coverage"])
self.version = safeEval(attrs["format"])
if not hasattr(self, "kernTable"):
self.kernTable = {}
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
self.kernTable[(attrs["l"], attrs["r"])] = safeEval(attrs["v"])
@@ -162,15 +161,9 @@
def __delitem__(self, pair):
del self.kernTable[pair]
-
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.__dict__, other.__dict__)
-class KernTable_format_2:
+class KernTable_format_2(object):
def decompile(self, data, ttFont):
self.data = data
@@ -185,11 +178,11 @@
writer.endtag("kernsubtable")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.decompile(readHex(content), ttFont)
-class KernTable_format_unkown:
+class KernTable_format_unkown(object):
def __init__(self, format):
self.format = format
@@ -209,7 +202,7 @@
writer.endtag("kernsubtable")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.decompile(readHex(content), ttFont)
diff --git a/Lib/fontTools/ttLib/tables/_l_o_c_a.py b/Lib/fontTools/ttLib/tables/_l_o_c_a.py
index 21c31ad..daa9d03 100644
--- a/Lib/fontTools/ttLib/tables/_l_o_c_a.py
+++ b/Lib/fontTools/ttLib/tables/_l_o_c_a.py
@@ -1,8 +1,8 @@
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from . import DefaultTable
import sys
-import DefaultTable
import array
-from fontTools import ttLib
-import struct
import warnings
class table__l_o_c_a(DefaultTable.DefaultTable):
@@ -17,7 +17,7 @@
format = "H"
locations = array.array(format)
locations.fromstring(data)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
locations.byteswap()
if not longFormat:
l = array.array("I")
@@ -37,12 +37,12 @@
if max_location < 0x20000:
locations = array.array("H")
for i in range(len(self.locations)):
- locations.append(self.locations[i] / 2)
+ locations.append(self.locations[i] // 2)
ttFont['head'].indexToLocFormat = 0
else:
locations = array.array("I", self.locations)
ttFont['head'].indexToLocFormat = 1
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
locations.byteswap()
return locations.tostring()
@@ -58,10 +58,4 @@
def __len__(self):
return len(self.locations)
-
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.locations, other.locations)
diff --git a/Lib/fontTools/ttLib/tables/_m_a_x_p.py b/Lib/fontTools/ttLib/tables/_m_a_x_p.py
index 5aafe90..2f42ae5 100644
--- a/Lib/fontTools/ttLib/tables/_m_a_x_p.py
+++ b/Lib/fontTools/ttLib/tables/_m_a_x_p.py
@@ -1,6 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
maxpFormat_0_5 = """
> # big endian
@@ -38,7 +40,7 @@
assert len(data) == 0
def compile(self, ttFont):
- if ttFont.has_key('glyf'):
+ if 'glyf' in ttFont:
if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
self.recalc(ttFont)
else:
@@ -75,7 +77,7 @@
for glyphName in ttFont.getGlyphOrder():
g = glyfTable[glyphName]
if g.numberOfContours:
- if hmtxTable[glyphName][1] <> g.xMin:
+ if hmtxTable[glyphName][1] != g.xMin:
allXMaxIsLsb = 0
xMin = min(xMin, g.xMin)
yMin = min(yMin, g.yMin)
@@ -112,12 +114,11 @@
headTable.flags = headTable.flags & ~0x2
def testrepr(self):
- items = self.__dict__.items()
- items.sort()
- print ". . . . . . . . ."
+ items = sorted(self.__dict__.items())
+ print(". . . . . . . . .")
for combo in items:
- print " %s: %s" % combo
- print ". . . . . . . . ."
+ print(" %s: %s" % combo)
+ print(". . . . . . . . .")
def toXML(self, writer, ttFont):
if self.tableVersion != 0x00005000:
@@ -129,14 +130,12 @@
names = names + names_1_0
for name in names:
value = getattr(self, name)
- if type(value) == type(0L):
- value=int(value)
if name == "tableVersion":
value = hex(value)
writer.simpletag(name, value=value)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
setattr(self, name, safeEval(attrs["value"]))
diff --git a/Lib/fontTools/ttLib/tables/_n_a_m_e.py b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
index 5234ae1..b6cc19b 100644
--- a/Lib/fontTools/ttLib/tables/_n_a_m_e.py
+++ b/Lib/fontTools/ttLib/tables/_n_a_m_e.py
@@ -1,9 +1,9 @@
-import DefaultTable
-import struct
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
-import string
-import types
+from . import DefaultTable
+import struct
nameRecordFormat = """
> # big endian
@@ -25,8 +25,7 @@
expectedStringOffset = 6 + n * nameRecordSize
if stringOffset != expectedStringOffset:
# XXX we need a warn function
- print "Warning: 'name' table stringOffset incorrect.",
- print "Expected: %s; Actual: %s" % (expectedStringOffset, stringOffset)
+ print("Warning: 'name' table stringOffset incorrect. Expected: %s; Actual: %s" % (expectedStringOffset, stringOffset))
stringData = data[stringOffset:]
data = data[6:]
self.names = []
@@ -49,8 +48,8 @@
# only happens when there are NO name table entries read
# from the TTX file
self.names = []
- self.names.sort() # sort according to the spec; see NameRecord.__cmp__()
- stringData = ""
+ self.names.sort() # sort according to the spec; see NameRecord.__lt__()
+ stringData = b""
format = 0
n = len(self.names)
stringOffset = 6 + n * sstruct.calcsize(nameRecordFormat)
@@ -58,7 +57,7 @@
lastoffset = 0
done = {} # remember the data so we can reuse the "pointers"
for name in self.names:
- if done.has_key(name.string):
+ if name.string in done:
name.offset, name.length = done[name.string]
else:
name.offset, name.length = done[name.string] = len(stringData), len(name.string)
@@ -70,14 +69,14 @@
for name in self.names:
name.toXML(writer, ttFont)
- def fromXML(self, (name, attrs, content), ttFont):
- if name <> "namerecord":
+ def fromXML(self, name, attrs, content, ttFont):
+ if name != "namerecord":
return # ignore unknown tags
if not hasattr(self, "names"):
self.names = []
name = NameRecord()
self.names.append(name)
- name.fromXML((name, attrs, content), ttFont)
+ name.fromXML(name, attrs, content, ttFont)
def getName(self, nameID, platformID, platEncID, langID=None):
for namerecord in self.names:
@@ -88,14 +87,8 @@
return namerecord
return None # not found
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
- return cmp(self.names, other.names)
-
-
-class NameRecord:
+class NameRecord(object):
def toXML(self, writer, ttFont):
writer.begintag("namerecord", [
@@ -109,52 +102,47 @@
if len(self.string) % 2:
# no, shouldn't happen, but some of the Apple
# tools cause this anyway :-(
- writer.write16bit(self.string + "\0")
+ writer.write16bit(self.string + b"\0", strip=True)
else:
- writer.write16bit(self.string)
+ writer.write16bit(self.string, strip=True)
else:
- writer.write8bit(self.string)
+ writer.write8bit(self.string, strip=True)
writer.newline()
writer.endtag("namerecord")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
self.nameID = safeEval(attrs["nameID"])
self.platformID = safeEval(attrs["platformID"])
self.platEncID = safeEval(attrs["platEncID"])
self.langID = safeEval(attrs["langID"])
+ s = strjoin(content).strip()
if self.platformID == 0 or (self.platformID == 3 and self.platEncID in (0, 1)):
- s = ""
- for element in content:
- s = s + element
- s = unicode(s, "utf8")
- s = s.strip()
self.string = s.encode("utf_16_be")
else:
- s = string.strip(string.join(content, ""))
- self.string = unicode(s, "utf8").encode("latin1")
+ # This is the inverse of write8bit...
+ self.string = s.encode("latin1")
- def __cmp__(self, other):
- """Compare method, so a list of NameRecords can be sorted
- according to the spec by just sorting it..."""
+ def __lt__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
- if type(self) != type(other): return cmp(type(self), type(other))
-
- selftuple = (
+ # implemented so that list.sort() sorts according to the spec.
+ selfTuple = (
getattr(self, "platformID", None),
getattr(self, "platEncID", None),
getattr(self, "langID", None),
getattr(self, "nameID", None),
getattr(self, "string", None),
)
- othertuple = (
+ otherTuple = (
getattr(other, "platformID", None),
getattr(other, "platEncID", None),
getattr(other, "langID", None),
getattr(other, "nameID", None),
getattr(other, "string", None),
)
- return cmp(selftuple, othertuple)
+ return selfTuple < otherTuple
def __repr__(self):
return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (
diff --git a/Lib/fontTools/ttLib/tables/_p_o_s_t.py b/Lib/fontTools/ttLib/tables/_p_o_s_t.py
index 82e91bc..eae5863 100644
--- a/Lib/fontTools/ttLib/tables/_p_o_s_t.py
+++ b/Lib/fontTools/ttLib/tables/_p_o_s_t.py
@@ -1,12 +1,13 @@
-import sys
-from fontTools.ttLib.standardGlyphOrder import standardGlyphOrder
-import DefaultTable
-import struct
-from fontTools.misc import sstruct
-import array
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools import ttLib
+from fontTools.ttLib.standardGlyphOrder import standardGlyphOrder
+from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval, readHex
-from types import TupleType
+from . import DefaultTable
+import sys
+import struct
+import array
postFormat = """
@@ -38,7 +39,7 @@
self.decode_format_3_0(data, ttFont)
else:
# supported format
- raise ttLib.TTLibError, "'post' table format %f not supported" % self.formatType
+ raise ttLib.TTLibError("'post' table format %f not supported" % self.formatType)
def compile(self, ttFont):
data = sstruct.pack(postFormat, self)
@@ -50,7 +51,7 @@
pass # we're done
else:
# supported format
- raise ttLib.TTLibError, "'post' table format %f not supported" % self.formatType
+ raise ttLib.TTLibError("'post' table format %f not supported" % self.formatType)
return data
def getGlyphOrder(self):
@@ -59,7 +60,7 @@
or its relatives instead!
"""
if not hasattr(self, "glyphOrder"):
- raise ttLib.TTLibError, "illegal use of getGlyphOrder()"
+ raise ttLib.TTLibError("illegal use of getGlyphOrder()")
glyphOrder = self.glyphOrder
del self.glyphOrder
return glyphOrder
@@ -79,7 +80,7 @@
data = data[2:]
indices = array.array("H")
indices.fromstring(data[:2*numGlyphs])
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
indices.byteswap()
data = data[2*numGlyphs:]
self.extraNames = extraNames = unpackPStrings(data)
@@ -105,11 +106,11 @@
allNames = {}
for i in range(ttFont['maxp'].numGlyphs):
glyphName = psName = self.glyphOrder[i]
- if allNames.has_key(glyphName):
+ if glyphName in allNames:
# make up a new glyphName that's unique
n = allNames[glyphName]
allNames[glyphName] = n + 1
- glyphName = glyphName + "#" + `n`
+ glyphName = glyphName + "#" + repr(n)
self.glyphOrder[i] = glyphName
mapping[glyphName] = psName
else:
@@ -132,11 +133,11 @@
extraDict[extraNames[i]] = i
for glyphID in range(numGlyphs):
glyphName = glyphOrder[glyphID]
- if self.mapping.has_key(glyphName):
+ if glyphName in self.mapping:
psName = self.mapping[glyphName]
else:
psName = glyphName
- if extraDict.has_key(psName):
+ if psName in extraDict:
index = 258 + extraDict[psName]
elif psName in standardGlyphOrder:
index = standardGlyphOrder.index(psName)
@@ -145,7 +146,7 @@
extraDict[psName] = len(extraNames)
extraNames.append(psName)
indices.append(index)
- if sys.byteorder <> "big":
+ if sys.byteorder != "big":
indices.byteswap()
return struct.pack(">H", numGlyphs) + indices.tostring() + packPStrings(extraNames)
@@ -165,8 +166,7 @@
"ps name mapping for those cases where they differ. That's what\n"
"you see below.\n")
writer.newline()
- items = self.mapping.items()
- items.sort()
+ items = sorted(self.mapping.items())
for name, psName in items:
writer.simpletag("psName", name=name, psName=psName)
writer.newline()
@@ -189,13 +189,13 @@
writer.endtag("hexdata")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name not in ("psNames", "extraNames", "hexdata"):
setattr(self, name, safeEval(attrs["value"]))
elif name == "psNames":
self.mapping = {}
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == "psName":
@@ -203,7 +203,7 @@
elif name == "extraNames":
self.extraNames = []
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
if name == "psName":
@@ -217,15 +217,15 @@
index = 0
dataLen = len(data)
while index < dataLen:
- length = ord(data[index])
- strings.append(data[index+1:index+1+length])
+ length = byteord(data[index])
+ strings.append(tostr(data[index+1:index+1+length]))
index = index + 1 + length
return strings
def packPStrings(strings):
- data = ""
+ data = b""
for s in strings:
- data = data + chr(len(s)) + s
+ data = data + bytechr(len(s)) + tobytes(s)
return data
diff --git a/Lib/fontTools/ttLib/tables/_v_h_e_a.py b/Lib/fontTools/ttLib/tables/_v_h_e_a.py
index 9adc63b..0ed0b7a 100644
--- a/Lib/fontTools/ttLib/tables/_v_h_e_a.py
+++ b/Lib/fontTools/ttLib/tables/_v_h_e_a.py
@@ -1,6 +1,8 @@
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
+from . import DefaultTable
vheaFormat = """
> # big endian
@@ -36,7 +38,7 @@
def recalc(self, ttFont):
vtmxTable = ttFont['vmtx']
- if ttFont.has_key('glyf'):
+ if 'glyf' in ttFont:
if not ttFont.isLoaded('glyf'):
return
glyfTable = ttFont['glyf']
@@ -68,11 +70,9 @@
formatstring, names, fixes = sstruct.getformat(vheaFormat)
for name in names:
value = getattr(self, name)
- if type(value) == type(0L):
- value = int(value)
writer.simpletag(name, value=value)
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
setattr(self, name, safeEval(attrs["value"]))
diff --git a/Lib/fontTools/ttLib/tables/asciiTable.py b/Lib/fontTools/ttLib/tables/asciiTable.py
index ee9455d..87ef62a 100644
--- a/Lib/fontTools/ttLib/tables/asciiTable.py
+++ b/Lib/fontTools/ttLib/tables/asciiTable.py
@@ -1,22 +1,23 @@
-import string
-import DefaultTable
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from . import DefaultTable
class asciiTable(DefaultTable.DefaultTable):
def toXML(self, writer, ttFont):
- data = self.data
+ data = tostr(self.data)
# removing null bytes. XXX needed??
- data = string.split(data, '\0')
- data = string.join(data, '')
+ data = data.split('\0')
+ data = strjoin(data)
writer.begintag("source")
writer.newline()
- writer.write_noindent(string.replace(data, "\r", "\n"))
+ writer.write_noindent(data.replace("\r", "\n"))
writer.newline()
writer.endtag("source")
writer.newline()
- def fromXML(self, (name, attrs, content), ttFont):
- lines = string.split(string.replace(string.join(content, ""), "\r", "\n"), "\n")
- self.data = string.join(lines[1:-1], "\r")
+ def fromXML(self, name, attrs, content, ttFont):
+ lines = strjoin(content).replace("\r", "\n").split("\n")
+ self.data = tobytes("\r".join(lines[1:-1]))
diff --git a/Lib/fontTools/ttLib/tables/otBase.py b/Lib/fontTools/ttLib/tables/otBase.py
index d3f4eb3..bf010b5 100644
--- a/Lib/fontTools/ttLib/tables/otBase.py
+++ b/Lib/fontTools/ttLib/tables/otBase.py
@@ -1,9 +1,9 @@
-from DefaultTable import DefaultTable
-import otData
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from .DefaultTable import DefaultTable
import struct
-from types import TupleType
-class OverflowErrorRecord:
+class OverflowErrorRecord(object):
def __init__(self, overflowTuple):
self.tableType = overflowTuple[0]
self.LookupListIndex = overflowTuple[1]
@@ -30,9 +30,9 @@
"""
def decompile(self, data, font):
- import otTables
+ from . import otTables
cachingStats = None if True else {}
- class GlobalState:
+ class GlobalState(object):
def __init__(self, tableType, cachingStats):
self.tableType = tableType
self.cachingStats = cachingStats
@@ -43,15 +43,14 @@
self.table = tableClass()
self.table.decompile(reader, font)
if cachingStats:
- stats = [(v, k) for k, v in cachingStats.items()]
- stats.sort()
+ stats = sorted([(v, k) for k, v in cachingStats.items()])
stats.reverse()
- print "cachingsstats for ", self.tableTag
+ print("cachingsstats for ", self.tableTag)
for v, k in stats:
if v < 2:
break
- print v, k
- print "---", len(stats)
+ print(v, k)
+ print("---", len(stats))
def compile(self, font):
""" Create a top-level OTFWriter for the GPOS/GSUB table.
@@ -74,7 +73,7 @@
If a lookup subtable overflows an offset, we have to start all over.
"""
- class GlobalState:
+ class GlobalState(object):
def __init__(self, tableType):
self.tableType = tableType
globalState = GlobalState(tableType=self.tableTag)
@@ -86,12 +85,12 @@
def toXML(self, writer, font):
self.table.toXML2(writer, font)
- def fromXML(self, (name, attrs, content), font):
- import otTables
+ def fromXML(self, name, attrs, content, font):
+ from . import otTables
if not hasattr(self, "table"):
tableClass = getattr(otTables, self.tableTag)
self.table = tableClass()
- self.table.fromXML((name, attrs, content), font)
+ self.table.fromXML(name, attrs, content, font)
class OTTableReader(object):
@@ -138,8 +137,7 @@
def readUInt24(self):
pos = self.pos
newpos = pos + 3
- value = (ord(self.data[pos]) << 16) | (ord(self.data[pos+1]) << 8) | ord(self.data[pos+2])
- value, = struct.unpack(">H", self.data[pos:newpos])
+ value, = struct.unpack(">l", b'\0'+self.data[pos:newpos])
self.pos = newpos
return value
@@ -153,7 +151,7 @@
def readTag(self):
pos = self.pos
newpos = pos + 4
- value = self.data[pos:newpos]
+ value = Tag(self.data[pos:newpos])
assert len(value) == 4
self.pos = newpos
return value
@@ -214,7 +212,7 @@
tableData = table.getData()
data.append(tableData)
- return "".join(data)
+ return bytesjoin(data)
def getDataLength(self):
"""Return the length of this table in bytes, without subtables."""
@@ -280,19 +278,18 @@
overflowErrorRecord = self.getOverflowErrorRecord(item)
- raise OTLOffsetOverflowError, overflowErrorRecord
+ raise OTLOffsetOverflowError(overflowErrorRecord)
- return "".join(items)
+ return bytesjoin(items)
def __hash__(self):
# only works after self._doneWriting() has been called
return hash(self.items)
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.items, other.items)
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self.items == other.items
def _doneWriting(self, internedTables=None):
# Convert CountData references to data string items
@@ -305,7 +302,7 @@
if internedTables is None:
internedTables = {}
items = self.items
- iRange = range(len(items))
+ iRange = list(range(len(items)))
if hasattr(self, "Extension"):
newTree = 1
@@ -320,7 +317,7 @@
item._doneWriting()
else:
item._doneWriting(internedTables)
- if internedTables.has_key(item):
+ if item in internedTables:
items[i] = item = internedTables[item]
else:
internedTables[item] = item
@@ -342,7 +339,7 @@
done[self] = 1
numItems = len(self.items)
- iRange = range(numItems)
+ iRange = list(range(numItems))
iRange.reverse()
if hasattr(self, "Extension"):
@@ -359,7 +356,7 @@
if hasattr(item, "name") and (item.name == "Coverage"):
sortCoverageLast = 1
break
- if not done.has_key(item):
+ if item not in done:
item._gatherTables(tables, extTables, done)
else:
index = max(item.parent.keys())
@@ -380,7 +377,7 @@
newDone = {}
item._gatherTables(extTables, None, newDone)
- elif not done.has_key(item):
+ elif item not in done:
item._gatherTables(tables, extTables, done)
else:
index = max(item.parent.keys())
@@ -408,7 +405,8 @@
def writeUInt24(self, value):
assert 0 <= value < 0x1000000
- self.items.append(''.join(chr(v) for v in (value>>16, (value>>8)&0xFF, value&0xff)))
+ b = struct.pack(">L", value)
+ self.items.append(b[1:])
def writeLong(self, value):
self.items.append(struct.pack(">l", value))
@@ -417,6 +415,7 @@
self.items.append(struct.pack(">L", value))
def writeTag(self, tag):
+ tag = Tag(tag).tobytes()
assert len(tag) == 4
self.items.append(tag)
@@ -429,7 +428,7 @@
return ref
def writeStruct(self, format, values):
- data = apply(struct.pack, (format,) + values)
+ data = struct.pack(*(format,) + values)
self.items.append(data)
def writeData(self, data):
@@ -469,7 +468,7 @@
return OverflowErrorRecord( (self.globalState.tableType, LookupListIndex, SubTableIndex, itemName, itemIndex) )
-class CountReference:
+class CountReference(object):
"""A reference to a Count value, not a count of references."""
def __init__(self, table, name):
self.table = table
@@ -514,14 +513,14 @@
if self.recurse > 2:
# shouldn't ever get here - we should only get to two levels of recursion.
# this guards against self.decompile NOT setting compileStatus to other than 1.
- raise AttributeError, attr
+ raise AttributeError(attr)
if self.compileStatus == 1:
self.ensureDecompiled()
val = getattr(self, attr)
self.recurse -=1
return val
- raise AttributeError, attr
+ raise AttributeError(attr)
"""Generic base class for all OpenType (sub)tables."""
@@ -659,7 +658,7 @@
value = getattr(self, conv.name)
conv.xmlWrite(xmlWriter, font, value, conv.name, [])
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
try:
conv = self.getConverterByName(name)
except KeyError:
@@ -674,13 +673,14 @@
else:
setattr(self, conv.name, value)
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
self.ensureDecompiled()
+ other.ensureDecompiled()
- return cmp(self.__dict__, other.__dict__)
+ return self.__dict__ == other.__dict__
class FormatSwitchingBaseTable(BaseTable):
@@ -696,7 +696,7 @@
def readFormat(self, reader):
self.Format = reader.readUShort()
- assert self.Format <> 0, (self, reader.pos, len(reader.data))
+ assert self.Format != 0, (self, reader.pos, len(reader.data))
def writeFormat(self, writer):
writer.writeUShort(self.Format)
@@ -740,7 +740,7 @@
valueRecordFormatDict = _buildDict()
-class ValueRecordFactory:
+class ValueRecordFactory(object):
"""Given a format code, this object convert ValueRecords."""
@@ -763,7 +763,7 @@
value = reader.readUShort()
if isDevice:
if value:
- import otTables
+ from . import otTables
subReader = reader.getSubReader(value)
value = getattr(otTables, name)()
value.decompile(subReader, font)
@@ -788,7 +788,7 @@
writer.writeUShort(value)
-class ValueRecord:
+class ValueRecord(object):
# see ValueRecordFactory
@@ -824,23 +824,23 @@
xmlWriter.simpletag(valueName, simpleItems)
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
- import otTables
+ def fromXML(self, name, attrs, content, font):
+ from . import otTables
for k, v in attrs.items():
setattr(self, k, int(v))
for element in content:
- if type(element) <> TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
value = getattr(otTables, name)()
for elem2 in content:
- if type(elem2) <> TupleType:
+ if not isinstance(elem2, tuple):
continue
- value.fromXML(elem2, font)
+ name2, attrs2, content2 = elem2
+ value.fromXML(name2, attrs2, content2, font)
setattr(self, name, value)
- def __cmp__(self, other):
- if type(self) != type(other): return cmp(type(self), type(other))
- if self.__class__ != other.__class__: return cmp(self.__class__, other.__class__)
-
- return cmp(self.__dict__, other.__dict__)
+ def __eq__(self, other):
+ if type(self) != type(other):
+ raise TypeError("unordered types %s() < %s()", type(self), type(other))
+ return self.__dict__ == other.__dict__
diff --git a/Lib/fontTools/ttLib/tables/otConverters.py b/Lib/fontTools/ttLib/tables/otConverters.py
index 0266c71..871ec1d 100644
--- a/Lib/fontTools/ttLib/tables/otConverters.py
+++ b/Lib/fontTools/ttLib/tables/otConverters.py
@@ -1,6 +1,8 @@
-from types import TupleType
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval
-from otBase import ValueRecordFactory
+from fontTools.misc.fixedTools import fixedToFloat as fi2fl, floatToFixed as fl2fi
+from .otBase import ValueRecordFactory
def buildConverters(tableSpec, tableNamespace):
@@ -38,7 +40,7 @@
for cls in conv.featureParamTypes.values():
convertersByName[cls.__name__] = Table(name, repeat, aux, cls)
converters.append(conv)
- assert not convertersByName.has_key(name)
+ assert name not in convertersByName
convertersByName[name] = conv
return converters, convertersByName
@@ -58,19 +60,19 @@
def read(self, reader, font, tableDict):
"""Read a value from the reader."""
- raise NotImplementedError, self
+ raise NotImplementedError(self)
def write(self, writer, font, tableDict, value, repeatIndex=None):
"""Write a value to the writer."""
- raise NotImplementedError, self
+ raise NotImplementedError(self)
def xmlRead(self, attrs, content, font):
"""Read a value from XML."""
- raise NotImplementedError, self
+ raise NotImplementedError(self)
def xmlWrite(self, xmlWriter, font, value, name, attrs):
"""Write a value to XML."""
- raise NotImplementedError, self
+ raise NotImplementedError(self)
class SimpleValue(BaseConverter):
@@ -94,10 +96,10 @@
def read(self, reader, font, tableDict):
value = reader.readLong()
assert (value >> 16) == 1, "Unsupported version 0x%08x" % value
- return float(value) / 0x10000
+ return fi2fl(value, 16)
def write(self, writer, font, tableDict, value, repeatIndex=None):
if value < 0x10000:
- value *= 0x10000
+ value = fl2fi(value, 16)
value = int(round(value))
assert (value >> 16) == 1, "Unsupported version 0x%08x" % value
writer.writeLong(value)
@@ -105,14 +107,14 @@
value = attrs["value"]
value = float(int(value, 0)) if value.startswith("0") else float(value)
if value >= 0x10000:
- value = float(value) / 0x10000
+ value = fi2fl(value, 16)
return value
def xmlWrite(self, xmlWriter, font, value, name, attrs):
if value >= 0x10000:
- value = float(value) / 0x10000
+ value = fi2fl(value, 16)
if value % 1 != 0:
# Write as hex
- value = "0x%08x" % (int(round(value * 0x10000)))
+ value = "0x%08x" % fl2fi(value, 16)
xmlWriter.simpletag(name, attrs + [("value", value)])
xmlWriter.newline()
@@ -162,7 +164,7 @@
class DeciPoints(FloatValue):
def read(self, reader, font, tableDict):
value = reader.readUShort()
- return value / 10.
+ return value / 10
def write(self, writer, font, tableDict, value, repeatIndex=None):
writer.writeUShort(int(round(value * 10)))
@@ -198,9 +200,9 @@
if Format is not None:
table.Format = int(Format)
for element in content:
- if type(element) == TupleType:
+ if isinstance(element, tuple):
name, attrs, content = element
- table.fromXML((name, attrs, content), font)
+ table.fromXML(name, attrs, content, font)
else:
pass
return table
@@ -225,8 +227,8 @@
return None
if offset <= 3:
# XXX hack to work around buggy pala.ttf
- print "*** Warning: offset is not 0, yet suspiciously low (%s). table: %s" \
- % (offset, self.tableClass.__name__)
+ print("*** Warning: offset is not 0, yet suspiciously low (%s). table: %s" \
+ % (offset, self.tableClass.__name__))
return None
table = self.tableClass()
table.reader = reader.getSubReader(offset)
@@ -298,9 +300,9 @@
else:
value.toXML(xmlWriter, font, self.name, attrs)
def xmlRead(self, attrs, content, font):
- from otBase import ValueRecord
+ from .otBase import ValueRecord
value = ValueRecord()
- value.fromXML((None, attrs, content), font)
+ value.fromXML(None, attrs, content, font)
return value
@@ -347,7 +349,7 @@
if shift == 0:
writer.writeUShort(tmp)
tmp, shift = 0, 16
- if shift <> 16:
+ if shift != 16:
writer.writeUShort(tmp)
def xmlWrite(self, xmlWriter, font, value, name, attrs):
diff --git a/Lib/fontTools/ttLib/tables/otData.py b/Lib/fontTools/ttLib/tables/otData.py
index e06bd42..4808dd0 100644
--- a/Lib/fontTools/ttLib/tables/otData.py
+++ b/Lib/fontTools/ttLib/tables/otData.py
@@ -639,7 +639,7 @@
('Offset', 'AttachList', None, None, 'Offset to list of glyphs with attachment points-from beginning of GDEF header (may be NULL)'),
('Offset', 'LigCaretList', None, None, 'Offset to list of positioning points for ligature carets-from beginning of GDEF header (may be NULL)'),
('Offset', 'MarkAttachClassDef', None, None, 'Offset to class definition table for mark attachment type-from beginning of GDEF header (may be NULL)'),
- ('Offset', 'MarkGlyphSetsDef', None, 'Version >= 0x00010002 / float(0x10000)', 'Offset to the table of mark set definitions-from beginning of GDEF header (may be NULL)'),
+ ('Offset', 'MarkGlyphSetsDef', None, 'int(round(Version*0x10000)) >= 0x00010002', 'Offset to the table of mark set definitions-from beginning of GDEF header (may be NULL)'),
]),
('AttachList', [
diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py
index 584d0c5..54a684f 100644
--- a/Lib/fontTools/ttLib/tables/otTables.py
+++ b/Lib/fontTools/ttLib/tables/otTables.py
@@ -4,9 +4,10 @@
Most are constructed upon import from data in otData.py, all are populated with
converter objects from otConverters.py.
"""
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
+from .otBase import BaseTable, FormatSwitchingBaseTable
import operator
-from otBase import BaseTable, FormatSwitchingBaseTable
-from types import TupleType
import warnings
@@ -42,7 +43,7 @@
# Some SIL fonts have coverage entries that don't have sorted
# StartCoverageIndex. If it is so, fixup and warn. We undo
# this when writing font out.
- sorted_ranges = sorted(ranges, cmp=lambda a,b: cmp(a.StartCoverageIndex,b.StartCoverageIndex))
+ sorted_ranges = sorted(ranges, key=lambda a: a.StartCoverageIndex)
if ranges != sorted_ranges:
warnings.warn("GSUB/GPOS Coverage is not sorted by glyph ids.")
ranges = sorted_ranges
@@ -105,7 +106,7 @@
index = index + end - start + 1
if brokenOrder:
warnings.warn("GSUB/GPOS Coverage is not sorted by glyph ids.")
- ranges.sort(cmp=lambda a,b: cmp(a.StartID,b.StartID))
+ ranges.sort(key=lambda a: a.StartID)
for r in ranges:
del r.StartID
format = 2
@@ -120,7 +121,7 @@
xmlWriter.simpletag("Glyph", value=glyphName)
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
glyphs = getattr(self, "glyphs", None)
if glyphs is None:
glyphs = []
@@ -142,16 +143,16 @@
if self.Format == 1:
delta = rawTable["DeltaGlyphID"]
inputGIDS = [ font.getGlyphID(name) for name in input ]
- inputGIDS = map(doModulo, inputGIDS)
+ inputGIDS = map(doModulo, inputGIDS)
outGIDS = [ glyphID + delta for glyphID in inputGIDS ]
- outGIDS = map(doModulo, outGIDS)
+ outGIDS = map(doModulo, outGIDS)
outNames = [ font.getGlyphName(glyphID) for glyphID in outGIDS ]
- map(operator.setitem, [mapping]*lenMapping, input, outNames)
+ list(map(operator.setitem, [mapping]*lenMapping, input, outNames))
elif self.Format == 2:
assert len(input) == rawTable["GlyphCount"], \
"invalid SingleSubstFormat2 table"
subst = rawTable["Substitute"]
- map(operator.setitem, [mapping]*lenMapping, input, subst)
+ list(map(operator.setitem, [mapping]*lenMapping, input, subst))
else:
assert 0, "unknown format: %s" % self.Format
self.mapping = mapping
@@ -160,11 +161,10 @@
mapping = getattr(self, "mapping", None)
if mapping is None:
mapping = self.mapping = {}
- items = mapping.items()
+ items = list(mapping.items())
getGlyphID = font.getGlyphID
gidItems = [(getGlyphID(item[0]), getGlyphID(item[1])) for item in items]
- sortableItems = zip(gidItems, items)
- sortableItems.sort()
+ sortableItems = sorted(zip(gidItems, items))
# figure out format
format = 2
@@ -193,14 +193,13 @@
return rawTable
def toXML2(self, xmlWriter, font):
- items = self.mapping.items()
- items.sort()
+ items = sorted(self.mapping.items())
for inGlyph, outGlyph in items:
xmlWriter.simpletag("Substitution",
[("in", inGlyph), ("out", outGlyph)])
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
mapping = getattr(self, "mapping", None)
if mapping is None:
mapping = {}
@@ -219,10 +218,10 @@
classList = rawTable["ClassValueArray"]
lenList = len(classList)
glyphID = font.getGlyphID(start)
- gidList = range(glyphID, glyphID + len(classList))
+ gidList = list(range(glyphID, glyphID + len(classList)))
keyList = [getGlyphName(glyphID) for glyphID in gidList]
- map(operator.setitem, [classDefs]*lenList, keyList, classList)
+ list(map(operator.setitem, [classDefs]*lenList, keyList, classList))
elif self.Format == 2:
records = rawTable["ClassRangeRecord"]
@@ -231,10 +230,10 @@
end = rec.End
cls = rec.Class
classDefs[start] = cls
- glyphIDs = range(font.getGlyphID(start) + 1, font.getGlyphID(end))
+ glyphIDs = list(range(font.getGlyphID(start) + 1, font.getGlyphID(end)))
lenList = len(glyphIDs)
keyList = [getGlyphName(glyphID) for glyphID in glyphIDs]
- map(operator.setitem, [classDefs]*lenList, keyList, [cls]*lenList)
+ list(map(operator.setitem, [classDefs]*lenList, keyList, [cls]*lenList))
classDefs[end] = cls
else:
assert 0, "unknown format: %s" % self.Format
@@ -244,7 +243,7 @@
classDefs = getattr(self, "classDefs", None)
if classDefs is None:
classDefs = self.classDefs = {}
- items = classDefs.items()
+ items = list(classDefs.items())
getGlyphID = font.getGlyphID
for i in range(len(items)):
glyphName, cls = items[i]
@@ -273,13 +272,12 @@
return {"ClassRangeRecord": ranges}
def toXML2(self, xmlWriter, font):
- items = self.classDefs.items()
- items.sort()
+ items = sorted(self.classDefs.items())
for glyphName, cls in items:
xmlWriter.simpletag("ClassDef", [("glyph", glyphName), ("class", cls)])
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
classDefs = getattr(self, "classDefs", None)
if classDefs is None:
classDefs = {}
@@ -307,7 +305,7 @@
alternates = getattr(self, "alternates", None)
if alternates is None:
alternates = self.alternates = {}
- items = alternates.items()
+ items = list(alternates.items())
for i in range(len(items)):
glyphName, set = items[i]
items[i] = font.getGlyphID(glyphName), glyphName, set
@@ -329,8 +327,7 @@
return {"Coverage": cov, "AlternateSet": alternates}
def toXML2(self, xmlWriter, font):
- items = self.alternates.items()
- items.sort()
+ items = sorted(self.alternates.items())
for glyphName, alternates in items:
xmlWriter.begintag("AlternateSet", glyph=glyphName)
xmlWriter.newline()
@@ -340,7 +337,7 @@
xmlWriter.endtag("AlternateSet")
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
alternates = getattr(self, "alternates", None)
if alternates is None:
alternates = {}
@@ -349,7 +346,7 @@
set = []
alternates[glyphName] = set
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
set.append(attrs["glyph"])
@@ -373,7 +370,7 @@
ligatures = getattr(self, "ligatures", None)
if ligatures is None:
ligatures = self.ligatures = {}
- items = ligatures.items()
+ items = list(ligatures.items())
for i in range(len(items)):
glyphName, set = items[i]
items[i] = font.getGlyphID(glyphName), glyphName, set
@@ -396,8 +393,7 @@
return {"Coverage": cov, "LigatureSet": ligSets}
def toXML2(self, xmlWriter, font):
- items = self.ligatures.items()
- items.sort()
+ items = sorted(self.ligatures.items())
for glyphName, ligSets in items:
xmlWriter.begintag("LigatureSet", glyph=glyphName)
xmlWriter.newline()
@@ -408,7 +404,7 @@
xmlWriter.endtag("LigatureSet")
xmlWriter.newline()
- def fromXML(self, (name, attrs, content), font):
+ def fromXML(self, name, attrs, content, font):
ligatures = getattr(self, "ligatures", None)
if ligatures is None:
ligatures = {}
@@ -417,7 +413,7 @@
ligs = []
ligatures[glyphName] = ligs
for element in content:
- if type(element) != TupleType:
+ if not isinstance(element, tuple):
continue
name, attrs, content = element
lig = Ligature()
@@ -523,14 +519,13 @@
if hasattr(oldSubTable, 'sortCoverageLast'):
newSubTable.sortCoverageLast = oldSubTable.sortCoverageLast
- oldAlts = oldSubTable.alternates.items()
- oldAlts.sort()
+ oldAlts = sorted(oldSubTable.alternates.items())
oldLen = len(oldAlts)
if overflowRecord.itemName in [ 'Coverage', 'RangeRecord']:
# Coverage table is written last. overflow is to or within the
# the coverage table. We will just cut the subtable in half.
- newLen = int(oldLen/2)
+ newLen = oldLen//2
elif overflowRecord.itemName == 'AlternateSet':
# We just need to back up by two items
@@ -552,14 +547,13 @@
def splitLigatureSubst(oldSubTable, newSubTable, overflowRecord):
ok = 1
newSubTable.Format = oldSubTable.Format
- oldLigs = oldSubTable.ligatures.items()
- oldLigs.sort()
+ oldLigs = sorted(oldSubTable.ligatures.items())
oldLen = len(oldLigs)
if overflowRecord.itemName in [ 'Coverage', 'RangeRecord']:
# Coverage table is written last. overflow is to or within the
# the coverage table. We will just cut the subtable in half.
- newLen = int(oldLen/2)
+ newLen = oldLen//2
elif overflowRecord.itemName == 'LigatureSet':
# We just need to back up by two items
@@ -648,8 +642,8 @@
def _buildClasses():
- import new, re
- from otData import otData
+ import re
+ from .otData import otData
formatPat = re.compile("([A-Za-z0-9]+)Format(\d+)$")
namespace = globals()
@@ -662,15 +656,15 @@
# XxxFormatN subtable, we only add the "base" table
name = m.group(1)
baseClass = FormatSwitchingBaseTable
- if not namespace.has_key(name):
+ if name not in namespace:
# the class doesn't exist yet, so the base implementation is used.
- cls = new.classobj(name, (baseClass,), {})
+ cls = type(name, (baseClass,), {})
namespace[name] = cls
for base, alts in _equivalents.items():
base = namespace[base]
for alt in alts:
- namespace[alt] = new.classobj(alt, (base,), {})
+ namespace[alt] = type(alt, (base,), {})
global lookupTypes
lookupTypes = {
@@ -711,7 +705,7 @@
featureParamTypes['cv%02d' % i] = FeatureParamsCharacterVariants
# add converters to classes
- from otConverters import buildConverters
+ from .otConverters import buildConverters
for name, table in otData:
m = formatPat.match(name)
if m:
diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py
index 647386e..156e4a2 100644
--- a/Lib/fontTools/ttLib/tables/ttProgram.py
+++ b/Lib/fontTools/ttLib/tables/ttProgram.py
@@ -1,8 +1,10 @@
"""ttLib.tables.ttProgram.py -- Assembler/disassembler for TrueType bytecode programs."""
-import array
-import re, string
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.misc.textTools import num2binary, binary2num, readHex
+import array
+import re
# first, the list of instructions that eat bytes or words from the instruction stream
@@ -198,7 +200,7 @@
return newPos
-class Program:
+class Program(object):
def __init__(self):
pass
@@ -242,11 +244,11 @@
j = 0
for j in range(nValues):
if j and not (j % 25):
- writer.write(string.join(line, " "))
+ writer.write(' '.join(line))
writer.newline()
line = []
line.append(assembly[i+j])
- writer.write(string.join(line, " "))
+ writer.write(' '.join(line))
writer.newline()
i = i + j + 1
writer.endtag("assembly")
@@ -256,9 +258,9 @@
writer.dumphex(self.getBytecode())
writer.endtag("bytecode")
- def fromXML(self, (name, attrs, content), ttFont):
+ def fromXML(self, name, attrs, content, ttFont):
if name == "assembly":
- self.fromAssembly(string.join(content, ""))
+ self.fromAssembly(strjoin(content))
self._assemble()
del self.assembly
else:
@@ -266,11 +268,11 @@
self.fromBytecode(readHex(content))
def _assemble(self,
- skipWhite=_skipWhite, mnemonicDict=mnemonicDict, strip=string.strip,
+ skipWhite=_skipWhite, mnemonicDict=mnemonicDict,
binary2num=binary2num):
assembly = self.assembly
- if type(assembly) == type([]):
- assembly = string.join(assembly, " ")
+ if isinstance(assembly, type([])):
+ assembly = ' '.join(assembly)
bytecode = []
push = bytecode.append
lenAssembly = len(assembly)
@@ -278,21 +280,21 @@
while pos < lenAssembly:
m = _tokenRE.match(assembly, pos)
if m is None:
- raise tt_instructions_error, "Syntax error in TT program (%s)" % assembly[pos-5:pos+15]
+ raise tt_instructions_error("Syntax error in TT program (%s)" % assembly[pos-5:pos+15])
dummy, mnemonic, arg, number, comment = m.groups()
pos = m.regs[0][1]
if comment:
continue
- arg = strip(arg)
+ arg = arg.strip()
if mnemonic.startswith("INSTR"):
# Unknown instruction
op = int(mnemonic[5:])
push(op)
elif mnemonic not in ("NPUSHB", "NPUSHW", "PUSHB", "PUSHW"):
op, argBits = mnemonicDict[mnemonic]
- if len(arg) <> argBits:
- raise tt_instructions_error, "Incorrect number of argument bits (%s[%s])" % (mnemonic, arg)
+ if len(arg) != argBits:
+ raise tt_instructions_error("Incorrect number of argument bits (%s[%s])" % (mnemonic, arg))
if arg:
arg = binary2num(arg)
push(op + arg)
@@ -304,7 +306,7 @@
while pos < lenAssembly:
m = _tokenRE.match(assembly, pos)
if m is None:
- raise tt_instructions_error, "Syntax error in TT program (%s)" % assembly[pos:pos+15]
+ raise tt_instructions_error("Syntax error in TT program (%s)" % assembly[pos:pos+15])
dummy, mnemonic, arg, number, comment = m.groups()
if number is None and comment is None:
break
@@ -330,7 +332,7 @@
push(op)
push(nArgs)
else:
- raise tt_instructions_error, "More than 255 push arguments (%s)" % nArgs
+ raise tt_instructions_error("More than 255 push arguments (%s)" % nArgs)
if words:
for value in args:
push((value >> 8) & 0xff)
@@ -378,14 +380,14 @@
assembly.append("%s[ ] /* %s values pushed */" % (mnemonic, nValues))
for j in range(pushBytes):
value = bytecode[i]
- assembly.append(`value`)
+ assembly.append(repr(value))
i = i + 1
for j in range(pushWords):
# cast to signed int16
value = (bytecode[i] << 8) | bytecode[i+1]
if value >= 0x8000:
value = value - 0x10000
- assembly.append(`value`)
+ assembly.append(repr(value))
i = i + 2
else:
assembly.append("INSTR%d[ ]" % op)
@@ -406,5 +408,5 @@
p.fromBytecode(bc)
asm = p.getAssembly()
p.fromAssembly(asm)
- print bc == p.getBytecode()
+ print(bc == p.getBytecode())
diff --git a/Lib/fontTools/ttx.py b/Lib/fontTools/ttx.py
index 08f7694..ae3c115 100644
--- a/Lib/fontTools/ttx.py
+++ b/Lib/fontTools/ttx.py
@@ -66,18 +66,20 @@
"""
-import sys
-import os
-import getopt
-import re
+from __future__ import print_function, division
+from fontTools.misc.py23 import *
from fontTools.ttLib import TTFont, TTLibError
from fontTools.ttLib.tables.otBase import OTLOffsetOverflowError
from fontTools.ttLib.tables.otTables import fixLookupOverFlows, fixSubTableOverFlows
from fontTools.misc.macCreatorType import getMacCreatorAndType
from fontTools import version
+import os
+import sys
+import getopt
+import re
def usage():
- print __doc__ % version
+ print(__doc__ % version)
sys.exit(2)
@@ -98,7 +100,7 @@
return output
-class Options:
+class Options(object):
listTables = False
outputDir = None
@@ -120,11 +122,11 @@
for option, value in rawOptions:
# general options
if option == "-h":
- print __doc__ % version
+ print(__doc__ % version)
sys.exit(0)
elif option == "-d":
if not os.path.isdir(value):
- print "The -d option value must be an existing directory"
+ print("The -d option value must be an existing directory")
sys.exit(2)
self.outputDir = value
elif option == "-o":
@@ -147,7 +149,7 @@
elif option == "-z":
validOptions = ('raw', 'row', 'bitwise', 'extfile')
if value not in validOptions:
- print "-z does not allow %s as a format. Use %s" % (option, validOptions)
+ print("-z does not allow %s as a format. Use %s" % (option, validOptions))
sys.exit(2)
self.bitmapGlyphDataFormat = value
elif option == "-y":
@@ -162,37 +164,35 @@
elif option == "-e":
self.ignoreDecompileErrors = False
if self.onlyTables and self.skipTables:
- print "-t and -x options are mutually exclusive"
+ print("-t and -x options are mutually exclusive")
sys.exit(2)
if self.mergeFile and numFiles > 1:
- print "Must specify exactly one TTX source file when using -m"
+ print("Must specify exactly one TTX source file when using -m")
sys.exit(2)
def ttList(input, output, options):
- import string
ttf = TTFont(input, fontNumber=options.fontNumber, lazy=True)
reader = ttf.reader
- tags = reader.keys()
- tags.sort()
- print 'Listing table info for "%s":' % input
+ tags = sorted(reader.keys())
+ print('Listing table info for "%s":' % input)
format = " %4s %10s %7s %7s"
- print format % ("tag ", " checksum", " length", " offset")
- print format % ("----", "----------", "-------", "-------")
+ print(format % ("tag ", " checksum", " length", " offset"))
+ print(format % ("----", "----------", "-------", "-------"))
for tag in tags:
entry = reader.tables[tag]
- checkSum = long(entry.checkSum)
+ checkSum = int(entry.checkSum)
if checkSum < 0:
- checkSum = checkSum + 0x100000000L
- checksum = "0x" + string.zfill(hex(checkSum)[2:-1], 8)
- print format % (tag, checksum, entry.length, entry.offset)
- print
+ checkSum = checkSum + 0x100000000
+ checksum = "0x%08X" % checkSum
+ print(format % (tag, checksum, entry.length, entry.offset))
+ print()
ttf.close()
def ttDump(input, output, options):
if not options.quiet:
- print 'Dumping "%s" to "%s"...' % (input, output)
+ print('Dumping "%s" to "%s"...' % (input, output))
ttf = TTFont(input, 0, verbose=options.verbose, allowVID=options.allowVID,
lazy=False,
quiet=options.quiet,
@@ -210,7 +210,7 @@
def ttCompile(input, output, options):
if not options.quiet:
- print 'Compiling "%s" to "%s"...' % (input, output)
+ print('Compiling "%s" to "%s"...' % (input, output))
ttf = TTFont(options.mergeFile,
lazy=False,
recalcBBoxes=options.recalcBBoxes,
@@ -218,13 +218,13 @@
ttf.importXML(input, quiet=options.quiet)
try:
ttf.save(output)
- except OTLOffsetOverflowError, e:
+ except OTLOffsetOverflowError as e:
# XXX This shouldn't be here at all, it should be as close to the
# OTL code as possible.
overflowRecord = e.value
- print "Attempting to fix OTLOffsetOverflowError", e
+ print("Attempting to fix OTLOffsetOverflowError", e)
lastItem = overflowRecord
- while 1:
+ while True:
ok = 0
if overflowRecord.itemName == None:
ok = fixLookupOverFlows(ttf, overflowRecord)
@@ -236,15 +236,15 @@
try:
ttf.save(output)
break
- except OTLOffsetOverflowError, e:
- print "Attempting to fix OTLOffsetOverflowError", e
+ except OTLOffsetOverflowError as e:
+ print("Attempting to fix OTLOffsetOverflowError", e)
overflowRecord = e.value
if overflowRecord == lastItem:
raise
if options.verbose:
import time
- print "finished at", time.strftime("%H:%M:%S", time.localtime(time.time()))
+ print("finished at", time.strftime("%H:%M:%S", time.localtime(time.time())))
def guessFileType(fileName):
@@ -259,16 +259,18 @@
if ext == ".dfont":
return "TTF"
header = f.read(256)
- head = header[:4]
+ head = Tag(header[:4])
if head == "OTTO":
return "OTF"
elif head == "ttcf":
return "TTC"
elif head in ("\0\1\0\0", "true"):
return "TTF"
- elif head in ("wOFF", "true"):
+ elif head == "wOFF":
return "WOFF"
elif head.lower() == "<?xm":
+ # Use 'latin1' because that can't fail.
+ header = tostr(header, 'latin1')
if opentypeheaderRE.search(header):
return "OTX"
else:
@@ -303,7 +305,7 @@
extension = ".otf"
action = ttCompile
else:
- print 'Unknown file type: "%s"' % input
+ print('Unknown file type: "%s"' % input)
continue
if options.outputFile:
@@ -323,7 +325,7 @@
"""Force the DOS Prompt window to stay open so the user gets
a chance to see what's wrong."""
import msvcrt
- print '(Hit any key to exit)'
+ print('(Hit any key to exit)')
while not msvcrt.kbhit():
pass
@@ -333,14 +335,14 @@
try:
process(jobs, options)
except KeyboardInterrupt:
- print "(Cancelled.)"
+ print("(Cancelled.)")
except SystemExit:
if sys.platform == "win32":
waitForKeyPress()
else:
raise
- except TTLibError, e:
- print "Error:",e
+ except TTLibError as e:
+ print("Error:",e)
except:
if sys.platform == "win32":
import traceback
diff --git a/Lib/fontTools/unicode.py b/Lib/fontTools/unicode.py
index 669d497..ef61b01 100644
--- a/Lib/fontTools/unicode.py
+++ b/Lib/fontTools/unicode.py
@@ -24471,7 +24471,7 @@
return unicodes
-class _Unicode:
+class _Unicode(object):
def __init__(self):
self.codes = _makeunicodes()
diff --git a/MetaTools/buildChangeLog.py b/MetaTools/buildChangeLog.py
index ec68e83..d29e379 100755
--- a/MetaTools/buildChangeLog.py
+++ b/MetaTools/buildChangeLog.py
@@ -7,4 +7,4 @@
os.chdir(fontToolsDir)
os.system("git2cl > Doc/ChangeLog")
-print "done."
+print("done.")
diff --git a/MetaTools/roundTrip.py b/MetaTools/roundTrip.py
index 9438f0b..122b39b 100755
--- a/MetaTools/roundTrip.py
+++ b/MetaTools/roundTrip.py
@@ -25,7 +25,7 @@
def usage():
- print __doc__
+ print(__doc__)
sys.exit(2)
@@ -46,7 +46,7 @@
diffcmd = 'diff -U2 -I ".*modified value\|checkSumAdjustment.*" "%s" "%s"' % (xmlFile1, xmlFile2)
output = os.popen(diffcmd, "r", 1)
lines = []
- while 1:
+ while True:
line = output.readline()
if not line:
break
@@ -58,7 +58,7 @@
report.write("-------------------------------------------------------------\n")
report.writelines(lines)
else:
- print "(TTX files are the same)"
+ print("(TTX files are the same)")
finally:
for tmpFile in (xmlFile1, ttFile2, xmlFile2):
if os.path.exists(tmpFile):
@@ -80,10 +80,10 @@
try:
roundTrip(ttFile, options, report)
except KeyboardInterrupt:
- print "(Cancelled)"
+ print("(Cancelled)")
break
except:
- print "*** round tripping aborted ***"
+ print("*** round tripping aborted ***")
traceback.print_exc()
report.write("=============================================================\n")
report.write(" An exception occurred while round tripping")
diff --git a/setup.py b/setup.py
index f00661e..4de9e07 100755
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,6 @@
#! /usr/bin/env python
+from __future__ import print_function
import os, sys
from distutils.core import setup, Extension
from distutils.command.build_ext import build_ext
@@ -13,8 +14,8 @@
try:
import xml.parsers.expat
except ImportError:
- print "*** Warning: FontTools needs PyXML, see:"
- print " http://sourceforge.net/projects/pyxml/"
+ print("*** Warning: FontTools needs PyXML, see:")
+ print(" http://sourceforge.net/projects/pyxml/")
class build_ext_optional(build_ext):