Need help with Glyph API and Python

I’m beginning with scripting in Python and Glyph API.
I would like to code a script to know how many glyphs had specific layer color.
I don’t know how to code the equivalent of “Check for each glyph in the font, if has the Layer color “Light Green” and return a list of them.”

For the moment I just have this little code

for glyph in font.glyphs:
	if Layer.color == 4:
		print(str(glyph.name))
	else:
		pass
colorCount = 0
for glyph in font.glyphs:
	if glyph.color == 4:
		colorCount += 1
		print(glyph.name)
print("There are %d glyphs with color 4" % colorCount)

Thanks Georg !
Just an additional question, how can I get the total number of glyphs in my file ?

colorCount = 0
glyphsCount = ???

for glyph in font.glyphs:
	for layer in glyph.layers :
		if layer.color == 4:
			colorCount += 1
			#print(glyph.name)
print("%d" % colorCount + "/" + "%d" % glyphsCount)
print(len(Font.glyphs))

There is a way to indicate to count only master layers?
I found this is the API :

# for master layers, use ID of masters
layer = font.glyphs['a'].layers[font.masters[0].id]

But it doesn’t seem to work here.

font = Glyphs.font
colorCount_1 = 0
glyphsCount = len(Font.glyphs)

#Red Layer Label : Redrawing
for glyph in font.glyphs:
	for layer in glyph.layers :
		if layer.color == 0:
			colorCount_1 += 1
			#print(glyph.name)
print("Redrawing : " + "%d" % colorCount_1 + "/" + "%d" % glyphsCount)

I found a solution after many hours of fails :partying_face:

Replace

for layer in glyph.layers :

by

x=-1	
for glyph in font.glyphs:
	layer = font.glyphs[x].layers[0]
	x += 1

Now I have a small script to know the progress of each of my masters.
Next step is to integrate this in a Palette Plugin.

You can write that like this:

for glyph in font.glyphs:
    layer = glyph.layers[0]
    …

But to get to all master layers, do this:

for master in font.masters:
    colorCount = 0
    for glyph in font.glyphs:
        layer = glyph.layers[master.id]
        if layer.color == 4: # add on of the color constants
            colorCount += 1
    print("master %s: %d of %d done" % (master.name, colorCount, len(font.glyphs)))
    …

Thanks, this will clean a lot my code !
I read the topic about Plugin Palette in GlyphsSDK, but I don’t know if my UI intention need to use Interface Builder or if it’s possible with only Vanilla?

This is what I would like to have for UI

Font-DashBoard-Palette

2 Likes

You can do that with vanilla. But for either solution you will need a custom view class for the progress bar (don’t bother with the built-in progress bar. Just make one from scratch will be easier.)

But I see some problems with putting it in a sidebar panel:

  • the bars will not change a lot so you look at the same data most of the time.
  • I don’t see a good way to trigger an update when the layer color changes and computing it all the time is too slow.

I’m not sure to understand what you said about progress bar.

Maybe add a button to update layer color changes or if it’s possible to update data when the file is saved (Cmd+S) ?

Good idea! Yes, that is possible. See about callback keys in the documentation. There is one called DOCUMENTWASSAVED: Glyphs.app Python Scripting API Documentation — Glyphs.app Python Scripting API 3.0 documentation

1 Like

Hi Georg,

I would like to finish this Plugin now that I am more comfortable with Python and GlyphAPI.
But just one thing, I don’t know how to draw shapes with Python (and without drawBot)

What kind of shapes?
Does this help? Drawing Shapes Using Bézier Paths

I’m not sure…
I would like to draw rectangle to create my own progress bar.

You probably need to subclass NSView and implement like this:

def drawRect_(self, rect):
    frame = self.bounds
    border = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius_(frame, 3, 3)
    NSColor.tertiaryLabelColor().set()
    border.fill()
    barRect = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width * self.percentage, frame.size.height)
    bar = NSBezierPath.bezierPathWithRect_(barRect)
    self.color.set()
    bar.fill()
    NSColor.gridColor().set()
    border.stroke()

def setPercentage_(self, percentage):
    self.percentage = percentage
    self.setNeedsDisplay_(True)

(I typed that in Safari, so it might not work out of the box. But you should get the point)

2 Likes

Georg, can I ask, with NSView, is there any method for dragging NSPoints with the cursor? I have a similar idea of some custom UI elements for a plugin, except I’d like to control them directly with the mouse, which is a little beyond my knowledge so far.

If you want a slider control, have a look at NSSlider:

https://developer.apple.com/documentation/appkit/nsslider

Here is a visual overview:

Not quite, I’d like to control offcurves of a bezier segment as a UI element (remember, “curves” controller in Photoshop). For now, I’ve solved that with sliders, but it’s not as intuitive.

Can you show a screenshot/mockup?