macOS 14 - NSAttributedString created from HTML displays as "undefined character" glyphs when certain fonts are used

I allow users to choose a font to use throughout the app, then display text using that font in 3 different ways:

  1. As the default body font of an HTML document displayed in a WKWebView.
  2. Used to create an NSAttributedString then displayed in an NSTextField.
  3. Used as the body font of a very small HTML document (2-3 lines), converted to NSAttributedString, then displayed in an NSTextField.

My code has been working fine for years, but starting with the release of Sonoma (macOS 14), any text that is converted from HTML to NSAttributedString displays as all "question marks in boxes" for each character. This happens when certain fonts are used. In particular I've seen it with Calibri, Candara, and SF Pro. Calibri and Candara are Microsoft fonts and I think are distributed with MS Office. SF Pro is an Apple font.

There could be others; I haven't done an exhaustive check. What I can tell you is that this has been working fine literally until a couple weeks ago when customers began installing macOS 14. If they go into my app and select a different font (such as Arial or Times New Roman) everything works fine. It is only certain fonts that don't work, and those fonts work when used as the body font of an HTML document in WKWebView and when used as the font for a new NSAttributedString. They just don't work if you make a little HTML document with the font selected as the body font, then convert to NSAttributedString.

Here's the code that worked up until macOS 14:

NSString *htmlString = @"<!DOCTYPE html>"
						 "<html>"
						 "<head>"
						 "<style>"
						 "body { font-family: 'Candara', serif; font-size: 14px; }"
						 "</style>"
						 "</head>"
						 "<body>"
						 "This won't display right."
						 "</body>"
						 "</html>";
NSData *htmlData = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
						  NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)};

NSError *error;
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:htmlData
																		options:options
															 documentAttributes:nil
																		  error:&error];

Note the fallback of "serif" — that doesn't matter. you get all undefined characters and the fallback font is not used. It's as if the renderer really believes the font is usable, but it isn't.

Replies

For me it is the same thing with every font I tried (including Arial) starting in macOS 14.2 beta 1. Still the same with beta 4.

Daniel