fix(font/CoreText): make system fallback fonts work again (#9649)
The code that re-creates the font descriptor from scratch using the same
attributes also rubs off the magic dust that makes CoreText not throw a
fit at us for using a "hidden" system font (name prefixed with a dot) by
name when we use the descriptor. This means that a small subset of chars
that only have glyphs in these fallback system fonts like ".CJK Symbols
Fallback HK Regular" and ".DecoType Nastaleeq Urdu UI" would not be able
to be rendered, since when we requested the font with the non-magical
descriptor CoreText would complain in the console and give us Times New
Roman instead.
Using `CTFontDescriptorCreateCopyWithAttributes` to clear the charset
attribute instead of recreating from scratch makes the copy come out
magical, and CoreText lets us instantiate the font from it, yippee!
### ℹ️ For anyone who came to this PR from a search engine rabbit hole
trying to figure this out for your own code:
It seems like if you want to use one of these fonts, you have to avoid
creating a new descriptor from scratch with the name. To create a
descriptor with one of these names that CoreText won't get upset about,
you have to get it in one of these ways (there may be others but these
are ones that definitely work at time of writing):
- Get it from `CTFontCreateForString`(`WithLanguage`) with a character
only provided by that font.
- Get it from `CTFontCreateUIFontForLanguage` or any of the mechanisms
for generally receiving a system font that you don't necessarily have
full control over the exact choice of font with.
- Get it from a collection created with
`CTFontCollectionCreateMatchingFontDescriptors`
- Get it from `CTFontCreateWithGraphicsFont` ... and it seems that for
now, `CGFontCreateWithFontName` lets you use these "hidden" names
without complaining :)
I wouldn't trust any of these methods to necessarily *continue* working
in to the future, since Apple seems to be trying to dissuade
*intentional* use of any particular named hidden system font.
Realistically, the `CreateForString` option is the most likely to stick
around.
If all else fails, check FireFox or Chrome's source code to see how
they're solving it in current year.
And to help it get indexed for those looking for it...
<details>
<summary>CoreText's angry message</summary>
```
CoreText note: Client requested name ".CJKSymbolsFallbackHK-Regular", it will get TimesNewRomanPSMT rather than the intended font. All system UI font access should be through proper APIs such as CTFontCreateUIFontForLanguage() or +[NSFont systemFontOfSize:].
CoreText note: Set a breakpoint on CTFontLogSystemFontNameRequest to debug.
```
</details>
pull/9656/merge
commit
ffe4afe538
|
|
@ -845,15 +845,20 @@ pub const CoreText = struct {
|
|||
// limitation because we may have used that to filter but we
|
||||
// don't want it anymore because it'll restrict the characters
|
||||
// available.
|
||||
//const desc = self.list.getValueAtIndex(macos.text.FontDescriptor, self.i);
|
||||
const desc = desc: {
|
||||
const original = self.list[self.i];
|
||||
|
||||
// For some reason simply copying the attributes and recreating
|
||||
// the descriptor removes the charset restriction. This is tested.
|
||||
const attrs = original.copyAttributes();
|
||||
// We create a copy, overwriting the character set attribute.
|
||||
const attrs = try macos.foundation.MutableDictionary.create(0);
|
||||
defer attrs.release();
|
||||
break :desc try macos.text.FontDescriptor.createWithAttributes(@ptrCast(attrs));
|
||||
|
||||
attrs.setValue(
|
||||
macos.text.FontAttribute.character_set.key(),
|
||||
macos.c.kCFNull,
|
||||
);
|
||||
|
||||
break :desc try macos.text.FontDescriptor.createCopyWithAttributes(
|
||||
self.list[self.i],
|
||||
@ptrCast(attrs),
|
||||
);
|
||||
};
|
||||
defer desc.release();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue