Sorting contours



  • Dear Frederik, Dear Robofont users,

    I need to order some contours inside a glyph.

    This sorting operation is not related to interpolation, so the glyph.autoContourOrder() method doesn’t come in help. Let’s say that I want to sort contours according to length, at the moment this would be my procedure:

    • collect the contours in a list
    • perform the length measurement
    • sort the list according to the results
    • clear the “original” contours
    • draw the sorted contours in the emptied glyph according to the order of the list that stores them

    This procedure works, but I was wondering if maybe there’s a method to achieve this goal without deleting the contours, just sorting in place. Like changing the “index” attribute to contour object. I tried to access this attribute, but this is the reply that I receive: AttributeError: 'RobofabWrapperContour' object has no attribute 'index'

    Any tips?

    Appendix to the problem: after this sorting operation, I need to automatically select one of this contours. I tried the select(state=True) RPoint method or to change to selected RContour attribute, but they do not seem to work. Any advice to solve this?

    Thanks



  • Perfect, it works.
    Thanks!


  • admin

    use:

    g = CurrentGlyph()
    
    contour = g[1]
    contour.selected = True
    g.update()
    


  • Thanks, I'll try today.
    And what about the selection problem?
    Any advice?

    What I found in the robofab documentation, doesn't seem to work in Robofont.
    Or maybe I misunderstood the intended use of those methods/attributes.


  • admin

    the best thing to do is to draw the glyph into a pen store and process the data and draw it back into the glyph

    this should work :)

    enjoy

    from robofab.pens.pointPen import AbstractPointPen
    
    class SortingPen(AbstractPointPen):
        
        def __init__(self):
            self._contours = []
            
        def beginPath(self):
            self._contours.append([])
                           
        def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
            self._contours[-1].append((pt, segmentType, smooth, name, kwargs))
        
        def endPath(self):
            pass
    
        def addComponent(self, baseGlyph, transformation):
            pass   
                
        def drawPoints(self, pen):
            # sort by the len of oncurves and offcurvers for each contour
            sortable = []
            for contour in self._contours:
                oncurves = 0
                offcurves = 0
                for pt, segmentType, smooth, name, kwargs in contour:
                    if segmentType is None:
                        offcurves += 1
                    else:
                        oncurves += 1
                sortable.append((oncurves, offcurves, contour))
            sortable.sort()
    
            for oncurvers, offcurvers, contour in sortable:
                pen.beginPath()
                for pt, segmentType, smooth, name, kwargs in contour:
                    pen.addPoint(pt, 
                                smooth=smooth, 
                                segmentType=segmentType, 
                                name=name, 
                                **kwargs)
                pen.endPath()
    
    # get the current glyph
    g = CurrentGlyph()
    # get the pen
    sorting = SortingPen()
    # draw into that pen
    g.drawPoints(sorting)
    # clear the contours
    g.clearContours()
    # draw back into the glyph
    sorting.drawPoints(g.getPointPen())