source: webkit/trunk/Source/WebCore/css/CSSFontFace.cpp

Last change on this file was 290026, checked in by Chris Dumez, 3 years ago

Clean up / optimize call sites constructing vectors
https://bugs.webkit.org/show_bug.cgi?id=236748

Reviewed by Dean Jackson.

Clean up / optimize call sites constructing vectors:

  • Use Vector::map() / WTF::map() where appropriate

Source/JavaScriptCore:

  • Replace Vector::reserveCapacity() with Vector::reserveInitialCapacity() where appropriate
  • Replace Vector::append() with Vector::uncheckedAppend() where appropriate
  • Leverage the fact that Vector<Ref<Foo>> is now copyable (Because Ref<> now has a copy constructor)
  • Call crossThreadCopy() to isolate-copy a Vector() without iterating.
  • Leverage Vector constructor that takes in an intialization list in more cases
  • Leverage Vector::from() in more cases to simplify vector construction in some case.
  • Drop unnecessary calls to Vector::reserve*Capacity() before calling Vector::append(T*, size_t) since the append() implementation already does this for us.
  • Leverage copyToVector() and copyToVectorOf<> in more cases
  • Call shrinkToFit() in some cases where we reserve capacity and then append() but may not append() as much as we reserved.
  • b3/air/AirCode.cpp:

(JSC::B3::Air::Code::setNumEntrypoints):

  • bytecompiler/NodesCodegen.cpp:

(JSC::ArrayPatternNode::emitDirectBinding):

  • dfg/DFGInPlaceAbstractState.cpp:

(JSC::DFG::setLiveValues):

  • dfg/DFGLivenessAnalysisPhase.cpp:
  • dfg/DFGScoreBoard.h:

(JSC::DFG::ScoreBoard::ScoreBoard):

  • inspector/agents/InspectorDebuggerAgent.cpp:

(Inspector::parseBreakpointOptions):

  • inspector/remote/socket/RemoteInspectorMessageParser.cpp:

(Inspector::MessageParser::pushReceivedData):

  • parser/VariableEnvironment.cpp:

(JSC::CompactTDZEnvironment::CompactTDZEnvironment):

  • wasm/WasmWorklist.cpp:

(JSC::Wasm::Worklist::Worklist):

Source/WebCore:

  • Replace Vector::reserveCapacity() with Vector::reserveInitialCapacity() where appropriate
  • Replace Vector::append() with Vector::uncheckedAppend() where appropriate
  • Leverage the fact that Vector<Ref<Foo>> is now copyable (Because Ref<> now has a copy constructor)
  • Call crossThreadCopy() to isolate-copy a Vector() without iterating.
  • Leverage Vector constructor that takes in an intialization list in more cases
  • Leverage Vector::from() in more cases to simplify vector construction in some case.
  • Drop unnecessary calls to Vector::reserve*Capacity() before calling Vector::append(T*, size_t) since the append() implementation already does this for us.
  • Leverage copyToVector() and copyToVectorOf<> in more cases
  • Call shrinkToFit() in some cases where we reserve capacity and then append() but may not append() as much as we reserved.
  • Modules/async-clipboard/Clipboard.cpp:

(WebCore::Clipboard::read):
(WebCore::Clipboard::ItemWriter::didSetAllData):

  • Modules/encryptedmedia/MediaKeySession.cpp:

(WebCore::MediaKeySession::updateKeyStatuses):

  • Modules/entriesapi/FileSystemEntriesCallback.cpp:

(WebCore::FileSystemEntriesCallback::scheduleCallback):
(WebCore::copyVector): Deleted.

  • Modules/entriesapi/HTMLInputElementEntriesAPI.cpp:

(WebCore::HTMLInputElementEntriesAPI::webkitEntries):

  • Modules/geolocation/GeolocationController.cpp:

(WebCore::GeolocationController::positionChanged):
(WebCore::GeolocationController::errorOccurred):

  • Modules/indexeddb/IDBDatabase.cpp:

(WebCore::IDBDatabase::stop):

  • Modules/indexeddb/IDBGetAllResult.cpp:

(WebCore::IDBGetAllResult::isolatedCopy):

  • Modules/indexeddb/IDBGetResult.cpp:

(WebCore::IDBGetResult::isolatedCopy):

  • Modules/indexeddb/IDBKeyPath.cpp:

(WebCore::isolatedCopy): Deleted.

  • Modules/indexeddb/IDBKeyPath.h:

(WebCore::isolatedCopy): Deleted.

  • Modules/indexeddb/IDBTransaction.cpp:

(WebCore::IDBTransaction::abortInProgressOperations):

  • Modules/indexeddb/client/IDBConnectionProxy.cpp:

(WebCore::IDBClient::removeItemsMatchingCurrentThread):

  • Modules/indexeddb/server/MemoryObjectStore.cpp:

(WebCore::IDBServer::MemoryObjectStore::deleteAllIndexes):

  • Modules/indexeddb/server/SQLiteIDBCursor.cpp:

(WebCore::IDBServer::SQLiteIDBCursor::currentData):

  • Modules/indexeddb/shared/IDBDatabaseInfo.cpp:

(WebCore::IDBDatabaseInfo::objectStoreNames const):

  • Modules/indexeddb/shared/IDBIndexInfo.cpp:

(WebCore::IDBIndexInfo::isolatedCopy const):

  • Modules/indexeddb/shared/IDBObjectStoreInfo.cpp:

(WebCore::IDBObjectStoreInfo::isolatedCopy const):
(WebCore::IDBObjectStoreInfo::indexNames const):

  • Modules/indexeddb/shared/IDBTransactionInfo.cpp:

(WebCore::IDBTransactionInfo::isolatedCopy):

  • Modules/indexeddb/shared/IndexKey.cpp:

(WebCore::IndexKey::isolatedCopy const):

  • Modules/mediastream/MediaStream.cpp:

(WebCore::MediaStream::clone):

  • Modules/mediastream/MediaStreamTrack.cpp:

(WebCore::capabilityStringVector):

  • Modules/mediastream/MediaTrackConstraints.cpp:

(WebCore::convertAdvancedToInternalForm):

  • Modules/mediastream/SFrameUtils.cpp:

(WebCore::toRbsp):

  • Modules/remoteplayback/RemotePlayback.cpp:

