Skip to content

Instantly share code, notes, and snippets.

@arrowtype
Last active March 29, 2024 16:51
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save arrowtype/6f47cea71beee7bde5a772007562e4a8 to your computer and use it in GitHub Desktop.
Save arrowtype/6f47cea71beee7bde5a772007562e4a8 to your computer and use it in GitHub Desktop.
For DrawBot in GlyphsApp: Draw a glyph's outlines & nodes, for presentation / social media purposes
"""
Script to create an image of a glyph in the current layer.
Instructions:
- Use within the Drawbot plugin of GlyphsApp.
- Get this plugin via Window > Plugin Manager, then search for "Drawbot" and install it.
- Then, go to File > New Drawbot, and paste in this code and run it.
- You may need to restart glyphs for the Plugin to work.
- Configure options & colors below in the "Configuration" area.
- If you want, open the pdf or svg file in Adboe Illustrator, etc, then edit further!
Credits:
Started from https://forum.glyphsapp.com/t/showing-nodes-and-handles-in-drawbot-with-custom-colours/17495/16
"""
from GlyphsApp import *
font = Glyphs.font
# ---------------------------------------------------
# Configuration below
# name of glyph to draw
glyphToDraw = "g"
# folder to save to
folder = "~/Desktop"
# filename + filetype. Possible types: png, svg, pdf, jpg
filename = "glyph-drawing.pdf"
# how wide to make canvas (it will be a square)
imageSize = 2160
# use to adjust scaling of glyph
glyphScaling = 1
# how thick to make paths
strokeThickness = 2
# how big to make points
handleSize = 8
# glyph colors (R, G, B, Alpha)
insideColor = (0/255, 0/255, 0/255, 0.125)
strokeColor = (0/255,0/255,0/255, 1)
# point colors (R, G, B, Alpha)
handleInsideColor = (255/255, 255/255, 255/255, 1)
handleStrokeColor = (255/255,0/255,175/255, 1)
handleConnectionColor = (255/255,0/255,175/255, 0.25)
# a color for the background (R, G, B, Alpha)
backgroundColor = (240/255, 240/255, 255/255, 1)
# Configuration above
# ---------------------------------------------------
def drawOnNode(node, handleSize):
if handleSize == 0:
return
pt = node.position
nodeType = node.type
size = handleSize
fill(*handleInsideColor)
if nodeType == GSCURVE or nodeType == GSLINE:
rect(pt.x - (size / 2), pt.y - (size / 2), size, size)
def drawOffNode(node, handleSize):
if handleSize == 0:
return
pt = node.position
nodeType = node.type
size = handleSize
fill(*handleInsideColor)
if nodeType != GSCURVE and nodeType != GSLINE:
index = node.parent.indexOfNode_(node)
prevNode = node.parent.nodes[index - 1]
nextNode = node.parent.nodes[index + 1]
stroke(*handleConnectionColor)
if prevNode.type == GSOFFCURVE:
newPath()
moveTo(node.position)
lineTo(nextNode.position)
drawPath()
else:
newPath()
moveTo(node.position)
lineTo(prevNode.position)
drawPath()
stroke(*handleStrokeColor)
oval(pt.x - (size / 2), pt.y - (size / 2), size, size)
def drawGlyph(layerGlyph, imageSizing, scaling, strokeThickness = 1, handleSize = 10):
newPage(imageSizing, imageSizing)
# draw background
fill(*backgroundColor)
rect(0,0, imageSizing, imageSizing)
offsetX = (imageSizing - (layerGlyph.width * scaling)) / 2
print(font.upm)
print(layerGlyph.bounds.origin.y)
print(layerGlyph.bounds.origin.y * scaling)
offsetY = ((imageSizing - (layerGlyph.bounds.size.height * scaling)) / 2) - ((layerGlyph.bounds.origin.y * scaling))
translate(offsetX,offsetY)
scale(scaling)
# draw glyph
fill(*insideColor)
stroke(*strokeColor)
strokeWidth(strokeThickness)
print(type(layerGlyph.bezierPath))
print(type(layerGlyph.openBezierPath))
drawPath(layerGlyph.bezierPath)
# draw paths
stroke(*handleStrokeColor)
for p in layerGlyph.paths:
for n in p.nodes:
drawOffNode(n, handleSize)
for n in p.nodes:
drawOnNode(n, handleSize)
saveImage(f"{folder}/{filename}")
layerId = Glyphs.font.selectedLayers[0].layerId
# note: make sure to use .copy(), or it will edit the source glyph!
layerGlyph = Glyphs.font[glyphToDraw].layers[layerId].copy()
# currently, this script can't show overlapping contours
layerGlyph.removeOverlap()
glyphScaling = glyphScaling * imageSize/font.upm
drawGlyph(layerGlyph, imageSize, glyphScaling, strokeThickness=strokeThickness, handleSize=handleSize)
@jmsole
Copy link

jmsole commented Jan 19, 2023

Hi Stephen, I wanted to use this gist for some images I need to prepare for a workshop. I needed to keep overlaps. In case that would be useful to you as well, you can get rid of layerGlyph.removeOverlap() by iterating through the paths instead of simply laying down the entire layer. Something like this replacing line 126:

for layerPaths in layerGlyph.paths:
        drawPath(layerPaths.bezierPath)

In any case, thanks for sharing the code!

@arrowtype
Copy link
Author

@jmsole ahh, nice, that’s a great addition! Thanks for figuring that out and taking the time to comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment