Index: python/src-main/tfs/common/TFSProject.py
--- python/src-main/tfs/common/TFSProject.py.orig	2012-06-23 16:43:25.000000000 +0200
+++ python/src-main/tfs/common/TFSProject.py	2014-03-23 13:23:43.700910985 +0100
@@ -68,14 +68,4 @@
 import os
 
 def findProjectRootFolder():
-    folder = os.path.abspath(os.curdir)
-    while True:
-        marker = os.path.join(folder, '.projectRoot')
-        if os.path.exists(marker):
-            return folder
-        parent = os.path.abspath(os.path.dirname(folder))
-        if parent is None:
-            return None
-        if parent == folder:
-            return None
-        folder = parent
+    return "@l_prefix@/lib/typefacet"

-----------------------------------------------------------------------------

Index: dependencies/RoboFab/Lib/robofab/pens/pointPen.py
--- dependencies/RoboFab/Lib/robofab/pens/pointPen.py.orig	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/pens/pointPen.py	2014-03-23 15:15:00.680881767 +0100
@@ -104,7 +104,8 @@
 
 		currentSegment = []
 		for pt, segmentType, smooth, name, kwargs in points:
-			currentSegment.append((pt, smooth, name, kwargs))
+			if pt is not None: 
+			    currentSegment.append((pt, smooth, name, kwargs))
 			if segmentType is None:
 				continue
 			segments.append((segmentType, currentSegment))

-----------------------------------------------------------------------------

Patches from RobotFab SVN as of 2014-03-23
http://code.robofab.com/

diff -ru3 dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs.py dependencies/RoboFab/Lib/robofab/interface/all/dialogs.py
--- dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/interface/all/dialogs.py	2014-03-23 14:35:46.811396000 +0100
@@ -114,8 +114,6 @@
     ('mac',     'fontlab',      (2,3,5),    "dialogs_fontlab_legacy1"),
     # because FontLab 5.01 and earlier on 2.3.5 can run EasyDialogs
     # |         |               |           |
-    #('mac',     'fontlab',      (2,5,4),    "dialogs_fontlab_legacy1"),
-    ('mac',     'fontlab',      (2,5,4),    "dialogs_fontlab_legacy2"),
     # because FontLab 5.1 on mac 10.6 should theoretically be able to run cocoa dialogs,
     # but they are very unreliable. So until we know what's going on, FL5.1 on 10.6
     # is going to have to live with DialogKit dialogs. 
@@ -173,7 +171,12 @@
         if __verbose__:
             print "loaded robofab.interface.all.dialogs_fontlab_legacy2"
         if platform == "mac":
-            from robofab.interface.all.dialogs_fontlab_legacy2 import AskString
+            #   
+            #
+            #
+            #
+            #
+            from robofab.interface.all.dialogs_legacy import AskString, TwoChecks, TwoFields, SelectGlyph, FindGlyph, OneList, SearchList, SelectFont, SelectGlyph
     except ImportError:
         print "can't import", platformApplicationModuleName
 
@@ -216,6 +219,42 @@
 
     
 def test():
+    """ This is a test that prints the available functions and where they're imported from.
+        The report can be useful for debugging.
+
+        For instance:
+
+        from robofab.interface.all.dialogs import test
+        test()
+        
+        testing RoboFab Dialogs:
+            python version: (2, 7, 1)
+            platform: mac
+            application: None
+            applicationVersion: None
+            platformVersion: 10.7
+            looking for module: dialogs_mac_vanilla
+                did we find it? True
+
+        Available dialogs and source:
+            AskString       robofab.interface.all.dialogs_mac_vanilla
+            AskYesNoCancel  robofab.interface.all.dialogs_mac_vanilla
+            FindGlyph       robofab.interface.all.dialogs_mac_vanilla
+            GetFile         robofab.interface.all.dialogs_mac_vanilla
+            GetFolder       robofab.interface.all.dialogs_mac_vanilla
+            GetFileOrFolder robofab.interface.all.dialogs_mac_vanilla
+            Message         robofab.interface.all.dialogs_mac_vanilla
+            OneList         robofab.interface.all.dialogs_mac_vanilla
+            PutFile         robofab.interface.all.dialogs_mac_vanilla
+            SearchList      robofab.interface.all.dialogs_mac_vanilla
+            SelectFont      robofab.interface.all.dialogs_mac_vanilla
+            SelectGlyph     robofab.interface.all.dialogs_mac_vanilla
+            TwoChecks       robofab.interface.all.dialogs_default
+            TwoFields       robofab.interface.all.dialogs_default
+            ProgressBar     robofab.interface.all.dialogs_mac_vanilla
+
+    """
+
     print
     print "testing RoboFab Dialogs:"
     print "\tpython version:", pyVersion
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs_fontlab_legacy1.py dependencies/RoboFab/Lib/robofab/interface/all/dialogs_fontlab_legacy1.py
--- dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs_fontlab_legacy1.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/interface/all/dialogs_fontlab_legacy1.py	2014-03-23 14:35:46.800907000 +0100
@@ -11,14 +11,14 @@
 from dialogKit import ModalDialog, Button, TextBox, EditText
 
 __all__ = [
-    "AskString",
-    "AskYesNoCancel",
+    #"AskString",
+    #"AskYesNoCancel",
     #"FindGlyph",
     "GetFile",
     "GetFolder",
-    "Message",
-    "OneList",
-    "PutFile",
+    #"Message",
+    #"OneList",
+    #"PutFile",
     #"SearchList",
     #"SelectFont",
     #"SelectGlyph",
@@ -28,54 +28,6 @@
 ]
 
 
