merging fixes & changes from delft-sprint-2012

git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@611 4cde692c-a291-49d1-8350-778aa11640f8
diff --git a/Lib/fontTools/afmLib.py b/Lib/fontTools/afmLib.py
index b0e5c12..aa303ad 100644
--- a/Lib/fontTools/afmLib.py
+++ b/Lib/fontTools/afmLib.py
@@ -367,10 +367,9 @@
 	
 
 if __name__ == "__main__":
-	import macfs
-	fss, ok = macfs.StandardGetFile('TEXT')
-	if ok:
-		path = fss.as_pathname()
+	import EasyDialogs
+	path = EasyDialogs.AskFileForOpen()
+	if path:
 		afm = AFM(path)
 		char = 'A'
 		if afm.has_char(char):
diff --git a/Lib/fontTools/cffLib.py b/Lib/fontTools/cffLib.py
index add4c3b..719a88b 100644
--- a/Lib/fontTools/cffLib.py
+++ b/Lib/fontTools/cffLib.py
@@ -549,7 +549,7 @@
 			return self.charStringsIndex.getItemAndSelector(index)
 		else:
 			if hasattr(self, 'fdSelect'):
-				sel = self.fdSelect[index]
+				sel = self.fdSelect[index]  # index is not defined at this point. Read R. ?
 			else:
 				raise KeyError("fdSelect array not yet defined.")
 			return self.charStrings[name], sel
diff --git a/Lib/fontTools/fondLib.py b/Lib/fontTools/fondLib.py
index a9d03e1..169792e 100644
--- a/Lib/fontTools/fondLib.py
+++ b/Lib/fontTools/fondLib.py
@@ -472,8 +472,6 @@
 class BitmapFontFile:
 	
 	def __init__(self, path, mode='r'):
-		import macfs
-		
 		if mode == 'r':
 			permission = 1	# read only
 		elif mode == 'w':
@@ -481,8 +479,7 @@
 		else:
 			raise error, 'mode should be either "r" or "w"'
 		self.mode = mode
-		fss = macfs.FSSpec(path)
-		self.resref = Res.FSpOpenResFile(fss, permission)
+		self.resref = Res.FSOpenResFile(path, permission)
 		Res.UseResFile(self.resref)
 		self.path = path
 		self.fonds = []
diff --git a/Lib/fontTools/misc/arrayTools.py b/Lib/fontTools/misc/arrayTools.py
index 2a35f5f..3f39e7e 100644
--- a/Lib/fontTools/misc/arrayTools.py
+++ b/Lib/fontTools/misc/arrayTools.py
@@ -3,157 +3,157 @@
 # name of this module (not).
 #
 
-import numpy
+
+import math
 
 def calcBounds(array):
-	"""Return the bounding rectangle of a 2D points array as a tuple:
-	(xMin, yMin, xMax, yMax)
-	"""
-	if len(array) == 0:
-		return 0, 0, 0, 0
-	xMin, yMin = numpy.minimum.reduce(array)
-	xMax, yMax = numpy.maximum.reduce(array)
-	return xMin, yMin, xMax, yMax
+    """Return the bounding rectangle of a 2D points array as a tuple:
+    (xMin, yMin, xMax, yMax)
+    """
+    if len(array) == 0:
+        return 0, 0, 0, 0
+    xs = [x for x, y in array]
+    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):
-	"""Return the bounding recangle of rectangle bounds and point (x, y)."""
-	xMin, yMin, xMax, yMax = bounds
-	return min(xMin, x), min(yMin, y), max(xMax, x), max(yMax, y)
+    """Return the bounding recangle of rectangle bounds and point (x, y)."""
+    xMin, yMin, xMax, yMax = bounds
+    return min(xMin, x), min(yMin, y), max(xMax, x), max(yMax, y)
 
 def pointInRect((x, y), rect):
-	"""Return True when point (x, y) is inside rect."""
-	xMin, yMin, xMax, yMax = rect
-	return (xMin <= x <= xMax) and (yMin <= y <= yMax)
+    """Return True when point (x, y) is inside rect."""
+    xMin, yMin, xMax, yMax = rect
+    return (xMin <= x <= xMax) and (yMin <= y <= yMax)
 
 def pointsInRect(array, rect):
-	"""Find out which points or array are inside rect. 
-	Returns an array with a boolean for each point.
-	"""
-	if len(array) < 1:
-		return []
-	lefttop = rect[:2]
-	rightbottom = rect[2:]
-	condition = numpy.logical_and(
-			numpy.greater_equal(array, lefttop), 
-			numpy.less_equal(array, rightbottom))
-	return numpy.logical_and.reduce(condition, -1)
+    """Find out which points or array are inside rect. 
+    Returns an array with a boolean for each point.
+    """
+    if len(array) < 1:
+        return []
+    xMin, yMin, xMax, yMax = rect
+    return [(xMin <= x <= xMax) and (yMin <= y <= yMax) for x, y in array]
 
 def vectorLength(vector):
-	"""Return the length of the given vector."""
-	return numpy.sqrt(vector[0]**2 + vector[1]**2)
+    """Return the length of the given vector."""
+    x, y = vector
+    return math.sqrt(x**2 + y**2)
 
 def asInt16(array):
-	"""Round and cast to 16 bit integer."""
-	return numpy.floor(array + 0.5).astype(numpy.int16)
-	
+    """Round and cast to 16 bit integer."""
+    return [int(math.floor(i+0.5)) for i in array]
+    
 
 def normRect((xMin, yMin, xMax, yMax)):
-	"""Normalize the rectangle so that the following holds:
-		xMin <= xMax and yMin <= yMax
-	"""
-	return min(xMin, xMax), min(yMin, yMax), max(xMin, xMax), max(yMin, yMax)
+    """Normalize the rectangle so that the following holds:
+        xMin <= xMax and yMin <= yMax
+    """
+    return min(xMin, xMax), min(yMin, yMax), max(xMin, xMax), max(yMin, yMax)
 
 def scaleRect((xMin, yMin, xMax, yMax), x, y):
-	"""Scale the rectangle by x, y."""
-	return xMin * x, yMin * y, xMax * x, yMax * y
+    """Scale the rectangle by x, y."""
+    return xMin * x, yMin * y, xMax * x, yMax * y
 
 def offsetRect((xMin, yMin, xMax, yMax), dx, dy):
-	"""Offset the rectangle by dx, dy."""
-	return xMin+dx, yMin+dy, xMax+dx, yMax+dy
+    """Offset the rectangle by dx, dy."""
+    return xMin+dx, yMin+dy, xMax+dx, yMax+dy
 
 def insetRect((xMin, yMin, xMax, yMax), dx, dy):
-	"""Inset the rectangle by dx, dy on all sides."""
-	return xMin+dx, yMin+dy, xMax-dx, yMax-dy
+    """Inset the rectangle by dx, dy on all sides."""
+    return xMin+dx, yMin+dy, xMax-dx, yMax-dy
 
 def sectRect((xMin1, yMin1, xMax1, yMax1), (xMin2, yMin2, xMax2, yMax2)):
-	"""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.
-	"""
-	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)
+    """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.
+    """
+    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)):
-	"""Return the smallest rectangle in which both input rectangles are fully
-	enclosed. In other words, return the total bounding rectangle of both input
-	rectangles.
-	"""
-	xMin, yMin, xMax, yMax = (min(xMin1, xMin2), min(yMin1, yMin2),
-	                          max(xMax1, xMax2), max(yMax1, yMax2))
-	return (xMin, yMin, xMax, yMax)
+    """Return the smallest rectangle in which both input rectangles are fully
+    enclosed. In other words, return the total bounding rectangle of both input
+    rectangles.
+    """
+    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)):
-	"""Return the center of the rectangle as an (x, y) coordinate."""
-	return (xMin+xMax)/2, (yMin+yMax)/2
+    """Return the center of the rectangle as an (x, y) coordinate."""
+    return (xMin+xMax)/2, (yMin+yMax)/2
 
 def intRect((xMin, yMin, xMax, yMax)):
-	"""Return the rectangle, rounded off to integer values, but guaranteeing that
-	the resulting rectangle is NOT smaller than the original.
-	"""
-	import math
-	xMin = int(math.floor(xMin))
-	yMin = int(math.floor(yMin))
-	xMax = int(math.ceil(xMax))
-	yMax = int(math.ceil(yMax))
-	return (xMin, yMin, xMax, yMax)
+    """Return the rectangle, rounded off to integer values, but guaranteeing that
+    the resulting rectangle is NOT smaller than the original.
+    """
+    import math
+    xMin = int(math.floor(xMin))
+    yMin = int(math.floor(yMin))
+    xMax = int(math.ceil(xMax))
+    yMax = int(math.ceil(yMax))
+    return (xMin, yMin, xMax, yMax)
 
 
 def _test():
-	"""
-	>>> import math
-	>>> calcBounds([(0, 40), (0, 100), (50, 50), (80, 10)])
-	(0, 10, 80, 100)
-	>>> updateBounds((0, 0, 0, 0), (100, 100))
-	(0, 0, 100, 100)
-	>>> pointInRect((50, 50), (0, 0, 100, 100))
-	True
-	>>> pointInRect((0, 0), (0, 0, 100, 100))
-	True
-	>>> pointInRect((100, 100), (0, 0, 100, 100))
-	True
-	>>> not pointInRect((101, 100), (0, 0, 100, 100))
-	True
-	>>> list(pointsInRect([(50, 50), (0, 0), (100, 100), (101, 100)], (0, 0, 100, 100)))
-	[True, True, True, False]
-	>>> vectorLength((3, 4))
-	5.0
-	>>> vectorLength((1, 1)) == math.sqrt(2)
-	True
-	>>> list(asInt16(numpy.array([0, 0.1, 0.5, 0.9])))
-	[0, 0, 1, 1]
-	>>> normRect((0, 10, 100, 200))
-	(0, 10, 100, 200)
-	>>> normRect((100, 200, 0, 10))
-	(0, 10, 100, 200)
-	>>> scaleRect((10, 20, 50, 150), 1.5, 2)
-	(15.0, 40, 75.0, 300)
-	>>> offsetRect((10, 20, 30, 40), 5, 6)
-	(15, 26, 35, 46)
-	>>> insetRect((10, 20, 50, 60), 5, 10)
-	(15, 30, 45, 50)
-	>>> insetRect((10, 20, 50, 60), -5, -10)
-	(5, 10, 55, 70)
-	>>> intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
-	>>> not intersects
-	True
-	>>> intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
-	>>> intersects
-	1
-	>>> rect
-	(5, 20, 20, 30)
-	>>> unionRect((0, 10, 20, 30), (0, 40, 20, 50))
-	(0, 10, 20, 50)
-	>>> rectCenter((0, 0, 100, 200))
-	(50, 100)
-	>>> rectCenter((0, 0, 100, 199.0))
-	(50, 99.5)
-	>>> intRect((0.9, 2.9, 3.1, 4.1))
-	(0, 2, 4, 5)
-	"""
+    """
+    >>> import math
+    >>> calcBounds([])
+    (0, 0, 0, 0)
+    >>> calcBounds([(0, 40), (0, 100), (50, 50), (80, 10)])
+    (0, 10, 80, 100)
+    >>> updateBounds((0, 0, 0, 0), (100, 100))
+    (0, 0, 100, 100)
+    >>> pointInRect((50, 50), (0, 0, 100, 100))
+    True
+    >>> pointInRect((0, 0), (0, 0, 100, 100))
+    True
+    >>> pointInRect((100, 100), (0, 0, 100, 100))
+    True
+    >>> not pointInRect((101, 100), (0, 0, 100, 100))
+    True
+    >>> list(pointsInRect([(50, 50), (0, 0), (100, 100), (101, 100)], (0, 0, 100, 100)))
+    [True, True, True, False]
+    >>> vectorLength((3, 4))
+    5.0
+    >>> vectorLength((1, 1)) == math.sqrt(2)
+    True
+    >>> list(asInt16([0, 0.1, 0.5, 0.9]))
+    [0, 0, 1, 1]
+    >>> normRect((0, 10, 100, 200))
+    (0, 10, 100, 200)
+    >>> normRect((100, 200, 0, 10))
+    (0, 10, 100, 200)
+    >>> scaleRect((10, 20, 50, 150), 1.5, 2)
+    (15.0, 40, 75.0, 300)
+    >>> offsetRect((10, 20, 30, 40), 5, 6)
+    (15, 26, 35, 46)
+    >>> insetRect((10, 20, 50, 60), 5, 10)
+    (15, 30, 45, 50)
+    >>> insetRect((10, 20, 50, 60), -5, -10)
+    (5, 10, 55, 70)
+    >>> intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50))
+    >>> not intersects
+    True
+    >>> intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50))
+    >>> intersects
+    1
+    >>> rect
+    (5, 20, 20, 30)
+    >>> unionRect((0, 10, 20, 30), (0, 40, 20, 50))
+    (0, 10, 20, 50)
+    >>> rectCenter((0, 0, 100, 200))
+    (50, 100)
+    >>> rectCenter((0, 0, 100, 199.0))
+    (50, 99.5)
+    >>> intRect((0.9, 2.9, 3.1, 4.1))
+    (0, 2, 4, 5)
+    """
 
 if __name__ == "__main__":
-	import doctest
-	doctest.testmod()
+    import doctest
+    doctest.testmod()
diff --git a/Lib/fontTools/misc/bezierTools.py b/Lib/fontTools/misc/bezierTools.py
index 9643beb..4c897d5 100644
--- a/Lib/fontTools/misc/bezierTools.py
+++ b/Lib/fontTools/misc/bezierTools.py
@@ -1,228 +1,251 @@
-"""fontTools.misc.bezierTools.py -- tools for working with bezier path segments."""
+"""fontTools.misc.bezierTools.py -- tools for working with bezier path segments.
+"""
 
 
 __all__ = [
-	"calcQuadraticBounds",
-	"calcCubicBounds",
-	"splitLine",
-	"splitQuadratic",
-	"splitCubic",
-	"splitQuadraticAtT",
-	"splitCubicAtT",
-	"solveQuadratic",
-	"solveCubic",
+    "calcQuadraticBounds",
+    "calcCubicBounds",
+    "splitLine",
+    "splitQuadratic",
+    "splitCubic",
+    "splitQuadraticAtT",
+    "splitCubicAtT",
+    "solveQuadratic",
+    "solveCubic",
 ]
 
 from fontTools.misc.arrayTools import calcBounds
-import numpy
 
 epsilon = 1e-12
 
 
 def calcQuadraticBounds(pt1, pt2, pt3):
-	"""Return the bounding rectangle for a qudratic bezier segment.
-	pt1 and pt3 are the "anchor" points, pt2 is the "handle".
+    """Return the bounding rectangle for a qudratic bezier segment.
+    pt1 and pt3 are the "anchor" points, pt2 is the "handle".
 
-		>>> calcQuadraticBounds((0, 0), (50, 100), (100, 0))
-		(0.0, 0.0, 100.0, 50.0)
-		>>> calcQuadraticBounds((0, 0), (100, 0), (100, 100))
-		(0.0, 0.0, 100.0, 100.0)
-	"""
-	a, b, c = calcQuadraticParameters(pt1, pt2, pt3)
-	# calc first derivative
-	ax, ay = a * 2
-	bx, by = b
-	roots = []
-	if ax != 0:
-		roots.append(-bx/ax)
-	if ay != 0:
-		roots.append(-by/ay)
-	points = [a*t*t + b*t + c for t in roots if 0 <= t < 1] + [pt1, pt3]
-	return calcBounds(points)
+        >>> calcQuadraticBounds((0, 0), (50, 100), (100, 0))
+        (0, 0, 100, 50.0)
+        >>> calcQuadraticBounds((0, 0), (100, 0), (100, 100))
+        (0.0, 0.0, 100, 100)
+    """
+    (ax, ay), (bx, by), (cx, cy) = calcQuadraticParameters(pt1, pt2, pt3)
+    ax2 = ax*2.0
+    ay2 = ay*2.0
+    roots = []
+    if ax2 != 0:
+        roots.append(-bx/ax2)
+    if ay2 != 0:
+        roots.append(-by/ay2)
+    points = [(ax*t*t + bx*t + cx, ay*t*t + by*t + cy) for t in roots if 0 <= t < 1] + [pt1, pt3]
+    return calcBounds(points)
 
 
 def calcCubicBounds(pt1, pt2, pt3, pt4):
-	"""Return the bounding rectangle for a cubic bezier segment.
-	pt1 and pt4 are the "anchor" points, pt2 and pt3 are the "handles".
+    """Return the bounding rectangle for a cubic bezier segment.
+    pt1 and pt4 are the "anchor" points, pt2 and pt3 are the "handles".
 
-		>>> calcCubicBounds((0, 0), (25, 100), (75, 100), (100, 0))
-		(0.0, 0.0, 100.0, 75.0)
-		>>> calcCubicBounds((0, 0), (50, 0), (100, 50), (100, 100))
-		(0.0, 0.0, 100.0, 100.0)
-		>>> calcCubicBounds((50, 0), (0, 100), (100, 100), (50, 0))
-		(35.5662432703, 0.0, 64.4337567297, 75.0)
-	"""
-	a, b, c, d = calcCubicParameters(pt1, pt2, pt3, pt4)
-	# calc first derivative
-	ax, ay = a * 3.0
-	bx, by = b * 2.0
-	cx, cy = c
-	xRoots = [t for t in solveQuadratic(ax, bx, cx) if 0 <= t < 1]
-	yRoots = [t for t in solveQuadratic(ay, by, cy) if 0 <= t < 1]
-	roots = xRoots + yRoots
-	
-	points = [(a*t*t*t + b*t*t + c * t + d) for t in roots] + [pt1, pt4]
-	return calcBounds(points)
+        >>> calcCubicBounds((0, 0), (25, 100), (75, 100), (100, 0))
+        (0, 0, 100, 75.0)
+        >>> calcCubicBounds((0, 0), (50, 0), (100, 50), (100, 100))
+        (0.0, 0.0, 100, 100)
+        >>> print "%f %f %f %f" % calcCubicBounds((50, 0), (0, 100), (100, 100), (50, 0))
+        35.566243 0.000000 64.433757 75.000000
+    """
+    (ax, ay), (bx, by), (cx, cy), (dx, dy) = calcCubicParameters(pt1, pt2, pt3, pt4)
+    # calc first derivative
+    ax3 = ax * 3.0
+    ay3 = ay * 3.0
+    bx2 = bx * 2.0
+    by2 = by * 2.0
+    xRoots = [t for t in solveQuadratic(ax3, bx2, cx) if 0 <= t < 1]
+    yRoots = [t for t in solveQuadratic(ay3, by2, cy) if 0 <= t < 1]
+    roots = xRoots + yRoots
+    
+    points = [(ax*t*t*t + bx*t*t + cx * t + dx, ay*t*t*t + by*t*t + cy * t + dy) for t in roots] + [pt1, pt4]
+    return calcBounds(points)
 
 
 def splitLine(pt1, pt2, where, isHorizontal):
-	"""Split the line between pt1 and pt2 at position 'where', which
-	is an x coordinate if isHorizontal is False, a y coordinate if
-	isHorizontal is True. Return a list of two line segments if the
-	line was successfully split, or a list containing the original
-	line.
+    """Split the line between pt1 and pt2 at position 'where', which
+    is an x coordinate if isHorizontal is False, a y coordinate if
+    isHorizontal is True. Return a list of two line segments if the
+    line was successfully split, or a list containing the original
+    line.
 
-		>>> printSegments(splitLine((0, 0), (100, 100), 50, True))
-		((0, 0), (50.0, 50.0))
-		((50.0, 50.0), (100, 100))
-		>>> printSegments(splitLine((0, 0), (100, 100), 100, True))
-		((0, 0), (100, 100))
-		>>> printSegments(splitLine((0, 0), (100, 100), 0, True))
-		((0, 0), (0.0, 0.0))
-		((0.0, 0.0), (100, 100))
-		>>> printSegments(splitLine((0, 0), (100, 100), 0, False))
-		((0, 0), (0.0, 0.0))
-		((0.0, 0.0), (100, 100))
-	"""
-	pt1, pt2 = numpy.array((pt1, pt2))
-	a = (pt2 - pt1)
-	b = pt1
-	ax = a[isHorizontal]
-	if ax == 0:
-		return [(pt1, pt2)]
-	t = float(where - b[isHorizontal]) / ax
-	if 0 <= t < 1:
-		midPt = a * t + b
-		return [(pt1, midPt), (midPt, pt2)]
-	else:
-		return [(pt1, pt2)]
+        >>> printSegments(splitLine((0, 0), (100, 100), 50, True))
+        ((0, 0), (50.0, 50.0))
+        ((50.0, 50.0), (100, 100))
+        >>> printSegments(splitLine((0, 0), (100, 100), 100, True))
+        ((0, 0), (100, 100))
+        >>> printSegments(splitLine((0, 0), (100, 100), 0, True))
+        ((0, 0), (0.0, 0.0))
+        ((0.0, 0.0), (100, 100))
+        >>> printSegments(splitLine((0, 0), (100, 100), 0, False))
+        ((0, 0), (0.0, 0.0))
+        ((0.0, 0.0), (100, 100))
+    """
+    pt1x, pt1y = pt1
+    pt2x, pt2y = pt2
+    
+    ax = (pt2x - pt1x)
+    ay = (pt2y - pt1y)
+    
+    bx = pt1x
+    by = pt1y
+    
+    ax1 = (ax, ay)[isHorizontal]
+    
+    if ax == 0:
+        return [(pt1, pt2)]
+        
+    t = float(where - (bx, by)[isHorizontal]) / ax
+    if 0 <= t < 1:
+        midPt = ax * t + bx, ay * t + by
+        return [(pt1, midPt), (midPt, pt2)]
+    else:
+        return [(pt1, pt2)]
 
 
 def splitQuadratic(pt1, pt2, pt3, where, isHorizontal):
-	"""Split the quadratic curve between pt1, pt2 and pt3 at position 'where',
-	which is an x coordinate if isHorizontal is False, a y coordinate if
-	isHorizontal is True. Return a list of curve segments.
+    """Split the quadratic curve between pt1, pt2 and pt3 at position 'where',
+    which is an x coordinate if isHorizontal is False, a y coordinate if
+    isHorizontal is True. Return a list of curve segments.
 
