From c549649b5d83c1dd80e5acc03f8a7c7643ab4103 Mon Sep 17 00:00:00 2001 From: "antti@apple.com" Date: Fri, 9 Jan 2015 19:33:40 +0000 Subject: [PATCH] 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): git-svn-id: https://svn.webkit.org/repository/webkit/trunk@178180 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 53 +++++++++++ Source/WebCore/platform/graphics/Font.cpp | 13 ++- Source/WebCore/platform/graphics/Font.h | 5 +- Source/WebCore/platform/graphics/FontCache.cpp | 49 ++-------- Source/WebCore/platform/graphics/FontCache.h | 11 +-- Source/WebCore/platform/graphics/FontGlyphs.cpp | 106 ++++++++++++--------- Source/WebCore/platform/graphics/FontGlyphs.h | 17 ++-- .../WebCore/platform/graphics/cairo/FontCairo.cpp | 2 +- .../WebCore/platform/graphics/ios/FontCacheIOS.mm | 2 +- .../WebCore/platform/graphics/mac/FontCacheMac.mm | 2 +- Source/WebCore/platform/graphics/mac/FontMac.mm | 2 +- 11 files changed, 144 insertions(+), 118 deletions(-) diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 552eade..7054cab 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,56 @@ +2015-01-09 Antti Koivisto + + 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 REGRESSION(r177925): It broke the !ENABLE(INSPECTOR) build diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp index 40615e1..edd9850 100644 --- a/Source/WebCore/platform/graphics/Font.cpp +++ b/Source/WebCore/platform/graphics/Font.cpp @@ -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) { diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index 16ff611..212b555 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -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 { diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp index d578c80..e1fc78a 100644 --- a/Source/WebCore/platform/graphics/FontCache.cpp +++ b/Source/WebCore/platform/graphics/FontCache.cpp @@ -490,48 +490,6 @@ size_t FontCache::inactiveFontDataCount() return count; } -RefPtr FontCache::fontForFamilyAtIndex(const FontDescription& description, int& familyIndex, FontSelector* fontSelector) -{ - ASSERT(familyIndex != cAllFamiliesScanned); - RefPtr 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 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* gClients; void FontCache::addClient(FontSelector* client) @@ -581,4 +539,11 @@ void FontCache::invalidate() purgeInactiveFontData(); } +#if !PLATFORM(COCOA) +RefPtr FontCache::similarFontPlatformData(const FontDescription&) +{ + return nullptr; +} +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/FontCache.h b/Source/WebCore/platform/graphics/FontCache.h index 5f83243..dc34f47 100644 --- a/Source/WebCore/platform/graphics/FontCache.h +++ b/Source/WebCore/platform/graphics/FontCache.h @@ -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 fontForFamilyAtIndex(const FontDescription&, int& familyIndex, FontSelector*); - // This method is implemented by the platform. RefPtr systemFallbackForCharacters(const FontDescription&, const SimpleFontData* originalFontData, bool isPlatformFont, const UChar* characters, int length); @@ -133,6 +130,8 @@ public: WEBCORE_EXPORT RefPtr fontForFamily(const FontDescription&, const AtomicString&, bool checkingAlternateName = false); WEBCORE_EXPORT Ref lastResortFallbackFont(const FontDescription&); + WEBCORE_EXPORT Ref fontForPlatformData(const FontPlatformData&); + RefPtr similarFontPlatformData(const FontDescription&); void addClient(FontSelector*); void removeClient(FontSelector*); @@ -183,11 +182,6 @@ private: PassRefPtr getSystemFontFallbackForCharacters(const FontDescription&, const SimpleFontData*, const UChar* characters, int length); #endif std::unique_ptr createFontPlatformData(const FontDescription&, const AtomicString& family); -#if PLATFORM(COCOA) - PassRefPtr similarFontPlatformData(const FontDescription&); -#endif - - WEBCORE_EXPORT Ref 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. diff --git a/Source/WebCore/platform/graphics/FontGlyphs.cpp b/Source/WebCore/platform/graphics/FontGlyphs.cpp index dd90cba..3b239fb 100644 --- a/Source/WebCore/platform/graphics/FontGlyphs.cpp +++ b/Source/WebCore/platform/graphics/FontGlyphs.cpp @@ -41,11 +41,7 @@ FontGlyphs::FontGlyphs(PassRefPtr 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 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 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 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 result = fontCache().fontForFamilyAtIndex(description, m_familyIndex, m_fontSelector.get()); - if (result) { - m_realizedFontData.append(result); - if (result->isLoading()) - m_loadingCustomFonts = true; + RefPtr 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()) diff --git a/Source/WebCore/platform/graphics/FontGlyphs.h b/Source/WebCore/platform/graphics/FontGlyphs.h index 16e78ba..0e329bf 100644 --- a/Source/WebCore/platform/graphics/FontGlyphs.h +++ b/Source/WebCore/platform/graphics/FontGlyphs.h @@ -40,8 +40,6 @@ class FontDescription; class FontPlatformData; class FontSelector; -const int cAllFamiliesScanned = -1; - class FontGlyphs : public RefCounted { 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, 1> m_realizedFontData; + GlyphData glyphDataForVariant(UChar32, const FontDescription&, FontDataVariant, unsigned fallbackIndex); + + Vector, 1> m_realizedFontData; RefPtr m_cachedPageZero; HashMap> m_cachedPages; @@ -89,11 +87,10 @@ private: RefPtr 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) diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp index a4c3403..825eed1 100644 --- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -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; diff --git a/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm b/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm index ba17a3c..930cf0e 100644 --- a/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm +++ b/Source/WebCore/platform/graphics/ios/FontCacheIOS.mm @@ -446,7 +446,7 @@ RefPtr FontCache::systemFallbackForCharacters(const FontDescript return lastResortFallbackFont(description); } -PassRefPtr FontCache::similarFontPlatformData(const FontDescription& description) +RefPtr 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. diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm index 059c450..646dacc 100644 --- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -405,7 +405,7 @@ RefPtr FontCache::systemFallbackForCharacters(const FontDescript return fontForPlatformData(alternateFont); } -PassRefPtr FontCache::similarFontPlatformData(const FontDescription& description) +RefPtr 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 diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index ded20a9..fa11790 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -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; -- 1.8.3.1