Please test new plugin: Springs

So, I’m pretty excited about this one. This adds a complete constraint system to Glyphs. (Think “Pwer Ndge”.) You can download it from my plugins repository; instructions on use below. This is quite early code and I expect lots of bugs, but it should also be lots of fun.

By the way: You will need the latest-and-greatest beta Glyphs to correctly load constraints from a .Glyphs file. Constraints can be saved just fine in older versions, but they won’t load up again!


Tie your nodes together with flexible springs!

How to install

Download my plugins repository or clone it with Git:

git clone

Double click the Springs.glyphsTool or move it into the Glyphs plugin folder. Now reload Glyphs.

How to use

Springs is a plugin which allows you to define relationships between nodes, and ensure that when nodes are moved, stretched or transformed, those relationships are maintained. An obvious relationship is a stem: when you move one node in a stem, you generally want the stem’s thickness to be preserved.

Think about the letter E for example. As you move one node in the E’s crossbar, you want the node on the other side to move too. This is a vertical stem, so we want the vertical distance between the two nodes to be preserved. We activate the Springs tool, select the two nodes at the end of the crossbar, right click, and choose “Add vertical constraint”. A blue line appears connecting the two nodes, and there’s a handle labelled “v” so we know this is a vertical constraint.

Now, as we move the bottom node, the top node moves too:

Very nice. We’ve kept the vertical distance the same, but as we moved our node horizontally, the node on the other side stayed at its previous X position. And maybe you want that for some things, but it’s not what we want for our E. There are two things we could do here. We could select the same two nodes and add another contraint - this time, a horizontal one. (If we do that we get a red line as well as the blue line.) But what we’re going to do instead is delete the vertical constraint by clicking on its handle and hitting delete, and then making a diagonal constraint instead. This constrains both X and Y distances between two nodes.

Now we find that the nodes move in parallel, maintaining the stem:

But what about the other nodes in our E? We want the arm to remain straight, which means that when we move the crossbar nodes around, we want the two nodes connecting the crossbar to the main stem to move in sync with them. Let’s add two vertical constraints keeping the Y coordinate of the end of the crossbar the same as the nodes on the vertical: one constraint fixing the coordinate of the top two nodes, one fixing the bottom two nodes. As we move one of the crossbar nodes around, everything else follows to keep the crossbar both straight and at a consistent stem thickness:

Well, so what? Surely we could just select four nodes at a time and drag them all around instead of just dragging one node, right? Well, yes, but Springs has a few more tricks up its sleeve. First, we can say that three nodes should stay in a fixed proportion. Take a look at the arch of this lower-case m:

We want to keep the middle node just under half-way between the outer nodes. We select the three nodes, and then add a horizontal proportion constraint:

We’ll also add a few more constraints, keeping the stems vertical and keeping the right-hand off-curve handle straight, but also making the left-hand off-curve handle move in proportion to the rest of the curve:

Now as we move any of the nodes of our arch around, the whole thing stays arch-shaped.

One final trick. You can also say fix the proportion of two distances. Rather than fixing the stem width of each of our m’s legs, we could say that the stem width of each leg must always be equal to the other legs. To do this, we select four points - the left and right of the right and middle legs - and add a yellow “horizontal proportion constraint”. Then we select the left and right nodes of the left and middle legs and do it add another yellow constraint. Our m ends up with quite a lot of constraints:

Now we grab two nodes in one of the legs, and change the stem width, and BOOM:

Stem widths have changed, but proportions have been kept in place. And that’s a good reminder, too - Springs doesn’t just maintain proportions as you drag around points with the mouse, but when you nudge with the keyboard or transform your glyph using the transformations palette and (to a certain degree) with filters. As long as the Springs tool is selected, it will attempt to maintain the constraints for you.


Springs is distributed free of charge under the terms of the MIT license (see LICENSE file), but if it is useful to you, please multiply how much time you expect it to save you by your hourly rate, and then make what you consider to be a fair donation to me via Paypal.


Simon Cozens, Please report bugs via the bug tracker

I installed it, but it doesn’t show in any menu, and there is no option to add constraints when I right click (ctrl+click).

It should appear as a new tool (with a spring icon) in the toolbar. If not, I guess it didn’t install properly - could you close Glyphs, open and look for any Glyphs-related errors appearing in the log when you start Glyphs again.

Could you right-click on the disclosure triangle where it says “An uncaught exception…” and tell me what that says? Also you should probably get rid of the Comb plugin for now, until we have this one working.

Ah, I think it means you need the beta (2.3) glyphs.

I have Glyphs 2.2.2, and this is also the latest available (even if I check “show cutting edge versions”).

I installed it, managed to link nodes (not sure if I done it the way it’s intended) and dragged nodes, but off-curve nodes are not nudged. Is it because of the errors I’ve got?

Also there seems to be no way of deleting constraints, and the only way to remove them (or reset) is to copy-paste the path.

I uploaded a new version. The one from yesterday was a bit crashy.

Toshi: When you deleted your nodes, the associated constraints were not being deleted, and so the solver was confused. I’ve added code to clean up the constraints if they are no longer valid. Try updating the plugin from the repository.

Also, you can delete constraints by clicking on the name (“h”, “v”, “p”, “hp” etc.) and hitting delete, just like deleting a hint. (Actually they are implemented as a special kind of hint - not a PS or TT hint, but a constraint hint.)

Georg, is there a way that I can get my constraint hints to display a nice label, like other hints? Also I would prefer them not to display as a stem with a grey background. (See the pictures above.)

I’ll have a look at the implementation with you plugin in mind, soon.

@SimonC — Color me dumb I guess, because I can’t get any of these tricks to work. G2.3b [860] OS X 10.11.3. It doesn’t work in Build [859] either. I have the latest version of Springs from your repo.

I think the concept might have some real value, although not necessarily in how it works right now.

Are you seeing the Springs tool in the toolbar? Getting any messages in the Macro window? Are you able to create constraints?

The Springs icon is present, no messages during use. I can create constraints and while I have read the above instructions several times, I cannot get the results described.

Maybe I should print the instructions so I can study the instructions more closely.

At this point in the code’s development it’s much, much more likely to be my fault than yours! Start with a simple rectangle in a new font, create a diagonal constraint between two nodes, and drag one of those nodes around. If the other node doesn’t move, then the whole thing is a bust.

I’ve been developing using 2.3b (851), but I’ll upgrade myself and see if that’s the problem.

The node behavior is what has been failing. If I move one node, it is the only one that moves.

::EDIT:: I had a copy of Build [846] in my Updates folder and just tried that. The rectangle performs as it should in that Build, but not in Build [860].

At this point I will wait for an update to Springs.

Confirmed. I’ve updated to 860 and now nothing works. I’ll get it fixed.

Update: I’ve narrowed this down to the fact that in 860, my update observer is silently not being fired. I don’t know why this is or where to go next. @GeorgSeifert, any ideas? Here’s the code:

NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(self,objc.selector(self.update,signature='v@:'), "GSUpdateInterface", None)

It used to work…

I fixed it. It should work again in versions 861.

I can’t get it to work in [861]., the gray background showing the constraints is gone. I found that useful.