-		>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 150, False))
-		((0, 0), (50, 100), (100, 0))
-		>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, False))
-		((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
-		((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
-		>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, False))
-		((0.0, 0.0), (12.5, 25.0), (25.0, 37.5))
-		((25.0, 37.5), (62.5, 75.0), (100.0, 0.0))
-		>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, True))
-		((0.0, 0.0), (7.32233047034, 14.6446609407), (14.6446609407, 25.0))
-		((14.6446609407, 25.0), (50.0, 75.0), (85.3553390593, 25.0))
-		((85.3553390593, 25.0), (92.6776695297, 14.6446609407), (100.0, -7.1054273576e-15))
-		>>> # XXX I'm not at all sure if the following behavior is desirable:
-		>>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, True))
-		((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
-		((50.0, 50.0), (50.0, 50.0), (50.0, 50.0))
-		((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
-	"""
-	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()
-	if not solutions:
-		return [(pt1, pt2, pt3)]
-	return _splitQuadraticAtT(a, b, c, *solutions)
+        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 150, False))
+        ((0, 0), (50, 100), (100, 0))
+        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, False))
+        ((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
+        ((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
+        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, False))
+        ((0.0, 0.0), (12.5, 25.0), (25.0, 37.5))
+        ((25.0, 37.5), (62.5, 75.0), (100.0, 0.0))
+        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, True))
+        ((0.0, 0.0), (7.32233047034, 14.6446609407), (14.6446609407, 25.0))
+        ((14.6446609407, 25.0), (50.0, 75.0), (85.3553390593, 25.0))
+        ((85.3553390593, 25.0), (92.6776695297, 14.6446609407), (100.0, -7.1054273576e-15))
+        >>> # XXX I'm not at all sure if the following behavior is desirable:
+        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, True))
+        ((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
+        ((50.0, 50.0), (50.0, 50.0), (50.0, 50.0))
+        ((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
+    """
+    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()
+    if not solutions:
+        return [(pt1, pt2, pt3)]
+    return _splitQuadraticAtT(a, b, c, *solutions)
 
 
 def splitCubic(pt1, pt2, pt3, pt4, where, isHorizontal):
-	"""Split the cubic curve between pt1, pt2, pt3 and pt4 at position 'where',
-	which is an x coordinate if isHorizontal is False, a y coordinate if
-	isHorizontal is True. Return a list of curve segments.
+    """Split the cubic curve between pt1, pt2, pt3 and pt4 at position 'where',
+    which is an x coordinate if isHorizontal is False, a y coordinate if
+    isHorizontal is True. Return a list of curve segments.
 
-		>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 150, False))
-		((0, 0), (25, 100), (75, 100), (100, 0))
-		>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 50, False))
-		((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
-		((50.0, 75.0), (68.75, 75.0), (87.5, 50.0), (100.0, 0.0))
-		>>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 25, True))
-		((0.0, 0.0), (2.2937927384, 9.17517095361), (4.79804488188, 17.5085042869), (7.47413641001, 25.0))
-		((7.47413641001, 25.0), (31.2886200204, 91.6666666667), (68.7113799796, 91.6666666667), (92.52586359, 25.0))
-		((92.52586359, 25.0), (95.2019551181, 17.5085042869), (97.7062072616, 9.17517095361), (100.0, 1.7763568394e-15))
-	"""
-	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()
-	if not solutions:
-		return [(pt1, pt2, pt3, pt4)]
-	return _splitCubicAtT(a, b, c, d, *solutions)
+        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 150, False))
+        ((0, 0), (25, 100), (75, 100), (100, 0))
+        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 50, False))
+        ((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
+        ((50.0, 75.0), (68.75, 75.0), (87.5, 50.0), (100.0, 0.0))
+        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 25, True))
+        ((0.0, 0.0), (2.2937927384, 9.17517095361), (4.79804488188, 17.5085042869), (7.47413641001, 25.0))
+        ((7.47413641001, 25.0), (31.2886200204, 91.6666666667), (68.7113799796, 91.6666666667), (92.52586359, 25.0))
+        ((92.52586359, 25.0), (95.2019551181, 17.5085042869), (97.7062072616, 9.17517095361), (100.0, 1.7763568394e-15))
+    """
+    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()
+    if not solutions:
+        return [(pt1, pt2, pt3, pt4)]
+    return _splitCubicAtT(a, b, c, d, *solutions)
 
 
 def splitQuadraticAtT(pt1, pt2, pt3, *ts):
-	"""Split the quadratic curve between pt1, pt2 and pt3 at one or more
-	values of t. Return a list of curve segments.
+    """Split the quadratic curve between pt1, pt2 and pt3 at one or more
+    values of t. Return a list of curve segments.
 
