Closed arrowtype closed 3 years ago
Interestingly, there used to be issues like this in DrawBot (https://github.com/typemytype/drawbot/issues/305), but I can no longer trigger them macOS 10.15.
Here's similar code to my first example from Sketch, working fine in Drawbot:
Fraunces is also working well in DrawBot:
Hello, I'm looking at this from the Sketch side. I think the problem lays in the default value for the axis. In the case of weight the default is 300
, which seems to be specified here:
When we request a font from the system with a value which matches the default for an axis, the returned font's descriptor does not have a value for variation on that axis - the returned font is as though we didn't specify that axis at all.
I believe the answer to this is to change the default value to 400
, or whatever the source glyph was designed at, though I don't know enough about how the fonts are made to be sure.
I also checked this in Fraunces and found the same thing. I believe their default weight should be 300
, but is specified as 100
.
Hey @randomsequence, thanks so much for commenting with insights from the mac developer side! That's helpful to hear that the returned font is as though we didn't specify that axis at all.
Are you working directly with Sketch, or on other mac software? Either way, I appreciate you commenting with perspective.
In Recursive, the default value for wght must be either 300, 800, or 1000, as these values align with sources, and define the base set of glyf data that will show if a system doesn't understand variable fonts at all. For Recursive, I have this set at 300, as it's closest to a Regular (400) weight.
In Fraunces (designspace here), sources have wght values of either 100 or 900, and it looks like they figured 100 would be the logical thing to make the default.
In short, if I tried to change the default to 400
or Fraunces tried to change their default to 300
, neither font would build at all.
However, my issue isn't really about the initial font style I get – the problem I'm experiencing is that values can be displayed inaccurately when I have moved some sliders around. For instance, in Fraunces if Goofy != 0
, then wght=100
won't display as a 100
, but rather snaps to 400
.
Perhaps this snapping-to-400 occurs because Sketch "stops requesting" the weight axis when wght is at a font's default, but then Mac assumes that wght
should be set to 400
, the value that people generally expect to be the default. And so, maybe mac is setting the value to 400 without Sketch asking for it to be.
Then again, I don't quite know why this specific circumstance might be triggered by non-0
values of other axes such as Goofy or Slant. I'd like to do more testing, but right now, I can't access the variable sliders at all ... :/
It is perfectly fine to have a variation axis default matching the minimum (or maximum).
When we request a font from the system with a value which matches the default for an axis, the returned font's descriptor does not have a value for variation on that axis - the returned font is as though we didn't specify that axis at all.
It is indeed true that when you request a font with variation axis value matching the default, the matched font descriptor from the font will not have that particular variation axis value. But it doesn't mean the information is lost, because the font file alone is enough to identify the value of that axis.
I believe what we observe here ("snapping-to-400") is not done by the system, but instead coming from Sketch confusing one instance with another in the same variable font. There is nothing indicating the system that it should pick 400 unless it has been explicitly asked to pick that.
Again, if @randomsequence can provide a snippet of code demonstrating how Sketch selects variable font, and we can reproduce the same problem with Recursive/Fraunces there, I will be happy to take a look.
Thanks for the helpful insights, @jjgod! I feel lucky to have both of you looking into this. :)
I believe what we observe here ("snapping-to-400") is not done by the system, but instead coming from Sketch confusing one instance with another in the same variable font
I suppose potentially, I could build a version of recursive with no instances, to test whether instance-guessing might be a potential cause of this...
@jjgod here's what we're doing, which you can run in a swift playground, assuming you have the "recursive" font installed:
import Cocoa
// get the default version of this font
let font = NSFont(name: "Recursive", size: 20) ?? NSFont()
print(font)
print(CTFontCopyVariation(font as CTFont) ?? "")
// the available variations
let axes = CTFontCopyVariationAxes(font)
print(axes ?? "")
// create a descriptor changing the weight to its default value
let weightID = NSNumber(integerLiteral: 2003265652) as CFNumber
var descriptor = CTFontDescriptorCreateCopyWithVariation(font.fontDescriptor as CTFontDescriptor, weightID, 300)
// the new font
let font2 = NSFont(descriptor: descriptor, size: font.pointSize)
print(font2 ?? "")
print(CTFontCopyVariation(font2!) ?? "")
Using Xcode 11.31. on macOS 10.14.6, this prints:
"RecursiveSansCsl-Regular 20.00 pt. P [] (0x7fe00bc3fbd0) fobj=0x7fe00bc56250, spc=6.00"
{
1128354636 = 1;
2003265652 = 400;
}
(
{
NSCTVariationAxisDefaultValue = 0;
NSCTVariationAxisIdentifier = 1297043023;
NSCTVariationAxisMaximumValue = 1;
NSCTVariationAxisMinimumValue = 0;
NSCTVariationAxisName = Monospace;
},
{
NSCTVariationAxisDefaultValue = 0;
NSCTVariationAxisIdentifier = 1128354636;
NSCTVariationAxisMaximumValue = 1;
NSCTVariationAxisMinimumValue = 0;
NSCTVariationAxisName = Casual;
},
{
NSCTVariationAxisDefaultValue = 300;
NSCTVariationAxisIdentifier = 2003265652;
NSCTVariationAxisMaximumValue = 1000;
NSCTVariationAxisMinimumValue = 300;
NSCTVariationAxisName = Weight;
},
{
NSCTVariationAxisDefaultValue = 0;
NSCTVariationAxisIdentifier = 1936486004;
NSCTVariationAxisMaximumValue = 0;
NSCTVariationAxisMinimumValue = "-15";
NSCTVariationAxisName = Slant;
},
{
NSCTVariationAxisDefaultValue = "0.5";
NSCTVariationAxisIdentifier = 1769234796;
NSCTVariationAxisMaximumValue = 1;
NSCTVariationAxisMinimumValue = 0;
NSCTVariationAxisName = Italic;
}
)
"RecursiveSansCsl-Med 20.00 pt. P [] (0x7fe01bd77b70) fobj=0x7fe01bd6b760, spc=6.00"
{
1128354636 = 1;
}
Note that by setting the weight to the default, we now have a different postscript name - what was RecursiveSansCsl-Regular
is now RecursiveSansCsl-Med
. Comparing these two visually (In FontBook), the latter appears heavier. The same thing happens in Sketch:
RecursiveSansCsl-Regular
RecursiveSansCsl-Med
@randomsequence Interesting! Thanks for trying this.
This looks like an old OS bug that has been addressed in macOS 10.15 (at least 10.15.4 should work), it might have something to do with the present of the avar
.
I just tried the same code as you shown above and I got RecursiveMonoCsl-Light 20.00 pt.
in return instead of RecursiveSansCsl-Med 20.00 pt.
as you shown. So I believe this particular bug has been addressed.
However, even with latest macOS 10.15.4, the Sketch bug as shown by @arrowtype still exists, so I think there is something else at play here. Care to take another look? Do you happen to have access to a 10.15 system to try?
@jjgod I tried the same Playground on 10.15.3 and got the same result as you - RecursiveMonoCsl-Light
. I also found that I couldn't reproduce the problem in Sketch on that system, so I guess this is a bug in macOS 10.14.
Thanks for your help.
Interesting, I believe @arrowtype said that he still experiences the same issue on 10.15.4 with Sketch: https://mobile.twitter.com/ArrowType/status/1230150358799876096
Can you check the video to see if that matches what you have tried? Could a specific Sketch version matter here?
I can reproduce the same issue on the same OS and latest Sketch I downloaded recently from sketch.com, too.
I'll keep looking @jjgod. I've found a bug in Sketch where we sometimes mistakenly mark variable fonts as unavailable, which causes them to render using a different code path.
Thanks to both of you for digging further into this!
I just tried the same code as you shown above and I got RecursiveMonoCsl-Light 20.00 pt. in return instead of RecursiveSansCsl-Med 20.00 pt. as you shown. So I believe this particular bug has been addressed.
This is almost correct, but actually, when requesting just CASL=1, wght=300
, I would expect the result to be RecursiveSansCsl-Light
(Sans, not Mono, as the default of the MONO
axis is 0
, or "Sans"). If it's not, that seems to be a bug somewhere along the line. Based on a ttx inspection of Recursive (both in v1.030 or the latest, v1.043), it seems that it is correctly hooked up:
From the fvar
table:
<!-- Sans Casual Light -->
<!-- PostScript: RecursiveSansCsl-Light -->
<NamedInstance flags="0x0" postscriptNameID="342" subfamilyNameID="341">
<coord axis="MONO" value="0.0"/>
<coord axis="CASL" value="1.0"/>
<coord axis="wght" value="300.0"/>
<coord axis="slnt" value="0.0"/>
<coord axis="ital" value="0.5"/>
</NamedInstance>
From the name
table, showing corresponding 342
name ID:
<namerecord nameID="342" platformID="1" platEncID="0" langID="0x0" unicode="True">
RecursiveSansCsl-Light
</namerecord>
@jjgod & @randomsequence, are you sure you are getting RecursiveMonoCsl-Light
from that playground? Or, is it possible that it's RecursiveSansCsl-Light
?
That is a good point. Let me take another look.
Oh, looks like we picked RecursiveMonoCsl-Regular
to begin with when we request for font with name Recursive
-- since it is not a PostScript name match we had to make a guess from the family name, then with RecursiveMonoCsl-Regular
when requesting for weight 300 we got RecursiveMonoCsl-Light
which is indeed expected.
If we do start with RecursiveSansCsl-Regular
then applying weight 300 we will get RecursiveSansCsl-Light
as expected. So I don't see any system problem here.
@jjgod I'm still finding problems with Recursive-SansLinearLight
face in particular. Again in a playground:
import Cocoa
for descriptor in NSFontCollection.withAllAvailableDescriptors.matchingDescriptors(forFamily: "Recursive")! {
let query = NSFontDescriptor(fontAttributes: descriptor.fontAttributes)
if let matched = query.matchingFontDescriptor(withMandatoryKeys: nil) {
if (descriptor != matched) {
print("font attributes: \(descriptor) do not match \(matched)")
}
} else {
print("no matching font descriptor for \(descriptor)")
}
}
Expected: no output Actual:
font attributes: NSCTFontDescriptor <0x7fbaf7e5f440> = {
NSFontNameAttribute = "Recursive-SansLinearLight";
} do not match NSCTFontDescriptor <0x7fbaf7d671d0> = {
NSFontNameAttribute = "RecursiveSansCsl-Med";
}
I thought this was the same matching bug you mentioned earlier, but I get the same output on 10.14 & 10.15.
Sorry, but it’s hard to follow. Do you have any speculation as to whether this bug might be in the font, or in the OS?
I plan to take another look, just didn’t get to it yet.
This should be addressed in macOS 11 developer seed now. Please give this a try. @randomsequence
I have confirmed that at least in macOS 11.0 Beta (20A4299v)
, this is still an issue in Sketch Version 66.1 (97080)
, and still working in Drawbot.
Drawbot:
Sketch:
But, macOS 11 does fix a ton of font bugs, so I am optimistic this one might be possible to solve!
@randomsequence I know you probably have a ton to work on to update for the new OS, but please let me know if there’s anything you need from my end on this. Hopefully this can get resolved soon! Thanks for all your help.
Closing this issue, as it is out of the control of the Recursive project. I think it is likely fixed in macOS 11, but I haven’t installed that yet, so I can’t confirm.
TL;DR: if an axis isn't working in Sketch or elsewhere on macOS, try changing it by
0.01
.Problem description
Sometimes, a slider won't have the expected effect in Sketch, if it is at its full min or max value. As a user, this can be handled by changing the value up or down by a very small amount, like
0.1
or0.01
. This small tweak doesn't change the visual appearance of the font, except that it somehow makes mac render the styles as expected.Example: Recursive with a wght of
300
and slnt of-7
will appear to have a weight more like400
, until I adjust it to300.1
:Another example: Recursive with a CASL value of
0
should be "Linear" (normal-looking), but when slnt is-5
, the font presents with a CASL value of1
("Casual" or brushy-looking) until I adjust CASL to0.01
:I believe this is a Core Text issue because:
Expected behavior
I expect the rendered text to have the values I have entered, even if these are integers at min or max values.
To Reproduce Steps to reproduce the behavior:
0
1
300
0
0.5
0
1
300
-7
(change this one)0.5
300.1
, at which point it looks fine again.Environment (please complete the following information):
Additional context
This is not an issue specific to Recursive. It also occurs in Fraunces