summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/CSSSegmentedFontFace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/CSSSegmentedFontFace.cpp')
-rw-r--r--Source/WebCore/css/CSSSegmentedFontFace.cpp190
1 files changed, 69 insertions, 121 deletions
diff --git a/Source/WebCore/css/CSSSegmentedFontFace.cpp b/Source/WebCore/css/CSSSegmentedFontFace.cpp
index f32832cc5..621344163 100644
--- a/Source/WebCore/css/CSSSegmentedFontFace.cpp
+++ b/Source/WebCore/css/CSSSegmentedFontFace.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -30,159 +30,107 @@
#include "CSSFontFaceSource.h"
#include "CSSFontSelector.h"
#include "Document.h"
+#include "Font.h"
+#include "FontCache.h"
#include "FontDescription.h"
#include "RuntimeEnabledFeatures.h"
-#include "SegmentedFontData.h"
-#include "SimpleFontData.h"
namespace WebCore {
-CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector)
- : m_fontSelector(fontSelector)
+CSSSegmentedFontFace::CSSSegmentedFontFace()
{
}
CSSSegmentedFontFace::~CSSSegmentedFontFace()
{
- pruneTable();
- unsigned size = m_fontFaces.size();
- for (unsigned i = 0; i < size; i++)
- m_fontFaces[i]->removedFromSegmentedFontFace(this);
+ for (auto& face : m_fontFaces)
+ face->removeClient(*this);
}
-void CSSSegmentedFontFace::pruneTable()
+void CSSSegmentedFontFace::appendFontFace(Ref<CSSFontFace>&& fontFace)
{
- // Make sure the glyph page tree prunes out all uses of this custom font.
- if (m_fontDataTable.isEmpty())
- return;
-
- m_fontDataTable.clear();
+ m_cache.clear();
+ fontFace->addClient(*this);
+ m_fontFaces.append(WTFMove(fontFace));
}
-bool CSSSegmentedFontFace::isValid() const
+void CSSSegmentedFontFace::fontLoaded(CSSFontFace&)
{
- // Valid if at least one font face is valid.
- unsigned size = m_fontFaces.size();
- for (unsigned i = 0; i < size; i++) {
- if (m_fontFaces[i]->isValid())
- return true;
- }
- return false;
+ m_cache.clear();
}
-void CSSSegmentedFontFace::fontLoaded(CSSFontFace*)
-{
- pruneTable();
-
-#if ENABLE(FONT_LOAD_EVENTS)
- if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && !isLoading()) {
- Vector<RefPtr<LoadFontCallback>> callbacks;
- m_callbacks.swap(callbacks);
- for (size_t index = 0; index < callbacks.size(); ++index) {
- if (checkFont())
- callbacks[index]->notifyLoaded();
- else
- callbacks[index]->notifyError();
- }
+class CSSFontAccessor final : public FontAccessor {
+public:
+ static Ref<CSSFontAccessor> create(CSSFontFace& fontFace, const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
+ {
+ return adoptRef(*new CSSFontAccessor(fontFace, fontDescription, syntheticBold, syntheticItalic));
}
-#endif
-}
-void CSSSegmentedFontFace::appendFontFace(PassRefPtr<CSSFontFace> fontFace)
-{
- pruneTable();
- fontFace->addedToSegmentedFontFace(this);
- m_fontFaces.append(fontFace);
-}
-
-static void appendFontDataWithInvalidUnicodeRangeIfLoading(SegmentedFontData* newFontData, PassRefPtr<SimpleFontData> prpFaceFontData, const Vector<CSSFontFace::UnicodeRange>& ranges)
-{
- RefPtr<SimpleFontData> faceFontData = prpFaceFontData;
- if (faceFontData->isLoading()) {
- newFontData->appendRange(FontDataRange(0, 0, faceFontData));
- return;
+ const Font* font() const final
+ {
+ if (!m_result)
+ m_result = m_fontFace->font(m_fontDescription, m_syntheticBold, m_syntheticItalic);
+ return m_result.value().get();
}
- unsigned numRanges = ranges.size();
- if (!numRanges) {
- newFontData->appendRange(FontDataRange(0, 0x7FFFFFFF, faceFontData));
- return;
+private:
+ CSSFontAccessor(CSSFontFace& fontFace, const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
+ : m_fontFace(fontFace)
+ , m_fontDescription(fontDescription)
+ , m_syntheticBold(syntheticBold)
+ , m_syntheticItalic(syntheticItalic)
+ {
}
- for (unsigned j = 0; j < numRanges; ++j)
- newFontData->appendRange(FontDataRange(ranges[j].from(), ranges[j].to(), faceFontData));
-}
-
-PassRefPtr<FontData> CSSSegmentedFontFace::getFontData(const FontDescription& fontDescription)
-{
- if (!isValid())
- return 0;
-
- FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
- unsigned hashKey = ((fontDescription.computedPixelSize() + 1) << (FontTraitsMaskWidth + FontWidthVariantWidth + 1))
- | ((fontDescription.orientation() == Vertical ? 1 : 0) << (FontTraitsMaskWidth + FontWidthVariantWidth))
- | fontDescription.widthVariant() << FontTraitsMaskWidth
- | desiredTraitsMask;
-
- RefPtr<SegmentedFontData>& fontData = m_fontDataTable.add(hashKey, nullptr).iterator->value;
- if (fontData && fontData->numRanges())
- return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has.
-
- if (!fontData)
- fontData = SegmentedFontData::create();
-
- unsigned size = m_fontFaces.size();
- for (unsigned i = 0; i < size; i++) {
- if (!m_fontFaces[i]->isValid())
- continue;
- FontTraitsMask traitsMask = m_fontFaces[i]->traitsMask();
- bool syntheticBold = !(traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask));
- bool syntheticItalic = !(traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask);
- if (RefPtr<SimpleFontData> faceFontData = m_fontFaces[i]->getFontData(fontDescription, syntheticBold, syntheticItalic)) {
- ASSERT(!faceFontData->isSegmented());
- appendFontDataWithInvalidUnicodeRangeIfLoading(fontData.get(), faceFontData.release(), m_fontFaces[i]->ranges());
- }
+ bool isLoading() const final
+ {
+ return m_result && m_result.value() && m_result.value()->isLoading();
}
- if (fontData->numRanges())
- return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has.
- return 0;
-}
+ mutable std::optional<RefPtr<Font>> m_result; // Caches nullptr too
+ mutable Ref<CSSFontFace> m_fontFace;
+ FontDescription m_fontDescription;
+ bool m_syntheticBold;
+ bool m_syntheticItalic;
+};
-#if ENABLE(FONT_LOAD_EVENTS)
-bool CSSSegmentedFontFace::isLoading() const
+static void appendFont(FontRanges& ranges, Ref<FontAccessor>&& fontAccessor, const Vector<CSSFontFace::UnicodeRange>& unicodeRanges)
{
- unsigned size = m_fontFaces.size();
- for (unsigned i = 0; i < size; i++) {
- if (m_fontFaces[i]->loadState() == CSSFontFace::Loading)
- return true;
+ if (unicodeRanges.isEmpty()) {
+ ranges.appendRange({ 0, 0x7FFFFFFF, WTFMove(fontAccessor) });
+ return;
}
- return false;
-}
-bool CSSSegmentedFontFace::checkFont() const
-{
- unsigned size = m_fontFaces.size();
- for (unsigned i = 0; i < size; i++) {
- if (m_fontFaces[i]->loadState() != CSSFontFace::Loaded)
- return false;
- }
- return true;
+ for (auto& range : unicodeRanges)
+ ranges.appendRange({ range.from, range.to, fontAccessor.copyRef() });
}
-void CSSSegmentedFontFace::loadFont(const FontDescription& fontDescription, PassRefPtr<LoadFontCallback> callback)
+FontRanges CSSSegmentedFontFace::fontRanges(const FontDescription& fontDescription)
{
- getFontData(fontDescription); // Kick off the load.
-
- if (callback) {
- if (isLoading())
- m_callbacks.append(callback);
- else if (checkFont())
- callback->notifyLoaded();
- else
- callback->notifyError();
+ FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
+
+ auto addResult = m_cache.add(FontDescriptionKey(fontDescription), FontRanges());
+ auto& result = addResult.iterator->value;
+
+ if (addResult.isNewEntry) {
+ for (auto& face : m_fontFaces) {
+ if (face->allSourcesFailed())
+ continue;
+
+ FontTraitsMask traitsMask = face->traitsMask();
+ bool syntheticBold = (fontDescription.fontSynthesis() & FontSynthesisWeight) && !(traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask));
+ bool syntheticItalic = (fontDescription.fontSynthesis() & FontSynthesisStyle) && !(traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask);
+
+ // This doesn't trigger an unnecessary download because every element styled with this family will need font metrics in order to run layout.
+ // Metrics used for layout come from FontRanges::fontForFirstRange(), which assumes that the first font is non-null.
+ // We're kicking off this necessary first download now.
+ auto fontAccessor = CSSFontAccessor::create(face, fontDescription, syntheticBold, syntheticItalic);
+ if (result.isNull() && !fontAccessor->font())
+ continue;
+ appendFont(result, WTFMove(fontAccessor), face->ranges());
+ }
}
+ return result;
}
-#endif
}