FontCache should only deal with SimpleFontData
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Jan 2015 19:33:40 +0000 (19:33 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Jan 2015 19:33:40 +0000 (19:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140293

Reviewed by Andreas Kling.

FontCache::fontForFamilyAtIndex hands out FontData objects and calls to FontSelector. That sort
of code does not belong to the cache layer. Move the functionality up to FontGlyphs.

* platform/graphics/Font.cpp:
(WebCore::Font::operator==):
(WebCore::Font::drawText):
(WebCore::Font::drawEmphasisMarks):
(WebCore::Font::isLoadingCustomFonts):
* platform/graphics/Font.h:
(WebCore::Font::loadingCustomFonts): Deleted.
* platform/graphics/FontCache.cpp:
(WebCore::FontCache::similarFontPlatformData):

    Generic null implementation to reduce #ifs.

(WebCore::FontCache::fontForFamilyAtIndex): Deleted.
* platform/graphics/FontCache.h:

    Unfriend FontGlyphs.

* platform/graphics/FontGlyphs.cpp:
(WebCore::FontGlyphs::FontGlyphs):
(WebCore::FontGlyphs::isLoadingCustomFonts):

    We can figure thus out cheaply without caching a bit.

(WebCore::realizeNextFamily):
(WebCore::FontGlyphs::realizeFontDataAt):

    Reorganize a bit to make the logic clearer.
    Get rid of the strange cAllFamiliesScanned constant.

(WebCore::FontGlyphs::glyphDataForVariant):
(WebCore::FontGlyphs::glyphDataForNormalVariant):

    Loop until null, that always works.

* platform/graphics/FontGlyphs.h:
(WebCore::FontGlyphs::loadingCustomFonts): Deleted.
* platform/graphics/ios/FontCacheIOS.mm:
(WebCore::FontCache::similarFontPlatformData):
* platform/graphics/mac/FontCacheMac.mm:
(WebCore::FontCache::similarFontPlatformData):
* platform/graphics/mac/FontMac.mm:
(WebCore::Font::dashesForIntersectionsWithRect):

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

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/Font.cpp
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/FontGlyphs.cpp
Source/WebCore/platform/graphics/FontGlyphs.h
Source/WebCore/platform/graphics/cairo/FontCairo.cpp
Source/WebCore/platform/graphics/ios/FontCacheIOS.mm
Source/WebCore/platform/graphics/mac/FontCacheMac.mm
Source/WebCore/platform/graphics/mac/FontMac.mm

index 552eade..7054cab 100644 (file)
@@ -1,3 +1,56 @@
+2015-01-09  Antti Koivisto  <antti@apple.com>
+
+        FontCache should only deal with SimpleFontData
+        https://bugs.webkit.org/show_bug.cgi?id=140293
+
+        Reviewed by Andreas Kling.
+
+        FontCache::fontForFamilyAtIndex hands out FontData objects and calls to FontSelector. That sort
+        of code does not belong to the cache layer. Move the functionality up to FontGlyphs.
+
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::operator==):
+        (WebCore::Font::drawText):
+        (WebCore::Font::drawEmphasisMarks):
+        (WebCore::Font::isLoadingCustomFonts):
+        * platform/graphics/Font.h:
+        (WebCore::Font::loadingCustomFonts): Deleted.
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::similarFontPlatformData):
+
+            Generic null implementation to reduce #ifs.
+
+        (WebCore::FontCache::fontForFamilyAtIndex): Deleted.
+        * platform/graphics/FontCache.h:
+
+            Unfriend FontGlyphs.
+
+        * platform/graphics/FontGlyphs.cpp:
+        (WebCore::FontGlyphs::FontGlyphs):
+        (WebCore::FontGlyphs::isLoadingCustomFonts):
+
+            We can figure thus out cheaply without caching a bit.
+
+        (WebCore::realizeNextFamily):
+        (WebCore::FontGlyphs::realizeFontDataAt):
+
+            Reorganize a bit to make the logic clearer.
+            Get rid of the strange cAllFamiliesScanned constant.
+
+        (WebCore::FontGlyphs::glyphDataForVariant):
+        (WebCore::FontGlyphs::glyphDataForNormalVariant):
+
+            Loop until null, that always works.
+
+        * platform/graphics/FontGlyphs.h:
+        (WebCore::FontGlyphs::loadingCustomFonts): Deleted.
+        * platform/graphics/ios/FontCacheIOS.mm:
+        (WebCore::FontCache::similarFontPlatformData):
+        * platform/graphics/mac/FontCacheMac.mm:
+        (WebCore::FontCache::similarFontPlatformData):
+        * platform/graphics/mac/FontMac.mm:
+        (WebCore::Font::dashesForIntersectionsWithRect):
+
 2015-01-09  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         REGRESSION(r177925): It broke the !ENABLE(INSPECTOR) build
