Change gradient in native Color Layer via Scripting

Hey everyone,
I have some trouble navigating how to change/apply gradient fills to shapes via the Macro Console. Does anybody have some experience with this?
My goal is to apply the same gradient to all closed paths (shapes that are in a native Color Layer).
I have been inspecting manually predefined gradients with print(thisPath.attributes['gradient']) → for example <GSGradient 0x60000032e500> 2 colors
I found (GSGradient Class Reference) as a reference, but couldn’t really understand how exactly the syntax works and how to apply it to my goal.
Greetings & Thanks!

The gradient is not covered by the python wrapper and docu. I’ll see that I can add it. Until then you can use the native API that is provided by pyobjc. How to translate the ObjectiveC syntax to python is explained here: An introduction to PyObjC — PyObjC - the Python to Objective-C bridge

1 Like

If you just need to propagate the same gradient from one path to the other, you can just copy it and add it

gradient = path.attributes['gradient']
for path in paths:
    path.attributes["gradient"] = gradient.copy()
1 Like

Thank you so much! With these hints I was able to solve my issue!

Is there a way to control the gradient direction via scripting? I would like to change a ‘vertical’ gradient to a ‘horizontal’ direction.
Something like
if (rule):
thisPath. ->switch Gradient direction

Best! Lena

The gradient is defined by a start and end point. You can see them in the UI as the knobs you drag the gradient around. They are stored relative to the bonding box of the path in a range from 0 to 1.

from Foundation import NSMakePoint
gradient = Layer.shapes[0].attributes["gradient"]
# make it horizontal
gradient.setStart_(NSMakePoint(0, 0.5))
gradient.setEnd_(NSMakePoint(1, 0.5))

# make it vertical
gradient.setStart_(NSMakePoint(0.5, 0))
gradient.setEnd_(NSMakePoint(0.5, 1))

I’ll see if I can add it to the wrapper and the docu.

1 Like

Thank you!

Hi there! Just adding that I would also love to be able to access the GSGradient() constructor to make new gradients rather than copy existing ones, and to see this documented so I know how to define my own Gradient with NSColor().

I’ve tried various approaches to script this, each one crashes Glyphs. (Crash reports submitted.)


for layer in font.selectedLayers:
	for path in layer.paths:
		gradient = srcGradient.copy()
		gradient.addColor_(NSColor.orangeColor())
		path.attributes["gradient"] = gradient
for layer in font.selectedLayers:
	for path in layer.paths:
		gradient = NSGradient.alloc().initWithStartingColor_endingColor_(
		NSColor.orangeColor(), NSColor.redColor() )
		path.attributes["gradient"] = gradient

Much appreciated!

Here is a working example:

from AppKit import NSColor
GSGradient = objc.lookUpClass("GSGradient")
g = GSGradient.new()
g.setColors_([
	(NSColor.colorWithString_("#ff0000"), 0),
	(NSColor.colorWithString_("#00ff00"), 0.5),
	(NSColor.colorWithString_("#0000ff"), 1),
])
Layer.shapes[0].attributes['gradient'] = g

The colors list takes color-offset pairs. There need to be at least two colors and the first color must be at offset 0 and the last at offset 1. GSGradient is not (yet) part of the public API, so you have to get a reference to its class using objc.lookUpClass.

2 Likes

I added GSGradient to the wrapper. The documentation still needs some more work.

2 Likes

Thanks so much to you both…truly appreciate it!