In the first section of this
draft, I describe a formula to make two G¹–continuous cubic Bézier curves G³–continuous. Though the formula actually works for two G¹–continuous cubic Bézier segments only, it seems to work for more segments as well, if being iterated.
The formula (and its iteration) is implemented in the
Curvatura script for FontForge. Feel free to try it.
Is this algorithm already known?
(As far as I can see, the RMX tools have an algorithm to make curves G³–continuous as well (called supersmooth), but my algorithm is probably different: "supersmooth" seems to move the node perpendicular to its handles, my algorithm scales the handles.)
Comments
I always thought harmonized is harmonized (of course, how harmony is achieved may differ), but now it turns out there are all sorts of harmonized.
I have a feeling that moving the nodes rather than the handles preserves more of the intended shape.
a3
because it's the on-curve point. Fine. Instead, compute wherea3
should go according to this algorithm, work out the delta between the new position and the current position, and apply that delta to the handlesa2
andb1
instead.Some more silly questions: do you think it would be difficult/possible to
1. Port this functionality to Glyphs app?
2. Give users a choice: adjust handles, adjust nodes, or say 50/50?
1. Yes, it should not be too problematic to write a Glyphs plugin with the same functionality. The math is open, the implementation under GPL. As I don't have Glyphs, someone else would have to do this.
2. You already have the choice: "Harmonize" will move the node, "Make G3 continuous" will move the handles. Mathematically speaking, going from G1 to G2 means 1 additional constraint (like moving the node), going from G1 to G3 means 2 additional constraints (like moving the two handles). Therefore, in generic cases the best you can get by moving the node ist G2. 50/50 does not make sense in a mathematical point of view, but one can easily implement a mixture of "Harmonize" and "Make G3 continuous".
This was created with 2 vector points like this...
Then, using "Nodes at Extremes" to create my final example above. Like this...
Tools and advanced algorithms are a help but no substitute for skill and developing a good eye. But, everyone is entitled to their opinion and methods. Your "G3-continuous" algorithm is an improvement. I commend you on your efforts. Someday, sorry to say, machines and automated programs will indeed replace the artist and the craftsman.
thank you very much for publishing openly available math alongside your Curvatura code. At FontLab, we’ve made a successful test implementation of your “Make G3 continuous” method in FontLab 7. The app already has included Harmonize, Balance aka Tunnify, and adding inflections, so G3 was a useful addition.
Since our Harmonize (G2) implementation only moves the node and keeps the handles in place (which allows us to have the dynamic G2 node aka Genius node), I realized that we can add specificity to Harmonize by calling it “Harmonize Nodes”, and then add the second operation (your Make G3 continuous), which we called “Harmonize Handles”, since it actually keeps the node position and only moves the handles.
- As previously, you can Harmonize a Smooth node with Alt+2xclick to make it G2, or convert it to Genius (dynamic G2) with Shift+Alt+2xclick
- You can now Harmonize Handles with Ctrl+Alt+2xclicking a Smooth or Genius node to make it G3
The new Harmonize Handles operation is available in the beta version of FontLab 7.1.0 that we just released. You can download the beta at https://download.fontlab.com/ — it’s available as a 30-day trial or with your FontLab 7 license, for macOS, Windows (32- and 64-bit). The 32-bit Windows version is said to work well under Linux with Wine.
I’ve described Harmonize Handles in the FontLab 7.1.0 beta release notes:
https://help.fontlab.com/fontlab/7/manual/Release-Notes-Beta/#harmonize-handles
I have found that Harmonize Node is a very neat way to get “some sort of reasonable defaults” for the handle configuration of a smooth node. Not universal and good for everything, but decent as quick defaults. This actually plays nicely with the Alt+2xclicking a Sharp node operation, which in FontLab 7 “normalizes a corner” i.e. makes reasonable defaults for a sharp node.
I can’t wait what others will think of it! Many thanks
Adam
G0 continuity (Sharp nodes):
G1 continuity (Smooth nodes):
G2 continuity (Smooth nodes with Harmonize Nodes applied, or Genius nodes):
G3 continuity (Smooth nodes with Harmonize Handles applied):
This gives you the idea.
In my view, Harmonize Handles is useful, but as Linus said, you need to be more aware of its limitations, so in FontLab 7, we’re only exposing it in the UI in a limited fashion (for example, there is no way to apply this to all glyphs, as it would not be advisable to do this thing "blind").
I agree, G3 "removes" any "visual structure" along a longer Bezier spline. In a single-master design, you may just as well remove that kind of node.
Harmonize Handles (G3) may be useful if you decide to keep a node which you want to be super-smooth (“silent” or “super-harmonic”) in one master, but then you need it to be "functional" (“have an individual voice”) in another master for whatever reason.
However, if G³-continuity can be gained without exceeding the tangent triangle, it may still be the superior solution.
I suppose you could trace the bitmaps to curves, then harmonize them, then re-rasterize them. But my suspicion is that in general the autotraced curves would be very yucky and harmonizing wouldn't work on them.
I haven’t looked at this aspect of TT quadratics to know, but it is at least possible that TrueType is (usually? always?) G³-continuous already, in those cases when the on-curve point is merely implied. Probably not, though, as it would involve a bit more processing from the rasterizer to figure out the implied point position. The design of TrueType is all about saving processor power, even when at the cost of needing more data.
Thanks!