-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
different interpolation between Glyphs.app and MutatorMath #264
Comments
@behdad , @anthrotype : what do you think about the differences? is this something that we should learn to live with? @JelleBosmaMT : FYI |
This is definitely something that nobody should live with. You will notice that the distortions are centered around the NotoSansTamil-ExtraCondensedBold. This has interpolation values weight 151 width 70 and is supposed to be a straight interpolation between the masters at 90-70 and 190-70. The interpolation algorithm must have assumptions about the location of masters, that is now being tested by a real world example that doesn't match the assumption. |
With regards to the height change of the bracketleft.tamil: all masters have the same height except the narrow thin (26-70). But that should not have any effect on 151-70. Or has it? |
Thank you Marek and Jelle for the thorough bug report. I've examined the sources and the outputted fonts from both Glyphs.app and fontmake (via glyphsLib and MutatorMath), and can confirm the above mentioned differences in the interpolated instances. As Jelle pointed out, it seems like, when we generate instances with MutatorMath, the seventh "SemiBold" master (weight=151, width=100) placed in between the "Regular" (90, 100) and "Bold" masters (190, 100) distorts the interpolation for the condensed instances around weight=151, e.g. "ExtraCondensed Bold" (weight=151, width=70). On the other hand, Glyphs.app seems to not be affected by such asymmetric arrangement of the masters (4 weights for the normal width, 3 weights for the condensed width). Here's the output from notodiff for "jatamil" and "two" glyphs in ExtraCondensed Bold, the red outline is Glyphs.app's, the green is MutatorMath's: I was also able to replicate this situation using the .designspace generated by glyphsLib (found inside "master_ufo" folder that fontmake produces) with Superpolator 3, which like fontmake uses MutatorMath under the hood. There one can quickly "mute" masters and see the results updated live and interactively. One thing I noticed is that the "ExtraCondensed Bold" (151, 70) is interpolated exactly the same way in Glyphs.app whether or not that "SemiBold" (151, 100) master is defined. That is, if I delete the "SemiBold" master, in Glyphs.app I get the same output for the "ExtraCondensed Bold" instance. Similarly, if I delete "SemiBold" (151, 100) master and interpolate "ExtraCondensed Bold" through MutatorMath, I get the same result as Glyphs.app. This leads me to think that if one were to add another intermediate master between "Condensed" (90, 70) and "Condensed Bold" (190, 70) masters, then the outputs from Glyphs.app and MutatorMath would agree? I still haven't tried that.. @JelleBosmaMT do you think this could be viable workaround? In conclusion, it's not clear to me whether this is a bug in MutatorMath, or rather a "feature". I'd be curious to know what @schriftgestalt or @LettError have to say about these different interpolations between their respective editors. To help debugging, I'm attaching below a small .glyphs file containing just a couple of outlines from NotoSansTamil, that reproduces the current issue when exported from Glyphs.app and fontmake: https://www.dropbox.com/s/a8cv56ga2p8d1zl/test_interpolation.zip?dl=0 (There's a AWS outage affecting Github so I can't upload attachments, so I'm using my own Dropbox) |
Here’s what I "sort of know", or at least my understanding of how design spaces differ in MutatorMath and Glyphs: Both Superpolator / MutatorMath and OpenType Variations iterate through each axis and determine the interpolated coordinates per each axis individually, step by step. This allows an arbitrary number of axes, but at a cost — predictable results are given if the masters are at "corresponding" locations, like you can see on the below image. In other words, in MutatorMath, the design space always needs to be divided into rectangular areas: Glyphs is different: it throws all the masters from all the axes into the interpolation mix at the same time, so with each additional axis, the complexity of the equation grows by a degree. This allows greater flexibility in the arrangement of masters, but makes it much more difficult to add more axes. This is why Glyphs has the limit of 3 axes. In Glyphs, different equations are used depending on whether you have 1 axis, or 2 axes or 3. My understanding is that in MutatorMath, and I think also in OT Variations, your designspace always needs to be divided into rectangular areas. In other words, in Glyphs, you can have a setup like this: but in MutatorMath or OT Variations, you cannot. |
Ps. The way I understand it, the current setup where Unfortunately, AFAIK, the Glyphs interpolation model isn’t public, so it’s hard to tell what it’s actually doing. :) I’m too poor at geometry myself to be sure that what I’ve written above is correct, so please treat this as just potential hints. I think @LettError and @schriftgestalt are much more qualified to give more solid feedback. |
Hi Cosimo,
On 28 Feb 2017, at 22:28, Cosimo Lupo ***@***.***> wrote:
In conclusion, it's not clear to me whether this is a bug in MutatorMath, or rather a "feature".
I'd be curious to know what @schriftgestalt or @LettError have to say about these different interpolations between their respective editors.
It seems Glyphs chose a different algorithm in which certain constellations of masters are preprogrammed, but the code is proprietary and there is no point in me guessing. If Monotype delivered data that depends on such a proprietary algorithm then that is not necessarily a bug in MutatorMath.
However, if the data can be used to generate working variable fonts *using fontTools*, then I would kindly ask another look at fonttools/fonttools#671.
This leads me to think that if one were to add another intermediate master between "Condensed" (90, 70) and "Condensed Bold" (190, 70) masters, then the outputs from Glyphs.app and MutatorMath would agree? I still haven't tried that.. @JelleBosmaMT do you think this could be viable workaround?
You could calculate intermediates and insert them as masters, completing the rectangles. That should be relatively easy to test.
E
|
I have the hunch if I am going to work out in detail how this works, my boss would like to quote for it first. But I can solve it for my 7 masters. All instances are within a rectangle. You can connect the masters by solid lines. So in my Tamil and Sinhala x = width, y is weight. One intermediate master left, two on the right. All instances that are on a solid line are interpolated between the nearest masters. That is why the "missing master" at 151-70 has nothing to do with either 151-100, nor with 26-70 (or vice versa). So for any instance that is within the rectangle, but not on a solid line, you need intermediate interpolation masters that are on a solid line. The additional challenge that is caused by the master without horizontal solid line, is to get an additional intermediate master at the same height, which is on a solid line. |
On 01 Mar 2017, at 10:57, Jelle Bosma ***@***.***> wrote:
However as we know from accessing instances trough Python, GlyphsApp handles them all as fractional values in the interpolations. Having a physical master adds rounding.
FWIW, UFOs can store floating point values for intermediates so that is not a problem.
E
|
On 01-mrt.-17 10:55, "Erik van Blokland" ***@***.***> wrote:
It seems Glyphs chose a different algorithm in which certain
constellations of masters are preprogrammed, but the code is proprietary
and there is no point in me guessing. If Monotype delivered data that
depends on such a proprietary algorithm then that is not necessarily a
bug in MutatorMath.
Anyone working on software that has to generate font from GlyphsApp files
has a hell of a job testing all possible settings and configurations, not
just interpolation. The amount of configurations of masters seems to be
limited by the UI, it is still a lot.
But interpolation itself does not seem to be something that depends on
math that is much more than Xi = X1 + a * (X2 - X1). The challenge is to
go through steps to decide where X1 and X2 that are needed for Xi are.
In our case, things are at their worst at the “missing master” instance
151-70. What is mysterious to me is how is is possible to end up with an
interpolation that is not using X1 and X2 from masters 90-70 and 190-70. I
can imagine algorithms that may depend on certain set configurations of
masters for the instances inside the rectangle, but in this case it seems
so bloody obvious. So a possibility is that “MutatorMath” can handle it
(to some extend), but is not given the right data.
|
Adam explained it quite accurately (only that it uses the same algorithms for all master setups and the algorithm actually supports an unlimited number of masters, Glyphs internally can use 5 (the settings are accessible by script). Only the UI is limiting it, still. The .glyphs file contains the interpolation values ( |
Indeed it is all there. Almost too easy ;-) |
@anthrotype , @behdad , @brawer : whom could make this happen? I'd like us to make progress on this. |
I don't think we are planning to "skip MutatorMath" anytime soon, however "easy" this may seem to some of you. |
On 20-mrt.-17 21:44, "Cosimo Lupo" ***@***.***> wrote:
What is relatively easier (i.e. wouldn't require changes to the code)
would be to modify the .glyphs sources that have such non-rectangular
interpolation space, and add intermediate masters to make it so.
The task of the “pipeline” software is to generate fonts from .glyphs
sources. It is not the job of font generating software to modify source
files and introduce an extra layer of rounding. These fonts are at a crude
1000 units per EM and there is plenty of rounding already.
And indeed, interpolating is not hard if the instance definitions already
specify masters and interpolation values. There are different ways of
doing. You can consider:
Get list of used masters with scale values needed for instance( instance )
Make a duplicate of master( first master )
If first scale <> 1 : scale master (first duplicate, first scale)
If number of used masters > 1 then for each additional master n:
{
Make a duplicate of master( n master )
scale master (n duplicate, n scale)
Add coordinates (n duplicate, first duplicate)
Remove master (n duplicate )
}
Round all coordinates (first duplicate)
I assume this is all done with UFO’s. There is a lot of talk how wonderful
UFO based work-flows are and how easy it all is. If half of it is true
there must be ready made code that do most of the things described above.
According to Erik van Blokland you can store fractional values so that is
not a problem either.
… |
Here are some pictures that show how VariationModel calculates the factors, and how to interpret a system with non-aligned masters. http://letterror.com/dev/mutmath_varmod/ |
I just realized, that if @anthrotype can use GlyphsLib to automatically add "missing masters", then GlyphsLib can generate ANY interpolated instance. Which would solve the problem too. |
Just a quick note, the 3-axis limitation of Glyphs is not a restriction of the algorithm that computes the coefficients. It can handle an unlimited number of axes and an unlimited number of masters. |
@justanotherfoundry great, publish it. |
Anyone who can reproduce the issue wants to try this patch? diff --git a/Lib/fontTools/varLib/models.py b/Lib/fontTools/varLib/models.py
index 10825ac8..3d10921c 100644
--- a/Lib/fontTools/varLib/models.py
+++ b/Lib/fontTools/varLib/models.py
@@ -233,7 +233,10 @@ class VariationModel(object):
if not axis in loc:
continue
locV = loc[axis]
- box[axis] = (self.lowerBound(locV, values), locV, self.upperBound(locV, values))
+ if locV > 0:
+ box[axis] = (0, locV, max({locV}|values))
+ else:
+ box[axis] = (min({locV}|values), locV, 0)
locAxes = set(loc.keys())
# Walk over previous masters now |
what is this patch supposed to do?
Diffing the fonts produced with and without the above patch shows no differences. |
Thanks Cosimo. Sorry about that. I fixed varLib for, I hope this issue, and the issues that @LettError pointed out at TYPO Labs 2017. Erik, care to give it another go? It should perform as you expect now. |
Err. This: |
Why not generate static fonts from the variable font? |
well, for one thing, that currently only works for TTFs. |
also, the outlines are converted interpolatably for the varfont's masters, whereas for a single instance they could be converted slightly more efficiently if taken by itself. And we don't remove overlaps for interpolatable TTF masters that make up the varfont, whereas we do for the static TTFs. |
Yeah we should import ufoLib, add math operations to our tiny UFO objects, and run varLib on them to interpolate before creating static fonts. Basically replace mutatorMath. |
I made another, I hope, "improvement" to the model: There's one more addition coming, but then that would be about it. |
I like the results :-)
…On Wed, Mar 28, 2018 at 2:16 AM Behdad Esfahbod ***@***.***> wrote:
I made another, I hope, "improvement" to the model:
***@***.***
<fonttools/fonttools@a523a69>
There's one more addition coming, but then that would be about it.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#264 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AMtJf0PVxR6cDzDH228wcYo5cfK88jf_ks5ti1TfgaJpZM4MNvl->
.
|
Can this be closed? |
Seems to be done. |
@LettError Hey Eric, your http://letterror.com/dev/mutmath_varmod/ is no longer online, have you still got a copy, do you mind uploading it again somewhere? This difference b/w varLib and MutatorMath came up in discussions with a colleague and would be nice to read your handy summary. Thanks EDIT: the Internet Archive Wayback Machine only has the text, no images: https://web.archive.org/web/20171014153346/https://letterror.com/dev/mutmath_varmod/ |
Page recreated at https://letterror.com/dev/mutmath_varmod/ with images from my archive and html from archive.org, as that was somehow newer than the version I had on disk. I did not edit the text, I did not study this specific current issue. In 5.3 conclusions it says that VariationModel does not extrapolate. This was recently added by Behdad. |
@LettError thanks! |
Thanks a lot, that page is great, I was looking for it the other day and wondered where it was! |
The metrics for the fonts produced by the pipeline and by the glyphs.app are NOT the same. In most of the cases I examined the fonts produced by the pipeline are slightly "taller" or slightly "fatter". While the differences are not that big, they might cause a font designer to exclaim: "Pipeline is NOT producing the font I designed" :-)
The following was shared with me via e-mail (the fatter [green width: 803] is from pipeline and the thinner [red width: 789] is from the glyphs.app).
source used: https://github.com/googlei18n/noto-source/tree/master/src/NotoSansTamil
I'm not sure about the weight and width of the image below, but I've done my own research (please see below the following image).
In my experiments I used notodiff (see https://github.com/googlei18n/nototools/tree/master/nototools ) with NotoSansTamil*.otf from https://github.com/googlei18n/noto-fonts/tree/master/alpha/from-glyphsapp/unhinted/otf/sans as --before fonts and NotoSansTamil*.otf from https://github.com/googlei18n/noto-fonts/tree/master/alpha/from-pipeline/unhinted/otf/sans as the --after font.
When generating images I set 3% (0.03) as the diff-threshhold value (i.e., ignored differences smaller than 3%).
Here are some of the difference samples (green indicates pipeline generated font, red the glyphs.app and black means common between the both fonts). I picked iitamil 0B88 for this, but there are many others:
I guess the above shape is boring :-)
Here's a difference with jaiivowelsigntamil
NotoSansTamil-CondensedBold
NotoSansTamil-ExtraCondensedBold
an example where height is changing:
bracketleft.tamil from NotoSansTamil-ExtraCondensedBold
Here's the entire collection of significant differences from NotoSansTamil-ExtraCondensedBold
NotoSansTamil-ExtraCondensedBold.zip
Note when I ask for the differences above 3% I get them in the following fonts:
NotoSansTamil-CondensedBold
NotoSansTamil-CondensedExtraBold
NotoSansTamil-CondensedMedium
NotoSansTamil-CondensedSemiBold
NotoSansTamil-ExtraCondensedBold
NotoSansTamil-ExtraCondensedExtraBold
NotoSansTamil-ExtraCondensedMedium
NotoSansTamil-ExtraCondensedSemiBold
NotoSansTamil-SemiCondensedBold
NotoSansTamil-SemiCondensedSemiBold
Note when I ask for the differences above 0.03% I get them in the following fonts:
NotoSansTamil-CondensedBlack
NotoSansTamil-CondensedBold
NotoSansTamil-CondensedExtraBold
NotoSansTamil-CondensedExtraLight
NotoSansTamil-CondensedMedium
NotoSansTamil-CondensedSemiBold
NotoSansTamil-ExtraCondensedBold
NotoSansTamil-ExtraCondensedExtraBold
NotoSansTamil-ExtraCondensedLight
NotoSansTamil-ExtraCondensedMedium
NotoSansTamil-ExtraCondensedSemiBold
NotoSansTamil-SemiCondensedBold
NotoSansTamil-SemiCondensedSemiBold
The text was updated successfully, but these errors were encountered: