Title: [188871] trunk/Source/WebCore
Revision
188871
Author
mmaxfi...@apple.com
Date
2015-08-24 11:37:37 -0700 (Mon, 24 Aug 2015)

Log Message

[Cocoa] Unify FontCache
https://bugs.webkit.org/show_bug.cgi?id=148358

Reviewed by Antti Koivisto.

Move all the duplicate code to FontCacheCoreText.

No new tests because there is no behavior change.

* platform/graphics/FontCache.h:
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::fontWeightFromCoreText):
(WebCore::toTraitsMask):
(WebCore::isFontWeightBold):
(WebCore::toCoreTextFontWeight):
(WebCore::invalidateFontCache):
(WebCore::fontCacheRegisteredFontsChangedNotificationCallback):
(WebCore::FontCache::platformInit):
(WebCore::FontCache::systemFontFamilies):
(WebCore::computeTraits):
(WebCore::computeNecessarySynthesis):
(WebCore::fontWhitelist):
(WebCore::FontCache::setFontWhitelist):
(WebCore::platformFontLookupWithFamily):
(WebCore::fontWithFamily):
(WebCore::shouldAutoActivateFontIfNeeded):
(WebCore::FontCache::createFontPlatformData):
(WebCore::fallbackDedupSet):
(WebCore::FontCache::platformPurgeInactiveFontData):
(WebCore::FontCache::systemFallbackForCharacters):
* platform/graphics/ios/FontCacheIOS.mm:
(WebCore::platformInvalidateFontCache):
(WebCore::getSystemFontFallbackForCharacters):
(WebCore::platformLookupFallbackFont):
(WebCore::FontCache::lastResortFallbackFont):
(WebCore::FontCache::weightOfCTFont):
(WebCore::platformFontWithFamilySpecialCase):
(WebCore::FontCache::platformInit): Deleted.
(WebCore::isFontWeightBold): Deleted.
(WebCore::FontCache::getSystemFontFallbackForCharacters): Deleted.
(WebCore::FontCache::systemFallbackForCharacters): Deleted.
(WebCore::FontCache::systemFontFamilies): Deleted.
(WebCore::createCTFontWithTextStyle): Deleted.
(WebCore::createCTFontWithFamilyNameAndWeight): Deleted.
(WebCore::toCTFontWeight): Deleted.
(WebCore::FontCache::createFontPlatformData): Deleted.
* platform/graphics/mac/FontCacheMac.mm:
(WebCore::appkitWeightToFontWeight):
(WebCore::toNSFontTraits):
(WebCore::platformFontWithFamilySpecialCase):
(WebCore::platformFontWithFamily):
(WebCore::platformInvalidateFontCache):
(WebCore::platformLookupFallbackFont):
(WebCore::FontCache::lastResortFallbackFont):
(WebCore::toCoreTextFontWeight): Deleted.
(WebCore::fontWhitelist): Deleted.
(WebCore::FontCache::setFontWhitelist): Deleted.
(WebCore::fontWithFamilySpecialCase): Deleted.
(WebCore::fontWithFamily): Deleted.
(WebCore::invalidateFontCache): Deleted.
(WebCore::fontCacheRegisteredFontsChangedNotificationCallback): Deleted.
(WebCore::FontCache::platformInit): Deleted.
(WebCore::isAppKitFontWeightBold): Deleted.
(WebCore::shouldAutoActivateFontIfNeeded): Deleted.
(WebCore::fallbackDedupSet): Deleted.
(WebCore::FontCache::platformPurgeInactiveFontData): Deleted.
(WebCore::lookupCTFont): Deleted.
(WebCore::FontCache::systemFallbackForCharacters): Deleted.
(WebCore::FontCache::systemFontFamilies): Deleted.
(WebCore::FontCache::createFontPlatformData): Deleted.
* rendering/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::updateCachedSystemFontDescription):
(WebCore::fromCTFontWeight): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (188870 => 188871)


--- trunk/Source/WebCore/ChangeLog	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/ChangeLog	2015-08-24 18:37:37 UTC (rev 188871)
@@ -1,3 +1,79 @@
+2015-08-24  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Unify FontCache
+        https://bugs.webkit.org/show_bug.cgi?id=148358
+
+        Reviewed by Antti Koivisto.
+
+        Move all the duplicate code to FontCacheCoreText.
+
+        No new tests because there is no behavior change.
+
+        * platform/graphics/FontCache.h:
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::fontWeightFromCoreText):
+        (WebCore::toTraitsMask):
+        (WebCore::isFontWeightBold):
+        (WebCore::toCoreTextFontWeight):
+        (WebCore::invalidateFontCache):
+        (WebCore::fontCacheRegisteredFontsChangedNotificationCallback):
+        (WebCore::FontCache::platformInit):
+        (WebCore::FontCache::systemFontFamilies):
+        (WebCore::computeTraits):
+        (WebCore::computeNecessarySynthesis):
+        (WebCore::fontWhitelist):
+        (WebCore::FontCache::setFontWhitelist):
+        (WebCore::platformFontLookupWithFamily):
+        (WebCore::fontWithFamily):
+        (WebCore::shouldAutoActivateFontIfNeeded):
+        (WebCore::FontCache::createFontPlatformData):
+        (WebCore::fallbackDedupSet):
+        (WebCore::FontCache::platformPurgeInactiveFontData):
+        (WebCore::FontCache::systemFallbackForCharacters):
+        * platform/graphics/ios/FontCacheIOS.mm:
+        (WebCore::platformInvalidateFontCache):
+        (WebCore::getSystemFontFallbackForCharacters):
+        (WebCore::platformLookupFallbackFont):
+        (WebCore::FontCache::lastResortFallbackFont):
+        (WebCore::FontCache::weightOfCTFont):
+        (WebCore::platformFontWithFamilySpecialCase):
+        (WebCore::FontCache::platformInit): Deleted.
+        (WebCore::isFontWeightBold): Deleted.
+        (WebCore::FontCache::getSystemFontFallbackForCharacters): Deleted.
+        (WebCore::FontCache::systemFallbackForCharacters): Deleted.
+        (WebCore::FontCache::systemFontFamilies): Deleted.
+        (WebCore::createCTFontWithTextStyle): Deleted.
+        (WebCore::createCTFontWithFamilyNameAndWeight): Deleted.
+        (WebCore::toCTFontWeight): Deleted.
+        (WebCore::FontCache::createFontPlatformData): Deleted.
+        * platform/graphics/mac/FontCacheMac.mm:
+        (WebCore::appkitWeightToFontWeight):
+        (WebCore::toNSFontTraits):
+        (WebCore::platformFontWithFamilySpecialCase):
+        (WebCore::platformFontWithFamily):
+        (WebCore::platformInvalidateFontCache):
+        (WebCore::platformLookupFallbackFont):
+        (WebCore::FontCache::lastResortFallbackFont):
+        (WebCore::toCoreTextFontWeight): Deleted.
+        (WebCore::fontWhitelist): Deleted.
+        (WebCore::FontCache::setFontWhitelist): Deleted.
+        (WebCore::fontWithFamilySpecialCase): Deleted.
+        (WebCore::fontWithFamily): Deleted.
+        (WebCore::invalidateFontCache): Deleted.
+        (WebCore::fontCacheRegisteredFontsChangedNotificationCallback): Deleted.
+        (WebCore::FontCache::platformInit): Deleted.
+        (WebCore::isAppKitFontWeightBold): Deleted.
+        (WebCore::shouldAutoActivateFontIfNeeded): Deleted.
+        (WebCore::fallbackDedupSet): Deleted.
+        (WebCore::FontCache::platformPurgeInactiveFontData): Deleted.
+        (WebCore::lookupCTFont): Deleted.
+        (WebCore::FontCache::systemFallbackForCharacters): Deleted.
+        (WebCore::FontCache::systemFontFamilies): Deleted.
+        (WebCore::FontCache::createFontPlatformData): Deleted.
+        * rendering/RenderThemeIOS.mm:
+        (WebCore::RenderThemeIOS::updateCachedSystemFontDescription):
+        (WebCore::fromCTFontWeight): Deleted.
+
 2015-08-24  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Unreviewed, attempt to fix iOS build after r188860

Modified: trunk/Source/WebCore/platform/graphics/FontCache.h (188870 => 188871)


--- trunk/Source/WebCore/platform/graphics/FontCache.h	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/platform/graphics/FontCache.h	2015-08-24 18:37:37 UTC (rev 188871)
@@ -154,7 +154,7 @@
 #if PLATFORM(IOS)
     static float weightOfCTFont(CTFontRef);
 #endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
     WEBCORE_EXPORT static void setFontWhitelist(const Vector<String>&);
 #endif
 #if PLATFORM(WIN)
@@ -203,9 +203,8 @@
     FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
 
     // These methods are implemented by each platform.
-#if PLATFORM(IOS)
+#if PLATFORM(COCOA)
     FontPlatformData* getCustomFallbackFont(const UInt32, const FontDescription&);
-    PassRefPtr<Font> getSystemFontFallbackForCharacters(const FontDescription&, const Font*, const UChar* characters, unsigned length);
 #endif
     std::unique_ptr<FontPlatformData> createFontPlatformData(const FontDescription&, const AtomicString& family);
 
@@ -218,13 +217,40 @@
 };
 
 #if PLATFORM(COCOA)
+
+struct SynthesisPair {
+    SynthesisPair(bool needsSyntheticBold, bool needsSyntheticOblique)
+        : needsSyntheticBold(needsSyntheticBold)
+        , needsSyntheticOblique(needsSyntheticOblique)
+    {
+    }
+
+    std::pair<bool, bool> boldObliquePair() const
+    {
+        return std::make_pair(needsSyntheticBold, needsSyntheticOblique);
+    }
+
+    bool needsSyntheticBold;
+    bool needsSyntheticOblique;
+};
+
 RetainPtr<CTFontRef> preparePlatformFont(CTFontRef, TextRenderingMode, const FontFeatureSettings*);
-#endif
+FontWeight fontWeightFromCoreText(CGFloat weight);
+uint16_t toCoreTextFontWeight(FontWeight);
+bool isFontWeightBold(FontWeight);
+void platformInvalidateFontCache();
+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, const FontFeatureSettings*, TextRenderingMode, float size);
+RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef, FontWeight, const AtomicString& locale, const UChar* characters, unsigned length);
+bool requiresCustomFallbackFont(UChar32 character);
 
-#if !PLATFORM(MAC)
+#else
+
 inline void FontCache::platformPurgeInactiveFontData()
 {
 }
+
 #endif
 
 }

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


--- trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp	2015-08-24 18:37:37 UTC (rev 188871)
@@ -31,6 +31,8 @@
 
 #include <CoreText/SFNTLayoutTypes.h>
 
+#include <wtf/HashSet.h>
+#include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
 
 namespace WebCore {
@@ -130,9 +132,9 @@
     RetainPtr<CFStringRef> featureKey = feature.tag().string().createCFString();
     int rawFeatureValue = feature.value();
     RetainPtr<CFNumberRef> featureValue = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &rawFeatureValue));
-    CFStringRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
+    CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
     CFTypeRef featureDictionaryValues[] = { featureKey.get(), featureValue.get() };
-    RetainPtr<CFDictionaryRef> featureDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, (const void**)featureDictionaryKeys, featureDictionaryValues, WTF_ARRAY_LENGTH(featureDictionaryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    RetainPtr<CFDictionaryRef> featureDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, WTF_ARRAY_LENGTH(featureDictionaryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     CFArrayAppendValue(features, featureDictionary.get());
 #else
     UNUSED_PARAM(features);
@@ -163,36 +165,84 @@
     return adoptCF(CTFontCreateCopyWithAttributes(originalFont, CTFontGetSize(originalFont), nullptr, descriptor.get()));
 }
 
+FontWeight fontWeightFromCoreText(CGFloat weight)
+{
+    if (weight < -0.6)
+        return FontWeight100;
+    if (weight < -0.365)
+        return FontWeight200;
+    if (weight < -0.115)
+        return FontWeight300;
+    if (weight <  0.130)
+        return FontWeight400;
+    if (weight <  0.235)
+        return FontWeight500;
+    if (weight <  0.350)
+        return FontWeight600;
+    if (weight <  0.500)
+        return FontWeight700;
+    if (weight <  0.700)
+        return FontWeight800;
+    return FontWeight900;
+}
+
 static inline FontTraitsMask toTraitsMask(CTFontSymbolicTraits ctFontTraits, CGFloat weight)
 {
-    FontTraitsMask weightMask = FontWeight100Mask;
-    if (weight < -0.6)
+    FontTraitsMask weightMask;
+    switch (fontWeightFromCoreText(weight)) {
+    case FontWeight100:
         weightMask = FontWeight100Mask;
-    else if (weight < -0.365)
+        break;
+    case FontWeight200:
         weightMask = FontWeight200Mask;
-    else if (weight < -0.115)
+        break;
+    case FontWeight300:
         weightMask = FontWeight300Mask;
-    else if (weight <  0.130)
+        break;
+    case FontWeight400:
         weightMask = FontWeight400Mask;
-    else if (weight <  0.235)
+        break;
+    case FontWeight500:
         weightMask = FontWeight500Mask;
-    else if (weight <  0.350)
+        break;
+    case FontWeight600:
         weightMask = FontWeight600Mask;
-    else if (weight <  0.500)
+        break;
+    case FontWeight700:
         weightMask = FontWeight700Mask;
-    else if (weight <  0.700)
+        break;
+    case FontWeight800:
         weightMask = FontWeight800Mask;
-    else
+        break;
+    case FontWeight900:
         weightMask = FontWeight900Mask;
+        break;
+    }
     return static_cast<FontTraitsMask>(((ctFontTraits & kCTFontTraitItalic) ? FontStyleItalicMask : FontStyleNormalMask)
         | FontVariantNormalMask | weightMask);
 }
 
-static inline bool isFontWeightBold(FontWeight fontWeight)
+bool isFontWeightBold(FontWeight fontWeight)
 {
     return fontWeight >= FontWeight600;
 }
 
+uint16_t toCoreTextFontWeight(FontWeight fontWeight)
+{
+    static const int coreTextFontWeights[] = {
+        100, // FontWeight100
+        200, // FontWeight200
+        300, // FontWeight300
+        400, // FontWeight400
+        500, // FontWeight500
+        600, // FontWeight600
+        700, // FontWeight700
+        800, // FontWeight800
+        900, // FontWeight900
+    };
+    return coreTextFontWeights[fontWeight];
+}
+
 RefPtr<Font> FontCache::similarFont(const FontDescription& description)
 {
     // Attempt to find an appropriate font using a match based on the presence of keywords in
@@ -240,8 +290,9 @@
 Vector<FontTraitsMask> FontCache::getTraitsInFamily(const AtomicString& familyName)
 {
     RetainPtr<CFStringRef> familyNameStr = familyName.string().createCFString();
-    CFStringRef familyNameStrPtr = familyNameStr.get();
-    RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontFamilyNameAttribute, (const void**)&familyNameStrPtr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    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));
     if (!matchedDescriptors)
@@ -268,4 +319,227 @@
     return traitsMasks;
 }
 
+static void invalidateFontCache()
+{
+    if (!isMainThread()) {
+        callOnMainThread([] {
+            invalidateFontCache();
+        });
+        return;
+    }
+
+    FontCache::singleton().invalidate();
+
+    platformInvalidateFontCache();
 }
+
+static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void *, CFDictionaryRef)
+{
+    ASSERT_UNUSED(observer, observer == &FontCache::singleton());
+    ASSERT_UNUSED(name, CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification));
+
+    invalidateFontCache();
+}
+
+void FontCache::platformInit()
+{
+    CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
+}
+
+Vector<String> FontCache::systemFontFamilies()
+{
+    // FIXME: <rdar://problem/21890188>
+    RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+    auto emptyFontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get()));
+    auto matchedDescriptors = adoptCF(CTFontDescriptorCreateMatchingFontDescriptors(emptyFontDescriptor.get(), nullptr));
+    if (!matchedDescriptors)
+        return { };
+
+    CFIndex numMatches = CFArrayGetCount(matchedDescriptors.get());
+    if (!numMatches)
+        return { };
+
+    HashSet<String> visited;
+    for (CFIndex i = 0; i < numMatches; ++i) {
+        auto fontDescriptor = static_cast<CTFontDescriptorRef>(CFArrayGetValueAtIndex(matchedDescriptors.get(), i));
+        if (auto familyName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute))))
+            visited.add(familyName.get());
+    }
+
+    Vector<String> result;
+    copyToVector(visited, result);
+    return result;
+}
+
+static CTFontSymbolicTraits computeTraits(const FontDescription& fontDescription)
+{
+    CTFontSymbolicTraits traits = 0;
+    if (fontDescription.italic())
+        traits |= kCTFontTraitItalic;
+    if (isFontWeightBold(fontDescription.weight()))
+        traits |= kCTFontTraitBold;
+    return traits;
+}
+
+SynthesisPair computeNecessarySynthesis(CTFontRef font, const FontDescription& fontDescription, bool isPlatformFont)
+{
+#if PLATFORM(IOS)
+    if (CTFontIsAppleColorEmoji(font))
+        return SynthesisPair(false, false);
+#endif
+
+    if (isPlatformFont)
+        return SynthesisPair(false, false);
+
+    CTFontSymbolicTraits desiredTraits = computeTraits(fontDescription);
+
+    CTFontSymbolicTraits actualTraits = 0;
+    if (isFontWeightBold(fontDescription.weight()) || fontDescription.italic())
+        actualTraits = CTFontGetSymbolicTraits(font);
+
+    bool needsSyntheticBold = (fontDescription.fontSynthesis() & FontSynthesisWeight) && (desiredTraits & kCTFontTraitBold) && !(actualTraits & kCTFontTraitBold);
+    bool needsSyntheticOblique = (fontDescription.fontSynthesis() & FontSynthesisStyle) && (desiredTraits & kCTFontTraitItalic) && !(actualTraits & kCTFontTraitItalic);
+
+    return SynthesisPair(needsSyntheticBold, needsSyntheticOblique);
+}
+
+typedef HashSet<String, CaseFoldingHash> Whitelist;
+static Whitelist& fontWhitelist()
+{
+    static NeverDestroyed<Whitelist> whitelist;
+    return whitelist;
+}
+
+void FontCache::setFontWhitelist(const Vector<String>& inputWhitelist)
+{
+    Whitelist& whitelist = fontWhitelist();
+    whitelist.clear();
+    for (auto& item : inputWhitelist)
+        whitelist.add(item);
+}
+
+#if ENABLE(PLATFORM_FONT_LOOKUP)
+static RetainPtr<CTFontRef> platformFontLookupWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, const FontFeatureSettings* featureSettings, TextRenderingMode textRenderingMode, float size)
+{
+    const auto& whitelist = fontWhitelist();
+    if (whitelist.size() && !whitelist.contains(family))
+        return nullptr;
+
+    auto foundFont = adoptCF(CTFontCreateForCSS(family.string().createCFString().get(), toCoreTextFontWeight(weight), requestedTraits, size));
+    return preparePlatformFont(foundFont.get(), textRenderingMode, featureSettings);
+}
+#endif
+
+static RetainPtr<CTFontRef> fontWithFamily(const AtomicString& family, CTFontSymbolicTraits desiredTraits, FontWeight weight, const FontFeatureSettings* featureSettings, TextRenderingMode textRenderingMode, float size)
+{
+    if (family.isEmpty())
+        return nullptr;
+    if (auto specialCase = platformFontWithFamilySpecialCase(family, weight, desiredTraits, size))
+        return specialCase;
+#if ENABLE(PLATFORM_FONT_LOOKUP)
+    return platformFontLookupWithFamily(family, desiredTraits, weight, featureSettings, textRenderingMode, size);
+#else
+    return platformFontWithFamily(family, desiredTraits, weight, featureSettings, textRenderingMode, size);
+#endif
+}
+
+#if PLATFORM(MAC)
+static bool shouldAutoActivateFontIfNeeded(const AtomicString& family)
+{
+#ifndef NDEBUG
+    // This cache is not thread safe so the following assertion is there to
+    // make sure this function is always called from the same thread.
+    static ThreadIdentifier initThreadId = currentThread();
+    ASSERT(currentThread() == initThreadId);
+#endif
+
+    static NeverDestroyed<HashSet<AtomicString>> knownFamilies;
+    static const unsigned maxCacheSize = 128;
+    ASSERT(knownFamilies.get().size() <= maxCacheSize);
+    if (knownFamilies.get().size() == maxCacheSize)
+        knownFamilies.get().remove(knownFamilies.get().begin());
+
+    // Only attempt to auto-activate fonts once for performance reasons.
+    return knownFamilies.get().add(family).isNewEntry;
+}
+#endif
+
+std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+    CTFontSymbolicTraits traits = computeTraits(fontDescription);
+    float size = fontDescription.computedPixelSize();
+
+    RetainPtr<CTFontRef> font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
+
+#if PLATFORM(MAC)
+    if (!font) {
+        if (!shouldAutoActivateFontIfNeeded(family))
+            return nullptr;
+
+        // Auto activate the font before looking for it a second time.
+        // Ignore the result because we want to use our own algorithm to actually find the font.
+        CFRelease(CTFontCreateWithName(family.string().createCFString().get(), size, nullptr));
+
+        font = platformFontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
+        if (!font)
+            return nullptr;
+    }
+#endif
+    if (!font)
+        return nullptr;
+
+    bool syntheticBold, syntheticOblique;
+    std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(font.get(), fontDescription).boldObliquePair();
+
+    return std::make_unique<FontPlatformData>(font.get(), size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
+}
+
+typedef HashSet<RetainPtr<CTFontRef>, WTF::RetainPtrObjectHash<CTFontRef>, WTF::RetainPtrObjectHashTraits<CTFontRef>> FallbackDedupSet;
+static FallbackDedupSet& fallbackDedupSet()
+{
+    static NeverDestroyed<FallbackDedupSet> dedupSet;
+    return dedupSet.get();
+}
+
+void FontCache::platformPurgeInactiveFontData()
+{
+    Vector<CTFontRef> toRemove;
+    for (auto& font : fallbackDedupSet()) {
+        if (CFGetRetainCount(font.get()) == 1)
+            toRemove.append(font.get());
+    }
+    for (auto& font : toRemove)
+        fallbackDedupSet().remove(font);
+}
+
+RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length)
+{
+#if PLATFORM(IOS)
+    if (length && requiresCustomFallbackFont(*characters)) {
+        auto* fallback = getCustomFallbackFont(*characters, description);
+        if (!fallback)
+            return nullptr;
+        return fontForPlatformData(*fallback);
+    }
+#endif
+
+    const FontPlatformData& platformData = originalFontData->platformData();
+    RetainPtr<CTFontRef> result = platformLookupFallbackFont(platformData.font(), description.weight(), description.locale(), characters, length);
+    result = preparePlatformFont(result.get(), description.textRenderingMode(), description.featureSettings());
+    if (!result)
+        return lastResortFallbackFont(description);
+
+    // FontCascade::drawGlyphBuffer() requires that there are no duplicate Font objects which refer to the same thing. This is enforced in
+    // FontCache::fontForPlatformData(), where our equality check is based on hashing the FontPlatformData, whose hash includes the raw CoreText
+    // font pointer.
+    CTFontRef substituteFont = fallbackDedupSet().add(result).iterator->get();
+
+    bool syntheticBold, syntheticOblique;
+    std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(substituteFont, description, isPlatformFont).boldObliquePair();
+
+    FontPlatformData alternateFont(substituteFont, platformData.size(), syntheticBold, syntheticOblique, platformData.m_orientation, platformData.m_widthVariant, platformData.m_textRenderingMode);
+
+    return fontForPlatformData(alternateFont);
+}
+
+}

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


--- trunk/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm	2015-08-24 18:37:37 UTC (rev 188871)
@@ -40,122 +40,15 @@
 
 namespace WebCore {
 
-void FontCache::platformInit()
+void platformInvalidateFontCache()
 {
 }
 
-static inline bool isFontWeightBold(NSInteger fontWeight)
+bool requiresCustomFallbackFont(UChar32 character)
 {
-    return fontWeight >= FontWeight600;
-}
-
-static inline bool requiresCustomFallbackFont(const UInt32 character)
-{
     return character == AppleLogo || character == blackCircle || character == narrowNonBreakingSpace;
 }
 
-PassRefPtr<Font> FontCache::getSystemFontFallbackForCharacters(const FontDescription& description, const Font* originalFontData, const UChar* characters, unsigned length)
-{
-    const FontPlatformData& platformData = originalFontData->platformData();
-    CTFontRef ctFont = platformData.font();
-
-    RetainPtr<CFStringRef> localeString;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED > 90000
-    if (!description.locale().isNull())
-        localeString = description.locale().string().createCFString();
-#endif
-
-    CFIndex coveredLength = 0;
-    RetainPtr<CTFontRef> substituteFont = adoptCF(CTFontCreatePhysicalFontForCharactersWithLanguage(ctFont, (const UTF16Char*)characters, (CFIndex)length, localeString.get(), &coveredLength));
-    if (!substituteFont)
-        return nullptr;
-
-    substituteFont = preparePlatformFont(substituteFont.get(), description.textRenderingMode(), description.featureSettings());
-
-    CTFontSymbolicTraits originalTraits = CTFontGetSymbolicTraits(ctFont);
-    CTFontSymbolicTraits actualTraits = 0;
-    if (isFontWeightBold(description.weight()) || description.italic())
-        actualTraits = CTFontGetSymbolicTraits(substituteFont.get());
-
-    bool syntheticBold = (originalTraits & kCTFontTraitBold) && !(actualTraits & kCTFontTraitBold);
-    bool syntheticOblique = (originalTraits & kCTFontTraitItalic) && !(actualTraits & kCTFontTraitItalic);
-
-    FontPlatformData alternateFont(substituteFont.get(), platformData.size(), syntheticBold, syntheticOblique, platformData.m_orientation);
-
-    return fontForPlatformData(alternateFont);
-}
-
-RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool, const UChar* characters, unsigned length)
-{
-    // Unlike OS X, our fallback font on iPhone is Arial Unicode, which doesn't have some apple-specific glyphs like F8FF.
-    // Fall back to the Apple Fallback font in this case.
-    if (length && requiresCustomFallbackFont(*characters)) {
-        auto* fallback = getCustomFallbackFont(*characters, description);
-        if (!fallback)
-            return nullptr;
-        return fontForPlatformData(*fallback);
-    }
-
-    UChar32 c = *characters;
-    if (length > 1 && U16_IS_LEAD(c) && U16_IS_TRAIL(characters[1]))
-        c = U16_GET_SUPPLEMENTARY(c, characters[1]);
-
-    // For system fonts we use CoreText fallback mechanism.
-    if (length) {
-        RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontCopyFontDescriptor(originalFontData->getCTFont()));
-        if (CTFontDescriptorIsSystemUIFont(fontDescriptor.get()))
-            return getSystemFontFallbackForCharacters(description, originalFontData, characters, length);
-    }
-
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000
-    RetainPtr<CTFontDescriptorRef> fallbackFontDescriptor = adoptCF(CTFontCreatePhysicalFontDescriptorForCharactersWithLanguage(originalFontData->getCTFont(), characters, length, nullptr, nullptr));
-#else
-    RetainPtr<CTFontRef> fallbackFont = adoptCF(CTFontCreateForCharactersWithLanguage(originalFontData->getCTFont(), characters, length, nullptr, nullptr));
-    RetainPtr<CTFontDescriptorRef> fallbackFontDescriptor = adoptCF(CTFontCopyFontDescriptor(fallbackFont.get()));
-#endif
-    if (auto foundFontName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fallbackFontDescriptor.get(), kCTFontNameAttribute)))) {
-        if (c >= 0x0600 && c <= 0x06ff) { // Arabic
-            auto familyName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fallbackFontDescriptor.get(), kCTFontFamilyNameAttribute)));
-            if (fontFamilyShouldNotBeUsedForArabic(familyName.get()))
-                foundFontName = isFontWeightBold(description.weight()) ? CFSTR("GeezaPro-Bold") : CFSTR("GeezaPro");
-        }
-        if (RefPtr<Font> font = fontForFamily(description, foundFontName.get(), false))
-            return font;
-    }
-
-    return lastResortFallbackFont(description);
-}
-
-Vector<String> FontCache::systemFontFamilies()
-{
-    // FIXME: <rdar://problem/21890188>
-    Vector<String> fontFamilies;
-    auto emptyFontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes((CFDictionaryRef) @{ }));
-    auto matchedDescriptors = adoptCF(CTFontDescriptorCreateMatchingFontDescriptors(emptyFontDescriptor.get(), nullptr));
-    if (!matchedDescriptors)
-        return fontFamilies;
-
-    CFIndex numMatches = CFArrayGetCount(matchedDescriptors.get());
-    if (!numMatches)
-        return fontFamilies;
-
-    HashSet<String> visited;
-    for (CFIndex i = 0; i < numMatches; ++i) {
-        auto fontDescriptor = static_cast<CTFontDescriptorRef>(CFArrayGetValueAtIndex(matchedDescriptors.get(), i));
-        if (auto familyName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute))))
-            visited.add(familyName.get());
-    }
-
-    copyToVector(visited, fontFamilies);
-    return fontFamilies;
-}
-
-Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
-{
-    static NeverDestroyed<AtomicString> fallbackFontFamily(".PhoneFallback", AtomicString::ConstructFromLiteral);
-    return *fontForFamily(fontDescription, fallbackFontFamily, false);
-}
-
 FontPlatformData* FontCache::getCustomFallbackFont(const UInt32 c, const FontDescription& description)
 {
     ASSERT(requiresCustomFallbackFont(c));
@@ -185,134 +78,111 @@
     return getCachedFontPlatformData(description, *family);
 }
 
-float FontCache::weightOfCTFont(CTFontRef font)
+static RetainPtr<CTFontRef> getSystemFontFallbackForCharacters(CTFontRef font, const AtomicString& locale, const UChar* characters, unsigned length)
 {
-    float result = 0;
-    RetainPtr<CFDictionaryRef> traits = adoptCF(CTFontCopyTraits(font));
-    if (!traits)
-        return result;
+    // FIXME: Unify this with platformLookupFallbackFont()
+    RetainPtr<CFStringRef> localeString;
+#if __IPHONE_OS_VERSION_MIN_REQUIRED > 90000
+    if (!locale.isNull())
+        localeString = locale.string().createCFString();
+#else
+    UNUSED_PARAM(locale);
+#endif
 
-    CFNumberRef resultRef = (CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontWeightTrait);
-    if (resultRef)
-        CFNumberGetValue(resultRef, kCFNumberFloatType, &result);
+    CFIndex coveredLength = 0;
+    return adoptCF(CTFontCreatePhysicalFontForCharactersWithLanguage(font, (const UTF16Char*)characters, (CFIndex)length, localeString.get(), &coveredLength));
+}
 
