Title: [210776] trunk/Source/WebCore
Revision
210776
Author
mmaxfi...@apple.com
Date
2017-01-15 00:23:31 -0800 (Sun, 15 Jan 2017)

Log Message

[Cocoa] Unify font fallback between macOS and iOS for when the font-family list is exhausted
https://bugs.webkit.org/show_bug.cgi?id=167056

Reviewed by Darin Adler.

When performing font fallback, each item in the font-family list is examined.
If no appropriate fonts are found, WebKit asks the system for an appropriate
font. As of a few years ago, both macOS and iOS used platform calls to
produce a font; however, each platform used a different platform call. This
patch migrates both platforms to use a shared function which uses only
one of the platform calls (which means the other platform call is never used).

There are still some behavior differences between macOS and iOS (which are now
hidden behind a PLATFORM() guard), but I'd like to minimize and eliminate these
in the future. Using a shared function is a step toward this goal.

No new tests because there is no behavior change.

* platform/graphics/FontCache.h:
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::lookupFallbackFont):
(WebCore::FontCache::systemFallbackForCharacters):
* platform/graphics/ios/FontCacheIOS.mm:
(WebCore::getSystemFontFallbackForCharacters): Deleted.
(WebCore::platformLookupFallbackFont): Deleted.
* platform/graphics/mac/FontCacheMac.mm:
(WebCore::platformLookupFallbackFont): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (210775 => 210776)


--- trunk/Source/WebCore/ChangeLog	2017-01-15 07:22:19 UTC (rev 210775)
+++ trunk/Source/WebCore/ChangeLog	2017-01-15 08:23:31 UTC (rev 210776)
@@ -1,3 +1,33 @@
+2017-01-15  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Unify font fallback between macOS and iOS for when the font-family list is exhausted
+        https://bugs.webkit.org/show_bug.cgi?id=167056
+
+        Reviewed by Darin Adler.
+
+        When performing font fallback, each item in the font-family list is examined.
+        If no appropriate fonts are found, WebKit asks the system for an appropriate
+        font. As of a few years ago, both macOS and iOS used platform calls to
+        produce a font; however, each platform used a different platform call. This
+        patch migrates both platforms to use a shared function which uses only
+        one of the platform calls (which means the other platform call is never used). 
+
+        There are still some behavior differences between macOS and iOS (which are now
+        hidden behind a PLATFORM() guard), but I'd like to minimize and eliminate these
+        in the future. Using a shared function is a step toward this goal. 
+
+        No new tests because there is no behavior change.
+
+        * platform/graphics/FontCache.h:
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::lookupFallbackFont):
+        (WebCore::FontCache::systemFallbackForCharacters):
+        * platform/graphics/ios/FontCacheIOS.mm:
+        (WebCore::getSystemFontFallbackForCharacters): Deleted.
+        (WebCore::platformLookupFallbackFont): Deleted.
+        * platform/graphics/mac/FontCacheMac.mm:
+        (WebCore::platformLookupFallbackFont): Deleted.
+
 2017-01-14  Chris Dumez  <cdu...@apple.com>
 
         Report CPU usage of tabs after they become non-visible using diagnostic logging

Modified: trunk/Source/WebCore/platform/graphics/FontCache.h (210775 => 210776)


--- trunk/Source/WebCore/platform/graphics/FontCache.h	2017-01-15 07:22:19 UTC (rev 210775)
+++ trunk/Source/WebCore/platform/graphics/FontCache.h	2017-01-15 08:23:31 UTC (rev 210776)
@@ -276,7 +276,6 @@
 SynthesisPair computeNecessarySynthesis(CTFontRef, const FontDescription&, bool isPlatformFont = false);
 RetainPtr<CTFontRef> platformFontWithFamilySpecialCase(const AtomicString& family, FontWeight, CTFontSymbolicTraits, float size);
 RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits, FontWeight, TextRenderingMode, float size);
-RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef, FontWeight, const AtomicString& locale, const UChar* characters, unsigned length);
 bool requiresCustomFallbackFont(UChar32 character);
 
 #else

Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp (210775 => 210776)


--- trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp	2017-01-15 07:22:19 UTC (rev 210775)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp	2017-01-15 08:23:31 UTC (rev 210776)
@@ -39,11 +39,11 @@
 
 static inline void appendRawTrueTypeFeature(CFMutableArrayRef features, int type, int selector)
 {
-    RetainPtr<CFNumberRef> typeNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &type));
-    RetainPtr<CFNumberRef> selectorNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &selector));
+    auto typeNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &type));
+    auto selectorNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &selector));
     CFTypeRef featureKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey };
     CFTypeRef featureValues[] = { typeNumber.get(), selectorNumber.get() };
-    RetainPtr<CFDictionaryRef> feature = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureKeys, featureValues, WTF_ARRAY_LENGTH(featureKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto feature = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureKeys, featureValues, WTF_ARRAY_LENGTH(featureKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     CFArrayAppendValue(features, feature.get());
 }
 
@@ -133,12 +133,12 @@
 
 static inline void appendOpenTypeFeature(CFMutableArrayRef features, const FontFeature& feature)
 {
-    RetainPtr<CFStringRef> featureKey = adoptCF(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(feature.tag().data()), feature.tag().size() * sizeof(FontTag::value_type), kCFStringEncodingASCII, false));
+    auto featureKey = adoptCF(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(feature.tag().data()), feature.tag().size() * sizeof(FontTag::value_type), kCFStringEncodingASCII, false));
     int rawFeatureValue = feature.value();
-    RetainPtr<CFNumberRef> featureValue = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rawFeatureValue));
+    auto featureValue = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rawFeatureValue));
     CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
     CFTypeRef featureDictionaryValues[] = { featureKey.get(), featureValue.get() };
-    RetainPtr<CFDictionaryRef> featureDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, WTF_ARRAY_LENGTH(featureDictionaryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto featureDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, WTF_ARRAY_LENGTH(featureDictionaryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     CFArrayAppendValue(features, featureDictionary.get());
 }
 
@@ -479,9 +479,9 @@
     }
 #endif
 
-    RetainPtr<CFMutableDictionaryRef> attributes = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto attributes = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     if (!featuresToBeApplied.isEmpty()) {
-        RetainPtr<CFMutableArrayRef> featureArray = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, features.size(), &kCFTypeArrayCallBacks));
+        auto featureArray = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, features.size(), &kCFTypeArrayCallBacks));
         for (auto& p : featuresToBeApplied) {
             auto feature = FontFeature(p.key, p.value);
             appendTrueTypeFeature(featureArray.get(), feature);
@@ -505,10 +505,10 @@
 
     if (textRenderingMode == OptimizeLegibility) {
         CGFloat size = CTFontGetSize(originalFont);
-        RetainPtr<CFNumberRef> sizeNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &size));
+        auto sizeNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &size));
         CFDictionaryAddValue(attributes.get(), kCTFontOpticalSizeAttribute, sizeNumber.get());
     }
-    RetainPtr<CTFontDescriptorRef> descriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
+    auto descriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
     auto result = adoptCF(CTFontCreateCopyWithAttributes(originalFont, CTFontGetSize(originalFont), nullptr, descriptor.get()));
     return result;
 }