-def AskString(message, value='', title='RoboFab'):
-    dialogInstance = _AskStringDialog(message, value, title)
-    return dialogInstance.getValue()
-
-class _AskStringDialog(object):
-    def __init__(self, message, value, title):
-        self.w = ModalDialog((360, 140), title)
-        self.w.button1 = Button((-100, -300, 80, 24), 'OK', callback=self.buttonCallback)
-        self.w.t = TextBox((5, 10, -5, 27), message)
-        self.w.inputValue = EditText((5, 35, -5, 50), value)
-        self.w.open()
-    
-    def getValue(self):
-        return self.w.inputValue.get()
-    
-    def buttonCallback(self, sender):
-        self.w.close()
-
-def AskYesNoCancel(message, title='RoboFab', default=1, informativeText=None):
-    dialogInstance = _AskYesNoCancelDialog(message, title=title, default=default)
-    result = dialogInstance.getValue()
-    if result is None and default is not None:
-        return default
-    return result
-
-class _AskYesNoCancelDialog(object):
-    def __init__(self, message, default=None, title="RoboFab"):
-        # default is ignord?
-        self.answer = -1
-        self.w = ModalDialog((360, 140), title, okCallback=self.buttonOKCallback)
-        self.w.noButton = Button((10, -35, 80, 24), 'No', callback=self.buttonNoCallback)
-        self.w.t = TextBox((5, 10, -5, 27), message)
-        self.w.open()
-    
-    def getValue(self):
-        return self.answer
-    
-    def buttonNoCallback(self, sender):
-        self.answer = 0
-        self.w.close()
-        
-    def buttonOKCallback(self, sender):
-        self.answer = 1
-        self.w.close()
-
-def FindGlyph(aFont, message="Search for a glyph:", title='RoboFab'):
-    raise NotImplementedError
-
 def GetFile(message=None, title=None, directory=None, fileName=None, allowsMultipleSelection=False, fileTypes=None):
     strFilter = "All Files  (*.*)|*.*|"
     defaultExt = ""
@@ -87,21 +39,6 @@
     if message is None:
         message = ""
     return fl.GetPathName(message)
-
-def Message(message, title='RoboFab', informativeText=None):
-    """ Display a standard message dialog.
-        Note: informativeText is not supported on this platform.
-    """
-    if informativeText is not None:
-        message = "%s\n%s"%(message, informativeText)
-    _MessageDialog(message, title)
-    
-class _MessageDialog(object):
-    def __init__(self, message, title):
-        self.w = ModalDialog((360, 100), title)
-        self.w.t = TextBox((5, 10, -5, -40), message)
-        self.w.open()
-
     
 def PutFile(message=None, fileName=None):
     # using fontlab's internal file dialogs
@@ -113,25 +50,6 @@
     defaultExt = ""
     return fl.GetFileName(0, defaultExt, fileName, '')
 
-def OneList(list, message="Select an item:", title='RoboFab'):
-    raise NotImplementedError
-
-def SearchList(list, message="Select an item:", title='RoboFab'):
-    raise NotImplementedError
-
-def SelectFont(message="Select a font:", title='RoboFab'):
-    raise NotImplementedError
-
-def SelectGlyph(font, message="Select a glyph:", title='RoboFab'):
-    raise NotImplementedError
-
-def TwoChecks(title_1="One",  title_2="Two", value1=1, value2=1, title='RoboFab'):
-    raise NotImplementedError
-
-def TwoFields(title_1="One:", value_1="0", title_2="Two:", value_2="0", title='RoboFab'):
-    raise NotImplementedError
-
-
 class ProgressBar(object):
 
     def __init__(self, title="RoboFab...", ticks=0, label=""):
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs_fontlab_legacy2.py dependencies/RoboFab/Lib/robofab/interface/all/dialogs_fontlab_legacy2.py
--- dependencies/RoboFab.orig/Lib/robofab/interface/all/dialogs_fontlab_legacy2.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/interface/all/dialogs_fontlab_legacy2.py	2014-03-23 14:35:46.800907000 +0100
@@ -4,25 +4,25 @@
     This might work in future versions of FontLab as well. 
     This is basically a butchered version of vanilla.dialogs.
     No direct import of, or dependency on Vanilla
+    
+    March 7 2012
+    It seems only the dialogs that deal with the file system
+    need to be replaced, the other dialogs still work. 
+    As we're not entirely sure whether it is worth to maintain
+    these dialogs, let's fix the imports in dialogs.py.
+    
+    This is the phenolic aldehyde version of dialogs.
 
 """
 
 #__import__("FL")
 from FL import *
-#from dialogKit import ModalDialog
-
-#import objc
-#from objc import selector
 
 from Foundation import NSObject
 from AppKit import *
 
-# is this the magic that will make this work in FL 5.1
-# however, what are the side effects?
 NSApplication.sharedApplication()
 
-
-
 __all__ = [
 #    "AskString",
     "AskYesNoCancel",
@@ -317,11 +317,26 @@
     return str(basePanel._result)
 
 
+class ProgressBar(object):
 
+    def __init__(self, title="RoboFab...", ticks=0, label=""):
+        self._tickValue = 1
+        fl.BeginProgress(title, ticks)
 
+    def getCurrentTick(self):
+        return self._tickValue
 
+    def tick(self, tickValue=None):
+        if not tickValue:
+            tickValue = self._tickValue
+        fl.TickProgress(tickValue)
+        self._tickValue = tickValue + 1
 
+    def label(self, label):
+        pass
 
+    def close(self):
+        fl.EndProgress()
 
 
 # we seem to have problems importing from here.
@@ -332,49 +347,27 @@
 #def AskString(message, value='', title='RoboFab'):
 #    raise NotImplementedError
 
-def FindGlyph(aFont, message="Search for a glyph:", title='RoboFab'):
-    raise NotImplementedError
+#def FindGlyph(aFont, message="Search for a glyph:", title='RoboFab'):
+#    raise NotImplementedError
 
-def OneList(list, message="Select an item:", title='RoboFab'):
-    raise NotImplementedError
+#def OneList(list, message="Select an item:", title='RoboFab'):
+#    raise NotImplementedError
     
 #def PutFile(message=None, fileName=None):
 #    raise NotImplementedError
 
-def SearchList(list, message="Select an item:", title='RoboFab'):
-    raise NotImplementedError
-
-def SelectFont(message="Select a font:", title='RoboFab'):
-    raise NotImplementedError
-
-def SelectGlyph(font, message="Select a glyph:", title='RoboFab'):
-    raise NotImplementedError
-
-def TwoChecks(title_1="One",  title_2="Two", value1=1, value2=1, title='RoboFab'):
-    raise NotImplementedError
-
-def TwoFields(title_1="One:", value_1="0", title_2="Two:", value_2="0", title='RoboFab'):
-    raise NotImplementedError
-
-class ProgressBar(object):
-
-    def __init__(self, title="RoboFab...", ticks=0, label=""):
-        self._tickValue = 1
-        fl.BeginProgress(title, ticks)
-
-    def getCurrentTick(self):
-        return self._tickValue
+#def SearchList(list, message="Select an item:", title='RoboFab'):
+#    raise NotImplementedError
 
-    def tick(self, tickValue=None):
-        if not tickValue:
-            tickValue = self._tickValue
-        fl.TickProgress(tickValue)
-        self._tickValue = tickValue + 1
+#def SelectFont(message="Select a font:", title='RoboFab'):
+#    raise NotImplementedError
 
-    def label(self, label):
-        pass
+#def SelectGlyph(font, message="Select a glyph:", title='RoboFab'):
+#    raise NotImplementedError
 
-    def close(self):
-        fl.EndProgress()
+#def TwoChecks(title_1="One",  title_2="Two", value1=1, value2=1, title='RoboFab'):
+#    raise NotImplementedError
 
+#def TwoFields(title_1="One:", value_1="0", title_2="Two:", value_2="0", title='RoboFab'):
+#    raise NotImplementedError
 
Only in dependencies/RoboFab.orig/Lib/robofab/interface/mac: .svn
Only in dependencies/RoboFab.orig/Lib/robofab/interface/win: .svn
Only in dependencies/RoboFab.orig/Lib/robofab/misc: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/misc/bezierTools.py dependencies/RoboFab/Lib/robofab/misc/bezierTools.py
--- dependencies/RoboFab.orig/Lib/robofab/misc/bezierTools.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/misc/bezierTools.py	2014-03-23 14:35:46.561891000 +0100
@@ -73,6 +73,12 @@
     line was successfully split, or a list containing the original
     line.
 
+        >>> printSegments(splitLine((0, 0), (100, 200), 50, False))
+        ((0, 0), (50.0, 100.0))
+        ((50.0, 100.0), (100, 200))
+        >>> printSegments(splitLine((0, 0), (100, 200), 50, True))
+        ((0, 0), (25.0, 50.0))
+        ((25.0, 50.0), (100, 200))
         >>> printSegments(splitLine((0, 0), (100, 100), 50, True))
         ((0, 0), (50.0, 50.0))
         ((50.0, 50.0), (100, 100))
@@ -96,10 +102,10 @@
     
     ax1 = (ax, ay)[isHorizontal]
     
-    if ax == 0:
+    if ax1 == 0:
         return [(pt1, pt2)]
         
-    t = float(where - (bx, by)[isHorizontal]) / ax
+    t = float(where - (bx, by)[isHorizontal]) / ax1
     if 0 <= t < 1:
         midPt = ax * t + bx, ay * t + by
         return [(pt1, midPt), (midPt, pt2)]
@@ -184,7 +190,7 @@
 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.
-
+        
         >>> 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))
Only in dependencies/RoboFab.orig/Lib/robofab/objects: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/objects/objectsBase.py dependencies/RoboFab/Lib/robofab/objects/objectsBase.py
--- dependencies/RoboFab.orig/Lib/robofab/objects/objectsBase.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/objects/objectsBase.py	2014-03-23 14:35:46.480986000 +0100
@@ -27,6 +27,10 @@
 from robofab.misc.arrayTools import updateBounds, pointInRect, unionRect, sectRect
 from fontTools.pens.basePen import AbstractPen
 
+try:
+	set
+except NameError:
+	from sets import Set as set
 
 #constants for dealing with segments, points and bPoints
 MOVE = 'move'
@@ -711,7 +715,7 @@
 
 	def round(self):
 		"""round all of the points in all of the glyphs"""
-		for glyph in self.glyphs:
+		for glyph in self:
 			glyph.round()
 	
 	def autoUnicodes(self):
@@ -805,13 +809,12 @@
 		"""Traditional interpolation method. Interpolates by factor between minFont and maxFont.
 		suppressError will supress all tracebacks and analyze only will not perform the interpolation
 		but it will analyze all glyphs and return a dict of problems."""
-		from sets import Set
 		errors = {}
 		if not isinstance(factor, tuple):
 			factor = factor, factor
 		minGlyphNames = minFont.keys()
 		maxGlyphNames = maxFont.keys()
-		allGlyphNames = list(Set(minGlyphNames) | Set(maxGlyphNames))
+		allGlyphNames = list(set(minGlyphNames) | set(maxGlyphNames))
 		if doProgress:
 			from robofab.interface.all.dialogs import ProgressBar
 			progress = ProgressBar('Interpolating...', len(allGlyphNames))
@@ -1066,7 +1069,6 @@
 	
 	def _mathAnchorCompare(self, selfMathAnchors, otherMathAnchors):
 		# collect compatible anchors
-		from sets import Set
 		selfAnchors = {}
 		for pt, name in selfMathAnchors:
 			if not selfAnchors.has_key(name):
@@ -1077,7 +1079,7 @@
 			if not otherAnchors.has_key(name):
 				otherAnchors[name] = []
 			otherAnchors[name].append(pt)
-		compatAnchors = Set(selfAnchors.keys()) & Set(otherAnchors.keys())
+		compatAnchors = set(selfAnchors.keys()) & set(otherAnchors.keys())
 		finalSelfAnchors = {}
 		finalOtherAnchors = {}
 		for name in compatAnchors:
@@ -1100,7 +1102,6 @@
 	
 	def _mathComponentCompare(self, selfMathComponents, otherMathComponents):
 		# collect compatible components
-		from sets import Set
 		selfComponents = {}
 		for baseName, transformation in selfMathComponents:
 			if not selfComponents.has_key(baseName):
@@ -1111,7 +1112,7 @@
 			if not otherComponents.has_key(baseName):
 				otherComponents[baseName] = []
 			otherComponents[baseName].append(transformation)
-		compatComponents = Set(selfComponents.keys()) & Set(otherComponents.keys())
+		compatComponents = set(selfComponents.keys()) & set(otherComponents.keys())
 		finalSelfComponents = {}
 		finalOtherComponents = {}
 		for baseName in compatComponents:
@@ -3228,13 +3229,12 @@
 		"""interpolate the kerning between sourceDictOne
 		and sourceDictTwo. clearExisting will clear existing
 		kerning first."""
-		from sets import Set
 		if isinstance(value, tuple):
 			# in case the value is a x, y tuple: use the x only.
 			value = value[0]
 		if clearExisting:
 			self.clear()
-		pairs = Set(sourceDictOne.keys()) | Set(sourceDictTwo.keys())
+		pairs = set(sourceDictOne.keys()) | set(sourceDictTwo.keys())
 		for pair in pairs:
 			s1 = sourceDictOne.get(pair, 0)
 			s2 = sourceDictTwo.get(pair, 0)
@@ -3407,17 +3407,15 @@
 			return kerning
 
 	def __add__(self, other):
-		from sets import Set
 		new = self.__class__()
-		k = Set(self.keys()) | Set(other.keys())
+		k = set(self.keys()) | set(other.keys())
 		for key in k:
 			new[key] = self.get(key, 0) + other.get(key, 0)
 		return new
 	
 	def __sub__(self, other):
-		from sets import Set
 		new = self.__class__()
-		k = Set(self.keys()) | Set(other.keys())
+		k = set(self.keys()) | set(other.keys())
 		for key in k:
 			new[key] = self.get(key, 0) - other.get(key, 0)
 		return new
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/objects/objectsFL.py dependencies/RoboFab/Lib/robofab/objects/objectsFL.py
--- dependencies/RoboFab.orig/Lib/robofab/objects/objectsFL.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/objects/objectsFL.py	2014-03-23 14:35:46.451198000 +0100
@@ -1028,7 +1028,7 @@
 					fontLib[postScriptHintDataLibKey] = d
 				## Export the glyph order to the lib
 				glyphOrder = [nakedGlyph.name for nakedGlyph in self.naked().glyphs]
-				fontLib["org.robofab.glyphOrder"] = glyphOrder
+				fontLib["public.glyphOrder"] = glyphOrder
 				## export the features
 				if doFeatures and formatVersion == 1:
 					self._writeOpenTypeFeaturesToLib(fontLib)
@@ -1173,10 +1173,14 @@
 			bar.close()
 
 	def _getGlyphOrderFromLib(self, fontLib, glyphSet):
-		glyphOrder = fontLib.get("org.robofab.glyphOrder")
+		key = "public.glyphOrder"  
+		glyphOrder = fontLib.get(key)
+		if glyphOrder is None:
+			key = "org.robofab.glyphOrder"
+		glyphOrder = fontLib.get(key)
 		if glyphOrder is not None:
 			# no need to keep track if the glyph order in lib once the font is loaded.
-			del fontLib["org.robofab.glyphOrder"]
+			del fontLib[key]
 			glyphNames = []
 			done = {}
 			for glyphName in glyphOrder:
Only in dependencies/RoboFab.orig/Lib/robofab/path: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/path/intersect.py dependencies/RoboFab/Lib/robofab/path/intersect.py
--- dependencies/RoboFab.orig/Lib/robofab/path/intersect.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/path/intersect.py	2014-03-23 14:35:46.590745000 +0100
@@ -1,4 +1,4 @@
-from robofab.pens.filterPen import FlattenPen
+from robofab.pens.filterPen import flattenGlyph
 from robofab.objects.objectsRF import RGlyph as _RGlyph
 import math
 
@@ -41,10 +41,7 @@
 	
 def _makeFlat(aGlyph, segmentLength = 10):
 	"""Helper function to flatten the glyph with a given approximate segment length."""
-	new = _RGlyph()
-	filterpen = FlattenPen(aGlyph, new.getPen(), segmentLength)
-	aGlyph.draw(filterpen)
-	return new
+	return flattenGlyph(aGlyph, segmentLength)
 
 def intersect(aGlyph,  startPt, endPt, segmentLength=10):
 	"""Find the intersections between a glyph and a straight line."""
@@ -109,4 +106,3 @@
 	g = makeTestGlyph()
 	print intersect(g, (-10, 200), (650, 150))
 	print intersect(g, (100, 100), (600, 600))
-	
\ No newline at end of file
Only in dependencies/RoboFab.orig/Lib/robofab/pens: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/pens/filterPen.py dependencies/RoboFab/Lib/robofab/pens/filterPen.py
--- dependencies/RoboFab.orig/Lib/robofab/pens/filterPen.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/pens/filterPen.py	2014-03-23 14:35:47.230832000 +0100
@@ -1,23 +1,82 @@
 """A couple of point pens to filter contours in various ways."""
 
-
 from fontTools.pens.basePen import AbstractPen, BasePen
 
-
-
 from robofab.pens.pointPen import AbstractPointPen
 from robofab.objects.objectsRF import RGlyph as _RGlyph
 from robofab.objects.objectsBase import _interpolatePt
 
 import math
 
-
 #
 #	 threshold filtering
 #
 
 def distance(pt1, pt2):
-	return math.sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
+	return math.hypot(pt1[0]-pt2[0], pt1[1]-pt2[1])
+
+class ThresholdPointPen(AbstractPointPen):
+	
+	"""
+		Rewrite of the ThresholdPen as a PointPen
+		so that we can preserve named points and other arguments.
+		This pen will add components from the original glyph, but
+		but it won't filter those components.
+		
+		"move", "line", "curve" or "qcurve"
+	
+	"""
+	def __init__(self, otherPointPen, threshold=10):
+		self.threshold = threshold
+		self._lastPt = None
+		self._offCurveBuffer = []
+		self.otherPointPen = otherPointPen
+		
+	def beginPath(self):
+		"""Start a new sub path."""
+		self.otherPointPen.beginPath()
+		self._lastPt = None
+
+	def endPath(self):
+		"""End the current sub path."""
+		self.otherPointPen.endPath()
+
+	def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
+		"""Add a point to the current sub path."""
+		if segmentType in ['curve', 'qcurve']:
+			# it's an offcurve, let's buffer them until we get another oncurve
+			# and we know what to do with them
+			self._offCurveBuffer.append((pt, segmentType, smooth, name, kwargs))
+			return
+		
+		elif segmentType == "move":
+			# start of an open contour
+			self.otherPointPen.addPoint(pt, segmentType, smooth, name)	# how to add kwargs?
+			self._lastPt = pt
+			self._offCurveBuffer = []
+
+		elif segmentType == "line":
+			if self._lastPt is None:
+				self.otherPointPen.addPoint(pt, segmentType, smooth, name)	# how to add kwargs?
+				self._lastPt = pt
+			elif distance(pt, self._lastPt) >= self.threshold:
+				# we're oncurve and far enough from the last oncurve
+				if self._offCurveBuffer:
+					# empty any buffered offcurves
+					for buf_pt, buf_segmentType, buf_smooth, buf_name, buf_kwargs in self._offCurveBuffer:
+						self.otherPointPen.addPoint(buf_pt, buf_segmentType, buf_smooth, buf_name)	# how to add kwargs?
+					self._offCurveBuffer = []
+				# finally add the oncurve.
+				self.otherPointPen.addPoint(pt, segmentType, smooth, name)	# how to add kwargs?
+				self._lastPt = pt
+			else:
+				# we're too short, so we're not going to make it.
+				# we need to clear out the offcurve buffer. 
+				self._offCurveBuffer = []
+
+	def addComponent(self, baseGlyphName, transformation):
+		"""Add a sub glyph. Note: this way components are not filtered."""
+		self.otherPointPen.addComponent(baseGlyphName, transformation)
 
 
 class ThresholdPen(AbstractPen):
@@ -59,6 +118,7 @@
 
 
 def thresholdGlyph(aGlyph, threshold=10):
+	""" Convenience function that handles the filtering. """
 	from robofab.pens.adapterPens import PointToSegmentPen
 	new = _RGlyph()
 	filterpen = ThresholdPen(new.getPen(), threshold)
@@ -68,6 +128,19 @@
 	aGlyph.appendGlyph(new)
 	aGlyph.update()
 	return aGlyph
+
+def thresholdGlyphPointPen(aGlyph, threshold=10):
+	""" Same a thresholdGlyph, but using the ThresholdPointPen, which should respect anchors."""
+	from robofab.pens.adapterPens import PointToSegmentPen
+	new = _RGlyph()
+	wrappedPen = new.getPointPen()
+	filterpen = ThresholdPointPen(wrappedPen, threshold)
+	aGlyph.drawPoints(filterpen)
+	aGlyph.clear()
+	new.drawPoints(aGlyph.getPointPen())
+	aGlyph.update()
+	return aGlyph
+
 	
 #
 # Curve flattening
@@ -184,7 +257,7 @@
 		
 	def addComponent(self, glyphName, transformation):
 		self.otherPen.addComponent(glyphName, transformation)
-
+		
 
 def flattenGlyph(aGlyph, threshold=10, segmentLines=True):
 
@@ -287,3 +360,48 @@
 		pen.lineTo((x-size, y-size))
 		pen.closePath()
 		aGlyph.update()
+
+
+if __name__ == "__main__":
+	from robofab.pens.pointPen import PrintingPointPen
+	pp = PrintingPointPen()
+	#pp.beginPath()
+	#pp.addPoint((100, 100))
+	#pp.endPath()
+
+	tpp = ThresholdPointPen(pp, threshold=20)
+	tpp.beginPath()
+	#segmentType=None, smooth=False, name=None
+	tpp.addPoint((100, 100), segmentType="line", smooth=True)
+	# section that should be too small
+	tpp.addPoint((100, 102), segmentType="line", smooth=True)
+	tpp.addPoint((200, 200), segmentType="line", smooth=True)
+	# curve section with final point that's far enough, but with offcurves that are under the threshold
+	tpp.addPoint((200, 205), segmentType="curve", smooth=True)
+	tpp.addPoint((300, 295), segmentType="curve", smooth=True)
+	tpp.addPoint((300, 300), segmentType="line", smooth=True)
+	# curve section with final point that is not far enough
+	tpp.addPoint((550, 350), segmentType="curve", smooth=True)
+	tpp.addPoint((360, 760), segmentType="curve", smooth=True)
+	tpp.addPoint((310, 310), segmentType="line", smooth=True)
+
+	tpp.addPoint((400, 400), segmentType="line", smooth=True)
+	tpp.addPoint((100, 100), segmentType="line", smooth=True)
+	tpp.endPath()
+
+	# couple of single points with names
+	tpp.beginPath()
+	tpp.addPoint((500, 500), segmentType="move", smooth=True, name="named point")
+	tpp.addPoint((600, 500), segmentType="move", smooth=True, name="named point")
+	tpp.addPoint((601, 501), segmentType="move", smooth=True, name="named point")
+	tpp.endPath()
+
+	# open path
+	tpp.beginPath()
+	tpp.addPoint((500, 500), segmentType="move", smooth=True)
+	tpp.addPoint((501, 500), segmentType="line", smooth=True)
+	tpp.addPoint((101, 500), segmentType="line", smooth=True)
+	tpp.addPoint((101, 100), segmentType="line", smooth=True)
+	tpp.addPoint((498, 498), segmentType="line", smooth=True)
+	tpp.endPath()
+	
\ No newline at end of file
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/pens/marginPen.py dependencies/RoboFab/Lib/robofab/pens/marginPen.py
--- dependencies/RoboFab.orig/Lib/robofab/pens/marginPen.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/pens/marginPen.py	2014-03-23 14:35:47.250830000 +0100
@@ -101,13 +101,16 @@
 		self.currentPt = None
 
 	def addComponent(self, baseGlyph, transformation):
+		from fontTools.pens.transformPen import TransformPen
 		if self.glyphSet is None:
 			return
 		if baseGlyph in self.glyphSet:
 			glyph = self.glyphSet[baseGlyph]
-		if glyph is not None:
-			glyph.draw(self)
-		
+			if glyph is None:
+				return
+			tPen = TransformPen(self, transformation)
+			glyph.draw(tPen)
+
 	def getMargins(self):
 		"""Get the horizontal margins for all contours combined, i.e. the whole glyph."""
 		allHits = []
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/plistlib.py dependencies/RoboFab/Lib/robofab/plistlib.py
--- dependencies/RoboFab.orig/Lib/robofab/plistlib.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/plistlib.py	2014-03-23 14:35:47.320898000 +0100
@@ -247,8 +247,8 @@
                 self.simpleElement("true")
             else:
                 self.simpleElement("false")
-        elif isinstance(value, int):
-            self.simpleElement("integer", str(value))
+        elif isinstance(value, (int, long)):
+            self.simpleElement("integer", "%d" % value)
         elif isinstance(value, float):
             self.simpleElement("real", repr(value))
         elif isinstance(value, dict):
Only in dependencies/RoboFab.orig/Lib/robofab/test: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/test/test_glifLib.py dependencies/RoboFab/Lib/robofab/test/test_glifLib.py
--- dependencies/RoboFab.orig/Lib/robofab/test/test_glifLib.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/test/test_glifLib.py	2014-03-23 14:35:46.221432000 +0100
@@ -113,8 +113,11 @@
 		
 
 	def testShortFileNameScheme(self):
+		print "testShortFileNameScheme"
 		self.assertEqual(glyphNameToShortFileName("a", None), "a.glif")
 		self.assertEqual(glyphNameToShortFileName("A", None), "A_.glif")
+		self.assertEqual(glyphNameToShortFileName("aE", None), "aE_.glif")
+		self.assertEqual(glyphNameToShortFileName("AE", None), "A_E_.glif")
 		self.assertEqual(glyphNameToShortFileName("a.alt", None), "a_alt.glif")
 		self.assertEqual(glyphNameToShortFileName("A.alt", None), "A__alt.glif")
 		self.assertEqual(glyphNameToShortFileName("a.alt#swash", None), "a_alt_swash.glif")
@@ -128,7 +131,16 @@
 		self.assertEqual(glyphNameToShortFileName("F#weight0.800_width0.425", None), "F__weight0_800_width0_425.glif")
 		self.assertEqual(glyphNameToShortFileName("F#weight0.83245511_width0.425693567", None), "F__weight0_8324551c9a4143c.glif")
 		self.assertEqual(len(glyphNameToShortFileName("F#weight0.83245511_width0.425693567", None)), 31)
-
+		
+	def testShortFileNameScheme_clashes(self):
+		# test for the condition in code.robofab.com ticket #5
+		name1 = glyphNameToShortFileName('Adieresis', None)
+		name2 = glyphNameToShortFileName('a_dieresis', None)
+		self.assertNotEqual(name1, name2)
+		name1 = glyphNameToShortFileName('AE', None)
+		name2 = glyphNameToShortFileName('aE', None)
+		self.assertNotEqual(name1, name2)
+		
 
 if __name__ == "__main__":
 	from robofab.test.testSupport import runTests
Only in dependencies/RoboFab.orig/Lib/robofab/tools: .svn
diff -ru3 dependencies/RoboFab.orig/Lib/robofab/ufoLib.py dependencies/RoboFab/Lib/robofab/ufoLib.py
--- dependencies/RoboFab.orig/Lib/robofab/ufoLib.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Lib/robofab/ufoLib.py	2014-03-23 14:35:47.320898000 +0100
@@ -792,7 +792,7 @@
 # fontinfo.plist.
 
 _fontInfoVersion2OpenTypeHeadFlagsOptions = range(0, 14)
-_fontInfoVersion2OpenTypeOS2SelectionOptions = [1, 2, 3, 4]
+_fontInfoVersion2OpenTypeOS2SelectionOptions = [1, 2, 3, 4, 7, 8, 9]
 _fontInfoVersion2OpenTypeOS2UnicodeRangesOptions = range(0, 128)
 _fontInfoVersion2OpenTypeOS2CodePageRangesOptions = range(0, 64)
 _fontInfoVersion2OpenTypeOS2TypeOptions = [0, 1, 2, 3, 8, 9]
Only in dependencies/RoboFab.orig/Scripts: .svn
Only in dependencies/RoboFab.orig/Scripts/Contributed: .svn
Only in dependencies/RoboFab.orig/Scripts/RoboFabIntro: .svn
Only in dependencies/RoboFab.orig/Scripts/RoboFabUFO: .svn
Only in dependencies/RoboFab.orig/Scripts/RoboFabUtils: .svn
Only in dependencies/RoboFab.orig/TestData: .svn
Only in dependencies/RoboFab.orig/TestData/TestFont1 (UFO1).ufo: .svn
Only in dependencies/RoboFab.orig/TestData/TestFont1 (UFO1).ufo/glyphs: .svn
Only in dependencies/RoboFab.orig/TestData/TestFont1 (UFO2).ufo: .svn
Only in dependencies/RoboFab.orig/TestData/TestFont1 (UFO2).ufo/glyphs: .svn
Only in dependencies/RoboFab.orig/Tools: .svn
Only in dependencies/RoboFab/Tools: autoDistroBuilder.py
diff -ru3 dependencies/RoboFab.orig/Tools/buildRoboFabDistroFromSVN.py dependencies/RoboFab/Tools/buildRoboFabDistroFromSVN.py
--- dependencies/RoboFab.orig/Tools/buildRoboFabDistroFromSVN.py	2012-06-23 16:43:25.000000000 +0200
+++ dependencies/RoboFab/Tools/buildRoboFabDistroFromSVN.py	2014-03-23 14:35:45.920807000 +0100
@@ -4,45 +4,163 @@
      Build the zipped robofab + dependency distros for RoboFab.
      Check out fresh copies of the code from SVN.
      Compile into zips.
+     Write optional html page.
     
 
 """
 
