Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Apple's text rendering draw a glyph that a font doesn't have?

I have a basic understanding of fonts and encoding, but recently I had to do something outside of my comfort zone: Turn the character ✖ (0x2716 "heavy multiplication x") into a CGPathRef.

I used Core Text's CTFontGetGlyphsForCharacters to accomplish this job. I understand that a CGGlyph is effectively an index into the set of glyphs supported by the given font. I soon discovered that this glyph is only supported by a very few fonts on iOS, including Zapf Dingbats, which is the one I chose.

Here's my question: I can use ✖ in any font, simply pasting it in. I did a little experiment in Pages where I pasted ✖ into a document, selected it, and then continually changed the font. I did a similar programmatic experiment. The glyph always displayed properly (and never changed). If very few of these fonts has ✖, how does this work? Is there some set of "fallback glyphs" (which I guess would be a "fallback font") if a given font doesn't have such a symbol? If so, is there any way to get programmatic access to these glyphs?

like image 268
Gregory Higley Avatar asked Mar 16 '15 03:03

Gregory Higley


1 Answers

A list of fallback fonts in Core Text is known as a "cascade list", which is an attribute of a CTFontDescriptor (the kCTFontCascadeListAttribute).

The system's default cascade list can be accessed using CTFontCopyDefaultCascadeListForLanguages(). For some reason this function isn't documented on Apple's website yet, but here's its documentation from the 'CTFont.h' header file:

/*!
    @function   CTFontCopyDefaultCascadeListForLanguages
    @abstract   Return an ordered list of CTFontDescriptorRef's for font
                fallback derived from the system default fallback region
                according to the given language preferences. The style of
                the given is also matched as well as the weight and width
                of the font is not one of the system UI font, otherwise
                the UI font fallback is applied.

    @param      font
                The font reference.

    @param      languagePrefList
                The language preference list - ordered array of
                CFStringRef's of ISO language codes.

    @result     The ordered list of fallback fonts - ordered array of
                CTFontDescriptors.
*/
CFArrayRef CTFontCopyDefaultCascadeListForLanguages(
    CTFontRef font,
    CFArrayRef languagePrefList ) CT_AVAILABLE(10_8, 6_0);

On Mac OS X 10.10, the default English cascade list contains 26 fonts that cover a wide set of languages and symbols.

You can customise the cascade list/fallback fonts for your own CTFont instances by setting the kCTFontCascadeListAttribute attribute of a custom CTFontDescriptor to an array of fallback CTFontDescriptor objects. Then, turn it into a CTFont with CTFontCreateWithFontDescriptor(). If you don't set a custom cascade list on your CTFontDescriptor, it will use the global list by default.

like image 170
一二三 Avatar answered Nov 15 '22 07:11

一二三