[Cocoa] Stop crashing in lastResortFallbackFont()
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jul 2018 18:34:24 +0000 (18:34 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jul 2018 18:34:24 +0000 (18:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187936

Reviewed by Jon Lee.

CoreText can get into a state where both Times and Lucida Grande are inaccessible.
Instead of crashing, we should use the real LastResort, which is backed by a section
in the .rodata of the CoreText dylib, and as such should always exist.

* platform/graphics/FontCache.cpp:
(WebCore::FontCache::fontForFamily):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::FontCache::lastResortFallbackFont):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234158 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

index d3dda81..6ee8945 100644 (file)
@@ -1,3 +1,19 @@
+2018-07-24  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [Cocoa] Stop crashing in lastResortFallbackFont()
+        https://bugs.webkit.org/show_bug.cgi?id=187936
+
+        Reviewed by Jon Lee.
+
+        CoreText can get into a state where both Times and Lucida Grande are inaccessible.
+        Instead of crashing, we should use the real LastResort, which is backed by a section
+        in the .rodata of the CoreText dylib, and as such should always exist.
+
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::fontForFamily):
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::FontCache::lastResortFallbackFont):
+
 2018-07-24  Daniel Bates  <dabates@apple.com>
 
         Cannot view PDF's on my.gov.au: "Refused to load https://my.gov.au/attachment/viewAttachment because it
index bc9720d..d248f2f 100644 (file)
@@ -324,11 +324,10 @@ RefPtr<Font> FontCache::fontForFamily(const FontDescription& fontDescription, co
     if (!m_purgeTimer.isActive())
         m_purgeTimer.startOneShot(0_s);
 
-    FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities, checkingAlternateName);
-    if (!platformData)
-        return nullptr;
+    if (auto* platformData = getCachedFontPlatformData(fontDescription, family, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities, checkingAlternateName))
+        return fontForPlatformData(*platformData);
 
-    return fontForPlatformData(*platformData);
+    return nullptr;
 }
 
 Ref<Font> FontCache::fontForPlatformData(const FontPlatformData& platformData)
index 0301fd0..63014e2 100644 (file)
@@ -1481,14 +1481,27 @@ Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescripti
 {
     // FIXME: Would be even better to somehow get the user's default font here.  For now we'll pick
     // the default that the user would get without changing any prefs.
-    if (RefPtr<Font> font = fontForFamily(fontDescription, AtomicString("Times", AtomicString::ConstructFromLiteral)))
-        return *font;
+    if (auto result = fontForFamily(fontDescription, AtomicString("Times", AtomicString::ConstructFromLiteral)))
+        return *result;
 
     // The Times fallback will almost always work, but in the highly unusual case where
-    // the user doesn't have it, we fall back on Lucida Grande because that's
-    // guaranteed to be there, according to Nathan Taylor. This is good enough
-    // to avoid a crash at least.
-    return *fontForFamily(fontDescription, AtomicString("Lucida Grande", AtomicString::ConstructFromLiteral), nullptr, nullptr, { }, false);
+    // the user doesn't have it, we fall back on Lucida Grande.
+    if (auto result = fontForFamily(fontDescription, AtomicString("Lucida Grande", AtomicString::ConstructFromLiteral), nullptr, nullptr, { }, false))
+        return *result;
+
+    // LastResort is guaranteed to be non-null.
+#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300)
+    auto fontDescriptor = adoptCF(CTFontDescriptorCreateLastResort());
+    auto font = adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), fontDescription.computedPixelSize(), nullptr));
+#else
+    // Even if Helvetica doesn't exist, CTFontCreateWithName will return
+    // a thin wrapper around a GraphicsFont which represents LastResort.
+    auto font = adoptCF(CTFontCreateWithName(CFSTR("Helvetica"), fontDescription.computedPixelSize(), nullptr));
+#endif
+    bool syntheticBold, syntheticOblique;
+    std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(font.get(), fontDescription).boldObliquePair();
+    FontPlatformData platformData(font.get(), fontDescription.computedPixelSize(), syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
+    return fontForPlatformData(platformData);
 }
 
 }