-    return result;
+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);
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000
+    RetainPtr<CFStringRef> localeString;
+    if (!locale.isNull())
+        localeString = locale.string().createCFString();
+    RetainPtr<CTFontDescriptorRef> fallbackFontDescriptor = adoptCF(CTFontCreatePhysicalFontDescriptorForCharactersWithLanguage(font, characters, length, localeString.get(), nullptr));
+#else
+    RetainPtr<CTFontRef> fallbackFont = adoptCF(CTFontCreateForCharactersWithLanguage(font, characters, length, nullptr, nullptr));
+    RetainPtr<CTFontDescriptorRef> fallbackFontDescriptor = adoptCF(CTFontCopyFontDescriptor(fallbackFont.get()));
+#endif
+    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[] = { kCTFontFamilyNameAttribute };
+            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));
 }
 
-static CTFontRef createCTFontWithTextStyle(const String& familyName, CTFontSymbolicTraits traits, CGFloat size)
+Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
 {
-    if (familyName.isNull())
-        return nullptr;
+    return *fontForFamily(fontDescription, AtomicString(".PhoneFallback", AtomicString::ConstructFromLiteral), false);
+}
 
-    CTFontSymbolicTraits symbolicTraits = 0;
-    if (traits & kCTFontBoldTrait)
-        symbolicTraits |= kCTFontBoldTrait;
-    if (traits & kCTFontTraitItalic)
-        symbolicTraits |= kCTFontTraitItalic;
-    RetainPtr<CFStringRef> familyNameStr = familyName.createCFString();
-    RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(familyNameStr.get(), RenderThemeIOS::contentSizeCategory(), nullptr));
-    if (symbolicTraits)
-        fontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithSymbolicTraits(fontDescriptor.get(), symbolicTraits, symbolicTraits));
+float FontCache::weightOfCTFont(CTFontRef font)
+{
+    RetainPtr<CFDictionaryRef> traits = adoptCF(CTFontCopyTraits(font));
 
-    return CTFontCreateWithFontDescriptor(fontDescriptor.get(), size, nullptr);
+    CFNumberRef resultRef = (CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontWeightTrait);
+    float result = 0;
+    CFNumberGetValue(resultRef, kCFNumberFloatType, &result);
+
+    return result;
 }
 
-static CTFontRef createCTFontWithFamilyNameAndWeight(const String& familyName, CTFontSymbolicTraits traits, float size, uint16_t weight)
+RetainPtr<CTFontRef> platformFontWithFamilySpecialCase(const AtomicString& family, FontWeight weight, CTFontSymbolicTraits traits, float size)
 {
-    if (familyName.isNull())
-        return nullptr;
+    if (family.startsWith("UICTFontTextStyle")) {
+        traits &= (kCTFontBoldTrait | kCTFontItalicTrait);
+        RetainPtr<CFStringRef> familyNameStr = family.string().createCFString();
+        RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(familyNameStr.get(), RenderThemeIOS::contentSizeCategory(), nullptr));
+        if (traits)
+            fontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithSymbolicTraits(fontDescriptor.get(), traits, traits));
 
+        return adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), size, nullptr));
+    }
+
     static NeverDestroyed<AtomicString> systemUIFontWithWebKitPrefix("-webkit-system-font", AtomicString::ConstructFromLiteral);
     static NeverDestroyed<AtomicString> systemUIFontWithApplePrefix("-apple-system", AtomicString::ConstructFromLiteral);
     static NeverDestroyed<AtomicString> systemUIFontWithAppleAlternatePrefix("-apple-system-font", AtomicString::ConstructFromLiteral);
-    if (equalIgnoringCase(familyName, systemUIFontWithWebKitPrefix) || equalIgnoringCase(familyName, systemUIFontWithApplePrefix) || equalIgnoringCase(familyName, systemUIFontWithAppleAlternatePrefix)) {
+    if (equalIgnoringCase(family, systemUIFontWithWebKitPrefix) || equalIgnoringCase(family, systemUIFontWithApplePrefix) || equalIgnoringCase(family, systemUIFontWithAppleAlternatePrefix)) {
         CTFontUIFontType fontType = kCTFontUIFontSystem;
-        if (weight > 300) {
+        if (weight > FontWeight300) {
             // The comment below has been copied from CoreText/UIFoundation. However, in WebKit we synthesize the oblique,
             // so we should investigate the result <rdar://problem/14449340>:
             if (traits & kCTFontTraitBold)
                 fontType = kCTFontUIFontEmphasizedSystem;
-        } else if (weight > 250)
+        } else if (weight > FontWeight200)
             fontType = static_cast<CTFontUIFontType>(kCTFontUIFontSystemLight);
-        else if (weight > 150)
+        else if (weight > FontWeight100)
             fontType = static_cast<CTFontUIFontType>(kCTFontUIFontSystemThin);
         else
             fontType = static_cast<CTFontUIFontType>(kCTFontUIFontSystemUltraLight);
         RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontDescriptorCreateForUIType(fontType, size, nullptr));
         if (traits & kCTFontTraitItalic)
             fontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithSymbolicTraits(fontDescriptor.get(), kCTFontItalicTrait, kCTFontItalicTrait));
-        return CTFontCreateWithFontDescriptor(fontDescriptor.get(), size, nullptr);
+        return adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), size, nullptr));
     }
 
     static NeverDestroyed<AtomicString> systemUIMonospacedNumbersFontWithApplePrefix("-apple-system-monospaced-numbers", AtomicString::ConstructFromLiteral);
-    if (equalIgnoringCase(familyName, systemUIMonospacedNumbersFontWithApplePrefix)) {
+    if (equalIgnoringCase(family, systemUIMonospacedNumbersFontWithApplePrefix)) {
         RetainPtr<CTFontDescriptorRef> systemFontDescriptor = adoptCF(CTFontDescriptorCreateForUIType(kCTFontUIFontSystem, size, nullptr));
         RetainPtr<CTFontDescriptorRef> monospaceFontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithFeature(systemFontDescriptor.get(), (CFNumberRef)@(kNumberSpacingType), (CFNumberRef)@(kMonospacedNumbersSelector)));
-        return CTFontCreateWithFontDescriptor(monospaceFontDescriptor.get(), size, nullptr);
+        return adoptCF(CTFontCreateWithFontDescriptor(monospaceFontDescriptor.get(), size, nullptr));
     }
 
-
-    RetainPtr<CFStringRef> familyNameStr = familyName.createCFString();
-    CTFontSymbolicTraits requestedTraits = (CTFontSymbolicTraits)(traits & (kCTFontBoldTrait | kCTFontItalicTrait));
-    return CTFontCreateForCSS(familyNameStr.get(), weight, requestedTraits, size);
+    return nullptr;
 }
 
-static uint16_t toCTFontWeight(FontWeight fontWeight)
-{
-    switch (fontWeight) {
-    case FontWeight100:
-        return 100;
-    case FontWeight200:
-        return 200;
-    case FontWeight300:
-        return 300;
-    case FontWeight400:
-        return 400;
-    case FontWeight500:
-        return 500;
-    case FontWeight600:
-        return 600;
-    case FontWeight700:
-        return 700;
-    case FontWeight800:
-        return 800;
-    case FontWeight900:
-        return 900;
-    default:
-        return 400;
-    }
-}
-
-std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
-{
-    CTFontSymbolicTraits traits = 0;
-    if (fontDescription.italic())
-        traits |= kCTFontTraitItalic;
-    if (isFontWeightBold(fontDescription.weight()))
-        traits |= kCTFontTraitBold;
-    float size = fontDescription.computedPixelSize();
-
-    RetainPtr<CTFontRef> ctFont;
-    if (family.startsWith("UICTFontTextStyle"))
-        ctFont = adoptCF(createCTFontWithTextStyle(family, traits, size));
-    else
-        ctFont = adoptCF(createCTFontWithFamilyNameAndWeight(family, traits, size, toCTFontWeight(fontDescription.weight())));
-    if (!ctFont)
-        return nullptr;
-
-    ctFont = preparePlatformFont(ctFont.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings());
-
-    CTFontSymbolicTraits actualTraits = 0;
-    if (isFontWeightBold(fontDescription.weight()) || fontDescription.italic())
-        actualTraits = CTFontGetSymbolicTraits(ctFont.get());
-
-    bool isAppleColorEmoji = CTFontIsAppleColorEmoji(ctFont.get());
-
-    bool syntheticBold = (fontDescription.fontSynthesis() & FontSynthesisWeight) && (traits & kCTFontTraitBold) && !(actualTraits & kCTFontTraitBold) && !isAppleColorEmoji;
-    bool syntheticOblique = (fontDescription.fontSynthesis() & FontSynthesisStyle) && (traits & kCTFontTraitItalic) && !(actualTraits & kCTFontTraitItalic) && !isAppleColorEmoji;
-
-    auto result = std::make_unique<FontPlatformData>(ctFont.get(), size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
-    return result;
-}
-
 } // namespace WebCore

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


--- trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2015-08-24 18:37:37 UTC (rev 188871)
@@ -112,9 +112,6 @@
     return candidateWeightDeltaMagnitude < chosenWeightDeltaMagnitude;
 }
 
-#endif
-
-#if !ENABLE(PLATFORM_FONT_LOOKUP)
 // Keep a cache for mapping desired font families to font families actually available on the system for performance.
 using AvailableFamilyMap = HashMap<std::pair<AtomicString, NSFontTraitMask>, AtomicString>;
 static AvailableFamilyMap& desiredFamilyToAvailableFamilyMap()
@@ -144,40 +141,6 @@
     familyMapping.add(std::make_pair(desiredFamily, desiredTraits), value);
 }
 
-#else
-
-static uint16_t toCoreTextFontWeight(FontWeight fontWeight)
-{
-    static const int coreTextFontWeights[] = {
-        100, // FontWeight100
-        200, // FontWeight200
-        300, // FontWeight300
-        400, // FontWeight400
-        500, // FontWeight500
-        600, // FontWeight600
-        700, // FontWeight700
-        800, // FontWeight800
-        900, // FontWeight900
-    };
-    return coreTextFontWeights[fontWeight];
-}
-#endif
-
-typedef HashSet<String, CaseFoldingHash> Whitelist;
-static Whitelist& fontWhitelist()
-{
-    static NeverDestroyed<Whitelist> whitelist;
-    return whitelist;
-}
-
-void FontCache::setFontWhitelist(const Vector<String>& inputWhitelist)
-{
-    Whitelist& whitelist = fontWhitelist();
-    whitelist.clear();
-    for (auto& item : inputWhitelist)
-        whitelist.add(item);
-}
-
 static int toAppKitFontWeight(FontWeight fontWeight)
 {
     static const int appKitFontWeights[] = {
@@ -194,6 +157,29 @@
     return appKitFontWeights[fontWeight];
 }
 
+static inline FontWeight appkitWeightToFontWeight(NSInteger appKitWeight)
+{
+    if (appKitWeight == 1)
+        return FontWeight100;
+    if (appKitWeight == 2)
+        return FontWeight200;
+    if (appKitWeight <= 4)
+        return FontWeight300;
+    if (appKitWeight == 5)
+        return FontWeight400;
+    if (appKitWeight == 6)
+        return FontWeight500;
+    if (appKitWeight <= 8)
+        return FontWeight600;
+    if (appKitWeight == 9)
+        return FontWeight700;
+    if (appKitWeight <= 11)
+        return FontWeight800;
+    return FontWeight900;
+}
+
+#endif // PLATFORM_FONT_LOOKUP
+
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
 static CGFloat toNSFontWeight(FontWeight fontWeight)
 {
@@ -213,77 +199,69 @@
 }
 #endif
 
-static Optional<NSFont*> fontWithFamilySpecialCase(const AtomicString& family, FontWeight weight, NSFontTraitMask desiredTraits, float size)
+static NSFontTraitMask toNSFontTraits(CTFontSymbolicTraits traits)
 {
+    NSFontTraitMask result = 0;
+    if (traits & kCTFontBoldTrait)
+        result |= NSBoldFontMask;
+    if (traits & kCTFontItalicTrait)
+        result |= NSItalicFontMask;
+    return result;
+}
+
+RetainPtr<CTFontRef> platformFontWithFamilySpecialCase(const AtomicString& family, FontWeight weight, CTFontSymbolicTraits desiredTraits, float size)
+{
     if (equalIgnoringASCIICase(family, "-webkit-system-font")
         || equalIgnoringASCIICase(family, "-apple-system")
         || equalIgnoringASCIICase(family, "-apple-system-font")) {
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-        NSFont *result = [NSFont systemFontOfSize:size weight:toNSFontWeight(weight)];
+        RetainPtr<CTFontRef> result = toCTFont([NSFont systemFontOfSize:size weight:toNSFontWeight(weight)]);
 #else
-        NSFont *result = (weight >= FontWeight600) ? [NSFont boldSystemFontOfSize:size] : [NSFont systemFontOfSize:size];
+        RetainPtr<CTFontRef> result = toCTFont((weight >= FontWeight600) ? [NSFont boldSystemFontOfSize:size] : [NSFont systemFontOfSize:size]);
 #endif
-        if (desiredTraits & NSFontItalicTrait)
-            result = [[NSFontManager sharedFontManager] convertFont:result toHaveTrait:desiredTraits];
+        if (desiredTraits & kCTFontItalicTrait) {
+            if (auto italicizedFont = adoptCF(CTFontCreateCopyWithSymbolicTraits(result.get(), size, nullptr, desiredTraits, desiredTraits)))
+                result = italicizedFont;
+        }
         return result;
     }
 
     if (equalIgnoringASCIICase(family, "-apple-system-monospaced-numbers")) {
-        NSArray *featureArray = @[ @{ NSFontFeatureTypeIdentifierKey : @(kNumberSpacingType),
-            NSFontFeatureSelectorIdentifierKey : @(kMonospacedNumbersSelector) } ];
+        int numberSpacingType = kNumberSpacingType;
+        int monospacedNumbersSelector = kMonospacedNumbersSelector;
+        RetainPtr<CFNumberRef> numberSpacingNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &numberSpacingType));
+        RetainPtr<CFNumberRef> monospacedNumbersNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &monospacedNumbersSelector));
+        CFTypeRef featureKeys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey };
+        CFTypeRef featureValues[] = { numberSpacingNumber.get(), monospacedNumbersNumber.get() };
+        RetainPtr<CFDictionaryRef> featureIdentifier = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, featureKeys, featureValues, WTF_ARRAY_LENGTH(featureKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+        CFTypeRef featureIdentifiers[] = { featureIdentifier.get() };
+        RetainPtr<CFArrayRef> featureArray = adoptCF(CFArrayCreate(kCFAllocatorDefault, featureIdentifiers, 1, &kCFTypeArrayCallBacks));
+        CFTypeRef attributesKeys[] = { kCTFontFeatureSettingsAttribute };
+        CFTypeRef attributesValues[] = { featureArray.get() };
+        RetainPtr<CFDictionaryRef> attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, attributesKeys, attributesValues, WTF_ARRAY_LENGTH(attributesKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
 
-        NSFont* systemFont = [NSFont systemFontOfSize:size];
-        NSFontDescriptor* desc = [systemFont.fontDescriptor fontDescriptorByAddingAttributes:@{ NSFontFeatureSettingsAttribute : featureArray }];
-        return [NSFont fontWithDescriptor:desc size:size];
+        RetainPtr<CTFontRef> result = toCTFont([NSFont systemFontOfSize:size]);
+        return adoptCF(CTFontCreateCopyWithAttributes(result.get(), size, nullptr, adoptCF(CTFontDescriptorCreateWithAttributes(attributes.get())).get()));
     }
 
     if (equalIgnoringASCIICase(family, "-apple-menu"))
-        return [NSFont menuFontOfSize:size];
+        return toCTFont([NSFont menuFontOfSize:size]);
 
     if (equalIgnoringASCIICase(family, "-apple-status-bar"))
-        return [NSFont labelFontOfSize:size];
+        return toCTFont([NSFont labelFontOfSize:size]);
 
-    return Optional<NSFont*>(Nullopt);
+    return nullptr;
 }
 
