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);
}