How to collect coordinate tuples to draw pen data

Hello, I am looking for a way to collect the layer’s path as pen data, like this:

(  # new path
    (s*0.05622, s*0.60655),
    ((s*0.06633, s*0.61681), (s*0.07300, s*0.63160), (s*0.08017, s*0.64389)),
    ((s*0.08715, s*0.65588), (s*0.09434, s*0.67221), (s*0.10359, s*0.68159)),
    (s*0.08769, s*0.68579),
)

to use in a function like this:

def draw_pen_data(layer, pen_data):
	for path in pen_data:
		pen = layer.getPen()
		pen.moveTo(path[0])
		for segment in path[1:]:
			if len(segment) == 2:
				pen.lineTo(segment)
			elif len(segment) == 3:
				pen.curveTo(*segment)
		pen.closePath()
		pen.endPath()

		layer.cleanUpPaths()
		layer.correctPathDirection()

I think I yoinked this function from the BuildGlyphs.py script by Rainer. A year or so ago I wrote my own adaptation for different paths, but can’t for the life of me remember how I collected the pen data. Any pointers?

Or any other way to encapsulate paths in a script efficiently so that I can draw them again?

Maybe the GSPathSegments are useful?

segments = path.segments

What does the s*0.05622 mean? Are those factors relative to the bounding box?

The s is the scaling factor (the font’s UPM).

GSPathSegments is not useful, because objects() doesn’t return all nodes, only the first and last (not the offcurve nodes), which is exactly what I’ve complained about a few times, for exactly this reason :grin:

If you have any other idea how to easily store (and redraw) path data in a script, I’m also very open to changing my method.

But your data structure has no nodes at all. I don’t understand what you are trying to accomplish.

I’m trying to save a path as coordinate tuples, so that I can embed them in a Python script. I later want to use this script to draw the path again.

But never mind, I figured it out and now have the working code.

I use this:

print(path.segments)

and this:

from GlyphsApp import GSPathSegment, GSPath
descs = [
	"C: |(9,0)--(76,-43), (139,-38)--(196,0)| >187,0)",
	"L: |(196,0)--(196,320)| >0,320)",
	"C: |(196,320)--(139,365), (76,369)--(9,320)| >-187,0)",
	"L: |(9,320)--(9,0)| >0,-320)"
]
segments = NSMutableArray.new()
for desc in descs:
	segments.append(GSPathSegment.alloc().initWithDescription_(desc))

shapes = []
for seg in segments:
	path = GSPath()
	path.segments = [seg]
	shapes.append(path)
Layer.shapes = shapes

this adds each segment as an open path. But you can adjust the script to put them all in one path.

I didn’t know you could initiate a segment object with that format, very cool. I’ll give that a try later. Thank you very much!

Hello again. How can I extract these descriptions from a GSPathSegment? There’s always the “obj:2” at the end. Just using .replace("obj:2", "") feels wrong. Is there a more proper way?

Either remove the obj:2 or ignore it.