Create composite with my recipe script

Hi!

I have a set of empty glyphs without outlines, but with defined kerning groups and colors. I need to create composites for them but with my own recipes. What I already tried:

  • Glyph / Create Composite – it’s works fine for glyphs that expect to have components, like IJ or Aacute. But it doesn’t work for the Iota glyph that I want to create from the I glyph component, etcetera.
  • Glyph / Add Glyphs – works perfect with my list of recipes like I=Iota or I+dieresiscomb=Iotadieresis. The only problem is that the generated glyphs are completely updated and lose their properties such as color or kerning groups.
  • Script – I believe it could be possible to make what I need but I can’t figure out how to write the right command.

I read the Python Scripting API Documentation but can’t find the command I need.
So far I understand it could be something like makeComponents. That’s where I’m stuck:

composites = [
	['I', 'Iota'],
	['I+dieresiscomb', 'Iotadieresis']
]

def updateGlyphWithRecipe(recipe, name):
	for layer in Glyphs.font.glyphs[name].layers:
		layer.makeComponents() # but with recipe

for g in composites:
	updateGlyphWithRecipe(g[0], g[1])

Is it possible to add the recipe to makeComponents() as an argument… or there is some other method for this?

Thanks.
Michael

There is a method on the layer object:

composites = [
	[['I'], 'Iota'],
	[['I' + 'dieresiscomb'], 'Iotadieresis']
]
def updateGlyphWithRecipe(recipe, name):
	for layer in Glyphs.font.glyphs[name].layers:
		layer.setComponentNames_(recipe)

Or you set up your own glyph data. Then “Create Composite” would work.

Thank you so much Georg :ok_hand:

Just + should be replaced by , in a recipe (line 3 in this example), and it’s work like what I need.

composites = [
	[['I'], 'Iota'],
	[['I', 'dieresiscomb'], 'Iotadieresis']
]

for g in composites:
	for layer in Glyphs.font.glyphs[g[1]].layers:
		layer.setComponentNames_(g[0])

You mean GlyphData.xml, I understood.

I’ll try both approaches to see which is more comfortable.
It’s nice to have an options to choice from!

If you’re comfortable with editing the GlyphData.xml, that’s definitely the preferable approach. That will bake it right into your workflow, you can just use the regular commands such as Create Composite without having to run a custom script every time.

1 Like

There is an app for that: EditGlyphData | Glyphs

1 Like

Yes, I agree, in most cases this is the best way. What I want is possible with using the GlyphData.xml + the Filter list to select all this glyphs at once. As I said, I want to try it too.

The reason why I want it is that certain Greek and Cyrillic glyphs claim to be built from the Latin alphabet. In the image, they are marked in yellow. This is only an approximate set of candidates for composites and there will still be revisions (not sure about sigmaLunateSymbol and some others), but I think the principle is clear.

Why not use a dict? Like this:

recipe = {
  "IJ": ("I", "J"),
}

Thank you Rainer, it’s more clear syntax of the recipe.
Just don’t know why but for me it only works with square brackets [] instead of round ones ().


recipe = {
	'Iota': ['I'],
	'Iotadieresis': ['I', 'dieresiscomb'],
}

for g in recipe:
	for layer in Glyphs.font.glyphs[g].layers:
		layer.setComponentNames_(recipe[g])

And here the Syntax Converter (from standard recipe to such an array)

If you only have a single item in a tuple, you need to add a comma. That’s a consequence of Python’s operator overload. Like this:

("I",)

Not that you’d notice much of a difference with the current scope of the script, but tuples are much more efficient (think memory and performance) than lists. If you have collections that won’t change, better use a tuple.

Thank you for the clarification, I see the difference now. It works.
And sorry for such a basic questions, I’m very new to Python.

recipe = {
	'Iota': ('I',),
	'Iotadieresis': ('I', 'dieresiscomb'),
}

for g in recipe:
	for layer in Glyphs.font.glyphs[g].layers:
		layer.setComponentNames_(recipe[g])