@@ -626,12 +626,12 @@
 
 Vector<FontTraitsMask> FontCache::getTraitsInFamily(const AtomicString& familyName)
 {
-    RetainPtr<CFStringRef> familyNameStr = familyName.string().createCFString();
+    auto familyNameStr = familyName.string().createCFString();
     CFTypeRef keys[] = { kCTFontFamilyNameAttribute };
     CFTypeRef values[] = { familyNameStr.get() };
-    RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-    RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
-    RetainPtr<CFArrayRef> matchedDescriptors = adoptCF(CTFontDescriptorCreateMatchingFontDescriptors(fontDescriptor.get(), nullptr));
+    auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto fontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
+    auto matchedDescriptors = adoptCF(CTFontDescriptorCreateMatchingFontDescriptors(fontDescriptor.get(), nullptr));
     if (!matchedDescriptors)
         return { };
 
@@ -642,7 +642,7 @@
     Vector<FontTraitsMask> traitsMasks;
     traitsMasks.reserveInitialCapacity(numMatches);
     for (CFIndex i = 0; i < numMatches; ++i) {
-        RetainPtr<CFDictionaryRef> traits = adoptCF((CFDictionaryRef)CTFontDescriptorCopyAttribute((CTFontDescriptorRef)CFArrayGetValueAtIndex(matchedDescriptors.get(), i), kCTFontTraitsAttribute));
+        auto traits = adoptCF((CFDictionaryRef)CTFontDescriptorCopyAttribute((CTFontDescriptorRef)CFArrayGetValueAtIndex(matchedDescriptors.get(), i), kCTFontTraitsAttribute));
         CFNumberRef resultRef = (CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait);
         CFNumberRef weightRef = (CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontWeightTrait);
         if (resultRef && weightRef) {
@@ -686,7 +686,7 @@
 Vector<String> FontCache::systemFontFamilies()
 {
     // FIXME: <rdar://problem/21890188>
-    RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     auto emptyFontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
     auto matchedDescriptors = adoptCF(CTFontDescriptorCreateMatchingFontDescriptors(emptyFontDescriptor.get(), nullptr));
     if (!matchedDescriptors)
@@ -776,7 +776,7 @@
     if (family.isEmpty())
         return nullptr;
 
-    RetainPtr<CTFontRef> foundFont = platformFontWithFamilySpecialCase(family, weight, desiredTraits, size);
+    auto foundFont = platformFontWithFamilySpecialCase(family, weight, desiredTraits, size);
     if (!foundFont) {
 #if ENABLE(PLATFORM_FONT_LOOKUP)
         foundFont = platformFontLookupWithFamily(family, desiredTraits, weight, size);
@@ -824,7 +824,7 @@
     CTFontSymbolicTraits traits = computeTraits(fontDescription);
     float size = fontDescription.computedPixelSize();
 
-    RetainPtr<CTFontRef> font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontDescription.variationSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size);
+    auto font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontDescription.variationSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size);
 
 #if PLATFORM(MAC)
     if (!font) {
@@ -866,6 +866,50 @@
         fallbackDedupSet().remove(font);
 }
 
+#if PLATFORM(IOS)
+static inline bool isArabicCharacter(UChar character)
+{
+    return character >= 0x0600 && character <= 0x06FF;
+}
+#endif
+
+static RetainPtr<CTFontRef> lookupFallbackFont(CTFontRef font, FontWeight fontWeight, const AtomicString& locale, const UChar* characters, unsigned length)
+{
+    ASSERT(length > 0);
+
+    RetainPtr<CFStringRef> localeString;
+#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+    if (!locale.isNull())
+        localeString = locale.string().createCFString();
+#else
+    UNUSED_PARAM(locale);
+#endif
+
+    CFIndex coveredLength = 0;
+    auto result = adoptCF(CTFontCreateForCharactersWithLanguage(font, characters, length, localeString.get(), &coveredLength));
+
+#if PLATFORM(IOS)
+    // Callers of this function won't include multiple code points. "Length" is to know how many code units
+    // are in the code point.
+    UChar firstCharacter = characters[0];
+    if (isArabicCharacter(firstCharacter)) {
+        auto familyName = adoptCF(static_cast<CFStringRef>(CTFontCopyAttribute(result.get(), kCTFontFamilyNameAttribute)));
+        if (fontFamilyShouldNotBeUsedForArabic(familyName.get())) {
+            CFStringRef newFamilyName = isFontWeightBold(fontWeight) ? CFSTR("GeezaPro-Bold") : CFSTR("GeezaPro");
+            CFTypeRef keys[] = { kCTFontNameAttribute };
+            CFTypeRef values[] = { newFamilyName };
+            auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+            auto modification = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
+            result = adoptCF(CTFontCreateCopyWithAttributes(result.get(), CTFontGetSize(result.get()), nullptr, modification.get()));
+        }
+    }
+#else
+    UNUSED_PARAM(fontWeight);
+#endif
+
+    return result;
+}
+
 RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length)
 {
 #if PLATFORM(IOS)
@@ -878,7 +922,7 @@
 #endif
 
     const FontPlatformData& platformData = originalFontData->platformData();
-    RetainPtr<CTFontRef> result = platformLookupFallbackFont(platformData.font(), description.weight(), description.locale(), characters, length);
+    auto result = lookupFallbackFont(platformData.font(), description.weight(), description.locale(), characters, length);
     result = preparePlatformFont(result.get(), description.textRenderingMode(), nullptr, nullptr, description.featureSettings(), description.variantSettings(), description.variationSettings());
     if (!result)
         return lastResortFallbackFont(description);

Modified: trunk/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm (210775 => 210776)


--- trunk/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm	2017-01-15 07:22:19 UTC (rev 210775)
+++ trunk/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm	2017-01-15 08:23:31 UTC (rev 210776)
@@ -78,46 +78,6 @@
     return getCachedFontPlatformData(description, *family);
 }
 
-static RetainPtr<CTFontRef> getSystemFontFallbackForCharacters(CTFontRef font, const AtomicString& locale, const UChar* characters, unsigned length)
-{
-    // FIXME: Unify this with platformLookupFallbackFont()
-    RetainPtr<CFStringRef> localeString;
-    if (!locale.isNull())
-        localeString = locale.string().createCFString();
-
-    CFIndex coveredLength = 0;
-    return adoptCF(CTFontCreatePhysicalFontForCharactersWithLanguage(font, (const UTF16Char*)characters, (CFIndex)length, localeString.get(), &coveredLength));
-}
-
-RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef font, FontWeight fontWeight, const AtomicString& locale, const UChar* characters, unsigned length)
-{
-    // For system fonts we use CoreText fallback mechanism.
-    if (length && CTFontDescriptorIsSystemUIFont(adoptCF(CTFontCopyFontDescriptor(font)).get()))
-        return getSystemFontFallbackForCharacters(font, locale, characters, length);
-
-    RetainPtr<CFStringRef> localeString;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
-    if (!locale.isNull())
-        localeString = locale.string().createCFString();
-#endif
-    RetainPtr<CTFontDescriptorRef> fallbackFontDescriptor = adoptCF(CTFontCreatePhysicalFontDescriptorForCharactersWithLanguage(font, characters, length, localeString.get(), nullptr));
-    UChar32 c = *characters;
-    if (length > 1 && U16_IS_LEAD(c) && U16_IS_TRAIL(characters[1]))
-        c = U16_GET_SUPPLEMENTARY(c, characters[1]);
-    // Arabic
-    if (c >= 0x0600 && c <= 0x06ff) {
-        auto familyName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fallbackFontDescriptor.get(), kCTFontFamilyNameAttribute)));
-        if (fontFamilyShouldNotBeUsedForArabic(familyName.get())) {
-            CFStringRef newFamilyName = isFontWeightBold(fontWeight) ? CFSTR("GeezaPro-Bold") : CFSTR("GeezaPro");
-            CFTypeRef keys[] = { kCTFontNameAttribute };
-            CFTypeRef values[] = { newFamilyName };
-            RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-            fallbackFontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithAttributes(fallbackFontDescriptor.get(), attributes.get()));
-        }
-    }
-    return adoptCF(CTFontCreateWithFontDescriptor(fallbackFontDescriptor.get(), CTFontGetSize(font), nullptr));
-}
-
 Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
 {
     return *fontForFamily(fontDescription, AtomicString(".PhoneFallback", AtomicString::ConstructFromLiteral));

Modified: trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm (210775 => 210776)


--- trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2017-01-15 07:22:19 UTC (rev 210775)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2017-01-15 08:23:31 UTC (rev 210776)
@@ -376,20 +376,6 @@
 #endif
 }
 
-RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef font, FontWeight, const AtomicString& locale, const UChar* characters, unsigned length)
-{
-    RetainPtr<CFStringRef> localeString;
-#if __MAC_OS_X_VERSION_MIN_REQUIRED > 101100
-    if (!locale.isNull())
-        localeString = locale.string().createCFString();
-#else
-    UNUSED_PARAM(locale);
-#endif
-
-    CFIndex coveredLength = 0;
-    return adoptCF(CTFontCreateForCharactersWithLanguage(font, characters, length, localeString.get(), &coveredLength));
-}
-
 Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
 {
     // FIXME: Would be even better to somehow get the user's default font here.  For now we'll pick
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to