(WebCore::RemotePlayback::availabilityChanged):

  • Modules/speech/SpeechRecognition.cpp:

(WebCore::SpeechRecognition::didReceiveResult):

  • Modules/webauthn/cbor/CBORValue.cpp:

(cbor::CBORValue::CBORValue):

  • Modules/webauthn/fido/AuthenticatorGetInfoResponse.cpp:

(fido::toArrayValue):

  • Modules/webauthn/fido/DeviceRequestConverter.cpp:

(fido::convertParametersToCBOR):

  • Modules/webauthn/fido/Pin.cpp:

(fido::pin::encodeRawPublicKey):

  • Modules/webdatabase/DatabaseTracker.cpp:

(WebCore::DatabaseTracker::databaseNames):
(WebCore::isolatedCopy): Deleted.

  • accessibility/AXObjectCache.cpp:

(WebCore::AXObjectCache::notificationPostTimerFired):

  • accessibility/isolatedtree/AXIsolatedObject.cpp:

(WebCore::AXIsolatedObject::setMathscripts):
(WebCore::AXIsolatedObject::setObjectVectorProperty):

  • accessibility/isolatedtree/AXIsolatedTree.cpp:

(WebCore::AXIsolatedTree::objectsForIDs const):
(WebCore::AXIsolatedTree::collectNodeChangesForSubtree):

  • animation/CSSPropertyAnimation.cpp:

(WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneDeserializer::readString):
(WebCore::SerializedScriptValue::blobURLs const):

  • crypto/mac/CryptoAlgorithmECDSAMac.cpp:

(WebCore::signECDSA):
(WebCore::verifyECDSA):

  • crypto/mac/CryptoKeyECMac.cpp:

(WebCore::CryptoKeyEC::platformExportSpki const):
(WebCore::CryptoKeyEC::platformExportPkcs8 const):

  • crypto/mac/CryptoKeyRSAMac.cpp:

(WebCore::CryptoKeyRSA::exportSpki const):
(WebCore::CryptoKeyRSA::exportPkcs8 const):

  • css/CSSBasicShapes.cpp:

(WebCore::CSSBasicShapePolygon::cssText const):

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::copyPropertiesInSet):
(WebCore::ComputedStyleExtractor::copyProperties):

  • css/CSSFontFace.cpp:

(WebCore::iterateClients):

  • css/CSSFontFaceSet.cpp:

(WebCore::CSSFontFaceSet::matchingFacesExcludingPreinstalledFonts):
(WebCore::CSSFontFaceSet::fontFace):

  • css/CSSKeyframesRule.cpp:

(WebCore::StyleRuleKeyframes::StyleRuleKeyframes):

  • css/StyleProperties.cpp:

(WebCore::StyleProperties::copyPropertiesInSet const):
(WebCore::DeferredStyleProperties::DeferredStyleProperties):

  • css/StyleRule.cpp:

(WebCore::DeferredStyleGroupRuleList::DeferredStyleGroupRuleList):
(WebCore::StyleRuleGroup::StyleRuleGroup):

  • css/calc/CSSCalcOperationNode.h:
  • css/calc/CSSCalcValue.cpp:

(WebCore::createCSS):

  • display/css/DisplayBoxDecorationPainter.cpp:

(WebCore::Display::BorderPainter::clipBorderSidePolygon const):
(WebCore::Display::BorderPainter::drawLineForBoxSide const):

  • dom/DOMRectList.cpp:

(WebCore::DOMRectList::DOMRectList):

  • dom/Document.cpp:

(WebCore::Document::updateElementsAffectedByMediaQueries):
(WebCore::Document::didAssociateFormControlsTimerFired):

  • dom/ElementData.cpp:

(WebCore::UniqueElementData::UniqueElementData):

  • dom/EventListenerMap.cpp:

(WebCore::EventListenerMap::eventTypes const):

  • dom/TreeScopeOrderedMap.cpp:

(WebCore::TreeScopeOrderedMap::keys const):

  • editing/CompositeEditCommand.cpp:

(WebCore::copyMarkers):

  • editing/Editor.cpp:

(WebCore::editableTextListsAtPositionInDescendingOrder):

  • fileapi/FileList.cpp:

(WebCore::FileList::paths const):

  • history/HistoryItem.cpp:

(WebCore::HistoryItem::HistoryItem):
(WebCore::m_formData):
(WebCore::m_identifier):

  • html/FileInputType.cpp:

(WebCore::FileInputType::setFiles):
(WebCore::FileInputType::filesChosen):

  • html/LinkIconCollector.cpp:

(WebCore::LinkIconCollector::iconsOfTypes):

  • html/URLSearchParams.cpp:

(WebCore::URLSearchParams::getAll const):

  • layout/formattingContexts/inline/InlineLineBuilder.cpp:

(WebCore::Layout::LineBuilder::layoutInlineContent):

  • loader/DocumentLoader.cpp:

(WebCore::DocumentLoader::startIconLoading):
(WebCore::DocumentLoader::setActiveContentRuleListActionPatterns):

  • loader/TextTrackLoader.cpp:

(WebCore::TextTrackLoader::getNewCues):

  • loader/archive/cf/LegacyWebArchive.cpp:

(WebCore::LegacyWebArchive::createFromSelection):

  • page/CaptionUserPreferencesMediaAF.cpp:

(WebCore::CaptionUserPreferencesMediaAF::preferredAudioCharacteristics const):

  • page/DOMWindow.cpp:

(WebCore::DOMWindow::dispatchAllPendingBeforeUnloadEvents):

  • page/IntersectionObserver.cpp:

(WebCore::IntersectionObserver::create):

  • page/Page.cpp:

(WebCore::Page::replaceRangesWithText):

  • page/csp/ContentSecurityPolicy.cpp:

(WebCore::ContentSecurityPolicy::responseHeaders const):

  • page/csp/ContentSecurityPolicyResponseHeaders.cpp:

(WebCore::ContentSecurityPolicyResponseHeaders::isolatedCopy const):

  • page/mac/ImageOverlayControllerMac.mm:

(WebCore::ImageOverlayController::updateDataDetectorHighlights):

  • page/mac/ServicesOverlayController.mm:

(WebCore::ServicesOverlayController::buildSelectionHighlight):
(WebCore::ServicesOverlayController::handleClick):

  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::AsyncScrollingCoordinator::childrenOfNode const):

  • page/scrolling/ScrollSnapOffsetsInfo.cpp:

(WebCore::convertOffsetInfo):

  • platform/Length.cpp:

(WebCore::makeCalculated):

  • platform/animation/AnimationList.cpp:

(WebCore::AnimationList::AnimationList):

  • platform/cocoa/PlaybackSessionModelMediaElement.mm:

(WebCore::PlaybackSessionModelMediaElement::audioMediaSelectionOptions const):

  • platform/encryptedmedia/CDMProxy.cpp:

(WebCore::KeyStore::convertToJSKeyStatusVector const):

  • platform/graphics/FloatPolygon.cpp:

(WebCore::FloatPolygon::overlappingEdges const):

  • platform/graphics/FloatQuad.cpp:

(WebCore::boundingBoxes):

  • platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:

(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense):

  • platform/graphics/ca/TileGrid.cpp:

(WebCore::TileGrid::removeTiles):
(WebCore::TileGrid::removeAllTiles):

  • platform/graphics/ca/TileGrid.h:
  • platform/graphics/cg/ImageUtilitiesCG.cpp:

(WebCore::findImagesForTranscoding):
(WebCore::transcodeImages):

  • platform/graphics/cocoa/FontCacheCoreText.cpp:

(WebCore::findClosestFont):
(WebCore::FontCache::getFontSelectionCapabilitiesInFamily):

  • platform/mediastream/RealtimeMediaSource.cpp:

(WebCore::RealtimeMediaSource::fitnessDistance):

  • platform/network/CacheValidation.cpp:

(WebCore::collectVaryingRequestHeadersInternal):

  • platform/network/FormData.cpp:

(WebCore::FormData::isolatedCopy const):

  • platform/network/SocketStreamHandleImpl.cpp:

(WebCore::SocketStreamHandleImpl::platformSendHandshake):

  • platform/network/cocoa/NetworkStorageSessionCocoa.mm:
  • platform/text/LocaleICU.cpp:

(WebCore::LocaleICU::createLabelVector):
(WebCore::createFallbackMonthLabels):
(WebCore::createFallbackAMPMLabels):

  • platform/text/LocaleNone.cpp:

(WebCore::LocaleNone::monthLabels):
(WebCore::LocaleNone::shortMonthLabels):
(WebCore::LocaleNone::timeAMPMLabels):

  • platform/text/cocoa/LocaleCocoa.mm:

(WebCore::LocaleCocoa::monthLabels):
(WebCore::LocaleCocoa::shortMonthLabels):
(WebCore::LocaleCocoa::standAloneMonthLabels):
(WebCore::LocaleCocoa::shortStandAloneMonthLabels):
(WebCore::LocaleCocoa::timeAMPMLabels):

  • plugins/DOMMimeTypeArray.cpp:

(WebCore::DOMMimeTypeArray::supportedPropertyNames const):
(WebCore::DOMMimeTypeArray::supportedPropertyNames): Deleted.

  • plugins/DOMMimeTypeArray.h:
  • plugins/DOMPlugin.cpp:

(WebCore::makeMimeTypes):
(WebCore::DOMPlugin::supportedPropertyNames const):
(WebCore::DOMPlugin::supportedPropertyNames): Deleted.

  • plugins/DOMPlugin.h:
  • plugins/DOMPluginArray.cpp:

(WebCore::DOMPluginArray::supportedPropertyNames const):
(WebCore::DOMPluginArray::supportedPropertyNames): Deleted.

  • plugins/DOMPluginArray.h:
  • rendering/LayerAncestorClippingStack.cpp:

(WebCore::LayerAncestorClippingStack::LayerAncestorClippingStack):
(WebCore::LayerAncestorClippingStack::compositedClipData const):

  • rendering/RenderBoxModelObject.cpp:

(WebCore::RenderBoxModelObject::clipBorderSidePolygon):

  • rendering/RenderElement.cpp:

(WebCore::RenderElement::drawLineForBoxSide const):

  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::trackSizesForComputedStyle const):

  • style/ClassChangeInvalidation.cpp:

(WebCore::Style::collectClasses):

  • style/StyleBuilderConverter.h:

(WebCore::Style::BuilderConverter::convertTo100PercentMinusLength):

  • testing/MockCDMFactory.cpp:

(WebCore::MockCDMInstanceSession::updateLicense):
(WebCore::MockCDMInstanceSession::removeSessionData):

  • workers/service/server/SWServer.cpp:

(WebCore::SWServer::getRegistrations):

Source/WebKit:

  • Replace Vector::reserveCapacity() with Vector::reserveInitialCapacity() where appropriate
  • Replace Vector::append() with Vector::uncheckedAppend() where appropriate
  • Leverage the fact that Vector<Ref<Foo>> is now copyable (Because Ref<> now has a copy constructor)
  • Call crossThreadCopy() to isolate-copy a Vector() without iterating.
  • Leverage Vector constructor that takes in an intialization list in more cases
  • Leverage Vector::from() in more cases to simplify vector construction in some case.
  • Drop unnecessary calls to Vector::reserve*Capacity() before calling Vector::append(T*, size_t) since the append() implementation already does this for us.
  • Leverage copyToVector() and copyToVectorOf<> in more cases
  • Call shrinkToFit() in some cases where we reserve capacity and then append() but may not append() as much as we reserved.
  • NetworkProcess/WebStorage/LocalStorageDatabaseTracker.cpp:

(WebKit::LocalStorageDatabaseTracker::originDetailsCrossThreadCopy):

  • NetworkProcess/cache/CacheStorageEngineCaches.cpp:

(WebKit::CacheStorage::Caches::cacheInfos):

  • Shared/API/APIArray.cpp:

(API::Array::createStringArray):
(API::Array::copy):

  • Shared/API/APIDictionary.cpp:

(API::Dictionary::keys const):

  • Shared/UserData.cpp:

(WebKit::transformGraph):

  • Shared/WebContextMenuItem.cpp:

(WebKit::WebContextMenuItem::create):
(WebKit::WebContextMenuItem::submenuItemsAsAPIArray const):

  • Shared/WebContextMenuItemData.cpp:

(WebKit::kitItems):
(WebKit::coreItems):

  • UIProcess/API/APIWebAuthenticationPanel.cpp:

(API::WebAuthenticationPanel::WebAuthenticationPanel):

  • UIProcess/API/APIWebsitePolicies.cpp:

(API::WebsitePolicies::copy const):
(API::WebsitePolicies::data):

  • UIProcess/API/C/WKPage.cpp:

(API::toAPIObjectVector):
(WKPageSetPageContextMenuClient):
(WKPageSetPageFindMatchesClient):
(WKPageSetPageLoaderClient):

  • UIProcess/Cocoa/VideoFullscreenManagerProxy.mm:

(WebKit::VideoFullscreenManagerProxy::forEachSession):

  • UIProcess/Gamepad/UIGamepadProvider.cpp:

(WebKit::UIGamepadProvider::snapshotGamepads):

  • UIProcess/Network/NetworkProcessProxy.cpp:

(WebKit::NetworkProcessProxy::allNetworkProcesses):
(WebKit::NetworkProcessProxy::updatePrevalentDomainsToBlockCookiesFor):

  • UIProcess/Notifications/WebNotificationManagerProxy.cpp:

(WebKit::WebNotificationManagerProxy::providerDidRemoveNotificationPolicies):

  • UIProcess/Notifications/WebNotificationProvider.cpp:

(WebKit::WebNotificationProvider::clearNotifications):

  • UIProcess/StatisticsRequest.cpp:

(WebKit::StatisticsRequest::completedRequest):

  • UIProcess/UserContent/WebUserContentControllerProxy.cpp:

(WebKit::WebUserContentControllerProxy::removeAllUserScripts):
(WebKit::WebUserContentControllerProxy::removeAllUserStyleSheets):

  • UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:

(WebKit::WebAuthenticationPanelClient::selectAssertionResponse const):

  • UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:

(WebKit::CtapAuthenticator::continueGetNextAssertionAfterResponseReceived):

  • UIProcess/WebBackForwardList.cpp:

(WebKit::WebBackForwardList::addItem):
(WebKit::WebBackForwardList::clear):
(WebKit::WebBackForwardList::restoreFromState):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::runJavaScriptInFrameInScriptWorld):
(WebKit::WebPageProxy::speechSynthesisVoiceList):

  • UIProcess/WebsiteData/WebsiteDataStore.cpp:

(WebKit::WebsiteDataStore::fetchDataAndApply):
(WebKit::WebsiteDataStore::parametersFromEachWebsiteDataStore):

  • UIProcess/mac/WKTextFinderClient.mm:

(-[WKTextFinderClient replaceMatches:withString:inSelectionOnly:resultCollector:]):

  • WebProcess/GPU/media/RemoteRemoteCommandListener.cpp:

(WebKit::RemoteRemoteCommandListener::updateSupportedCommands):

  • WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:

(contextMenuItems):
(WKBundlePageCopyOriginsWithApplicationCache):

  • WebProcess/InjectedBundle/InjectedBundlePageContextMenuClient.cpp:

(WebKit::InjectedBundlePageContextMenuClient::getCustomMenuFromDefaultItems):

  • WebProcess/InjectedBundle/InjectedBundlePageFormClient.cpp:

(WebKit::InjectedBundlePageFormClient::didAssociateFormControls):

  • WebProcess/Network/WebSocketStream.cpp:

(WebKit::WebSocketStream::networkProcessCrashed):

  • WebProcess/Network/webrtc/WebRTCResolver.cpp:

(WebKit::WebRTCResolver::setResolvedAddress):

  • WebProcess/WebCoreSupport/WebResourceLoadObserver.cpp:

(WebKit::WebResourceLoadObserver::takeStatistics):

  • WebProcess/WebPage/FindController.cpp:

(WebKit::FindController::replaceMatches):

  • WebProcess/WebPage/RemoteLayerTree/PlatformCAAnimationRemote.mm:

(WebKit::toKeyframeValueVector):
(WebKit::PlatformCAAnimationRemote::setValues):
(WebKit::PlatformCAAnimationRemote::setTimingFunctions):

  • WebProcess/WebPage/ViewGestureGeometryCollector.cpp:

(WebKit::ViewGestureGeometryCollector::computeTextLegibilityScales):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::trackedRepaintRects):
(WebKit::dumpHistoryItem):

Source/WTF:

  • Replace Vector::reserveCapacity() with Vector::reserveInitialCapacity() where appropriate
  • Replace Vector::append() with Vector::uncheckedAppend() where appropriate
  • Leverage the fact that Vector<Ref<Foo>> is now copyable (Because Ref<> now has a copy constructor)
  • Call crossThreadCopy() to isolate-copy a Vector() without iterating.
  • Leverage Vector constructor that takes in an intialization list in more cases
  • Leverage Vector::from() in more cases to simplify vector construction in some case.
  • Drop unnecessary calls to Vector::reserve*Capacity() before calling Vector::append(T*, size_t) since the append() implementation already does this for us.
  • Leverage copyToVector() and copyToVectorOf<> in more cases
  • Call shrinkToFit() in some cases where we reserve capacity and then append() but may not append() as much as we reserved.
  • wtf/Language.cpp:

(WTF::userPreferredLanguages):
(WTF::isolatedCopy): Deleted.

  • Property svn:eol-style set to native
File size: 25.5 KB
Line 
1/*
2 * Copyright (C) 2007-2021 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "CSSFontFace.h"
28
29#include "CSSFontFaceSource.h"
30#include "CSSFontFaceSrcValue.h"
31#include "CSSFontFeatureValue.h"
32#include "CSSFontSelector.h"
33#include "CSSFontStyleRangeValue.h"
34#include "CSSPrimitiveValueMappings.h"
35#include "CSSUnicodeRangeValue.h"
36#include "CSSValue.h"
37#include "CSSValueList.h"
38#include "CachedFont.h"
39#include "Document.h"
40#include "Font.h"
41#include "FontCache.h"
42#include "FontDescription.h"
43#include "FontFace.h"
44#include "FontPaletteValues.h"
45#include "Settings.h"
46#include "SharedBuffer.h"
47#include "StyleBuilderConverter.h"
48#include "StyleProperties.h"
49#include "StyleRule.h"
50
51namespace WebCore {
52
53DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(CSSFontFace);
54
55template<typename T> void iterateClients(HashSet<CSSFontFace::Client*>& clients, T callback)
56{
57 for (auto& client : copyToVectorOf<RefPtr<CSSFontFace::Client>>(clients))
58 callback(*client);
59}
60
61void CSSFontFace::appendSources(CSSFontFace& fontFace, CSSValueList& srcList, ScriptExecutionContext* context, bool isInitiatingElementInUserAgentShadowTree)
62{
63 for (auto& src : srcList) {
64 // An item in the list either specifies a string (local font name) or a URL (remote font to download).
65 CSSFontFaceSrcValue& item = downcast<CSSFontFaceSrcValue>(src.get());
66 std::unique_ptr<CSSFontFaceSource> source;
67 SVGFontFaceElement* fontFaceElement = nullptr;
68 bool foundSVGFont = false;
69
70 foundSVGFont = item.isSVGFontFaceSrc() || item.svgFontFaceElement();
71 fontFaceElement = item.svgFontFaceElement();
72 if (!item.isLocal()) {
73 const auto* settings = context ? &context->settingsValues() : nullptr;
74 bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled);
75 if (allowDownloading && item.isSupportedFormat()) {
76 if (auto fontRequest = item.fontLoadRequest(context, foundSVGFont, isInitiatingElementInUserAgentShadowTree))
77 source = makeUnique<CSSFontFaceSource>(fontFace, item.resource(), *context->cssFontSelector(), makeUniqueRefFromNonNullUniquePtr(WTFMove(fontRequest)));
78 }
79 } else
80 source = (fontFaceElement ? makeUnique<CSSFontFaceSource>(fontFace, item.resource(), *fontFaceElement)
81 : makeUnique<CSSFontFaceSource>(fontFace, item.resource()));
82
83 if (source)
84 fontFace.adoptSource(WTFMove(source));
85 }
86 fontFace.sourcesPopulated();
87}
88
89Ref<CSSFontFace> CSSFontFace::create(CSSFontSelector& fontSelector, StyleRuleFontFace* cssConnection, FontFace* wrapper, bool isLocalFallback)
90{
91 auto* context = fontSelector.scriptExecutionContext();
92 const auto* settings = context ? &context->settingsValues() : nullptr;
93 auto result = adoptRef(*new CSSFontFace(settings, cssConnection, wrapper, isLocalFallback));
94 result->addClient(fontSelector);
95 return result;
96}
97
98CSSFontFace::CSSFontFace(const Settings::Values* settings, StyleRuleFontFace* cssConnection, FontFace* wrapper, bool isLocalFallback)
99 : m_cssConnection(cssConnection)
100 , m_wrapper(wrapper)
101 , m_isLocalFallback(isLocalFallback)
102 , m_mayBePurged(!wrapper)
103 , m_shouldIgnoreFontLoadCompletions(settings && settings->shouldIgnoreFontLoadCompletions)
104 , m_fontLoadTimingOverride(settings ? settings->fontLoadTimingOverride : FontLoadTimingOverride::None)
105 , m_allowUserInstalledFonts(settings && !settings->shouldAllowUserInstalledFonts ? AllowUserInstalledFonts::No : AllowUserInstalledFonts::Yes)
106 , m_timeoutTimer(*this, &CSSFontFace::timeoutFired)
107{
108}
109
110CSSFontFace::~CSSFontFace() = default;
111
112bool CSSFontFace::setFamilies(CSSValue& family)
113{
114 if (!is<CSSValueList>(family))
115 return false;
116
117 CSSValueList& familyList = downcast<CSSValueList>(family);
118 if (!familyList.length())
119 return false;
120
121 RefPtr<CSSValueList> oldFamilies = m_families;
122 m_families = &familyList;
123
124 if (m_cssConnection)
125 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontFamily, &family);
126
127 iterateClients(m_clients, [&](Client& client) {
128 client.fontPropertyChanged(*this, oldFamilies.get());
129 });
130
131 return true;
132}
133
134FontFace* CSSFontFace::existingWrapper()
135{
136 return m_wrapper.get();
137}
138
139static FontSelectionRange calculateWeightRange(CSSValue& value)
140{
141 if (value.isValueList()) {
142 auto& valueList = downcast<CSSValueList>(value);
143 ASSERT(valueList.length() == 2);
144 if (valueList.length() != 2)
145 return { normalWeightValue(), normalWeightValue() };
146 ASSERT(valueList.item(0)->isPrimitiveValue());
147 ASSERT(valueList.item(1)->isPrimitiveValue());
148 auto& value0 = downcast<CSSPrimitiveValue>(*valueList.item(0));
149 auto& value1 = downcast<CSSPrimitiveValue>(*valueList.item(1));
150 auto result0 = Style::BuilderConverter::convertFontWeightFromValue(value0);
151 auto result1 = Style::BuilderConverter::convertFontWeightFromValue(value1);
152 return { result0, result1 };
153 }
154
155 ASSERT(is<CSSPrimitiveValue>(value));
156 auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
157 FontSelectionValue result = Style::BuilderConverter::convertFontWeightFromValue(primitiveValue);
158 return { result, result };
159}
160
161void CSSFontFace::setWeight(CSSValue& weight)
162{
163 auto range = calculateWeightRange(weight);
164 if (m_fontSelectionCapabilities.weight == range)
165 return;
166
167 setWeight(range);
168
169 if (m_cssConnection)
170 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontWeight, &weight);
171
172 iterateClients(m_clients, [&](Client& client) {
173 client.fontPropertyChanged(*this);
174 });
175}
176
177static FontSelectionRange calculateStretchRange(CSSValue& value)
178{
179 if (value.isValueList()) {
180 auto& valueList = downcast<CSSValueList>(value);
181 ASSERT(valueList.length() == 2);
182 if (valueList.length() != 2)
183 return { normalStretchValue(), normalStretchValue() };
184 ASSERT(valueList.item(0)->isPrimitiveValue());
185 ASSERT(valueList.item(1)->isPrimitiveValue());
186 auto& value0 = downcast<CSSPrimitiveValue>(*valueList.item(0));
187 auto& value1 = downcast<CSSPrimitiveValue>(*valueList.item(1));
188 auto result0 = Style::BuilderConverter::convertFontStretchFromValue(value0);
189 auto result1 = Style::BuilderConverter::convertFontStretchFromValue(value1);
190 return { result0, result1 };
191 }
192
193 ASSERT(is<CSSPrimitiveValue>(value));
194 const auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
195 FontSelectionValue result = Style::BuilderConverter::convertFontStretchFromValue(primitiveValue);
196 return { result, result };
197}
198
199void CSSFontFace::setStretch(CSSValue& style)
200{
201 auto range = calculateStretchRange(style);
202 if (m_fontSelectionCapabilities.width == range)
203 return;
204
205 setStretch(range);
206
207 if (m_cssConnection)
208 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontStretch, &style);
209
210 iterateClients(m_clients, [&](Client& client) {
211 client.fontPropertyChanged(*this);
212 });
213}
214
215static FontSelectionRange calculateItalicRange(CSSValue& value)
216{
217 if (value.isFontStyleValue()) {
218 auto result = Style::BuilderConverter::convertFontStyleFromValue(value);
219 return { result.value_or(normalItalicValue()), result.value_or(normalItalicValue()) };
220 }
221
222 ASSERT(value.isFontStyleRangeValue());
223 auto& rangeValue = downcast<CSSFontStyleRangeValue>(value);
224 ASSERT(rangeValue.fontStyleValue->isValueID());
225 auto valueID = rangeValue.fontStyleValue->valueID();
226 if (!rangeValue.obliqueValues) {
227 if (valueID == CSSValueNormal)
228 return { normalItalicValue(), normalItalicValue() };
229 ASSERT(valueID == CSSValueItalic || valueID == CSSValueOblique);
230 return { italicValue(), italicValue() };
231 }
232 ASSERT(valueID == CSSValueOblique);
233 auto length = rangeValue.obliqueValues->length();
234 if (length == 1) {
235 auto& primitiveValue = downcast<CSSPrimitiveValue>(*rangeValue.obliqueValues->item(0));
236 FontSelectionValue result(primitiveValue.value<float>(CSSUnitType::CSS_DEG));
237 return { result, result };
238 }
239 ASSERT(length == 2);
240 auto& primitiveValue1 = downcast<CSSPrimitiveValue>(*rangeValue.obliqueValues->item(0));
241 auto& primitiveValue2 = downcast<CSSPrimitiveValue>(*rangeValue.obliqueValues->item(1));
242 FontSelectionValue result1(primitiveValue1.value<float>(CSSUnitType::CSS_DEG));
243 FontSelectionValue result2(primitiveValue2.value<float>(CSSUnitType::CSS_DEG));
244 return { result1, result2 };
245}
246
247void CSSFontFace::setStyle(CSSValue& style)
248{
249 auto range = calculateItalicRange(style);
250 if (m_fontSelectionCapabilities.slope == range)
251 return;
252
253 setStyle(range);
254
255 if (m_cssConnection)
256 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontStyle, &style);
257
258 iterateClients(m_clients, [&](Client& client) {
259 client.fontPropertyChanged(*this);
260 });
261}
262
263bool CSSFontFace::setUnicodeRange(CSSValue& unicodeRange)
264{
265 if (!is<CSSValueList>(unicodeRange))
266 return false;
267
268 auto& list = downcast<CSSValueList>(unicodeRange);
269
270 Vector<UnicodeRange> ranges;
271 ranges.reserveInitialCapacity(list.length());
272
273 for (auto& rangeValue : list) {
274 auto& range = downcast<CSSUnicodeRangeValue>(rangeValue.get());
275 ranges.uncheckedAppend({ range.from(), range.to() });
276 }
277
278 if (ranges == m_ranges)
279 return true;
280
281 m_ranges = WTFMove(ranges);
282
283 if (m_cssConnection)
284 m_cssConnection->mutableProperties().setProperty(CSSPropertyUnicodeRange, &unicodeRange);
285
286 iterateClients(m_clients, [&](Client& client) {
287 client.fontPropertyChanged(*this);
288 });
289
290 return true;
291}
292
293void CSSFontFace::setFeatureSettings(CSSValue& featureSettings)
294{
295 // Can only call this with a primitive value of normal, or a value list containing font feature values.
296 ASSERT(is<CSSPrimitiveValue>(featureSettings) || is<CSSValueList>(featureSettings));
297
298 FontFeatureSettings settings;
299
300 if (is<CSSValueList>(featureSettings)) {
301 auto& list = downcast<CSSValueList>(featureSettings);
302 for (auto& rangeValue : list) {
303 auto& feature = downcast<CSSFontFeatureValue>(rangeValue.get());
304 settings.insert({ feature.tag(), feature.value() });
305 }
306 }
307
308 if (m_featureSettings == settings)
309 return;
310
311 m_featureSettings = WTFMove(settings);
312
313 if (m_cssConnection)
314 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontFeatureSettings, &featureSettings);
315
316 iterateClients(m_clients, [&](Client& client) {
317 client.fontPropertyChanged(*this);
318 });
319}
320
321void CSSFontFace::setLoadingBehavior(CSSValue& loadingBehaviorValue)
322{
323 auto loadingBehavior = static_cast<FontLoadingBehavior>(downcast<CSSPrimitiveValue>(loadingBehaviorValue));
324
325 if (m_loadingBehavior == loadingBehavior)
326 return;
327
328 m_loadingBehavior = loadingBehavior;
329
330 if (m_cssConnection)
331 m_cssConnection->mutableProperties().setProperty(CSSPropertyFontDisplay, &loadingBehaviorValue);
332
333 iterateClients(m_clients, [&](Client& client) {
334 client.fontPropertyChanged(*this);
335 });
336}
337
338bool CSSFontFace::rangesMatchCodePoint(UChar32 character) const
339{
340 if (m_ranges.isEmpty())
341 return true;
342
343 for (auto& range : m_ranges) {
344 if (range.from <= character && character <= range.to)
345 return true;
346 }
347 return false;
348}
349
350void CSSFontFace::fontLoadEventOccurred()
351{
352 // If the font is already in the cache, CSSFontFaceSource may report it's loaded before it is added here as a source.
353 // Let's not pump the state machine until we've got all our sources. font() and load() are smart enough to act correctly
354 // when a source is failed or succeeded before we have asked it to load.
355 if (m_sourcesPopulated)
356 pump(ExternalResourceDownloadPolicy::Forbid);
357
358 iterateClients(m_clients, [&](Client& client) {
359 client.fontLoaded(*this);
360 });
361}
362
363void CSSFontFace::timeoutFired()
364{
365 Ref<CSSFontFace> protectedThis(*this);
366
367 switch (status()) {
368 case Status::Loading:
369 setStatus(Status::TimedOut);
370 break;
371 case Status::TimedOut:
372 // Cancelling the network request here could lead to a situation where a site's font never gets
373 // shown as the user navigates around to different pages on the site. This would occur if the
374 // download always takes longer than the timeout (even though the user may spend substantial time
375 // on each page). Therefore, we shouldn't cancel the network request here, but should use the
376 // loading infrastructure's timeout policies instead.
377 setStatus(Status::Failure);
378 break;
379 default:
380 ASSERT_NOT_REACHED();
381 break;
382 }
383
384 fontLoadEventOccurred();
385}
386
387Document* CSSFontFace::document()
388{
389 if (m_wrapper && is<Document>(m_wrapper->scriptExecutionContext()))
390 return &downcast<Document>(*m_wrapper->scriptExecutionContext());
391 return nullptr;
392}
393
394bool CSSFontFace::computeFailureState() const
395{
396 if (status() == Status::Failure)
397 return true;
398 for (auto& source : m_sources) {
399 if (source->status() != CSSFontFaceSource::Status::Failure)
400 return false;
401 }
402 return true;
403}
404
405void CSSFontFace::addClient(Client& client)
406{
407 m_clients.add(&client);
408}
409
410void CSSFontFace::removeClient(Client& client)
411{
412 ASSERT(m_clients.contains(&client));
413 m_clients.remove(&client);
414}
415
416void CSSFontFace::initializeWrapper()
417{
418 switch (m_status) {
419 case Status::Pending:
420 break;
421 case Status::Loading:
422 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Loading);
423 break;
424 case Status::TimedOut:
425 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Loading);
426 m_wrapper->fontStateChanged(*this, Status::Loading, Status::TimedOut);
427 break;
428 case Status::Success:
429 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Loading);
430 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Success);
431 break;
432 case Status::Failure:
433 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Loading);
434 m_wrapper->fontStateChanged(*this, Status::Pending, Status::Failure);
435 break;
436 }
437 m_mayBePurged = false;
438}
439
440Ref<FontFace> CSSFontFace::wrapper(ScriptExecutionContext* context)
441{
442 if (m_wrapper) {
443 ASSERT(m_wrapper->scriptExecutionContext() == context);
444 return *m_wrapper.get();
445 }
446
447 auto wrapper = FontFace::create(context, *this);
448 m_wrapper = wrapper;
449 initializeWrapper();
450 return wrapper;
451}
452
453void CSSFontFace::setWrapper(FontFace& newWrapper)
454{
455 m_wrapper = newWrapper;
456 initializeWrapper();
457}
458
459void CSSFontFace::adoptSource(std::unique_ptr<CSSFontFaceSource>&& source)
460{
461 m_sources.append(WTFMove(source));
462
463 // We should never add sources in the middle of loading.
464 ASSERT(!m_sourcesPopulated);
465}
466
467auto CSSFontFace::fontLoadTiming() const -> FontLoadTiming
468{
469 switch (m_fontLoadTimingOverride) {
470 case FontLoadTimingOverride::None:
471 switch (m_loadingBehavior) {
472 case FontLoadingBehavior::Auto:
473 case FontLoadingBehavior::Block:
474 return { 3_s, Seconds::infinity() };
475 case FontLoadingBehavior::Swap:
476 return { 0_s, Seconds::infinity() };
477 case FontLoadingBehavior::Fallback:
478 return { 0.1_s, 3_s };
479 case FontLoadingBehavior::Optional:
480 return { 0.1_s, 0_s };
481 }
482 RELEASE_ASSERT_NOT_REACHED();
483 case FontLoadTimingOverride::Block:
484 return { Seconds::infinity(), 0_s };
485 case FontLoadTimingOverride::Swap:
486 return { 0_s, Seconds::infinity() };
487 case FontLoadTimingOverride::Failure:
488 return { 0_s, 0_s };
489 }
490 RELEASE_ASSERT_NOT_REACHED();
491}
492
493void CSSFontFace::setStatus(Status newStatus)
494{
495 switch (newStatus) {
496 case Status::Pending:
497 ASSERT_NOT_REACHED();
498 break;
499 case Status::Loading:
500 ASSERT(m_status == Status::Pending);
501 break;
502 case Status::TimedOut:
503 ASSERT(m_status == Status::Loading);
504 break;
505 case Status::Success:
506 ASSERT(m_status == Status::Loading || m_status == Status::TimedOut);
507 break;
508 case Status::Failure:
509 ASSERT(m_status == Status::Loading || m_status == Status::TimedOut);
510 break;
511 }
512
513 iterateClients(m_clients, [&](Client& client) {
514 client.fontStateChanged(*this, m_status, newStatus);
515 });
516
517 m_status = newStatus;
518
519 Seconds blockPeriodTimeout;
520 Seconds swapPeriodTimeout;
521 auto timeouts = fontLoadTiming();
522 blockPeriodTimeout = timeouts.blockPeriod;
523 swapPeriodTimeout = timeouts.swapPeriod;
524
525 // Transfer across 0-delay timers synchronously. Layouts/script may
526 // take arbitrarily long time, and we shouldn't be in a 0-duration
527 // state for an arbitrarily long time. Also it's necessary for
528 // testing so we don't have a race with the font load.
529 switch (newStatus) {
530 case Status::Pending:
531 ASSERT_NOT_REACHED();
532 break;
533 case Status::Loading:
534 if (blockPeriodTimeout == 0_s)
535 setStatus(Status::TimedOut);
536 else if (std::isfinite(blockPeriodTimeout.value()))
537 m_timeoutTimer.startOneShot(blockPeriodTimeout);
538 break;
539 case Status::TimedOut:
540 if (swapPeriodTimeout == 0_s)
541 setStatus(Status::Failure);
542 else if (std::isfinite(swapPeriodTimeout.value()))
543 m_timeoutTimer.startOneShot(swapPeriodTimeout);
544 break;
545 case Status::Success:
546 case Status::Failure:
547 m_timeoutTimer.stop();
548 break;
549 }
550}
551
552void CSSFontFace::fontLoaded(CSSFontFaceSource&)
553{
554 Ref<CSSFontFace> protectedThis(*this);
555
556 fontLoadEventOccurred();
557}
558
559void CSSFontFace::opportunisticallyStartFontDataURLLoading()
560{
561 // We don't want to go crazy here and blow the cache. Usually these data URLs are the first item in the src: list, so let's just check that one.
562 if (!m_sources.isEmpty())
563 m_sources[0]->opportunisticallyStartFontDataURLLoading();
564}
565
566size_t CSSFontFace::pump(ExternalResourceDownloadPolicy policy)
567{
568 if (status() == Status::Failure)
569 return 0;
570
571 size_t i;
572 for (i = 0; i < m_sources.size(); ++i) {
573 auto& source = m_sources[i];
574
575 if (source->status() == CSSFontFaceSource::Status::Pending) {
576 ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut);
577 // This is a little tricky. After calling CSSFontFace::font(Forbid), a font must never fail later in
578 // this turn of the runloop because the return value of CSSFontFace::font() shouldn't get nulled out
579 // from under an existing FontRanges object. Remote fonts are all downloaded asynchronously, so this
580 // isn't a problem for them because CSSFontFace::font() will always return the interstitial font.
581 // However, local fonts may synchronously fail when you call load() on them. Therefore, we have to call
582 // load() here in order to guarantee that, if the font synchronously fails, it happens now during the
583 // first call to CSSFontFace::font() and the FontRanges object sees a consistent view of the
584 // CSSFontFace. This means we eagerly create some internal font objects when they may not be needed,
585 // but it seems that this behavior is a requirement of the design of FontRanges. FIXME: Perhaps rethink
586 // this design.
587 if (policy == ExternalResourceDownloadPolicy::Allow || !source->requiresExternalResource()) {
588 if (policy == ExternalResourceDownloadPolicy::Allow && m_status == Status::Pending)
589 setStatus(Status::Loading);
590 source->load(document());
591 }
592 }
593
594 switch (source->status()) {
595 case CSSFontFaceSource::Status::Pending:
596 ASSERT(policy == ExternalResourceDownloadPolicy::Forbid);
597 return i;
598 case CSSFontFaceSource::Status::Loading:
599 ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut || m_status == Status::Failure);
600 if (policy == ExternalResourceDownloadPolicy::Allow && m_status == Status::Pending)
601 setStatus(Status::Loading);
602 return i;
603 case CSSFontFaceSource::Status::Success:
604 ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut || m_status == Status::Success || m_status == Status::Failure);
605 if (m_status == Status::Pending)
606 setStatus(Status::Loading);
607 if (m_status == Status::Loading || m_status == Status::TimedOut)
608 setStatus(Status::Success);
609 return i;
610 case CSSFontFaceSource::Status::Failure:
611 if (policy == ExternalResourceDownloadPolicy::Allow && m_status == Status::Pending)
612 setStatus(Status::Loading);
613 break;
614 }
615 }
616 if (m_sources.isEmpty() && m_status == Status::Pending)
617 setStatus(Status::Loading);
618 if (m_status == Status::Loading || m_status == Status::TimedOut)
619 setStatus(Status::Failure);
620 return m_sources.size();
621}
622
623void CSSFontFace::load()
624{
625 pump(ExternalResourceDownloadPolicy::Allow);
626}
627
628static Font::Visibility visibility(CSSFontFace::Status status, CSSFontFace::FontLoadTiming timing)
629{
630 switch (status) {
631 case CSSFontFace::Status::Pending:
632 return timing.blockPeriod == 0_s ? Font::Visibility::Visible : Font::Visibility::Invisible;
633 case CSSFontFace::Status::Loading:
634 return Font::Visibility::Invisible;
635 case CSSFontFace::Status::TimedOut:
636 case CSSFontFace::Status::Failure:
637 case CSSFontFace::Status::Success:
638 default:
639 return Font::Visibility::Visible;
640 }
641}
642
643RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy policy, const FontPaletteValues& fontPaletteValues)
644{
645 if (computeFailureState())
646 return nullptr;
647
648 Ref<CSSFontFace> protectedThis(*this);
649
650 // Our status is derived from the first non-failed source. However, this source may
651 // return null from font(), which means we need to continue looping through the remainder
652 // of the sources to try to find a font to use. These subsequent tries should not affect
653 // our own state, though.
654 size_t startIndex = pump(policy);
655
656 if (computeFailureState())
657 return nullptr;
658
659 for (size_t i = startIndex; i < m_sources.size(); ++i) {
660 auto& source = m_sources[i];
661 if (source->status() == CSSFontFaceSource::Status::Pending && (policy == ExternalResourceDownloadPolicy::Allow || !source->requiresExternalResource()))
662 source->load(document());
663
664 switch (source->status()) {
665 case CSSFontFaceSource::Status::Pending:
666 case CSSFontFaceSource::Status::Loading: {
667 Font::Visibility visibility = WebCore::visibility(status(), fontLoadTiming());
668 return Font::create(FontCache::forCurrentThread().lastResortFallbackFont(fontDescription)->platformData(), Font::Origin::Local, Font::Interstitial::Yes, visibility);
669 }
670 case CSSFontFaceSource::Status::Success: {
671 FontCreationContext fontCreationContext { m_featureSettings, m_fontSelectionCapabilities, fontPaletteValues };
672 if (auto result = source->font(fontDescription, syntheticBold, syntheticItalic, fontCreationContext))
673 return result;
674 break;
675 }
676 case CSSFontFaceSource::Status::Failure:
677 break;
678 }
679 }
680
681 return nullptr;
682}
683
684bool CSSFontFace::purgeable() const
685{
686 return cssConnection() && m_mayBePurged;
687}
688
689void CSSFontFace::updateStyleIfNeeded()
690{
691 iterateClients(m_clients, [&](Client& client) {
692 client.updateStyleIfNeeded(*this);
693 });
694}
695
696bool CSSFontFace::hasSVGFontFaceSource() const
697{
698 size_t size = m_sources.size();
699 for (size_t i = 0; i < size; i++) {
700 if (m_sources[i]->isSVGFontFaceSource())
701 return true;
702 }
703 return false;
704}
705
706void CSSFontFace::setErrorState()
707{
708 switch (m_status) {
709 case Status::Pending:
710 setStatus(Status::Loading);
711 break;
712 case Status::Success:
713 ASSERT_NOT_REACHED();
714 break;
715 case Status::Failure:
716 return;
717 default:
718 break;
719 }
720
721 setStatus(Status::Failure);
722}
723
724}
Note: See TracBrowser for help on using the repository browser.