-		>>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5))
-		((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
-		((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
-		>>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5, 0.75))
-		((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
-		((50.0, 50.0), (62.5, 50.0), (75.0, 37.5))
-		((75.0, 37.5), (87.5, 25.0), (100.0, 0.0))
-	"""
-	a, b, c = calcQuadraticParameters(pt1, pt2, pt3)
-	return _splitQuadraticAtT(a, b, c, *ts)
+        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5))
+        ((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
+        ((50.0, 50.0), (75.0, 50.0), (100.0, 0.0))
+        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5, 0.75))
+        ((0.0, 0.0), (25.0, 50.0), (50.0, 50.0))
+        ((50.0, 50.0), (62.5, 50.0), (75.0, 37.5))
+        ((75.0, 37.5), (87.5, 25.0), (100.0, 0.0))
+    """
+    a, b, c = calcQuadraticParameters(pt1, pt2, pt3)
+    return _splitQuadraticAtT(a, b, c, *ts)
 
 
 def splitCubicAtT(pt1, pt2, pt3, pt4, *ts):
-	"""Split the cubic curve between pt1, pt2, pt3 and pt4 at one or more
-	values of t. Return a list of curve segments.
+    """Split the cubic curve between pt1, pt2, pt3 and pt4 at one or more
+    values of t. Return a list of curve segments.
 
-		>>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5))
-		((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
-		((50.0, 75.0), (68.75, 75.0), (87.5, 50.0), (100.0, 0.0))
-		>>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5, 0.75))
-		((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
-		((50.0, 75.0), (59.375, 75.0), (68.75, 68.75), (77.34375, 56.25))
-		((77.34375, 56.25), (85.9375, 43.75), (93.75, 25.0), (100.0, 0.0))
-	"""
-	a, b, c, d = calcCubicParameters(pt1, pt2, pt3, pt4)
-	return _splitCubicAtT(a, b, c, d, *ts)
+        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5))
+        ((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
+        ((50.0, 75.0), (68.75, 75.0), (87.5, 50.0), (100.0, 0.0))
+        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5, 0.75))
+        ((0.0, 0.0), (12.5, 50.0), (31.25, 75.0), (50.0, 75.0))
+        ((50.0, 75.0), (59.375, 75.0), (68.75, 68.75), (77.34375, 56.25))
+        ((77.34375, 56.25), (85.9375, 43.75), (93.75, 25.0), (100.0, 0.0))
+    """
+    a, b, c, d = calcCubicParameters(pt1, pt2, pt3, pt4)
+    return _splitCubicAtT(a, b, c, d, *ts)
 
 
 def _splitQuadraticAtT(a, b, c, *ts):
-	ts = list(ts)
-	segments = []
-	ts.insert(0, 0.0)
-	ts.append(1.0)
-	for i in range(len(ts) - 1):
-		t1 = ts[i]
-		t2 = ts[i+1]
-		delta = (t2 - t1)
-		# calc new a, b and c
-		a1 = a * delta**2
-		b1 = (2*a*t1 + b) * delta
-		c1 = a*t1**2 + b*t1 + c
-		pt1, pt2, pt3 = calcQuadraticPoints(a1, b1, c1)
-		segments.append((pt1, pt2, pt3))
-	return segments
+    ts = list(ts)
+    segments = []
+    ts.insert(0, 0.0)
+    ts.append(1.0)
+    ax, ay = a
+    bx, by = b
+    cx, cy = c
+    for i in range(len(ts) - 1):
+        t1 = ts[i]
+        t2 = ts[i+1]
+        delta = (t2 - t1)
+        # calc new a, b and c
+        a1x = ax * delta**2
+        a1y = ay * delta**2
+        b1x = (2*ax*t1 + bx) * delta
+        b1y = (2*ay*t1 + by) * delta
+        c1x = ax*t1**2 + bx*t1 + cx
+        c1y = ay*t1**2 + by*t1 + cy
+    
+        pt1, pt2, pt3 = calcQuadraticPoints((a1x, a1y), (b1x, b1y), (c1x, c1y))
+        segments.append((pt1, pt2, pt3))
+    return segments
 
 
 def _splitCubicAtT(a, b, c, d, *ts):
-	ts = list(ts)
-	ts.insert(0, 0.0)
-	ts.append(1.0)
-	segments = []
-	for i in range(len(ts) - 1):
-		t1 = ts[i]
-		t2 = ts[i+1]
-		delta = (t2 - t1)
-		# calc new a, b, c and d
-		a1 = a * delta**3
-		b1 = (3*a*t1 + b) * delta**2
-		c1 = (2*b*t1 + c + 3*a*t1**2) * delta
-		d1 = a*t1**3 + b*t1**2 + c*t1 + d
-		pt1, pt2, pt3, pt4 = calcCubicPoints(a1, b1, c1, d1)
-		segments.append((pt1, pt2, pt3, pt4))
-	return segments
+    ts = list(ts)
+    ts.insert(0, 0.0)
+    ts.append(1.0)
+    segments = []
+    ax, ay = a
+    bx, by = b
+    cx, cy = c
+    dx, dy = d
+    for i in range(len(ts) - 1):
+        t1 = ts[i]
+        t2 = ts[i+1]
+        delta = (t2 - t1)
+        # calc new a, b, c and d
+        a1x = ax * delta**3
+        a1y = ay * delta**3
+        b1x = (3*ax*t1 + bx) * delta**2
+        b1y = (3*ay*t1 + by) * delta**2
+        c1x = (2*bx*t1 + cx + 3*ax*t1**2) * delta
+        c1y = (2*by*t1 + cy + 3*ay*t1**2) * delta
+        d1x = ax*t1**3 + bx*t1**2 + cx*t1 + dx
+        d1y = ay*t1**3 + by*t1**2 + cy*t1 + dy
+        pt1, pt2, pt3, pt4 = calcCubicPoints((a1x, a1y), (b1x, b1y), (c1x, c1y), (d1x, d1y))
+        segments.append((pt1, pt2, pt3, pt4))
+    return segments
 
 
 #
@@ -233,74 +256,74 @@
 
 
 def solveQuadratic(a, b, c,
-		sqrt=sqrt):
-	"""Solve a quadratic equation where a, b and c are real.
-	    a*x*x + b*x + c = 0
-	This function returns a list of roots. Note that the returned list
-	is neither guaranteed to be sorted nor to contain unique values!
-	"""
-	if abs(a) < epsilon:
-		if abs(b) < epsilon:
-			# We have a non-equation; therefore, we have no valid solution
-			roots = []
-		else:
-			# We have a linear equation with 1 root.
-			roots = [-c/b]
-	else:
-		# We have a true quadratic equation.  Apply the quadratic formula to find two roots.
-		DD = b*b - 4.0*a*c
-		if DD >= 0.0:
-			rDD = sqrt(DD)
-			roots = [(-b+rDD)/2.0/a, (-b-rDD)/2.0/a]
-		else:
-			# complex roots, ignore
-			roots = []
-	return roots
+        sqrt=sqrt):
+    """Solve a quadratic equation where a, b and c are real.
+        a*x*x + b*x + c = 0
+    This function returns a list of roots. Note that the returned list
+    is neither guaranteed to be sorted nor to contain unique values!
+    """
+    if abs(a) < epsilon:
+        if abs(b) < epsilon:
+            # We have a non-equation; therefore, we have no valid solution
+            roots = []
+        else:
+            # We have a linear equation with 1 root.
+            roots = [-c/b]
+    else:
+        # We have a true quadratic equation.  Apply the quadratic formula to find two roots.
+        DD = b*b - 4.0*a*c
+        if DD >= 0.0:
+            rDD = sqrt(DD)
+            roots = [(-b+rDD)/2.0/a, (-b-rDD)/2.0/a]
+        else:
+            # complex roots, ignore
+            roots = []
+    return roots
 
 
 def solveCubic(a, b, c, d,
-		abs=abs, pow=pow, sqrt=sqrt, cos=cos, acos=acos, pi=pi):
-	"""Solve a cubic equation where a, b, c and d are real.
-	    a*x*x*x + b*x*x + c*x + d = 0
-	This function returns a list of roots. Note that the returned list
-	is neither guaranteed to be sorted nor to contain unique values!
-	"""
-	#
-	# adapted from:
-	#   CUBIC.C - Solve a cubic polynomial
-	#   public domain by Ross Cottrell
-	# found at: http://www.strangecreations.com/library/snippets/Cubic.C
-	#
-	if abs(a) < epsilon:
-		# don't just test for zero; for very small values of 'a' solveCubic()
-		# returns unreliable results, so we fall back to quad.
-		return solveQuadratic(b, c, d)
-	a = float(a)
-	a1 = b/a
-	a2 = c/a
-	a3 = d/a
-	
-	Q = (a1*a1 - 3.0*a2)/9.0
-	R = (2.0*a1*a1*a1 - 9.0*a1*a2 + 27.0*a3)/54.0
-	R2_Q3 = R*R - Q*Q*Q
+        abs=abs, pow=pow, sqrt=sqrt, cos=cos, acos=acos, pi=pi):
+    """Solve a cubic equation where a, b, c and d are real.
+        a*x*x*x + b*x*x + c*x + d = 0
+    This function returns a list of roots. Note that the returned list
+    is neither guaranteed to be sorted nor to contain unique values!
+    """
+    #
+    # adapted from:
+    #   CUBIC.C - Solve a cubic polynomial
+    #   public domain by Ross Cottrell
+    # found at: http://www.strangecreations.com/library/snippets/Cubic.C
+    #
+    if abs(a) < epsilon:
+        # don't just test for zero; for very small values of 'a' solveCubic()
+        # returns unreliable results, so we fall back to quad.
+        return solveQuadratic(b, c, d)
+    a = float(a)
+    a1 = b/a
+    a2 = c/a
+    a3 = d/a
+    
+    Q = (a1*a1 - 3.0*a2)/9.0
+    R = (2.0*a1*a1*a1 - 9.0*a1*a2 + 27.0*a3)/54.0
+    R2_Q3 = R*R - Q*Q*Q
 
-	if R2_Q3 < 0:
-		theta = acos(R/sqrt(Q*Q*Q))
-		rQ2 = -2.0*sqrt(Q)
-		x0 = rQ2*cos(theta/3.0) - a1/3.0
-		x1 = rQ2*cos((theta+2.0*pi)/3.0) - a1/3.0
-		x2 = rQ2*cos((theta+4.0*pi)/3.0) - a1/3.0
-		return [x0, x1, x2]
-	else:
-		if Q == 0 and R == 0:
-			x = 0
-		else:
-			x = pow(sqrt(R2_Q3)+abs(R), 1/3.0)
-			x = x + Q/x
-		if R >= 0.0:
-			x = -x
-		x = x - a1/3.0
-		return [x]
+    if R2_Q3 < 0:
+        theta = acos(R/sqrt(Q*Q*Q))
+        rQ2 = -2.0*sqrt(Q)
+        x0 = rQ2*cos(theta/3.0) - a1/3.0
+        x1 = rQ2*cos((theta+2.0*pi)/3.0) - a1/3.0
+        x2 = rQ2*cos((theta+4.0*pi)/3.0) - a1/3.0
+        return [x0, x1, x2]
+    else:
+        if Q == 0 and R == 0:
+            x = 0
+        else:
+            x = pow(sqrt(R2_Q3)+abs(R), 1/3.0)
+            x = x + Q/x
+        if R >= 0.0:
+            x = -x
+        x = x - a1/3.0
+        return [x]
 
 
 #
@@ -308,58 +331,79 @@
 #
 
 def calcQuadraticParameters(pt1, pt2, pt3):
-	pt1, pt2, pt3 = numpy.array((pt1, pt2, pt3))
-	c = pt1
-	b = (pt2 - c) * 2.0
-	a = pt3 - c - b
-	return a, b, c
+    x2, y2 = pt2
+    x3, y3 = pt3
+    cx, cy = pt1
+    bx = (x2 - cx) * 2.0
+    by = (y2 - cy) * 2.0
+    ax = x3 - cx - bx
+    ay = y3 - cy - by
+    return (ax, ay), (bx, by), (cx, cy)
 
 
 def calcCubicParameters(pt1, pt2, pt3, pt4):
-	pt1, pt2, pt3, pt4 = numpy.array((pt1, pt2, pt3, pt4))
-	d = pt1
-	c = (pt2 - d) * 3.0
-	b = (pt3 - pt2) * 3.0 - c
-	a = pt4 - d - c - b
-	return a, b, c, d
+    x2, y2 = pt2
+    x3, y3 = pt3
+    x4, y4 = pt4
+    dx, dy = pt1
+    cx = (x2 -dx) * 3.0
+    cy = (y2 -dy) * 3.0
+    bx = (x3 - x2) * 3.0 - cx
+    by = (y3 - y2) * 3.0 - cy
+    ax = x4 - dx - cx - bx
+    ay = y4 - dy - cy - by
+    return (ax, ay), (bx, by), (cx, cy), (dx, dy)
 
 
 def calcQuadraticPoints(a, b, c):
-	pt1 = c
-	pt2 = (b * 0.5) + c
-	pt3 = a + b + c
-	return pt1, pt2, pt3
+    ax, ay = a
+    bx, by = b
+    cx, cy = c
+    x1 = cx
+    y1 = cy
+    x2 = (bx * 0.5) + cx
+    y2 = (by * 0.5) + cy
+    x3 = ax + bx + cx
+    y3 = ay + by + cy
+    return (x1, y1), (x2, y2), (x3, y3)
 
 
 def calcCubicPoints(a, b, c, d):
-	pt1 = d
-	pt2 = (c / 3.0) + d
-	pt3 = (b + c) / 3.0 + pt2
-	pt4 = a + d + c + b
-	return pt1, pt2, pt3, pt4
+    ax, ay = a
+    bx, by = b
+    cx, cy = c
+    dx, dy = d
+    x1 = dx
+    y1 = dy
+    x2 = (cx / 3.0) + dx
+    y2 = (cy / 3.0) + dy
+    x3 = (bx + cx) / 3.0 + x2
+    y3 = (by + cy) / 3.0 + y2
+    x4 = ax + dx + cx + bx
+    y4 = ay + dy + cy + by
+    return (x1, y1), (x2, y2), (x3, y3), (x4, y4)
 
 
 def _segmentrepr(obj):
-	"""
-		>>> _segmentrepr([1, [2, 3], [], [[2, [3, 4], numpy.array([0.1, 2.2])]]])
-		'(1, (2, 3), (), ((2, (3, 4), (0.1, 2.2))))'
-	"""
-	try:
-		it = iter(obj)
-	except TypeError:
-		return str(obj)
-	else:
-		return "(%s)" % ", ".join([_segmentrepr(x) for x in it])
+    """
+        >>> _segmentrepr([1, [2, 3], [], [[2, [3, 4], [0.1, 2.2]]]])
+        '(1, (2, 3), (), ((2, (3, 4), (0.1, 2.2))))'
+    """
+    try:
+        it = iter(obj)
+    except TypeError:
+        return str(obj)
+    else:
+        return "(%s)" % ", ".join([_segmentrepr(x) for x in it])
 
 
 def printSegments(segments):
-	"""Helper for the doctests, displaying each segment in a list of
-	segments on a single line as a tuple.
-	"""
-	for segment in segments:
-		print _segmentrepr(segment)
-
+    """Helper for the doctests, displaying each segment in a list of
+    segments on a single line as a tuple.
+    """
+    for segment in segments:
+        print _segmentrepr(segment)
 
 if __name__ == "__main__":
-	import doctest
-	doctest.testmod()
+    import doctest
+    doctest.testmod()
diff --git a/Lib/fontTools/misc/psLib.py b/Lib/fontTools/misc/psLib.py
index 848f71d..3c7bd37 100644
--- a/Lib/fontTools/misc/psLib.py
+++ b/Lib/fontTools/misc/psLib.py
@@ -343,9 +343,9 @@
 
 
 if __name__ == "__main__":
-	import macfs
-	fss, ok = macfs.StandardGetFile("LWFN")
-	if ok:
+	import EasyDialogs
+	path = EasyDialogs.AskFileForOpen()
+	if path:
 		from fontTools import t1Lib
-		data, kind = t1Lib.read(fss.as_pathname())
+		data, kind = t1Lib.read(path)
 		font = suckfont(data)
diff --git a/Lib/fontTools/misc/textTools.py b/Lib/fontTools/misc/textTools.py
index 4c6a650..2fd5d0b 100644
--- a/Lib/fontTools/misc/textTools.py
+++ b/Lib/fontTools/misc/textTools.py
@@ -5,7 +5,7 @@
 
 
 def safeEval(data, eval=eval):
-	"""A safe replacement for eval."""
+	"""A (kindof) safe replacement for eval."""
 	return eval(data, {"__builtins__":{}}, {})
 
 
diff --git a/Lib/fontTools/nfntLib.py b/Lib/fontTools/nfntLib.py
index 9646606..561e8c6 100644
--- a/Lib/fontTools/nfntLib.py
+++ b/Lib/fontTools/nfntLib.py
@@ -269,12 +269,7 @@
 
 def dataFromFile(pathOrFSSpec, nameOrID="", resType='NFNT'):
 	from Carbon import Res
-	import macfs
-	if type(pathOrFSSpec) == types.StringType:
-		fss = macfs.FSSpec(pathOrFSSpec)
-	else:
-		fss = pathOrFSSpec
-	resref = Res.FSpOpenResFile(fss, 1)	# readonly
+	resref = Res.FSOpenResFile(pathOrFSSpec, 1)	# readonly
 	try:
 		Res.UseResFile(resref)
 		if not nameOrID:
@@ -297,10 +292,10 @@
 
 
 if __name__ == "__main__":
-	import macfs
-	fss, ok = macfs.StandardGetFile('FFIL')
-	if ok:
-		data = dataFromFile(fss)
+	import EasyDialogs
+	path = EasyDialogs.AskFileForOpen()
+	if path:
+		data = dataFromFile(path)
 		font = NFNT(data)
 		font.unpackGlyphs()
 		font.packGlyphs()
diff --git a/Lib/fontTools/pens/basePen.py b/Lib/fontTools/pens/basePen.py
index 01592dc..bc81814 100644
--- a/Lib/fontTools/pens/basePen.py
+++ b/Lib/fontTools/pens/basePen.py
@@ -41,7 +41,7 @@
            "decomposeSuperBezierSegment", "decomposeQuadraticSegment"]
 
 
-class AbstractPen:
+class AbstractPen(object):
 
 	def moveTo(self, pt):
 		"""Begin a new sub path, set the current point to 'pt'. You must
diff --git a/Lib/fontTools/t1Lib.py b/Lib/fontTools/t1Lib.py
index c5e2e5c..42d95c2 100644
--- a/Lib/fontTools/t1Lib.py
+++ b/Lib/fontTools/t1Lib.py
@@ -143,7 +143,7 @@
 
 def readLWFN(path, onlyHeader=0):
 	"""reads an LWFN font file, returns raw data"""
-	resRef = Res.FSpOpenResFile(path, 1)  # read-only
+	resRef = Res.FSOpenResFile(path, 1)  # read-only
 	try:
 		Res.UseResFile(resRef)
 		n = Res.Count1Resources('POST')
@@ -217,7 +217,7 @@
 
 def writeLWFN(path, data):
 	Res.FSpCreateResFile(path, "just", "LWFN", 0)
-	resRef = Res.FSpOpenResFile(path, 2)  # write-only
+	resRef = Res.FSOpenResFile(path, 2)  # write-only
 	try:
 		Res.UseResFile(resRef)
 		resID = 501
diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py
index 69e90a5..1b8117f 100644
--- a/Lib/fontTools/ttLib/__init__.py
+++ b/Lib/fontTools/ttLib/__init__.py
@@ -178,9 +178,8 @@
 			else:
 				file = open(file, "wb")
 				if os.name == "mac":
-					import macfs
-					fss = macfs.FSSpec(file.name)
-					fss.SetCreatorType('mdos', 'BINA')
+					from fontTools.misc.macCreator import setMacCreatorAndType
+					setMacCreatorAndType(file.name, 'mdos', 'BINA')
 		else:
 			# assume "file" is a writable file object
 			closeStream = 0
diff --git a/Lib/fontTools/ttLib/macUtils.py b/Lib/fontTools/ttLib/macUtils.py
index 5e1f0cb..2d5aedb 100644
--- a/Lib/fontTools/ttLib/macUtils.py
+++ b/Lib/fontTools/ttLib/macUtils.py
@@ -15,7 +15,7 @@
 def MyOpenResFile(path):
 	mode = 1  # read only
 	try:
-		resref = Res.FSpOpenResFile(path, mode)
+		resref = Res.FSOpenResFile(path, mode)
 	except Res.Error:
 		# try data fork
 		resref = Res.FSOpenResourceFile(path, u'', mode)
@@ -104,7 +104,7 @@
 			os.remove(self.name)
 		# XXX datafork support
 		Res.FSpCreateResFile(self.name, 'DMOV', 'FFIL', 0)
-		self.resref = Res.FSpOpenResFile(self.name, 3)  # exclusive read/write permission
+		self.resref = Res.FSOpenResFile(self.name, 3)  # exclusive read/write permission
 	
 	def close(self):
 		if self.closed:
diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py
index 6019d5f..7ba40f4 100644
--- a/Lib/fontTools/ttLib/sfnt.py
+++ b/Lib/fontTools/ttLib/sfnt.py
@@ -14,7 +14,6 @@
 
 import sys
 import struct, sstruct
-import numpy
 import os
 
 
@@ -152,24 +151,28 @@
 				seenHead = 1
 			directory = directory + entry.toString()
 		if seenHead:
-			self.calcMasterChecksum(directory)
+			self.writeMasterChecksum(directory)
 		self.file.seek(0)
 		self.file.write(directory)
-	
-	def calcMasterChecksum(self, directory):
+
+	def _calcMasterChecksum(self, directory):
 		# calculate checkSumAdjustment
 		tags = self.tables.keys()
-		checksums = numpy.zeros(len(tags)+1, numpy.uint32)
+		checksums = []
 		for i in range(len(tags)):
-			checksums[i] = self.tables[tags[i]].checkSum
-		
+			checksums.append(self.tables[tags[i]].checkSum)
+
 		directory_end = sfntDirectorySize + len(self.tables) * sfntDirectoryEntrySize
 		assert directory_end == len(directory)
-		
-		checksums[-1] = calcChecksum(directory)
-		checksum = numpy.add.reduce(checksums,dtype=numpy.uint32)
+
+		checksums.append(calcChecksum(directory))
+		checksum = sum(checksums) & 0xffffffff
 		# BiboAfba!
-		checksumadjustment = int(numpy.subtract.reduce(numpy.array([0xB1B0AFBA, checksum], numpy.uint32)))
+		checksumadjustment = (0xB1B0AFBA - checksum) & 0xffffffff
+		return checksumadjustment
+
+	def writeMasterChecksum(self, directory):
+		checksumadjustment = self._calcMasterChecksum(directory)
 		# write the checksum to the file
 		self.file.seek(self.tables['head'].offset + 8)
 		self.file.write(struct.pack(">L", checksumadjustment))
@@ -230,7 +233,7 @@
 			return "<SFNTDirectoryEntry at %x>" % id(self)
 
 
-def calcChecksum(data, start=0):
+def calcChecksum(data):
 	"""Calculate the checksum for an arbitrary block of data.
 	Optionally takes a 'start' argument, which allows you to
 	calculate a checksum in chunks by feeding it a previous
@@ -238,14 +241,23 @@
 	
 	If the data length is not a multiple of four, it assumes
 	it is to be padded with null byte. 
+
+		>>> print calcChecksum("abcd")
+		1633837924
+		>>> print calcChecksum("abcdxyz")
+		3655064932
 	"""
-	from fontTools import ttLib
 	remainder = len(data) % 4
 	if remainder:
-		data = data + '\0' * (4-remainder)
-	data = struct.unpack(">%dL"%(len(data)/4), data)
-	a = numpy.array((start,)+data, numpy.uint32)
-	return int(numpy.sum(a,dtype=numpy.uint32))
+		data += "\0" * (4 - remainder)
+	value = 0
+	blockSize = 4096
+	assert blockSize % 4 == 0
+	for i in xrange(0, len(data), blockSize):
+		block = data[i:i+blockSize]
+		longs = struct.unpack(">%dL" % (len(block) // 4), block)
+		value = (value + sum(longs)) & 0xffffffff
+	return value
 
 
 def maxPowerOfTwo(x):
@@ -271,3 +283,7 @@
 	rangeShift = n * 16 - searchRange
 	return searchRange, entrySelector, rangeShift
 
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
diff --git a/Lib/fontTools/ttLib/tables/D_S_I_G_.py b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
index bea5654..344a214 100644
--- a/Lib/fontTools/ttLib/tables/D_S_I_G_.py
+++ b/Lib/fontTools/ttLib/tables/D_S_I_G_.py
@@ -1,12 +1,115 @@
 import DefaultTable
+from fontTools.misc.textTools import safeEval
+import sstruct
+
+DSIG_HeaderFormat = """
+	> # big endian
+	ulVersion:      L
+	usNumSigs:      H
+	usFlag:         H
+"""
+# followed by an array of usNumSigs DSIG_Signature records
+DSIG_SignatureFormat = """
+	> # big endian
+	ulFormat:       L
+	ulLength:       L # length includes DSIG_SignatureBlock header
+	ulOffset:       L
+"""
+# followed by an array of usNumSigs DSIG_SignatureBlock records,
+# each followed immediately by the pkcs7 bytes
+DSIG_SignatureBlockFormat = """
+	> # big endian
+	usReserved1:    H
+	usReserved2:    H
+	cbSignature:    l # length of following raw pkcs7 data
+"""
+
+#
+# NOTE
+# the DSIG table format allows for SignatureBlocks residing
+# anywhere in the table and possibly in a different order as
+# listed in the array after the first table header
+#
+# this implementation does not keep track of any gaps and/or data
+# before or after the actual signature blocks while decompiling,
+# and puts them in the same physical order as listed in the header
+# on compilation with no padding whatsoever.
+#
 
 class table_D_S_I_G_(DefaultTable.DefaultTable):
 	
+	def decompile(self, data, ttFont):
+		dummy, newData = sstruct.unpack2(DSIG_HeaderFormat, data, self)
+		assert self.ulVersion == 1, "DSIG ulVersion must be 1"
+		assert self.usFlag & ~1 == 0, "DSIG usFlag must be 0x1 or 0x0"
+		self.signatureRecords = sigrecs = []
+		for n in range(self.usNumSigs):
+			sigrec, newData = sstruct.unpack2(DSIG_SignatureFormat, newData, SignatureRecord())
+			assert sigrec.ulFormat == 1, "DSIG signature record #%d ulFormat must be 1" % n
+			sigrecs.append(sigrec)
+		for sigrec in sigrecs:
+			dummy, newData = sstruct.unpack2(DSIG_SignatureBlockFormat, data[sigrec.ulOffset:], sigrec)
+			assert sigrec.usReserved1 == 0, "DSIG signature record #%d usReserverd1 must be 0" % n
+			assert sigrec.usReserved2 == 0, "DSIG signature record #%d usReserverd2 must be 0" % n
+			sigrec.pkcs7 = newData[:sigrec.cbSignature]
+	
+	def compile(self, ttFont):
+		packed = sstruct.pack(DSIG_HeaderFormat, self)
+		headers = [packed]
+		offset = len(packed) + self.usNumSigs * sstruct.calcsize(DSIG_SignatureFormat)
+		data = []
+		for sigrec in self.signatureRecords:
+			# first pack signature block
+			sigrec.cbSignature = len(sigrec.pkcs7)
+			packed = sstruct.pack(DSIG_SignatureBlockFormat, sigrec) + sigrec.pkcs7
+			data.append(packed)
+			# update redundant length field
+			sigrec.ulLength = len(packed)
+			# update running table offset
+			sigrec.ulOffset = offset
+			headers.append(sstruct.pack(DSIG_SignatureFormat, sigrec))
+			offset += sigrec.ulLength
+		return ''.join(headers+data)
+	
 	def toXML(self, xmlWriter, ttFont):
 		xmlWriter.comment("note that the Digital Signature will be invalid after recompilation!")
 		xmlWriter.newline()
-		xmlWriter.begintag("hexdata")
+		xmlWriter.simpletag("tableHeader", version=self.ulVersion, numSigs=self.usNumSigs, flag="0x%X" % self.usFlag)
+		for sigrec in self.signatureRecords:
+			xmlWriter.newline()
+			sigrec.toXML(xmlWriter, ttFont)
 		xmlWriter.newline()
-		xmlWriter.dumphex(self.compile(ttFont))
-		xmlWriter.endtag("hexdata")
-		xmlWriter.newline()
+	
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == "tableHeader":
+			self.signatureRecords = []
+			self.ulVersion = safeEval(attrs["version"])
+			self.usNumSigs = safeEval(attrs["numSigs"])
+			self.usFlag = safeEval(attrs["flag"])
+			return
+		if name == "SignatureRecord":
+			sigrec = SignatureRecord()
+			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 __repr__(self):
+		return "<%s: %s>" % (self.__class__.__name__, self.__dict__)
+	
+	def toXML(self, writer, ttFont):
+		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("-----END PKCS7-----\n")
+		writer.endtag(self.__class__.__name__)
+	
+	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')
diff --git a/Lib/fontTools/ttLib/tables/_g_a_s_p.py b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
index 4aa83ec..43f513f 100644
--- a/Lib/fontTools/ttLib/tables/_g_a_s_p.py
+++ b/Lib/fontTools/ttLib/tables/_g_a_s_p.py
@@ -3,8 +3,8 @@
 from fontTools.misc.textTools import safeEval
 
 
-GASP_SYMMETRIC_GRIDFIT = 0x0008
-GASP_SYMMETRIC_SMOOTHING = 0x0004
+GASP_SYMMETRIC_GRIDFIT = 0x0004
+GASP_SYMMETRIC_SMOOTHING = 0x0008
 GASP_DOGRAY = 0x0002
 GASP_GRIDFIT = 0x0001
 
diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
index f1a9818..01c82a0 100644
--- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py
+++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py
@@ -280,9 +280,9 @@
 	
 	def fromXML(self, (name, attrs, content), ttFont):
 		if name == "contour":
-			self.numberOfContours = self.numberOfContours + 1
 			if self.numberOfContours < 0:
 				raise ttLib.TTLibError, "can't mix composites and contours in glyph"
+			self.numberOfContours = self.numberOfContours + 1
 			coordinates = []
 			flags = []
 			for element in content:
diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py
index ec828a5..32e1dd2 100644
--- a/Lib/fontTools/ttLib/tables/ttProgram.py
+++ b/Lib/fontTools/ttLib/tables/ttProgram.py
@@ -258,7 +258,7 @@
 	
 	def fromXML(self, (name, attrs, content), ttFont):
 		if name == "assembly":
-			self.fromAssembly(content)
+			self.fromAssembly(string.join(content, ""))
 			self._assemble()
 			del self.assembly
 		else:
@@ -270,7 +270,7 @@
 			binary2num=binary2num):
 		assembly = self.assembly
 		if type(assembly) == type([]):
-			assembly = string.join(assembly, "")
+			assembly = string.join(assembly, " ")
 		bytecode = []
 		push = bytecode.append
 		lenAssembly = len(assembly)
diff --git a/Lib/xmlWriter.py b/Lib/xmlWriter.py
index e9f8559..50f46f0 100644
--- a/Lib/xmlWriter.py
+++ b/Lib/xmlWriter.py
@@ -12,9 +12,6 @@
 	def __init__(self, fileOrPath, indentwhite=INDENT, idlefunc=None, encoding="ISO-8859-1"):
 		if not hasattr(fileOrPath, "write"):
 			self.file = open(fileOrPath, "w")
-			if os.name == "mac":
-				import macfs
-				macfs.FSSpec(fileOrPath).SetCreatorType('R*ch', 'TEXT')
 		else:
 			# assume writable file object
 			self.file = fileOrPath