Using Robofab Pens in Glyphs3 Doubles Glyph Size

Hello Glyphs! I am a late adopter to Glyphs3 and only just purchased it, so forgive me if this has already been discussed; I have tried searching for similar issues but I fear it might be something unique to me.

So I rely on a lot of scripts using robofab and pens, over the years I have managed to adapt them for FontLab/RoboFont/Glyphs2, but I discovered that when I use pens in Glyphs3 it appears to double the processed glyph in size.

The simplest example of this is when copying a glyph and then appending it as shown below.
I beleive that under the hood this is using pens, and for me the result is the appending glyph is 2x the size as it was originally.

I have tested with other pen examples with the same result (longer code example at end)

I have tested this on newly created Glyphs3 files @ 1000upm as default, and I have got the same result on files created in Glyphs2 @ 2000upm.

I have installed all of the modules from the plugin manager including Python for Glyphs which I have selected as my python environment and the app has been restarted multiple times.

I still have glyphs2 installed and the problem does not happen there.

Please let me know if you need more information, and if there’s anything I can do to help debug, I would just like to get this behaving as expected so I’m more than happy to provide anything you need.
Thanks, Matt

from robofab.world import *

# get Current Glyph
cg = CurrentGlyph()

# make a copy of Current Glyph
cgcopy = cg.copy()

# clear the Current Glyph
cg.clear()

# append the copy (shifted 100,100 helping to show a change was made if it was working correctly glyph would appear to move but remain same size, in my case it also doubles in size)
cg.appendGlyph(cgcopy,(100,100))

And this pen usage adapted from TypoLabs2016/14 Randomize Glyph.py at master · jenskutilek/TypoLabs2016 · GitHub



# MenuTitle: 14 Randomize Glyph

#from mojo.roboFont import CurrentFont, RGlyph 
# import from robofab instead
from robofab.world import *

from fontTools.pens.basePen import BasePen

from random import randint


class MyPen(BasePen):

    # from fontTools.pens.basePen.BasePen:
    def __init__(self, glyphSet, writer_pen, max_move=0):
        self.glyphSet = glyphSet
        self.__currentPoint = None
        self.writer_pen = writer_pen
        self.max_move = max_move

    def randomize(self, pt):
        dx = randint(-self.max_move, self.max_move)
        dy = randint(-self.max_move, self.max_move)
        return (pt[0] + dx, pt[1] + dy)

    def _moveTo(self, pt):
        self.writer_pen.moveTo(self.randomize(pt))

    def _lineTo(self, pt):
        self.writer_pen.lineTo(self.randomize(pt))

    def _curveToOne(self, bcp1, bcp2, pt):
        self.writer_pen.curveTo(
            self.randomize(bcp1), self.randomize(bcp2), self.randomize(pt)
        )

    def _closePath(self):
        self.writer_pen.closePath()

    def _endPath(self):
        self.writer_pen.endPath()

    def addComponent(self, baseGlyphName, transformation):
        pass


def randomize_glyph(glyph,font):
    source = glyph
    #font = glyph.font

    # Save the anchors from the original glyph in a list
    anchors = [a for a in source.anchors]

    # Remove all anchors from the glyph so they don't interfere with our processing
    for a in anchors:
        source.removeAnchor(a)

    # Temporary glyph to which the pen is writing
    target = RGlyph()
    target_pen = target.getPen()

    source_pen = MyPen(font, target_pen, 10)
    source.draw(source_pen)

    # Clear the original glyph and add the modfied outline
    source.clear(components=False)
    source.appendGlyph(target)

    # Restore the saved anchors
    for a in anchors:
        source.appendAnchor(a.name, a.position)


if __name__ == "__main__":
    font = CurrentFont()

    for glyph_name in font.selection:
        g = font[glyph_name]
        print(g)
        randomize_glyph(g, font)

I’ll look into this.
But as a note: The roboFab support is not staying around forever. So, if possible, port the scripts to the native scripting API. We can help with that if needed.

So the first snippet could look like this:

layerCopy = Layer.copy()
layerCopy.applyTransform((1, 0, 0, 1, 100, 100))
Layer.shapes = layerCopy.shapes
Layer.anchors = layerCopy.anchors
# copy whatever else you need copied 
1 Like

