RFont subclass not generating "otf"



  • Hello,

    I'm working on a set of animations that are going to use some .ufos I have and I'm facing a problem that I don't know how to solve. The point is that I want to generate otf files out of them while using generateto the Font object but it says The RFont subclass does not implement this method. Any idea what I'm doing wrong?

    Here's a simplyfied version of the code that returns this error:

    from fontParts.world import NewFont, OpenFont
    
    ufos = ['Patufet-Black.ufo', 'Patufet-Light.ufo']
    
    new_f = OpenFont(ufos[0], showInterface=False)
    print(new_f)
    new_f.generate("otfcff", "_Install-otf/new_f.otf")
    

    Thanks.


  • admin

    Inside the app DrawBot an RFont has no implementation for the method generate.

    Inside RoboFont you can use the DrawBot extension, where you can have all the powers DrawBot has to draw and all the powers RoboFont has to edit font data, and also call font.generate(...).



  • I see. Then, if I want to make an animation with a long text interpolating between two .ufo files, which would be the the best option? Generating a .designspace with an axis, export the .otf and use it in the script?

    For what you say, it looks doable also inside Robofont itself, though.

    Thanks!



  • hello @RicardGarcia,

    for a simple interpolation between two masters you can use font.interpolate(factor, font1, font2) – see this example script.

    hope this helps!


  • admin

    there are several options:

    • font.interpolate will returns a ufo
    • a designspace document with a given location will also returns a ufo, use mutatorMath
    • generate a variable font

    Generating variable fonts from design spaces is not difficult: in RoboFont you can use the Batch extension. In DrawBot you can pip install ufo2ft to generate a var font and use it inside your type setting.

    good luck!



  • Thank you so much for your help to both of you. @gferreira, the example you linked is super helpful and clear. I've read a bunch of code samples in Robofont's website and I don't know why I didn't run into this one. @frederik, thanks! I think that the main thing I was doing wrong was doing it outside Robofont. With the hints you both gave me I can manage to do what I wanted inside Robofont.

    Thanks!



  • Hi again. Even though both of your comments helped me a lot I'm still facing a last problem that I don't know how to solve.

    From my opened ufos, I'm generating a new interpolated font that I'm using in each frame to make an animation. The point is that, if I'm writting the factorright away like 0, .25or 1 it does the correct interpolation but it doesn't if I use the variable interp_factor. Is it something about overwritting the new_f.otf file?

    I've tried to clean the code as much as possible and hope that helps others pointing out what's going on here:

    text2Use  = """
    A monospaced font, also called a fixed-pitch, fixed-width, or non-proportional font, is a font whose letters and characters each occupy the same amount of horizontal space.
    """
    
    def animationInstagram(text = text2Use):
        
        # Size of the page in px
        w, h = 1200, 2134.4
        
        # Number of frames
        frames = 4
            
        # Step factor
        maxFactor = 1
        stepFactor = maxFactor / (frames)
        
        # Interpolation factor (starting point)
        interp_factor = 1
        
    
        #Accessing opened ufos
        f1, f2 = AllFonts()[0], AllFonts()[1]
    
        f1.generate("otfcff", "f1.otf")
        f_1 = OpenFont("f1.otf", showInterface=False)
    
        f2.generate("otfcff", "f2.otf")  
        f_2 = OpenFont("f2.otf", showInterface=False)
        
        
        # Frames
        for f in range(frames):
            # Page settings
            newPage( w , h )
            
            fill(0) # BG
            rect(0,0,w,h)
            
            fill(1) # FG
    
            # Creating font to interpolate
            new_f = NewFont(showInterface=False)
            new_f.interpolate(interp_factor, f_1, f_2, round=False)
            print("Interpolation factor: ", interp_factor)
        
            new_f.generate("otfcff", "new_f.otf")
        
            #Installing the interpolated (temporary) font
            fontName = installFont("new_f.otf")
    
            # ------------------
            # Text box
            extraSpace = -200
    
            boxX, boxY, boxW, boxH = extraSpace, extraSpace, w-extraSpace*2.7, h-extraSpace*2
        
            font(fontName, 100)
            textBox(text, (boxX, boxY, boxW, boxH), align="left")
            
            # ------------------
    
            # Subtracting step factor
            interp_factor -= stepFactor
    
            # Uninstalling
            uninstallFont("new_f.otf")
    
    # Calling the function
    animationInstagram()
       
    # Saving the image
    saveImage("Test-interpolation.gif")
    
    

    Thank you so much once again!


  • admin

    two things:

    why generate a binary and read the the binary back in? see f1.generate("otfcff", "f1.otf")

    Give you new font a unique name based on the interp_factor. The font familyName and styleName makes up the postScriptName which has to be unique to set a font in drawBot (and everywhere else). In your case the font familyName and styleName will be "None" "None". This is not good...



  • Hi, @frederik:

    why generate a binary and read the the binary back in? see f1.generate("otfcff", "f1.otf")

    You mean I can use the opened ufo files right away as f1 and f2 to interpolate with, right?

    Give you new font a unique name based on the interp_factor. The font familyName and styleName makes up the postScriptName which has to be unique to set a font in drawBot (and everywhere else). In your case the font familyName and styleName will be "None" "None". This is not good...

    All right. I thought that after uninstalling the interpolated font I could generate another one I could use in the new page afterwards. So, in this case, would it make sense to set the same name for familyName while the styleName could be related to inerp_factor as you say?


Log in to reply