index 40615e1..edd9850 100644 (file)
@@ -182,9 +182,7 @@ Font& Font::operator=(const Font& other)
 
 bool Font::operator==(const Font& other) const
 {
-    // Our FontData don't have to be checked, since checking the font description will be fine.
-    // FIXME: This does not work if the font was made with the FontPlatformData constructor.
-    if (loadingCustomFonts() || other.loadingCustomFonts())
+    if (isLoadingCustomFonts() || other.isLoadingCustomFonts())
         return false;
 
     if (m_fontDescription != other.m_fontDescription || m_letterSpacing != other.m_letterSpacing || m_wordSpacing != other.m_wordSpacing)
@@ -337,7 +335,7 @@ float Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPo
     // Don't draw anything while we are using custom fonts that are in the process of loading,
     // except if the 'force' argument is set to true (in which case it will use a fallback
     // font).
-    if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
+    if (isLoadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
         return 0;
 
     to = (to == -1 ? run.length() : to);
@@ -355,7 +353,7 @@ float Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPo
 
 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
 {
-    if (loadingCustomFonts())
+    if (isLoadingCustomFonts())
         return;
 
     if (to < 0)
@@ -1083,6 +1081,11 @@ bool Font::canReceiveTextEmphasis(UChar32 c)
 
     return true;
 }
+
+bool Font::isLoadingCustomFonts() const
+{
+    return m_glyphs && m_glyphs->isLoadingCustomFonts();
+}
     
 GlyphToPathTranslator::GlyphUnderlineType computeUnderlineType(const TextRun& textRun, const GlyphBuffer& glyphBuffer, int index)
 {
index 16ff611..212b555 100644 (file)
@@ -289,10 +289,7 @@ public:
     FontGlyphs* glyphs() const { return m_glyphs.get(); }
 
 private:
-    bool loadingCustomFonts() const
-    {
-        return m_glyphs && m_glyphs->loadingCustomFonts();
-    }
+    bool isLoadingCustomFonts() const;
 
     TypesettingFeatures computeTypesettingFeatures() const
     {
index d578c80..e1fc78a 100644 (file)
@@ -490,48 +490,6 @@ size_t FontCache::inactiveFontDataCount()
     return count;
 }
 
-RefPtr<FontData> FontCache::fontForFamilyAtIndex(const FontDescription& description, int& familyIndex, FontSelector* fontSelector)
-{
-    ASSERT(familyIndex != cAllFamiliesScanned);
-    RefPtr<FontData> result;
-
-    bool isFirst = !familyIndex;
-    int familyCount = description.familyCount();
-    for (;familyIndex < familyCount && !result; ++familyIndex) {
-        const AtomicString& family = description.familyAt(familyIndex);
-        if (family.isEmpty())
-            continue;
-        if (fontSelector)
-            result = fontSelector->getFontData(description, family);
-        if (!result)
-            result = fontForFamily(description, family);
-    }
-    if (familyIndex == familyCount)
-        familyIndex = cAllFamiliesScanned;
-
-#if PLATFORM(COCOA)
-    if (!result) {
-        // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform.
-        // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
-        // Geeza Pro font.
-        result = similarFontPlatformData(description);
-    }
-#endif
-
-    if (!result && isFirst) {
-        // If it's the primary font that we couldn't find, we try the following. In all other cases, we will
-        // just use per-character system fallback.
-        if (fontSelector) {
-            // Try the user's preferred standard font.
-            if (RefPtr<FontData> data = fontSelector->getFontData(description, standardFamily))
-                return data.release();
-        }
-        // Still no result.  Hand back our last resort fallback font.
-        result = lastResortFallbackFont(description);
-    }
-    return result.release();
-}
-
 static HashSet<FontSelector*>* gClients;
 
 void FontCache::addClient(FontSelector* client)
@@ -581,4 +539,11 @@ void FontCache::invalidate()
     purgeInactiveFontData();
 }
 
+#if !PLATFORM(COCOA)
+RefPtr<SimpleFontData> FontCache::similarFontPlatformData(const FontDescription&)
+{
+    return nullptr;
+}
+#endif
+
 } // namespace WebCore
index 5f83243..dc34f47 100644 (file)
@@ -52,7 +52,6 @@ namespace WebCore {
 
 class Font;
 class FontPlatformData;
-class FontData;
 class FontSelector;
 class OpenTypeVerticalData;
 class SimpleFontData;
@@ -111,8 +110,6 @@ class FontCache {
 public:
     friend FontCache& fontCache();
 
-    RefPtr<FontData> fontForFamilyAtIndex(const FontDescription&, int& familyIndex, FontSelector*);
-
     // This method is implemented by the platform.
     RefPtr<SimpleFontData> systemFallbackForCharacters(const FontDescription&, const SimpleFontData* originalFontData, bool isPlatformFont, const UChar* characters, int length);
 
@@ -133,6 +130,8 @@ public:
 
     WEBCORE_EXPORT RefPtr<SimpleFontData> fontForFamily(const FontDescription&, const AtomicString&, bool checkingAlternateName = false);
     WEBCORE_EXPORT Ref<SimpleFontData> lastResortFallbackFont(const FontDescription&);
+    WEBCORE_EXPORT Ref<SimpleFontData> fontForPlatformData(const FontPlatformData&);
+    RefPtr<SimpleFontData> similarFontPlatformData(const FontDescription&);
 
     void addClient(FontSelector*);
     void removeClient(FontSelector*);
@@ -183,11 +182,6 @@ private:
     PassRefPtr<SimpleFontData> getSystemFontFallbackForCharacters(const FontDescription&, const SimpleFontData*, const UChar* characters, int length);
 #endif
     std::unique_ptr<FontPlatformData> createFontPlatformData(const FontDescription&, const AtomicString& family);
-#if PLATFORM(COCOA)
-    PassRefPtr<SimpleFontData> similarFontPlatformData(const FontDescription&);
-#endif
-
-    WEBCORE_EXPORT Ref<SimpleFontData> fontForPlatformData(const FontPlatformData&);
 
     // Don't purge if this count is > 0;
     int m_purgePreventCount;
@@ -196,7 +190,6 @@ private:
     friend class ComplexTextController;
 #endif
     friend class SimpleFontData;
-    friend class FontGlyphs;
 };
 
 // Get the global fontCache.
index dd90cba..3b239fb 100644 (file)
@@ -41,11 +41,7 @@ FontGlyphs::FontGlyphs(PassRefPtr<FontSelector> fontSelector)
     : m_cachedPrimarySimpleFontData(0)
     , m_fontSelector(fontSelector)
     , m_fontSelectorVersion(m_fontSelector ? m_fontSelector->version() : 0)
-    , m_familyIndex(0)
     , m_generation(fontCache().generation())
-    , m_pitch(UnknownPitch)
-    , m_loadingCustomFonts(false)
-    , m_isForPlatformFont(false)
 {
 }
 
@@ -53,10 +49,7 @@ FontGlyphs::FontGlyphs(const FontPlatformData& platformData)
     : m_cachedPrimarySimpleFontData(0)
     , m_fontSelector(0)
     , m_fontSelectorVersion(0)
-    , m_familyIndex(cAllFamiliesScanned)
     , m_generation(fontCache().generation())
-    , m_pitch(UnknownPitch)
-    , m_loadingCustomFonts(false)
     , m_isForPlatformFont(true)
 {
     m_realizedFontData.append(fontCache().fontForPlatformData(platformData));
@@ -81,40 +74,72 @@ void FontGlyphs::determinePitch(const FontDescription& description)
     }
 }
 
-const FontData* FontGlyphs::realizeFontDataAt(const FontDescription& description, unsigned realizedFontIndex)
+bool FontGlyphs::isLoadingCustomFonts() const
 {
-    if (realizedFontIndex < m_realizedFontData.size())
-        return m_realizedFontData[realizedFontIndex].get(); // This fallback font is already in our list.
+    for (auto& font : m_realizedFontData) {
+        if (font->isLoading())
+            return true;
+    }
+    return false;
+}
 
-    // Make sure we're not passing in some crazy value here.
-    ASSERT(realizedFontIndex == m_realizedFontData.size());
+static RefPtr<FontData> realizeNextFamily(const FontDescription& description, unsigned& index, FontSelector* fontSelector)
+{
+    ASSERT(index < description.familyCount());
 
-    if (m_familyIndex <= cAllFamiliesScanned) {
-        if (!m_fontSelector)
-            return 0;
+    while (index < description.familyCount()) {
+        const AtomicString& family = description.familyAt(index++);
+        if (family.isEmpty())
+            continue;
+        if (fontSelector) {
+            if (auto font = fontSelector->getFontData(description, family))
+                return font;
+        }
+        if (auto font = fontCache().fontForFamily(description, family))
+            return font;
+    }
+    // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform.
+    // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
+    // Geeza Pro font.
+    return fontCache().similarFontPlatformData(description);
+}
 
-        size_t index = cAllFamiliesScanned - m_familyIndex;
-        if (index == m_fontSelector->fallbackFontDataCount())
-            return 0;
+const FontData* FontGlyphs::realizeFontDataAt(const FontDescription& description, unsigned index)
+{
+    if (index < m_realizedFontData.size())
+        return &m_realizedFontData[index].get();
 
-        m_familyIndex--;
-        RefPtr<FontData> fallback = m_fontSelector->getFallbackFontData(description, index);
-        if (fallback)
-            m_realizedFontData.append(fallback);
-        return fallback.get();
+    ASSERT(index == m_realizedFontData.size());
+    ASSERT(fontCache().generation() == m_generation);
+
+    if (!index) {
+        RefPtr<FontData> result = realizeNextFamily(description, m_lastRealizedFamilyIndex, m_fontSelector.get());
+        if (!result && m_fontSelector)
+            result = m_fontSelector->getFontData(description, standardFamily);
+        if (!result)
+            result = fontCache().lastResortFallbackFont(description);
+
+        m_realizedFontData.append(*result);
+        return result.get();
     }
 
-    // Ask the font cache for the font data.
-    // We are obtaining this font for the first time. We keep track of the families we've looked at before
-    // in |m_familyIndex|, so that we never scan the same spot in the list twice. fontForFamilyAtIndex will adjust our
-    // |m_familyIndex| as it scans for the right font to make.
-    ASSERT(fontCache().generation() == m_generation);
-    RefPtr<FontData> result = fontCache().fontForFamilyAtIndex(description, m_familyIndex, m_fontSelector.get());
-    if (result) {
-        m_realizedFontData.append(result);
-        if (result->isLoading())
-            m_loadingCustomFonts = true;
+    RefPtr<FontData> result;
+    if (m_lastRealizedFamilyIndex < description.familyCount())
+        result = realizeNextFamily(description, m_lastRealizedFamilyIndex, m_fontSelector.get());
+
+    if (!result && m_fontSelector) {
+        ASSERT(m_lastRealizedFamilyIndex >= description.familyCount());
+
+        unsigned fontSelectorFallbackIndex = m_lastRealizedFamilyIndex - description.familyCount();
+        if (fontSelectorFallbackIndex == m_fontSelector->fallbackFontDataCount())
+            return nullptr;
+        ++m_lastRealizedFamilyIndex;
+        result = m_fontSelector->getFallbackFontData(description, fontSelectorFallbackIndex);
     }
+    if (!result)
+        return nullptr;
+
+    m_realizedFontData.append(*result);
     return result.get();
 }
 
@@ -268,13 +293,9 @@ GlyphData FontGlyphs::glyphDataForSystemFallback(UChar32 c, const FontDescriptio
     return fallbackGlyphData;
 }
 
-GlyphData FontGlyphs::glyphDataForVariant(UChar32 c, const FontDescription& description, FontDataVariant variant, unsigned fallbackLevel)
+GlyphData FontGlyphs::glyphDataForVariant(UChar32 c, const FontDescription& description, FontDataVariant variant, unsigned fallbackIndex)
 {
-    for (; fallbackLevel <= description.familyCount(); ++fallbackLevel) {
-        auto* fontData = realizeFontDataAt(description, fallbackLevel);
-        if (!fontData)
-            break;
-
+    while (auto* fontData = realizeFontDataAt(description, fallbackIndex++)) {
         auto* simpleFontData = fontData->simpleFontDataForCharacter(c);
         GlyphData data = simpleFontData ? simpleFontData->glyphDataForCharacter(c) : GlyphData();
         if (data.fontData) {
@@ -295,10 +316,7 @@ GlyphData FontGlyphs::glyphDataForNormalVariant(UChar32 c, const FontDescription
 {
     const unsigned pageNumber = c / GlyphPage::size;
 
-    for (unsigned fallbackLevel = 0; fallbackLevel <= description.familyCount(); ++fallbackLevel) {
-        auto* fontData = realizeFontDataAt(description, fallbackLevel);
-        if (!fontData)
-            break;
+    for (unsigned fallbackIndex = 0; auto* fontData = realizeFontDataAt(description, fallbackIndex); ++fallbackIndex) {
         auto* simpleFontData = fontData->simpleFontDataForCharacter(c);
         auto* page = simpleFontData ? simpleFontData->glyphPage(pageNumber) : nullptr;
         if (!page)
@@ -312,7 +330,7 @@ GlyphData FontGlyphs::glyphDataForNormalVariant(UChar32 c, const FontDescription
                 if (!data.fontData->hasVerticalGlyphs()) {
                     // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
                     // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
-                    return glyphDataForVariant(c, description, BrokenIdeographVariant, fallbackLevel);
+                    return glyphDataForVariant(c, description, BrokenIdeographVariant, fallbackIndex);
                 }
 #if PLATFORM(COCOA)
                 if (data.fontData->platformData().syntheticOblique())
index 16e78ba..0e329bf 100644 (file)
@@ -40,8 +40,6 @@ class FontDescription;
 class FontPlatformData;
 class FontSelector;
 
-const int cAllFamiliesScanned = -1;
-
 class FontGlyphs : public RefCounted<FontGlyphs> {
     WTF_MAKE_NONCOPYABLE(FontGlyphs);
 public:
@@ -57,7 +55,7 @@ public:
     bool isFixedPitch(const FontDescription&);
     void determinePitch(const FontDescription&);
 
-    bool loadingCustomFonts() const { return m_loadingCustomFonts; }
+    bool isLoadingCustomFonts() const;
 
     FontSelector* fontSelector() { return m_fontSelector.get(); }
     // FIXME: It should be possible to combine fontSelectorVersion and generation.
@@ -76,9 +74,9 @@ private:
 
     GlyphData glyphDataForSystemFallback(UChar32, const FontDescription&, FontDataVariant);
     GlyphData glyphDataForNormalVariant(UChar32, const FontDescription&);
-    GlyphData glyphDataForVariant(UChar32, const FontDescription&, FontDataVariant, unsigned fallbackLevel);
-    
-    Vector<RefPtr<FontData>, 1> m_realizedFontData;
+    GlyphData glyphDataForVariant(UChar32, const FontDescription&, FontDataVariant, unsigned fallbackIndex);
+
+    Vector<Ref<FontData>, 1> m_realizedFontData;
 
     RefPtr<GlyphPage> m_cachedPageZero;
     HashMap<int, RefPtr<GlyphPage>> m_cachedPages;
@@ -89,11 +87,10 @@ private:
     RefPtr<FontSelector> m_fontSelector;
     WidthCache m_widthCache;
     unsigned m_fontSelectorVersion;
-    int m_familyIndex;
     unsigned short m_generation;
-    unsigned m_pitch : 3; // Pitch
-    unsigned m_loadingCustomFonts : 1;
-    unsigned m_isForPlatformFont : 1;
+    unsigned m_lastRealizedFamilyIndex { 0 };
+    Pitch m_pitch { UnknownPitch };
+    bool m_isForPlatformFont { false };
 };
 
 inline bool FontGlyphs::isFixedPitch(const FontDescription& description)
index a4c3403..825eed1 100644 (file)
@@ -292,7 +292,7 @@ void CairoGlyphToPathTranslator::advance()
 
 DashArray Font::dashesForIntersectionsWithRect(const TextRun& run, const FloatPoint& textOrigin, const FloatRect& lineExtents) const
 {
-    if (loadingCustomFonts())
+    if (isLoadingCustomFonts())
         return DashArray();
 
     GlyphBuffer glyphBuffer;
index ba17a3c..930cf0e 100644 (file)
@@ -446,7 +446,7 @@ RefPtr<SimpleFontData> FontCache::systemFallbackForCharacters(const FontDescript
     return lastResortFallbackFont(description);
 }
 
-PassRefPtr<SimpleFontData> FontCache::similarFontPlatformData(const FontDescription& description)
+RefPtr<SimpleFontData> FontCache::similarFontPlatformData(const FontDescription& description)
 {
     // Attempt to find an appropriate font using a match based on the presence of keywords in
     // the requested names. For example, we'll match any name that contains "Arabic" to Geeza Pro.
index 059c450..646dacc 100644 (file)
@@ -405,7 +405,7 @@ RefPtr<SimpleFontData> FontCache::systemFallbackForCharacters(const FontDescript
     return fontForPlatformData(alternateFont);
 }
 
-PassRefPtr<SimpleFontData> FontCache::similarFontPlatformData(const FontDescription& description)
+RefPtr<SimpleFontData> FontCache::similarFontPlatformData(const FontDescription& description)
 {
     // Attempt to find an appropriate font using a match based on 
     // the presence of keywords in the the requested names.  For example, we'll
index ded20a9..fa11790 100644 (file)
@@ -528,7 +528,7 @@ void MacGlyphToPathTranslator::advance()
 
 DashArray Font::dashesForIntersectionsWithRect(const TextRun& run, const FloatPoint& textOrigin, const FloatRect& lineExtents) const
 {
-    if (loadingCustomFonts())
+    if (isLoadingCustomFonts())
         return DashArray();
 
     GlyphBuffer glyphBuffer;