Thank you, yes I understand it would be better to work with the native API, I’ve just been very lucky so far that robofab (or at least very similar syntax in fontparts) keeps going and is easily used across different tools, keeping my old code snippets alive and mostly cross-compatible.
I feel like I might be the last person using robofab but I will miss it!
Anyway, I appreciate you looking into this. Let me know how I can help :slight_smile:

PS: I’m writing this on the weekend because that’s when I have time to play with my ideas, I don’t expect you or anyone on your team to work on the weekend to solve this, save it for monday :wink:

I fixed the scaling issue. Thanks for reporting.

I didn’t get the other script to run. But for what it’s doing, it’s quite a bit of overkill. The same (as far as I can see) in Glyphs API.

# MenuTitle: 14 Randomize Glyph
from random import randint
from GlyphsApp import Glyphs
max_move=10

def randomize(pt):
	dx = randint(-max_move, max_move)
	dy = randint(-max_move, max_move)
	return (pt[0] + dx, pt[1] + dy)

font = Glyphs.font
for layer in font.selectedLayers:
	for path in layer.paths:
		for node in path.nodes:
			node.position = randomize(node.position)

Thank you for looking into it and fixing, is that coming in an update? Or cutting edge?
And thank you for the pointers how to do similar things in native API, I will likely start converting my scripts as I need to.

Hi again, I tried installing cutting edge version hoping to find that fix but I still experience the same scaling issue.

Can you advise how to get the fix you mentioned?

My version is: 3.3.1 (3342)
Thanks!

Can you remove and re-install robofab in the Plugin Manager.

Unfortunately that didn’t seem to fix it, I also had a look at the github link and I don’t see any recent commits on the repo (GitHub - schriftgestalt/robofab: RoboFab)

The changes are in an extra branch.

Oh ok, are you planning to merge it into master? Please let me know so I can reinstall it from the plugin manager

The plugin manager is getting that branch. So removing/re-installing should get that code.

Unfortunately that doesn’t seem to work, I have tried uninstalling it and reinstalling it with restarts in between each step and I still get that scaling issue.

I tried uninstalling from the plugin manager and then running my example script and it can’t find robofab as expected. I did this to ensure that it wasn’t finding robofab from somewhere else somehow and to eliminate that possibility.

Then I installed it from the plugin manager, and when running my script is finds robofab as expected but the result is scaled like how I originally reported.
I restarted and tried the script again and get the same issue.

I also tried something unconventional; I downloaded the code from the python3 branch (GitHub - schriftgestalt/robofab at python3) and tried replacing the contents of the robofab in Glyphs3 application support, and I still get the same issue even after restart.
I did this to test the branch in case the plugin manager was still pulling from master branch.

I kind of expected this to work tbh :sweat_smile:

In all cases I am using the test script that does the copy, clear, and appendGlyph basic actions that I originally posted.

I was hopeful when you said it was fixed, & I wish I could help more, is there anything I can do to help you debug this?

Thanks for your help on this

I put the fix in the wrong branch. Will be in the next update.

1 Like

Hi, I got the update but I get the following error, I also tried uninstalling/reinstalling robofab from the plugins manager with restarts in between

  File "objectsBase.py", line 1535, in appendGlyph
    aGlyph.move((x, y))
  File "objectsBase.py", line 1723, in move
    contour.move((x, y))
  File "GlyphsApp/objectsGS.py", line 1040, in __GSPath__move__
  File "GlyphsApp/GlyphsApp/__init__.py", line 9882, in __GSNode__add__
TypeError: unsupported operand type(s) for +: 'GSNode' and 'tuple'

What script is causing this?

The simple copy and append glyph example below

from robofab.world import *

# get Current Glyph
cg = CurrentGlyph()

# make a copy of Current Glyph
cgcopy = cg.copy()

# clear the Current Glyph
cg.clear()

# append the copy (shifted 100,100 helping to show a change was made if it was working correctly glyph would appear to move but remain same size, in my case it also doubles in size)
cg.appendGlyph(cgcopy,(100,100))

I just realized that some changes were only in the newer branch. So it will work with the next update.

1 Like