-// Family name is somewhat of a misnomer here. We first attempt to find an exact match
-// comparing the desiredFamily to the PostScript name of the installed fonts. If that fails
-// we then do a search based on the family names of the installed fonts.
-static NSFont *fontWithFamily(const AtomicString& family, NSFontTraitMask desiredTraits, FontWeight weight, const FontFeatureSettings* featureSettings, TextRenderingMode textRenderingMode, float size)
+#if !ENABLE(PLATFORM_FONT_LOOKUP)
+RetainPtr<CTFontRef> platformFontWithFamily(const AtomicString& family, CTFontSymbolicTraits requestedTraits, FontWeight weight, const FontFeatureSettings*, TextRenderingMode, float size)
 {
-    if (const auto& specialCase = fontWithFamilySpecialCase(family, weight, desiredTraits, size))
-        return specialCase.value();
-
     NSFontManager *fontManager = [NSFontManager sharedFontManager];
     NSString *availableFamily;
     int chosenWeight;
     NSFont *font;
 
-#if ENABLE(PLATFORM_FONT_LOOKUP)
-
-    const auto& whitelist = fontWhitelist();
-    if (whitelist.size() && !whitelist.contains(family.lower()))
-        return nil;
-    CTFontSymbolicTraits requestedTraits = 0;
-    if (desiredTraits & NSFontItalicTrait)
-        requestedTraits |= kCTFontItalicTrait;
-    if (weight >= FontWeight600)
-        requestedTraits |= kCTFontBoldTrait;
-
-    NSString *desiredFamily = family;
-    RetainPtr<CTFontRef> foundFont = adoptCF(CTFontCreateForCSS((CFStringRef)desiredFamily, toCoreTextFontWeight(weight), requestedTraits, size));
-    foundFont = preparePlatformFont(foundFont.get(), textRenderingMode, featureSettings);
-    if (!foundFont)
-        return nil;
-    font = CFBridgingRelease(CFRetain(foundFont.get()));
-    availableFamily = [font familyName];
-    chosenWeight = [fontManager weightOfFont:font];
-
-#else
-
-    UNUSED_PARAM(featureSettings);
-    UNUSED_PARAM(textRenderingMode);
-
+    NSFontTraitMask desiredTraits = toNSFontTraits(requestedTraits);
     NSFontTraitMask desiredTraitsForNameMatch = desiredTraits | (weight >= FontWeight600 ? NSBoldFontMask : 0);
     if (hasDesiredFamilyToAvailableFamilyMapping(family, desiredTraitsForNameMatch, availableFamily)) {
         if (!availableFamily) {
@@ -313,11 +291,11 @@
                     // Special case Osaka-Mono. According to <rdar://problem/3999467>, we need to
                     // treat Osaka-Mono as fixed pitch.
                     if ([desiredFamily caseInsensitiveCompare:@"Osaka-Mono"] == NSOrderedSame && !desiredTraitsForNameMatch)
-                        return nameMatchedFont;
+                        return toCTFont(nameMatchedFont);
 
                     NSFontTraitMask traits = [fontManager traitsOfFont:nameMatchedFont];
                     if ((traits & desiredTraitsForNameMatch) == desiredTraitsForNameMatch)
-                        return [fontManager convertFont:nameMatchedFont toHaveTrait:desiredTraitsForNameMatch];
+                        return toCTFont([fontManager convertFont:nameMatchedFont toHaveTrait:desiredTraitsForNameMatch]);
 
                     availableFamily = [nameMatchedFont familyName];
                     break;
@@ -372,9 +350,9 @@
     NSFontTraitMask actualTraits = 0;
     if (desiredTraits & NSFontItalicTrait)
         actualTraits = [fontManager traitsOfFont:font];
-    int actualWeight = [fontManager weightOfFont:font];
+    FontWeight actualWeight = appkitWeightToFontWeight([fontManager weightOfFont:font]);
 
-    bool syntheticBold = toAppKitFontWeight(weight) >= 7 && actualWeight < 7;
+    bool syntheticBold = isFontWeightBold(weight) && isFontWeightBold(actualWeight);
     bool syntheticOblique = (desiredTraits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait);
 
     // There are some malformed fonts that will be correctly returned by -fontWithFamily:traits:weight:size: as a match for a particular trait,
@@ -396,89 +374,24 @@
             font = fontWithoutSyntheticTraits;
     }
 
+    return toCTFont(font);
+}
 #endif
 
-    return font;
-}
-
-static void invalidateFontCache()
+void platformInvalidateFontCache()
 {
-    if (!isMainThread()) {
-        callOnMainThread([] {
-            invalidateFontCache();
-        });
-        return;
-    }
-
-    FontCache::singleton().invalidate();
-
 #if !ENABLE(PLATFORM_FONT_LOOKUP)
     desiredFamilyToAvailableFamilyMap().clear();
 #endif
 }
 
-static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void *, CFDictionaryRef)
+RetainPtr<CTFontRef> platformLookupFallbackFont(CTFontRef font, FontWeight, const AtomicString& locale, const UChar* characters, unsigned length)
 {
-    ASSERT_UNUSED(observer, observer == &FontCache::singleton());
-    ASSERT_UNUSED(name, CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification));
-
-    invalidateFontCache();
-}
-
-void FontCache::platformInit()
-{
-    CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
-}
-
-static inline bool isAppKitFontWeightBold(NSInteger appKitFontWeight)
-{
-    return appKitFontWeight >= 7;
-}
-
-static bool shouldAutoActivateFontIfNeeded(const AtomicString& family)
-{
-#ifndef NDEBUG
-    // This cache is not thread safe so the following assertion is there to
-    // make sure this function is always called from the same thread.
-    static ThreadIdentifier initThreadId = currentThread();
-    ASSERT(currentThread() == initThreadId);
-#endif
-
-    static NeverDestroyed<HashSet<AtomicString>> knownFamilies;
-    static const unsigned maxCacheSize = 128;
-    ASSERT(knownFamilies.get().size() <= maxCacheSize);
-    if (knownFamilies.get().size() == maxCacheSize)
-        knownFamilies.get().remove(knownFamilies.get().begin());
-
-    // Only attempt to auto-activate fonts once for performance reasons.
-    return knownFamilies.get().add(family).isNewEntry;
-}
-
-typedef HashSet<RetainPtr<CTFontRef>, WTF::RetainPtrObjectHash<CTFontRef>, WTF::RetainPtrObjectHashTraits<CTFontRef>> FallbackDedupSet;
-static FallbackDedupSet& fallbackDedupSet()
-{
-    static NeverDestroyed<FallbackDedupSet> dedupSet;
-    return dedupSet.get();
-}
-
-void FontCache::platformPurgeInactiveFontData()
-{
-    Vector<CTFontRef> toRemove;
-    for (auto& font : fallbackDedupSet()) {
-        if (CFGetRetainCount(font.get()) == 1)
-            toRemove.append(font.get());
-    }
-    for (auto& font : toRemove)
-        fallbackDedupSet().remove(font);
-}
-
-static inline RetainPtr<CTFontRef> lookupCTFont(CTFontRef font, float fontSize, const AtomicString& locale, const UChar* characters, unsigned length)
-{
     RetainPtr<CFStringRef> localeString;
 #if __MAC_OS_X_VERSION_MIN_REQUIRED == 1090
     UNUSED_PARAM(locale);
     if (!font) {
-        font = toCTFont([NSFont userFontOfSize:fontSize]);
+        font = toCTFont([NSFont userFontOfSize:CTFontGetSize(font)]);
         bool acceptable = true;
         
         RetainPtr<CFCharacterSetRef> characterSet = adoptCF(CTFontCopyCharacterSet(font));
@@ -492,11 +405,9 @@
             return font;
     }
 #elif __MAC_OS_X_VERSION_MIN_REQUIRED > 101100
-    UNUSED_PARAM(fontSize);
     if (!locale.isNull())
         localeString = locale.string().createCFString();
 #else
-    UNUSED_PARAM(fontSize);
     UNUSED_PARAM(locale);
 #endif
 
@@ -504,120 +415,20 @@
     return adoptCF(CTFontCreateForCharactersWithLanguage(font, characters, length, localeString.get(), &coveredLength));
 }
 
-RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length)
-{
-    const FontPlatformData& platformData = originalFontData->platformData();
-    NSFont *nsFont = platformData.nsFont();
-    RetainPtr<CTFontRef> result = lookupCTFont(platformData.font(), platformData.size(), description.locale(), characters, length);
-    result = preparePlatformFont(result.get(), description.textRenderingMode(), description.featureSettings());
-    if (!result)
-        return nullptr;
-
-    // FontCascade::drawGlyphBuffer() requires that there are no duplicate Font objects which refer to the same thing. This is enforced in
-    // FontCache::fontForPlatformData(), where our equality check is based on hashing the FontPlatformData, whose hash includes the raw CoreText
-    // font pointer.
-    NSFont *substituteFont = toNSFont(fallbackDedupSet().add(result).iterator->get());
-
-    NSFontManager *fontManager = [NSFontManager sharedFontManager];
-
-    NSFontTraitMask traits = 0;
-    NSInteger weight;
-
-    if (nsFont) {
-        if (description.italic())
-            traits = [fontManager traitsOfFont:nsFont];
-        if (platformData.m_syntheticBold)
-            traits |= NSBoldFontMask;
-        if (platformData.m_syntheticOblique)
-            traits |= NSFontItalicTrait;
-        weight = [fontManager weightOfFont:nsFont];
-    } else {
-        ASSERT(!CORETEXT_WEB_FONTS);
-        traits = description.italic() ? NSFontItalicTrait : 0;
-        weight = toAppKitFontWeight(description.weight());
-    }
-
-    NSFontTraitMask substituteFontTraits = [fontManager traitsOfFont:substituteFont];
-    NSInteger substituteFontWeight = [fontManager weightOfFont:substituteFont];
-
-    FontPlatformData alternateFont(toCTFont(substituteFont), platformData.size(),
-        !isPlatformFont && isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(substituteFontWeight),
-        !isPlatformFont && (traits & NSFontItalicTrait) && !(substituteFontTraits & NSFontItalicTrait),
-        platformData.m_orientation, platformData.m_widthVariant, platformData.m_textRenderingMode);
-
-    return fontForPlatformData(alternateFont);
-}
-
-Vector<String> FontCache::systemFontFamilies()
-{
-    Vector<String> fontFamilies;
-    RetainPtr<CFArrayRef> availableFontFamilies = adoptCF(CTFontManagerCopyAvailableFontFamilyNames());
-    CFIndex count = CFArrayGetCount(availableFontFamilies.get());
-    for (CFIndex i = 0; i < count; ++i) {
-        CFStringRef fontName = static_cast<CFStringRef>(CFArrayGetValueAtIndex(availableFontFamilies.get(), i));
-        if (CFGetTypeID(fontName) != CFStringGetTypeID()) {
-            ASSERT_NOT_REACHED();
-            continue;
-        }
-        // We don't want to make the hidden system fonts visible and since they
-        // all begin with a period, ignore all fonts that begin with a period.
-        if (CFStringHasPrefix(fontName, CFSTR(".")))
-            continue;
-        fontFamilies.append(fontName);
-    }
-    return fontFamilies;
-}
-
 Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
 {
-    DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times", AtomicString::ConstructFromLiteral));
-
     // 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.
-    RefPtr<Font> font = fontForFamily(fontDescription, timesStr, false);
-    if (font)
+    if (RefPtr<Font> font = fontForFamily(fontDescription, AtomicString("Times", AtomicString::ConstructFromLiteral), false))
         return *font;
 
     // 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.
-    DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, lucidaGrandeStr, ("Lucida Grande", AtomicString::ConstructFromLiteral));
-    return *fontForFamily(fontDescription, lucidaGrandeStr, false);
+    return *fontForFamily(fontDescription, AtomicString("Lucida Grande", AtomicString::ConstructFromLiteral), false);
 }
 
-std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
-{
-    NSFontTraitMask traits = fontDescription.italic() ? NSFontItalicTrait : 0;
-    float size = fontDescription.computedPixelSize();
-
-    NSFont *nsFont = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
-    if (!nsFont) {
-        if (!shouldAutoActivateFontIfNeeded(family))
-            return nullptr;
-
-        // Auto activate the font before looking for it a second time.
-        // Ignore the result because we want to use our own algorithm to actually find the font.
-        [NSFont fontWithName:family size:size];
-
-        nsFont = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.textRenderingMode(), size);
-        if (!nsFont)
-            return nullptr;
-    }
-
-    NSFontManager *fontManager = [NSFontManager sharedFontManager];
-    NSFontTraitMask actualTraits = 0;
-    if (fontDescription.italic())
-        actualTraits = [fontManager traitsOfFont:nsFont];
-    NSInteger actualWeight = [fontManager weightOfFont:nsFont];
-
-    NSFont *platformFont = [nsFont printerFont];
-    bool syntheticBold = (fontDescription.fontSynthesis() & FontSynthesisWeight) && isAppKitFontWeightBold(toAppKitFontWeight(fontDescription.weight())) && !isAppKitFontWeightBold(actualWeight);
-    bool syntheticOblique = (fontDescription.fontSynthesis() & FontSynthesisStyle) && (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait);
-
-    return std::make_unique<FontPlatformData>(toCTFont(platformFont), size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
-}
-
 } // namespace WebCore
 
 #endif // !PLATFORM(IOS)

Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (188870 => 188871)


--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2015-08-24 18:07:48 UTC (rev 188870)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm	2015-08-24 18:37:37 UTC (rev 188871)
@@ -1078,30 +1078,6 @@
     return false;
 }
 
-static FontWeight fromCTFontWeight(float fontWeight)
-{
-    if (fontWeight <= -0.8)
-        return FontWeight100;
-    else if (fontWeight <= -0.4)
-        return FontWeight200;
-    else if (fontWeight <= -0.2)
-        return FontWeight300;
-    else if (fontWeight <= 0.0)
-        return FontWeight400;
-    else if (fontWeight <= 0.2)
-        return FontWeight500;
-    else if (fontWeight <= 0.3)
-        return FontWeight600;
-    else if (fontWeight <= 0.4)
-        return FontWeight700;
-    else if (fontWeight <= 0.6)
-        return FontWeight800;
-    else if (fontWeight <= 0.8)
-        return FontWeight900;
-
-    return FontWeightNormal;
-}
-
 FontDescription& RenderThemeIOS::cachedSystemFontDescription(CSSValueID valueID) const
 {
     static NeverDestroyed<FontDescription> systemFont;
@@ -1265,7 +1241,7 @@
     fontDescription.setIsAbsoluteSize(true);
     fontDescription.setOneFamily(textStyle);
     fontDescription.setSpecifiedSize(CTFontGetSize(font.get()));
-    fontDescription.setWeight(fromCTFontWeight(FontCache::weightOfCTFont(font.get())));
+    fontDescription.setWeight(fontWeightFromCoreText(FontCache::weightOfCTFont(font.get())));
     fontDescription.setItalic(FontItalicOff);
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to