Linear Contrast Growth - a slightly different interpolation
The width of vertical and horizontal strokes is almost never equal in type design. It is assumed that horizontals tend to look thicker than verticals of the same width, but the effect is much more visible in the bold weights than it is in the light weights. Thus it is a common practise to design light weights with lower stroke contrast than the bold weights.
However, to my eye the standard linear interpolation between a very light weight with almost no stroke contrast and a very bold one with hight contrast doesnât produce satisfying in-between weights. Horizontals tend to look too thin in most of the interpolated weights.
The problem
Letâs assume that we designed an ExtraLight master with equal vertical and horizontal strokes (LightMasterWeightX = 20; LightMasterWeightY = 20) and an ExtraBold master with horizontals that are 80% of verticals (BoldMasterWeightX = 200; BoldMasterWeightY = 160). The linear interpolation of Light (InterpolationWeightX = 65), Medium (InterpolationWeightX = 110) and Bold (InterpolationWeightX = 155) weights would result in horizontal strokes of 55, 90 and 125.
So the contrast would grows like this:
- ExtraLight - 20á20 = 100%
- Light - 55á65 â 85%
- Medium - 90á110 â 82%
- Bold - 125á155 â 80%
- ExtraBold - 160á200 = 80%
Iâd prefer it to grow linearly:
- ExtraLight - 20á20 = 100%
- Light - 62á65 â 95%
- Medium - 99á110 = 90%
- Bold - 132á155 â 85%
- ExtraBold - 160á200 = 80%
To achieve this, we would need to transform horizontal and vertical weights independently.
The solution: Linear Contrast Growth formula
Interpolation of the x coordinates
Coordinates on the x axis are interpolated traditionally. We start by calculating the âinterpolation pointâ using this formula:
InterpolationPointX = (InterpolationWeightX - LightMasterWeightX) á (BoldMasterWeightX - LightMasterWeightX)
It designates the position on the interpolation axis. For our ExtraLight (InterpolationWeightX = 20) the InterpolationPointX is 0, for Light (InterpolationWeightX = 65) it is 0.25, for Medium (InterpolationWeightX = 110) it is 0.5, for Bold (InterpolationWeightX = 155) it is 0.75, for ExtraBold (InterpolationWeightX = 200) it is 1.
Then we apply the interpolation to x coordinates of our points:
x = InterpolationPointX Ă (x1 - x0) + x0
Interpolation of the y coordinates
To calculate the âinterpolation pointâ on the y axis we can use the InterpolationWeightY (which is a different parameter than the one currently used in Glyphs app). We calculate it with this equation:
InterpolationWeightY = [(1 - InterpolationPointX) à (LightMasterWeightY á LightMasterWeightX - BoldMasterWeightY á BoldMasterWeightX) + BoldMasterWeightY á BoldMasterWeightX] à InterpolationWeightX
Since the formula for the âinterpolation pointâ is:
InterpolationPointY = (InterpolationWeightY - LightMasterWeightY) á (BoldMasterWeightY - LightMasterWeightY)
we get:
InterpolationPointY = {[(-InterpolationWeightX + LightMasterWeightX) á (BoldMasterWeightX - LightMasterWeightX) + 1] à (LightMasterWeightY á LightMasterWeightX - BoldMasterWeightY á BoldMasterWeightX) à InterpolationWeightX + BoldMasterWeightY à InterpolationWeightX á BoldMasterWeightX - LightMasterWeightY} á (BoldMasterWeightY - LightMasterWeightY)
So, for our ExtraLight (InterpolationWeightX = 20) the InterpolationPointY is again 0, for Light (InterpolationWeightX = 65) it is 0.2982, for Medium (InterpolationWeightX = 110) it is 0.5643, for Bold (InterpolationWeightX = 155) it is 0.7982, for ExtraBold (InterpolationWeightX = 200) it is 1.
Now we apply the interpolation to y coordinates of your points:
y = InterpolationPointY Ă (y1 - y0) + y0
Testing in Glyphs app
It is possible to test this in Glyphs app using the InterpolationWeightY custom parameter. To calculate it, apply the InterpolationPointY value to the x axis.
GlyphsInterpolationWeightY = (BoldMasterWeightX - LightMasterWeightX) Ă InterpolationPointY + LightMasterWeightX
Implementing in Glyphs app
If there was an option to provide a separate parameter for WeightY in the masters, the Linear Contrast Growth interpolation could be calculated automatically. It could result in adding the InterpolationWeightY parameter to the instances.