-import os
+import os, glob, time
 
-def checkoutPackage(url, stagingFolder):
+def getRevision(url):
+    """ Ask svn for the revision."""
+    cmd = "svn info \"%s\""%url
+    d = os.popen(cmd)
+    data = d.read()
+    lines = data.split("\n")
+    for l in lines:
+        if l.find("Revision:")==0:
+            rev = l.split(' ')[-1]
+            #print "svn rev:", rev
+            return rev
+    return "svn: no revision found"
+    
+def checkoutPackage(url, stagingFolder, verbose=True):
+    """ checkoutPackage"""
     cwd = os.getcwd()
     if not os.path.exists(stagingFolder):
         os.makedirs(stagingFolder)
     os.chdir(stagingFolder)
-    cmd = "svn co \"%s\" ."%(url)
+    cmd = "svn export \"%s\" . --force"%(url)
     d = os.popen(cmd)
-    print d.read()
+    if verbose:
+        print d.read()
+    else:
+        d.read()
     d.close()
-    d = os.popen("svnversion")
-    revision = d.read()
-    os.chdir(cwd)
-    return revision.strip()
+    #d = os.popen("svnversion")
+    #revision = d.read()
+    #os.chdir(cwd)
+    #return revision.strip()
 
-def buildProducts(products):
+def buildProducts(products, buildFolder=None, deleteBuilds=False, verbose=True):
+    """ Build the different distro products.
+        - checkout a clean version from svn
+        - add svn revision number to folder
+        - zip folder
+    """
     versions = {}
-    buildFolder = os.path.join(os.path.dirname(__file__), "build")
+    cleanup = []
+    filenames = []  # collect filenames of the new zips
+    if buildFolder is None:
+        buildFolder = os.path.join(os.path.dirname(__file__), "build")
+        if verbose:
+            print "\tNo build folder specified, using", buildFolder
+        
     for productName, packages in products.items():
         cwd = os.getcwd()
+        if verbose:
+            print "cwd", cwd
         stagingFolder = os.path.join(buildFolder, productName%"temp")
         for url, name in packages:
-            version = checkoutPackage(url, os.path.join(stagingFolder, name))
-            versions[name] = version
+            checkoutPackage(url, os.path.join(stagingFolder, name), verbose)
+            versions[name] = getRevision(url)
         finalFolder = os.path.join(buildFolder, productName%versions.get('RoboFab', "?"))
+        filenames.append(os.path.basename(finalFolder))
         d = os.popen("mv \"%s\" \"%s\""%(stagingFolder, finalFolder))
-        print d.read()
+        if verbose:
+            print d.read()
+        else:
+            d.read()
         os.chdir(finalFolder)
         d = os.popen("zip -r \"%s\" *"%finalFolder)
-        print d.read()
-        os.chdir(cwd)
-        d = os.popen
+        if verbose:
+            print d.read()
+        else:
+            d.read()
+        cleanup.append(finalFolder)
+        d.close()
+
+    if deleteBuilds:
+        for path in cleanup:
+            if verbose:
+                print "cleaning", path
+            d = os.popen("rm -r \"%s\""%(path))
+            if verbose:
+                print d.read()
+            else:
+                d.read()
+    return filenames, versions.get("RoboFab")
+            
+downloadPageTemplate = """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+"http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+<link href="http://robofab.com/default.css" type="text/css" rel="stylesheet" />
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>RoboFab Downloads</title>
+<meta name="generator" content="TextMate http://macromates.com/">
+<meta name="author" content="Erik van Blokland">
+<!-- Date: 2012-08-18 -->
+</head>
+<body>
+<div id="modellogo">
+	<img src="http://robofab.com/img/drawmodel_header.jpg" width="595" height="112" />
+</div>
+<div class="content">
+<h1>Download RoboFab</h1>
+<p>This page lists the current and (some) older distributions of RoboFab. These distributions contain packages from other developers. License info for these packages is contained in the distribution. This page is automatically generated.</p>
+<p><a href="http://code.robofab.com/changeset/%s">Changeset for revision %s on code.robofab.com.</a></p>
+<p><a href="http://robofab.com" target="_new">Back to the RoboFab site</a></p>
+
+<h2>Current distribution</h2>
+<ul>%s</ul>
+
+<h2>Old distributions</h2>
+<ul>%s</ul>
+
+<h2>Generated</h2>
+<p>%s</p>
+
+</div>
+</body>
+</html>
+"""
+
+def buildDownloadPage(folder, new=None, changeSet=None):
+    """ Build a new download page for the zips available in folder/."""
+    if new is None:
+        new = []
+    htmlPath = os.path.join(folder, "index.html")
+    timeStamp = str(time.asctime(time.localtime(time.time())))
+    # collect .zip names
+    newZips = []
+    oldZips = []
+    for n in glob.glob(os.path.join(folder, "*.zip")):
+        name = os.path.basename(n)
+        isNew = False
+        for testName in new:
+            if name.find(testName)==0:
+                isNew = True
+                break
+        if isNew:
+            newZips.append(name)
+        else:
+            oldZips.append(name)
+    newZips.sort()
+    oldZips.sort()
+    oldZips.reverse()
+    oldZips = oldZips[:200]
+    newLinks = "\n\t".join(["<li><a href=\"%s\">%s</a></li>"%(n,n) for n in newZips])
+    oldLinks = "\n\t".join(["<li><a href=\"%s\">%s</a></li>"%(n,n) for n in oldZips])
+    html = downloadPageTemplate%(changeSet, changeSet, newLinks, oldLinks, timeStamp)
+    
+    f = open(htmlPath, 'w')
+    f.write(html)
+    f.close()
     
 if __name__ == "__main__":
+    
     robofabProducts = {
         'RoboFab_%s_plusAllDependencies':[
             ("http://svn.robofab.com/trunk", "RoboFab"),
@@ -58,6 +176,4 @@
             ("http://svn.robofab.com/trunk", "RoboFab"),
         ],
     }
-    buildProducts(robofabProducts)
-    
-    
\ No newline at end of file
+    newProducts, revision = buildProducts(robofabProducts)
