Title: [187982] trunk/Source/WebCore
Revision
187982
Author
mmaxfi...@apple.com
Date
2015-08-05 13:07:37 -0700 (Wed, 05 Aug 2015)

Log Message

[OS X] Migrate to CTFontCreateForCharactersWithLanguage from [NSFont findFontLike:forString:withRange:inLanguage]
https://bugs.webkit.org/show_bug.cgi?id=147483

Reviewed by Dean Jackson.

[NSFont findFontLike:forString:withRange:inLanguage] doesn't properly handle its last argument. In
addition, we want to be moving away from NSFont in the first place and on to Core Text. This new
CoreText function correctly handles its language argument, which is required for language-specific
font fallback.

This patch rolls r187707 back in which was rolled out in r187802 due to test flakiness. This patch
fixes the flakiness.

No new tests because there is no behavior change.

* platform/graphics/FontCache.cpp:
(WebCore::FontCache::purgeInactiveFontData):
* platform/graphics/FontCache.h:
(WebCore::FontCache::platformPurgeInactiveFontData):
* platform/graphics/mac/FontCacheMac.mm:
(WebCore::fallbackDedupSet):
(WebCore::FontCache::platformPurgeInactiveFontData):
(WebCore::lookupCTFont):
(WebCore::FontCache::systemFallbackForCharacters):
* platform/spi/cocoa/CoreTextSPI.h:
* platform/spi/mac/NSFontSPI.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (187981 => 187982)


--- trunk/Source/WebCore/ChangeLog	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/ChangeLog	2015-08-05 20:07:37 UTC (rev 187982)
@@ -1,3 +1,32 @@
+2015-08-05  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [OS X] Migrate to CTFontCreateForCharactersWithLanguage from [NSFont findFontLike:forString:withRange:inLanguage]
+        https://bugs.webkit.org/show_bug.cgi?id=147483
+
+        Reviewed by Dean Jackson.
+
+        [NSFont findFontLike:forString:withRange:inLanguage] doesn't properly handle its last argument. In
+        addition, we want to be moving away from NSFont in the first place and on to Core Text. This new
+        CoreText function correctly handles its language argument, which is required for language-specific
+        font fallback.
+
+        This patch rolls r187707 back in which was rolled out in r187802 due to test flakiness. This patch
+        fixes the flakiness.
+
+        No new tests because there is no behavior change.
+
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::purgeInactiveFontData):
+        * platform/graphics/FontCache.h:
+        (WebCore::FontCache::platformPurgeInactiveFontData):
+        * platform/graphics/mac/FontCacheMac.mm:
+        (WebCore::fallbackDedupSet):
+        (WebCore::FontCache::platformPurgeInactiveFontData):
+        (WebCore::lookupCTFont):
+        (WebCore::FontCache::systemFallbackForCharacters):
+        * platform/spi/cocoa/CoreTextSPI.h:
+        * platform/spi/mac/NSFontSPI.h:
+
 2015-08-05  Anders Carlsson  <ander...@apple.com>
 
         Get rid of DatabaseBackend as another step towards merging Database and DatabaseBackendBase

Modified: trunk/Source/WebCore/platform/graphics/FontCache.cpp (187981 => 187982)


--- trunk/Source/WebCore/platform/graphics/FontCache.cpp	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/platform/graphics/FontCache.cpp	2015-08-05 20:07:37 UTC (rev 187982)
@@ -467,6 +467,8 @@
             fontVerticalDataCache.remove(key);
     }
 #endif
+
+    platformPurgeInactiveFontData();
 }
 
 size_t FontCache::fontCount()

Modified: trunk/Source/WebCore/platform/graphics/FontCache.h (187981 => 187982)


--- trunk/Source/WebCore/platform/graphics/FontCache.h	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/platform/graphics/FontCache.h	2015-08-05 20:07:37 UTC (rev 187982)
@@ -150,6 +150,7 @@
     WEBCORE_EXPORT size_t fontCount();
     WEBCORE_EXPORT size_t inactiveFontCount();
     WEBCORE_EXPORT void purgeInactiveFontData(unsigned count = UINT_MAX);
+    void platformPurgeInactiveFontData();
 
 #if PLATFORM(WIN)
     RefPtr<Font> fontFromDescriptionAndLogFont(const FontDescription&, const LOGFONT&, AtomicString& outFontFamilyName);
@@ -184,6 +185,12 @@
     friend class Font;
 };
 
+#if !PLATFORM(MAC)
+inline void FontCache::platformPurgeInactiveFontData()
+{
 }
+#endif
 
+}
+
 #endif

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


--- trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm	2015-08-05 20:07:37 UTC (rev 187982)
@@ -459,22 +459,59 @@
     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<RetainPtr<CTFontRef>> toRemove;
+    for (auto& font : fallbackDedupSet()) {
+        if (CFGetRetainCount(font.get()) == 1)
+            toRemove.append(font);
+    }
+    for (auto& font : toRemove)
+        fallbackDedupSet().remove(font);
+}
+
+static inline RetainPtr<CTFontRef> lookupCTFont(CTFontRef font, float fontSize, const UChar* characters, unsigned length)
+{
+#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1090
+    if (!font) {
+        font = reinterpret_cast<CTFontRef>([NSFont userFontOfSize:fontSize]);
+        bool acceptable = true;
+        
+        RetainPtr<CFCharacterSetRef> characterSet = adoptCF(CTFontCopyCharacterSet(font));
+        for (auto character : StringView(characters, length).codePoints()) {
+            if (!CFCharacterSetIsLongCharacterMember(characterSet.get(), character)) {
+                acceptable = false;
+                break;
+            }
+        }
+        if (acceptable)
+            return font;
+    }
+#endif
+    CFIndex coveredLength = 0;
+    return adoptCF(CTFontCreateForCharactersWithLanguage(font, characters, length, nullptr, &coveredLength));
+}
+
 RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length)
 {
-    UChar32 character;
-    U16_GET(characters, 0, 0, length, character);
     const FontPlatformData& platformData = originalFontData->platformData();
     NSFont *nsFont = platformData.nsFont();
+    RetainPtr<CTFontRef> result = lookupCTFont(platformData.font(), platformData.size(), characters, length);
+    if (!result)
+        return nullptr;
 
-    NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(characters) length:length freeWhenDone:NO];
-    NSFont *substituteFont = [NSFont findFontLike:nsFont forString:string withRange:NSMakeRange(0, [string length]) inLanguage:nil];
-    [string release];
+    // 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 = reinterpret_cast<NSFont *>(const_cast<__CTFont*>(fallbackDedupSet().add(result).iterator->get()));
 
-    if (!substituteFont && length == 1)
-        substituteFont = [NSFont findFontLike:nsFont forCharacter:characters[0] inLanguage:nil];
-    if (!substituteFont)
-        return 0;
-
     // Use the family name from the AppKit-supplied substitute font, requesting the
     // traits, weight, and size we want. One way this does better than the original
     // AppKit request is that it takes synthetic bold and oblique into account.
@@ -508,6 +545,8 @@
 
     if (traits != substituteFontTraits || weight != substituteFontWeight || !nsFont) {
         if (NSFont *bestVariation = [fontManager fontWithFamily:[substituteFont familyName] traits:traits weight:weight size:size]) {
+            UChar32 character;
+            U16_GET(characters, 0, 0, length, character);
             if (!nsFont || (([fontManager traitsOfFont:bestVariation] != substituteFontTraits || [fontManager weightOfFont:bestVariation] != substituteFontWeight)
                 && [[bestVariation coveredCharacterSet] longCharacterIsMember:character]))
                 substituteFont = bestVariation;

Modified: trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h (187981 => 187982)


--- trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h	2015-08-05 20:07:37 UTC (rev 187982)
@@ -91,6 +91,7 @@
 
 bool CTFontDescriptorIsSystemUIFont(CTFontDescriptorRef);
 CTFontRef CTFontCreateForCSS(CFStringRef name, uint16_t weight, CTFontSymbolicTraits, CGFloat size);
+CTFontRef CTFontCreateForCharactersWithLanguage(CTFontRef currentFont, const UTF16Char *characters, CFIndex length, CFStringRef language, CFIndex *coveredLength);
 
 #if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
 extern const CFStringRef kCTUIFontTextStyleShortHeadline;

Modified: trunk/Source/WebCore/platform/spi/mac/NSFontSPI.h (187981 => 187982)


--- trunk/Source/WebCore/platform/spi/mac/NSFontSPI.h	2015-08-05 20:04:07 UTC (rev 187981)
+++ trunk/Source/WebCore/platform/spi/mac/NSFontSPI.h	2015-08-05 20:07:37 UTC (rev 187982)
@@ -35,9 +35,6 @@
 #else
 
 @interface NSFont (Private)
-+ (NSFont *)findFontLike:(NSFont *)aFont forCharacter:(UInt32)c inLanguage:(id) language;
-+ (NSFont *)findFontLike:(NSFont *)aFont forString:(NSString *)string withRange:(NSRange)range inLanguage:(id) language;
-
 + (NSFont *)systemFontOfSize:(CGFloat)size weight:(CGFloat)weight;
 @end
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to