Macro Window: copyDecomposedLayer() crashing

I am trying to write a simple script that would creates a decomposed copy of all masters and layers with smart settings (i.e. skip basic layers created via “+” in Layers), but the script results in the app becoming unresponsive.

I’d be happy to debug it myself, but I get no error or crash report. Is there a special folder that such crash reports land in the file system so I can see what’s wrong?

The script:

import copy
from datetime import date

Glyphs.clearLog()

today = date.today().strftime("(%d %b)")

if Font.selectedLayers: # Selection in Edit View
	selectedGlyphs = list()
	for layer in Font.selectedLayers:
		selectedGlyphs.append(layer.parent)
else: # Selection from Font View
	selectedGlyphs = Font.selection
	
for glyph in selectedGlyphs:
	glyph.color = 3 # Mark with Yellow Label
	for layer in glyph.layers:
		if layer.isSpecialLayer:
			newName = layer.name + " " + today
			decomposedLayer = layer.copyDecomposedLayer()
			decomposedLayer.name = newName
			glyph.layers.append(decomposedLayer)

I’ve tried making sure the layers have the corrent Master ID associated. Creating the layers with GSLayer() instead seems to work OK.

Thanks for any pointers.

You are iterating glyphs.layers and adding to it inside that same loop. That is forbidden. And if that loop is not crashing, you’ll keep adding and copying endlessly. Something like this might work:

for glyph in selectedGlyphs:
	glyph.color = 3 # Mark with Yellow Label
	newLayers = []
	for layer in glyph.layers:
		if layer.isSpecialLayer:
			newName = layer.name + " " + today
			decomposedLayer = layer.copyDecomposedLayer()
			decomposedLayer.name = newName
			newLayers.append(decomposedLayer)
	glyph.layers.append(newLayers)
1 Like

Thank you!

I’ve made it to work with slight changes. The last thing I am struggling with is the duplicated layer has the Smart Glyph (if exists) attached, I’ve tried removing the “smartComponentPoleMapping” attribute or changing the individual axes value to 0 (which results in no checkbox selection in the Smart Glyph Settings > Layers window but still acts as a Smart Glyph layer), so the result is incompatible (layers decomposed but acting as Smart):

for glyph in selectedGlyphs:
	glyph.color = 3 # Mark with Yellow Label
	newLayers = list()
	for layer in glyph.layers:
		if layer.isMasterLayer or layer.isSpecialLayer:
			newName = layer.name + " " + today
			decomposedLayer = layer.copyDecomposedLayer()
			decomposedLayer.name = newName
			if decomposedLayer.smartComponentPoleMapping: # Reset Smart Glyph Settings
				for axis in glyph.smartComponentAxes:
					decomposedLayer.smartComponentPoleMapping[axis.id] = 0
			newLayers.append(decomposedLayer)
	for newLayer in newLayers:
		glyph.layers.append(newLayer)

Wondering if anyone has experience removing the Smart Glyph Settings from a single layer using Glyphs API?

Can you send me the file and the full script?

Sure. Here’s an archive of a minimal test file with a “_smart.f” glyph (intentionally including a component to test the copyDecomposedLayer() behaviour) and the script.

Basically I need the copying behaviour to create the backup layers without any Smart Glyph Settings assigned (= unchecked in Smart Glyph Settings > Layers). So the glyph interplation does not break since the backup layers are not included in interpolation.

Smart Settings Test.zip (3.8 KB)

Thanks!

I still don’t get it. You like to remove the smart glyphs settings from a copy of a layer in the _smart.f? That doesn’t work as the smart settings are one the glyph.
You could use the _smart.f as a component and flatten that composite layer.

I see. Yes, I’d like to “disconnect” the newly created layers from Smart Glyph Settings altogether so something like this would happen:

Screenshot 2021-06-03 at 15.33.09

I.e. the newly created layers are not “bolded”—I’ve achieved it by running the script as-is now and manually checking and unchecking the settings in the Smart Glyph Settings > Layers window.

Seems strange that something like this is not possible via API if I can do it manually via UI. Based on the Smart Settings window UI it is permissable to have a single layer not assigned to either of the axes (= leave everything unchecked) and still the interpolation works and is compatible.

The whole point of the script is to go through the entire typeface and make a sensible backups of all masters and it’s relevant “smart” layers.

The is nothing that you can’t access from a script. This is only a question of documenting it and make it nicer with the wrapper.

Makes sense. How should I proceed then?

What do you need that new layer to do?

There is one line that needs fixing:

decomposedLayer.smartComponentPoleMapping[axis.id] = 0

should be:

del(decomposedLayer.smartComponentPoleMapping[axis.id])
1 Like

Works like a charm. Thank you!