Drawbot in Glyphs question

Maybe is a silly question, but her I go. How can I use the current font in glyphs to “write” a string?

Thanks in advance!

That should work as in all other versions of DrawBot. There has to be sample code.

This is super old but does anyone have an answer to this? I suppose you could export the font you’re editing and install it temporarily, but then you’d lose access to the Glyphs python API, right?

It still work and that’s what I do if I need to display more text than just a short string. Btw you don’t need to install the font system wide, you just need to export it somewhere and can call it from DB (maybe that’s what you meant).
If it’s counterproductive to export fonts at this point of your design process, the easiest way I found is to keep track of the width of the glyph you just displayed and pass that to Translate() before displaying your next glyph. Can get more complex if you want kerning though.

I have the same question. In RoboFont, there is an API .testInstall() to install the font locally and can be used within the drawbot app (it works by generating the otf files). There is an api in drawbot to install the font too. In this meantime, I’ll just go with this way, to write my custom testInstall function:

from GlyphsApp import *

def testInstall():
    font = Glyphs.font
    path = '/var/tmp/'
    format = 'OTF'
    ext = '.otf'
    names = []

    for instance in font.instances:
        if instance.active:
            fontName = instance.fontName
            instance.generate(Format=format, FontPath=path, Containers=[PLAIN])
            n = installFont(path + fontName + ext)
            names.append(n)
    return names

installedFonts = testInstall()

newPage('A4Landscape')

t = FormattedString()
t.fontSize(90)

for f in installedFonts:
    t.font(f)
    t += 'hamburgefontsiv\n'

textBox(t, (30, 30, width()-60, height()-60))

Use it with the drawbot Glyphs plugin. But there is an issue with the installFont function when I rerun the code that sometimes it doesn’t recognize the font:

*** DrawBot warning: font: 'FontName-Regular' is not installed, back to the fallback font: 'LucidaGrande' ***

@GeorgSeifert do you know what is the problem? It seems to occur on the original drawbot app as well.

Installing fonts in the system is dangerous – font cache problems and such. Have you tried to uninstall the fonts, first?

The installFont() function in Drawbot doesn’t install fonts in the system, they’re supposed to be active for the current Drawbot session only I think.
I’ve had the same occasional issue as @sovichet but I think it’s something that should better be brought to the Drawbot people?

Even when it is only active for the current process it is still processed by the system.

Oh, I didn’t know that, thought it would work like the Adobe fonts folder, or your Text Preview app.

I see. I thought the same as @joachimvu.

Yeah that’s what I meant. Ideally I would prefer not to do that, because I like how easy it is to access some elements through the Glyphs API, like for drawing nodes and handles. But I’ve been looking at the DrawBot documentation and I think I might still be able to do what I want this way, so I’ll give it a try.

Adobe is not useing the system font handling at all. They do all of it themselves. And the Textpreview app is specially crafted around the system.

So what’s the recommended workflow, @GeorgSeifert? Is there any way we can use a font Drawbot without having it “dangerously” “processed by the system”? I have the same needs for a Drawbot proofing script I made… I wrote a similar function as @sovichet, and I get the same *** Drawbot warning error about the font not being installed (although it always seems to work anyway). Typesetting with the current font is a super fundamental need for Glyphs + Drawbot to work together—what’s the right way to do it?

And at the risk of sounding ignorant and unappreciative, can I ask how it’s possible that Robofont can have a Test Install feature + API, whereas Glyphs can’t? I wrote the same proofing script for RF too, and using the Test Install font in DrawBot was a breeze.

Why not access the shapes of the font directly? You can from GlyphsApp import * and then access the Glyphs object As you would in a regular Pythons script: Glyphs.font gives you the current font, etc.

For good sample code, see @Ricard_Garcia’s repository:

Thanks, @mekkablue, although @Ricard_Garcia’s scripts appear to only use Drawbot to render individual glyphs in a character set grid—which is a perfect use case for drawPath(GSLayer.bezierPath). It sounds like that’s what you’re recommending, right? Unfortunately, many of my proofs include 10+ pages of full paragraphs, and I remember someone (perhaps @GeorgSeifert?) mentioning that it’s a good idea to use an exported font for that quantity of text. And that makes sense, as it would be unnecessarily complicated to code a function to recreate basic text and typesetting (+tracking, leading, kerning, opentype features, &c.) that draws each letter as a vector path.

There has to be a way to type actual text (and use Drawbot’s typesetting features), using a test font from the current Glyphs project. What is preventing Glyphs from having an equivalent to Robofont’s Test Install feature?

For typesetting, you need an exported font. Still, you do not need to install the font first. Exporting will do, see the DrawBot documentation:

font ( fontName , fontSize=None )

Set a font with the name of the font. If a font path is given the font will be installed and used directly. Optionally a fontSize can be set directly. The default font, also used as fallback font, is ‘LucidaGrande’. The default fontSize is 10pt.

The name of the font relates to the font’s postscript name.

The font name is returned, which is handy when the font was loaded from a path.

So you should be able to do something like this:

fontName = font("~/exports/myfont.otf")
font(fontName, 12) # or in this case just: fontSize(12)
myText = "The quick brown fox jumps over the lazy dog."
pageSize, inset = 500, 30
newPage(pageSize, pageSize)
textBox(
    myText*10, 
    (inset, inset, pageSize-inset*2, pageSize-inset*2),
)

Just tried it and it works for me in DrawBot.

I love the thorough response, Ranier! This is almost exactly the approach I’m taking in my script (and I think it’s what @sovichet is doing too)… right after a step that generates the OTF from Glyphs. The only difference is that we were using DB’s installFont() function, then later accessing the font by its returned postscript name, perhaps throughout the script in font() functions. I just tried your way—loading a path into the font() function—and it seems to work the same way. If I make a change to my font (ex: edit a path in the letter A), then re-run the script, the change doesn’t appear in the proof. The new OTF has the updated A design, but the changes don’t show in the proof because the old OTF (with the same name) has been cached.

So it seems that loading a font in Drawbot via font( path ) does not alleviate caching issues. It suffers from the same caching as DB’s installFont(path) function.

I could make my own testInstall function (similar to @sovichet’s, above) append a timestamp to the exported file name (as @hagenburger’s script does), but this is still a workaround. Is that really the best solution you recommend?

And please, I’m dying for an answer to this: What is preventing Glyphs from having an equivalent to Robofont’s Test Install feature? :pray::pray::pray:

1 Like

I’m working on that. But method mentioned by @mekkablue is safer an easier then the installfont function. Or if you like to have it anyway, you can add it yourself (as long as you only need it inside Drawbot).

1 Like

Maybe this makes some sense as an alternative way to do it. Taking the path of your script, I would export a .UFO of that instance you want to use in the text box. Then from defcon import Font and use that .ufo file you’ve previously exported as a font object. Even though I’m figuring out why the “generate” function is not working for me (maybe @GeorgSeifert can help me) the idea would look like this:

from defcon import Font

path2Script = "…/path/to/your/script"

for instance in Glyphs.font.instances:
    instance.generate(UFO, FontPath = path2Script)

# Using the Font object
Font("yourInstanceName.ufo")

As said, I couldn’t actually use this script because I can’t generate .ufos as in Glyphs’ API but hope that would help. I’ll be reading the discussion.

Why using an ufo instead of a real font. In the best case this is slower and in the worst you loose Informationen.

I’ll have a look at this and see what I can do.