Exporting a variable font from DrawBot



  • Hello all,
    I am working on a variable font that wasn't supposed to be variable but hey, why not? We drew a font and this is then imported in DrawBot to be "messed up". @justvanrossum helped me set it up already and I have a few examples.

    Original:
    Screenshot 2019-05-26 at 12.20.01.png

    Slightly modified:
    Screenshot 2019-05-26 at 12.20.18.png

    Heavily modified:
    Screenshot 2019-05-26 at 12.20.28.png

    Modification is randomly applied to each character:
    Screenshot 2019-05-26 at 12.20.40.png

    Now the "variation" only happens in this intensity of messing it up. I am interested how I can let the user create this intensity in InDesign or other software, instead of it being hard-coded.

    Here is my code:

    from fontParts.world import RFont
    from fontTools.agl import UV2AGL
    import math
    import random
    from defcon import Font
    # create a font object
    myFont = RFont(showInterface=False)
    # some default example values
    myFont.info.descender=-250
    myFont.info.xHeight=500
    myFont.info.ascender=750
    myFont.info.capHeight=750
    myFont.info.unitsPerEm=1000
    myFont.info.unitsPerEm=1000
    myFont.info.familyName="Bogota"
    
    Variable([
        dict(name="offsetValue", ui="Slider",
                args=dict(
                    value=0.0,
                    minValue=-2.0,
                    maxValue=2.0)),
        dict(name="Save_As_UFO", ui="CheckBox"),
        dict(name="Reset_Offset", ui="CheckBox"),
        ], globals())
    
    if Reset_Offset == True:
        offsetValue = 0.0
        
    fontName = "PanamaDisplay-Regular.otf"
    charSet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9",".",",","!","?","[","]","-","—",'“','”','‘','’','"',"'"]
    
    def calculateDistance(pt1, pt2):  
        x1, y1 = pt1
        x2, y2 = pt2
        dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)  
        return dist  
    
    def calculateHandles(pt1, pt2):
        x1, y1 = pt1
        x2, y2 = pt2
        dx = x2 - x1
        dy = y2 - y1
        offset = offsetValue
        # vector (y, -x) is perpendicular to vector (x, y):
        handleOffsetX = offset * dy
        handleOffsetY = -offset * dx
        
        h1Pos = 0.25
        h2Pos = 0.75
    
        h1x = x1 + h1Pos * dx + handleOffsetX
        h1y = y1 + h1Pos * dy + handleOffsetY
    
        h2x = x1 + h2Pos * dx + handleOffsetX
        h2y = y1 + h2Pos * dy + handleOffsetY
    
        return (h1x, h1y), (h2x, h2y)
        
    def extractContours(bez):
        contours = []
        for cont in bez.contours:
            poly = []
            for seg in cont:
                for pt in seg:
                    poly.append(pt)
            contours.append(poly)
        return contours
        
    def saveAsUFO(path, char):
        # get unicode for character
        uni = ord(char)
        # get glyph name for unicode
        glyphName = UV2AGL.get(uni)
        # create a glyph object
        myGlyph = myFont.newGlyph(glyphName)
        # set unicode
        myGlyph.unicode = uni
        # get the pen
        pen = myGlyph.getPen()
        font(fontName)
        fontSize(1000)
        w, h = textSize(char)
        myGlyph.width = w
        # draw path into glyph with pen
        path.drawToPen(pen)
        
    def drawContours(contours, char):
        bez = BezierPath()
        for contour in contours:
            prevPoint = contour[0]
            bez.moveTo(prevPoint)
            for pt in contour[1:]:
                h1, h2 = calculateHandles(prevPoint, pt)
                bez.curveTo(h1, h2, pt)
                # bez.lineTo(pt)
                prevPoint = pt
            bez.closePath()
        drawPath(bez)
        
        saveAsUFO(bez, char)
    
        # Convert the letter into Bezier Path
    for i in range(len(charSet)):
        newPage(1000, 1000)
        # offsetValue = random.uniform(-0.5, 0.5)
        bez = BezierPath()
        bez.text(charSet[i], font=fontName, fontSize=840)
        xMin, yMin, xMax, yMax = bez.bounds()
        cx = (xMin + xMax) / 6
        cy = 0
        bez.translate(cx, cy)
    
        # drawPath(bez)
    
        contours = extractContours(bez)
        # print(contours)
        drawContours(contours, charSet[i])
        
    if Save_As_UFO:
        # save the ufo
        myFont.save("Bogota.ufo")
    
    
    


  • hello @michelangelo,

    to create a variable font you’ll need at least two compatible UFO masters and a .designspace file.

    see I Can Variable Font for instructions on generating variable fonts from UFOs using fontmake.

    you might also want to check pages tagged with interpolation and variable fonts in the RoboFont documentation.

    hope this helps… good luck!