Last active
August 20, 2024 23:42
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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 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
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:In any case, thanks for sharing the code!