Changeset 196954 in webkit
- Timestamp:
- Feb 22, 2016 1:40:02 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r196948 r196954 1 2016-02-22 Myles C. Maxfield <mmaxfield@apple.com> 2 3 [Font Loading] Split CSSFontSelector into a FontFaceSet implementation and the rest of the class 4 https://bugs.webkit.org/show_bug.cgi?id=153347 5 6 Reviewed by Antti Koivisto. 7 8 * fast/text/font-face-javascript.html: 9 * fast/text/font-face-set-document-expected.txt: Added. 10 * fast/text/font-face-set-document.html: Added. 11 1 12 2016-02-22 Konstantin Tokarev <annulen@yandex.ru> 2 13 -
trunk/LayoutTests/fast/text/font-face-javascript.html
r196604 r196954 1 1 <!DOCTYPE html> 2 <html> 2 3 <head> 3 4 <script src="../../resources/js-test-pre.js"></script> -
trunk/Source/WebCore/ChangeLog
r196947 r196954 1 2016-02-22 Myles C. Maxfield <mmaxfield@apple.com> 2 3 [Font Loading] Split CSSFontSelector into a FontFaceSet implementation and the rest of the class 4 https://bugs.webkit.org/show_bug.cgi?id=153347 5 6 Reviewed by Antti Koivisto. 7 8 This patch implements the document.fonts Javascript object. It does so by briding the 9 already-existing FontFaceSet Javascript object with the CSSFontSelector WebCore object. 10 CSSFontSelector used to hold internal objects for each @font-face object in the 11 Document. These objects have been moved into CSSFontFaceSet, so CSSFontSelector simply 12 just owns an instance of a CSSFontFaceSet. 13 14 The lifetime of the FontFace and FontFaceSet objects is a little interesting: because 15 all the ownership references are inside the WebCore CSSFontFace{,Set} objects, the 16 higher-level Javascript FontFace{,Set} objects are held through a WeakPtr. This means 17 that if all the references to these higher-level objects go away, and you re-query the 18 document for its FontFace objects, you may get a new object (albeit with the same 19 state as a previous object). However, this won't occur if there are any references to 20 the old object, which means it is almost not observable. 21 22 This patch doesn't implement the relationship between the CSSOM and the FontFace 23 objects. Changing one should result in a change in the other, but that will be 24 implemented in a forthcoming patch. 25 26 This patch also doesn't alter the lifetime of the CSSFontSelector, which means that all 27 the Document's fonts may be destroyed and recreated from CSS. There are a few things 28 which can trigger this. A subsequent patch will make the CSSFontSelector outlive the 29 Document. 30 31 This patch does implement (and test) the ability to add a new FontFace to the Document 32 to cause a relayout, as well as changing properties of existing FontFace objects already 33 in the Document to cause a relayout. 34 35 Test: fast/text/font-face-set-document.html 36 37 * Modules/fetch/FetchHeaders.cpp: 38 (WebCore::FetchHeaders::Iterator::next): Pass an extra argument. 39 * Modules/fetch/FetchHeaders.h: 40 * bindings/js/JSKeyValueIterator.h: The ExecState is necessary to build an external 41 wrapper from an existing CSSFontFace object. 42 (WebCore::JSKeyValueIterator<JSWrapper>::next): 43 * css/CSSFontFace.cpp: 44 (WebCore::CSSFontFace::appendSources): Moved from CSSFontSelector. 45 (WebCore::CSSFontFace::CSSFontFace): 46 (WebCore::CSSFontFace::notifyClientsOfFontPropertyChange): 47 (WebCore::CSSFontFace::setFamilies): 48 (WebCore::CSSFontFace::calculateStyle): Shared code between CSSFontFaceSet and 49 CSSFontFace. 50 (WebCore::CSSFontFace::setStyle): Update to use calculateStyle(). 51 (WebCore::CSSFontFace::calculateWeight): Ditto. 52 (WebCore::CSSFontFace::setWeight): Update to use caculateWeight(). 53 (WebCore::CSSFontFace::setUnicodeRange): Notify clients. 54 (WebCore::CSSFontFace::setVariantLigatures): Ditto. 55 (WebCore::CSSFontFace::setVariantPosition): Ditto. 56 (WebCore::CSSFontFace::setVariantCaps): Ditto. 57 (WebCore::CSSFontFace::setVariantNumeric): Ditto. 58 (WebCore::CSSFontFace::setVariantAlternates): Ditto. 59 (WebCore::CSSFontFace::setVariantEastAsian): Ditto. 60 (WebCore::CSSFontFace::setFeatureSettings): Ditto. 61 (WebCore::CSSFontFace::removeClient): 62 (WebCore::CSSFontFace::wrapper): Build a new wrapper if one doesn't already 63 exist. Note that this requires an ExecState to create a promise. 64 (WebCore::CSSFontFace::setStatus): 65 (WebCore::CSSFontFace::fontLoaded): 66 (WebCore::CSSFontFace::pump): 67 (WebCore::CSSFontFace::font): 68 * css/CSSFontFace.h: 69 * css/CSSFontFaceSet.cpp: 70 (WebCore::CSSFontFaceSet::CSSFontFaceSet): Moved code from CSSFontSelector. 71 (WebCore::CSSFontFaceSet::~CSSFontFaceSet): 72 (WebCore::CSSFontFaceSet::addClient): This object can now have multiple 73 clients. 74 (WebCore::CSSFontFaceSet::removeClient): 75 (WebCore::CSSFontFaceSet::incrementActiveCount): Update for multiple clients. 76 (WebCore::CSSFontFaceSet::decrementActiveCount): Ditto. 77 (WebCore::CSSFontFaceSet::hasFace): 78 (WebCore::CSSFontFaceSet::registerLocalFontFacesForFamily): Moved from 79 CSSFontSelector. 80 (WebCore::CSSFontFaceSet::familyNameFromPrimitive): Ditto. 81 (WebCore::CSSFontFaceSet::addToFacesLookupTable): This helper function can 82 be used when a property of a FontFace is changed. 83 (WebCore::CSSFontFaceSet::add): Update to use addToFacesLookupTable(). 84 (WebCore::CSSFontFaceSet::removeFromFacesLookupTable): Same as 85 addToFacesLookupTable(). 86 (WebCore::CSSFontFaceSet::remove): Update to use removeFromFacesLookupTable(). 87 (WebCore::CSSFontFaceSet::clear): 88 (WebCore::CSSFontFaceSet::operator[]): 89 (WebCore::computeFontTraitsMask): Moved from CSSFontSelector. 90 (WebCore::CSSFontFaceSet::matchingFaces): Update to use new data structures. 91 (WebCore::FontFaceComparator::FontFaceComparator): Moved from 92 CSSFontSelector. 93 (WebCore::FontFaceComparator::operator()): 94 (WebCore::CSSFontFaceSet::getFontFace): Update to use new data structures. 95 (WebCore::CSSFontFaceSet::fontStateChanged): Update to use multiple clients. 96 (WebCore::CSSFontFaceSet::fontPropertyChanged): We must update our internal 97 data structure if the family name changed. 98 (WebCore::extractFamilies): Deleted. 99 (WebCore::familiesIntersect): Deleted. 100 (WebCore::CSSFontFaceSet::load): Deleted. 101 (WebCore::CSSFontFaceSet::stateChanged): Deleted. 102 * css/CSSFontFaceSet.h: Now needs to be RefCounted. New data structures are 103 taken from CSSFontSelector. 104 (WebCore::CSSFontFaceSetClient::faceFinished): 105 (WebCore::CSSFontFaceSetClient::fontModified): 106 (WebCore::CSSFontFaceSetClient::startedLoading): 107 (WebCore::CSSFontFaceSetClient::completedLoading): 108 * css/CSSFontFaceSource.h: 109 * css/CSSFontSelector.cpp: Move code into CSSFontFaceSet. 110 (WebCore::CSSFontSelector::CSSFontSelector): 111 (WebCore::CSSFontSelector::~CSSFontSelector): 112 (WebCore::CSSFontSelector::fontFaceSet): 113 (WebCore::CSSFontSelector::isEmpty): 114 (WebCore::CSSFontSelector::addFontFaceRule): 115 (WebCore::CSSFontSelector::fontModified): 116 (WebCore::CSSFontSelector::fontRangesForFamily): 117 (WebCore::CSSFontSelector::clearDocument): 118 (WebCore::CSSFontSelector::appendSources): Deleted. 119 (WebCore::CSSFontSelector::familyNameFromPrimitive): Deleted. 120 (WebCore::CSSFontSelector::registerLocalFontFacesForFamily): Deleted. 121 (WebCore::FontFaceComparator::FontFaceComparator): Deleted. 122 (WebCore::FontFaceComparator::operator()): Deleted. 123 (WebCore::CSSFontSelector::getFontFace): Deleted. 124 * css/CSSFontSelector.h: 125 * css/CSSSegmentedFontFace.cpp: 126 (WebCore::CSSSegmentedFontFace::CSSSegmentedFontFace): 127 * css/CSSSegmentedFontFace.h: 128 * css/FontFace.cpp: 129 (WebCore::FontFace::create): 130 (WebCore::FontFace::FontFace): 131 (WebCore::FontFace::createWeakPtr): 132 (WebCore::FontFace::fontStateChanged): 133 (WebCore::FontFace::stateChanged): Deleted. 134 * css/FontFace.h: 135 * css/FontFaceSet.cpp: 136 (WebCore::FontFaceSet::create): 137 (WebCore::FontFaceSet::FontFaceSet): 138 (WebCore::FontFaceSet::~FontFaceSet): 139 (WebCore::FontFaceSet::Iterator::next): 140 (WebCore::FontFaceSet::has): 141 (WebCore::FontFaceSet::size): 142 (WebCore::FontFaceSet::add): 143 (WebCore::FontFaceSet::remove): 144 (WebCore::FontFaceSet::clear): 145 (WebCore::FontFaceSet::load): 146 (WebCore::FontFaceSet::check): 147 (WebCore::FontFaceSet::status): 148 (WebCore::FontFaceSet::canSuspendForDocumentSuspension): 149 (WebCore::FontFaceSet::faceFinished): 150 * css/FontFaceSet.h: 151 * css/FontFaceSet.idl: 152 * dom/Document.cpp: 153 (WebCore::Document::fonts): 154 * dom/Document.h: 155 * dom/Document.idl: 156 * svg/SVGFontFaceElement.h: 157 1 158 2016-02-22 Konstantin Tokarev <annulen@yandex.ru> 2 159 -
trunk/Source/WebCore/Modules/fetch/FetchHeaders.cpp
r196128 r196954 180 180 } 181 181 182 bool FetchHeaders::Iterator::next( String& nextKey, String& nextValue)182 bool FetchHeaders::Iterator::next(JSC::ExecState&, String& nextKey, String& nextValue) 183 183 { 184 184 while (m_currentIndex < m_keys.size()) { -
trunk/Source/WebCore/Modules/fetch/FetchHeaders.h
r196900 r196954 34 34 #include "HTTPHeaderMap.h" 35 35 36 namespace JSC { 37 class ExecState; 38 } 39 36 40 namespace WebCore { 37 41 … … 66 70 public: 67 71 explicit Iterator(FetchHeaders&); 68 bool next( String& nextKey, String& nextValue);72 bool next(JSC::ExecState&, String& nextKey, String& nextValue); 69 73 70 74 private: -
trunk/Source/WebCore/bindings/js/JSKeyValueIterator.h
r196900 r196954 130 130 typename JSWrapper::IteratorValue nextValue; 131 131 auto iterator = wrapper->wrapped().createIterator(); 132 while (!iterator.next( nextKey, nextValue)) {132 while (!iterator.next(state, nextKey, nextValue)) { 133 133 JSC::MarkedArgumentBuffer arguments; 134 134 arguments.append(toJS(&state, wrapper->globalObject(), nextValue)); … … 154 154 typename JSWrapper::IteratorKey nextKey; 155 155 typename JSWrapper::IteratorValue nextValue; 156 if (m_iterator.next( nextKey, nextValue)) {156 if (m_iterator.next(state, nextKey, nextValue)) { 157 157 value = JSC::jsUndefined(); 158 158 return true; -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r196900 r196954 4040 4040 return "${svgNativeType}*" if $svgNativeType; 4041 4041 return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; 4042 return "RefPtr<FontFace>" if $type eq "FontFace"; 4042 4043 return "RefPtr<${type}>" if $codeGenerator->IsTypedArrayType($type) and not $type eq "ArrayBuffer"; 4043 4044 return $nativeType{$type} if exists $nativeType{$type}; -
trunk/Source/WebCore/css/CSSFontFace.cpp
r196747 r196954 28 28 29 29 #include "CSSFontFaceSource.h" 30 #include "CSSFontFaceSrcValue.h" 30 31 #include "CSSFontFamily.h" 31 32 #include "CSSFontFeatureValue.h" … … 39 40 #include "Font.h" 40 41 #include "FontDescription.h" 41 #include "Font Loader.h"42 #include "FontFace.h" 42 43 #include "FontVariantBuilder.h" 43 44 #include "RuntimeEnabledFeatures.h" 45 #include "Settings.h" 44 46 #include "StyleProperties.h" 47 #include "StyleRule.h" 45 48 46 49 namespace WebCore { 47 50 48 CSSFontFace::CSSFontFace(CSSFontSelector& fontSelector, FontFace* wrapper, bool isLocalFallback) 51 void CSSFontFace::appendSources(CSSFontFace& fontFace, CSSValueList& srcList, Document* document, bool isInitiatingElementInUserAgentShadowTree) 52 { 53 for (auto& src : srcList) { 54 // An item in the list either specifies a string (local font name) or a URL (remote font to download). 55 CSSFontFaceSrcValue& item = downcast<CSSFontFaceSrcValue>(src.get()); 56 std::unique_ptr<CSSFontFaceSource> source; 57 SVGFontFaceElement* fontFaceElement = nullptr; 58 bool foundSVGFont = false; 59 60 #if ENABLE(SVG_FONTS) 61 foundSVGFont = item.isSVGFontFaceSrc() || item.svgFontFaceElement(); 62 fontFaceElement = item.svgFontFaceElement(); 63 #endif 64 if (!item.isLocal()) { 65 Settings* settings = document ? document->settings() : nullptr; 66 bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled()); 67 if (allowDownloading && item.isSupportedFormat() && document) { 68 if (CachedFont* cachedFont = item.cachedFont(document, foundSVGFont, isInitiatingElementInUserAgentShadowTree)) 69 source = std::make_unique<CSSFontFaceSource>(fontFace, item.resource(), cachedFont); 70 } 71 } else 72 source = std::make_unique<CSSFontFaceSource>(fontFace, item.resource(), nullptr, fontFaceElement); 73 74 if (source) 75 fontFace.adoptSource(WTFMove(source)); 76 } 77 fontFace.sourcesPopulated(); 78 } 79 80 CSSFontFace::CSSFontFace(CSSFontSelector* fontSelector, StyleRuleFontFace* cssConnection, FontFace* wrapper, bool isLocalFallback) 49 81 : m_fontSelector(fontSelector) 50 , m_wrapper(wrapper) 82 , m_cssConnection(cssConnection) 83 , m_wrapper(wrapper ? wrapper->createWeakPtr() : WeakPtr<FontFace>()) 51 84 , m_isLocalFallback(isLocalFallback) 52 85 { … … 55 88 CSSFontFace::~CSSFontFace() 56 89 { 90 } 91 92 void CSSFontFace::notifyClientsOfFontPropertyChange() 93 { 94 auto clientsCopy = m_clients; 95 for (auto* client : clientsCopy) { 96 if (m_clients.contains(client)) 97 client->fontPropertyChanged(*this); 98 } 57 99 } 58 100 … … 66 108 return false; 67 109 110 RefPtr<CSSValueList> oldFamilies = m_families; 68 111 m_families = &familyList; 69 return true; 70 } 71 72 bool CSSFontFace::setStyle(CSSValue& style) 112 113 auto clientsCopy = m_clients; 114 for (auto* client : clientsCopy) { 115 if (m_clients.contains(client)) 116 client->fontPropertyChanged(*this, oldFamilies.get()); 117 } 118 119 return true; 120 } 121 122 Optional<FontTraitsMask> CSSFontFace::calculateStyleMask(CSSValue& style) 73 123 { 74 124 if (!is<CSSPrimitiveValue>(style)) 75 return false; 76 77 unsigned styleMask = 0; 125 return Nullopt; 126 78 127 switch (downcast<CSSPrimitiveValue>(style).getValueID()) { 79 128 case CSSValueNormal: 80 styleMask = FontStyleNormalMask; 81 break; 129 return FontStyleNormalMask; 82 130 case CSSValueItalic: 83 131 case CSSValueOblique: 84 styleMask = FontStyleItalicMask; 85 break; 132 return FontStyleItalicMask; 86 133 default: 87 styleMask = FontStyleNormalMask; 88 break; 89 } 90 91 m_traitsMask = static_cast<FontTraitsMask>((static_cast<unsigned>(m_traitsMask) & (~FontStyleMask)) | styleMask); 92 return true; 93 } 94 95 bool CSSFontFace::setWeight(CSSValue& weight) 134 return FontStyleNormalMask; 135 } 136 137 return FontStyleNormalMask; 138 } 139 140 bool CSSFontFace::setStyle(CSSValue& style) 141 { 142 if (auto mask = calculateStyleMask(style)) { 143 m_traitsMask = static_cast<FontTraitsMask>((static_cast<unsigned>(m_traitsMask) & (~FontStyleMask)) | mask.value()); 144 145 notifyClientsOfFontPropertyChange(); 146 147 return true; 148 } 149 return false; 150 } 151 152 Optional<FontTraitsMask> CSSFontFace::calculateWeightMask(CSSValue& weight) 96 153 { 97 154 if (!is<CSSPrimitiveValue>(weight)) 98 return false; 99 100 unsigned weightMask = 0; 155 return Nullopt; 156 101 157 switch (downcast<CSSPrimitiveValue>(weight).getValueID()) { 102 158 case CSSValueBold: 103 159 case CSSValueBolder: 104 160 case CSSValue700: 105 weightMask = FontWeight700Mask; 106 break; 161 return FontWeight700Mask; 107 162 case CSSValueNormal: 108 163 case CSSValue400: 109 weightMask = FontWeight400Mask; 110 break; 164 return FontWeight400Mask; 111 165 case CSSValue900: 112 weightMask = FontWeight900Mask; 113 break; 166 return FontWeight900Mask; 114 167 case CSSValue800: 115 weightMask = FontWeight800Mask; 116 break; 168 return FontWeight800Mask; 117 169 case CSSValue600: 118 weightMask = FontWeight600Mask; 119 break; 170 return FontWeight600Mask; 120 171 case CSSValue500: 121 weightMask = FontWeight500Mask; 122 break; 172 return FontWeight500Mask; 123 173 case CSSValue300: 124 weightMask = FontWeight300Mask; 125 break; 174 return FontWeight300Mask; 126 175 case CSSValueLighter: 127 176 case CSSValue200: 128 weightMask = FontWeight200Mask; 129 break; 177 return FontWeight200Mask; 130 178 case CSSValue100: 131 weightMask = FontWeight100Mask; 132 break; 179 return FontWeight100Mask; 133 180 default: 134 weightMask = FontWeight400Mask; 135 break; 136 } 137 138 m_traitsMask = static_cast<FontTraitsMask>((static_cast<unsigned>(m_traitsMask) & (~FontWeightMask)) | weightMask); 139 return true; 181 return FontWeight400Mask; 182 } 183 184 return FontWeight400Mask; 185 } 186 187 bool CSSFontFace::setWeight(CSSValue& weight) 188 { 189 if (auto mask = calculateWeightMask(weight)) { 190 m_traitsMask = static_cast<FontTraitsMask>((static_cast<unsigned>(m_traitsMask) & (~FontWeightMask)) | mask.value()); 191 192 notifyClientsOfFontPropertyChange(); 193 194 return true; 195 } 196 197 return false; 140 198 } 141 199 … … 151 209 m_ranges.append(UnicodeRange(range.from(), range.to())); 152 210 } 211 212 notifyClientsOfFontPropertyChange(); 213 153 214 return true; 154 215 } … … 161 222 m_variantSettings.historicalLigatures = ligatures.historicalLigatures; 162 223 m_variantSettings.contextualAlternates = ligatures.contextualAlternates; 224 225 notifyClientsOfFontPropertyChange(); 226 163 227 return true; 164 228 } … … 169 233 return false; 170 234 m_variantSettings.position = downcast<CSSPrimitiveValue>(variantPosition); 235 236 notifyClientsOfFontPropertyChange(); 237 171 238 return true; 172 239 } … … 177 244 return false; 178 245 m_variantSettings.caps = downcast<CSSPrimitiveValue>(variantCaps); 246 247 notifyClientsOfFontPropertyChange(); 248 179 249 return true; 180 250 } … … 188 258 m_variantSettings.numericOrdinal = numeric.ordinal; 189 259 m_variantSettings.numericSlashedZero = numeric.slashedZero; 260 261 notifyClientsOfFontPropertyChange(); 262 190 263 return true; 191 264 } … … 196 269 return false; 197 270 m_variantSettings.alternates = downcast<CSSPrimitiveValue>(variantAlternates); 271 272 notifyClientsOfFontPropertyChange(); 273 198 274 return true; 199 275 } … … 205 281 m_variantSettings.eastAsianWidth = eastAsian.width; 206 282 m_variantSettings.eastAsianRuby = eastAsian.ruby; 283 284 notifyClientsOfFontPropertyChange(); 285 207 286 return true; 208 287 } … … 219 298 m_featureSettings.insert(FontFeature(feature.tag(), feature.value())); 220 299 } 300 301 notifyClientsOfFontPropertyChange(); 302 221 303 return true; 222 304 } … … 238 320 void CSSFontFace::removeClient(Client& client) 239 321 { 322 ASSERT(m_clients.contains(&client)); 240 323 m_clients.remove(&client); 324 } 325 326 Ref<FontFace> CSSFontFace::wrapper(JSC::ExecState& execState) 327 { 328 if (m_wrapper) 329 return Ref<FontFace>(*m_wrapper.get()); 330 331 Ref<FontFace> wrapper = FontFace::create(execState, *this); 332 switch (m_status) { 333 case Status::Pending: 334 break; 335 case Status::Loading: 336 wrapper->fontStateChanged(*this, Status::Pending, Status::Loading); 337 break; 338 case Status::TimedOut: 339 wrapper->fontStateChanged(*this, Status::Pending, Status::Loading); 340 wrapper->fontStateChanged(*this, Status::Loading, Status::TimedOut); 341 break; 342 case Status::Success: 343 wrapper->fontStateChanged(*this, Status::Pending, Status::Loading); 344 wrapper->fontStateChanged(*this, Status::Pending, Status::Success); 345 break; 346 case Status::Failure: 347 wrapper->fontStateChanged(*this, Status::Pending, Status::Loading); 348 wrapper->fontStateChanged(*this, Status::Pending, Status::Failure); 349 break; 350 } 351 m_wrapper = wrapper->createWeakPtr(); 352 return wrapper; 241 353 } 242 354 … … 269 381 } 270 382 271 for (auto &client : m_clients)272 client-> stateChanged(*this, m_status, newStatus);383 for (auto* client : m_clients) 384 client->fontStateChanged(*this, m_status, newStatus); 273 385 274 386 m_status = newStatus; … … 283 395 pump(); 284 396 397 ASSERT(m_fontSelector); 285 398 m_fontSelector->fontLoaded(); 286 399 287 for (auto &client : m_clients)400 for (auto* client : m_clients) 288 401 client->fontLoaded(*this); 289 402 } … … 297 410 if (source->status() == CSSFontFaceSource::Status::Pending) { 298 411 ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut); 412 ASSERT(m_fontSelector); 299 413 if (m_status == Status::Pending) 300 414 setStatus(Status::Loading); 301 source->load( m_fontSelector.get());415 source->load(*m_fontSelector); 302 416 } 303 417 … … 346 460 for (size_t i = startIndex; i < m_sources.size(); ++i) { 347 461 auto& source = m_sources[i]; 348 if (source->status() == CSSFontFaceSource::Status::Pending) 349 source->load(m_fontSelector.get()); 462 if (source->status() == CSSFontFaceSource::Status::Pending) { 463 ASSERT(m_fontSelector); 464 source->load(*m_fontSelector); 465 } 350 466 351 467 switch (source->status()) { -
trunk/Source/WebCore/css/CSSFontFace.h
r196747 r196954 28 28 29 29 #include "CSSFontFaceRule.h" 30 #include "CSSFontFaceSource.h"31 30 #include "FontFeatureSettings.h" 32 31 #include "TextFlags.h" … … 37 36 #include <wtf/RefCounted.h> 38 37 #include <wtf/Vector.h> 38 #include <wtf/WeakPtr.h> 39 40 namespace JSC { 41 class ExecState; 42 } 39 43 40 44 namespace WebCore { 41 45 46 class CSSFontFaceSource; 47 class CSSFontSelector; 42 48 class CSSSegmentedFontFace; 43 49 class CSSValue; 44 50 class CSSValueList; 51 class Document; 45 52 class FontDescription; 46 53 class Font; 47 54 class FontFace; 48 55 49 // FIXME: This class does not need to be reference counted.50 56 class CSSFontFace final : public RefCounted<CSSFontFace> { 51 57 public: 52 static Ref<CSSFontFace> create(CSSFontSelector & fontSelector, FontFace* wrapper = nullptr, bool isLocalFallback = false)58 static Ref<CSSFontFace> create(CSSFontSelector* fontSelector, StyleRuleFontFace* cssConnection = nullptr, FontFace* wrapper = nullptr, bool isLocalFallback = false) 53 59 { 54 return adoptRef(*new CSSFontFace(fontSelector, wrapper, isLocalFallback));60 return adoptRef(*new CSSFontFace(fontSelector, cssConnection, wrapper, isLocalFallback)); 55 61 } 56 62 virtual ~CSSFontFace(); … … 79 85 bool isLocalFallback() const { return m_isLocalFallback; } 80 86 Status status() const { return m_status; } 87 StyleRuleFontFace* cssConnection() const { return m_cssConnection.get(); } 88 89 static Optional<FontTraitsMask> calculateStyleMask(CSSValue& style); 90 static Optional<FontTraitsMask> calculateWeightMask(CSSValue& weight); 81 91 82 92 class Client; … … 94 104 RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic); 95 105 106 static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree); 107 96 108 class Client { 97 109 public: 98 110 virtual ~Client() { } 99 111 virtual void fontLoaded(CSSFontFace&) { }; 100 virtual void stateChanged(CSSFontFace&, Status oldState, Status newState) { UNUSED_PARAM(oldState); UNUSED_PARAM(newState); }; 112 virtual void fontStateChanged(CSSFontFace&, Status oldState, Status newState) { UNUSED_PARAM(oldState); UNUSED_PARAM(newState); }; 113 virtual void fontPropertyChanged(CSSFontFace&, CSSValueList* oldFamilies = nullptr) { UNUSED_PARAM(oldFamilies); }; 101 114 }; 102 115 … … 133 146 }; 134 147 135 FontFace* wrapper() const { return m_wrapper; } 148 // We don't guarantee that the FontFace wrapper will be the same every time you ask for it. 149 Ref<FontFace> wrapper(JSC::ExecState&); 136 150 137 151 #if ENABLE(SVG_FONTS) … … 140 154 141 155 private: 142 CSSFontFace(CSSFontSelector &, FontFace*, bool isLocalFallback);156 CSSFontFace(CSSFontSelector*, StyleRuleFontFace*, FontFace*, bool isLocalFallback); 143 157 144 158 size_t pump(); 145 159 void setStatus(Status); 160 void notifyClientsOfFontPropertyChange(); 146 161 147 162 RefPtr<CSSValueList> m_families; 148 163 FontTraitsMask m_traitsMask { static_cast<FontTraitsMask>(FontStyleNormalMask | FontWeight400Mask) }; 149 164 Vector<UnicodeRange> m_ranges; 150 HashSet<Client*> m_clients;151 Ref<CSSFontSelector> m_fontSelector;152 FontFace* m_wrapper;153 165 FontFeatureSettings m_featureSettings; 154 166 FontVariantSettings m_variantSettings; 155 167 Vector<std::unique_ptr<CSSFontFaceSource>> m_sources; 168 RefPtr<CSSFontSelector> m_fontSelector; 169 RefPtr<StyleRuleFontFace> m_cssConnection; 170 HashSet<Client*> m_clients; 171 WeakPtr<FontFace> m_wrapper; 156 172 Status m_status { Status::Pending }; 157 173 bool m_isLocalFallback { false }; -
trunk/Source/WebCore/css/CSSFontFaceSet.cpp
r196747 r196954 27 27 #include "CSSFontFaceSet.h" 28 28 29 #include "CSSFontFaceSource.h" 29 30 #include "CSSFontFamily.h" 30 31 #include "CSSFontSelector.h" 31 32 #include "CSSParser.h" 32 33 #include "CSSPrimitiveValue.h" 34 #include "CSSSegmentedFontFace.h" 33 35 #include "CSSValueList.h" 36 #include "CSSValuePool.h" 37 #include "FontCache.h" 34 38 #include "StyleProperties.h" 35 39 36 40 namespace WebCore { 37 41 38 CSSFontFaceSet::CSSFontFaceSet(CSSFontFaceSetClient& client) 39 : m_client(client) 42 CSSFontFaceSet::CSSFontFaceSet() 40 43 { 41 44 } … … 45 48 for (auto& face : m_faces) 46 49 face->removeClient(*this); 50 51 for (auto& pair : m_locallyInstalledFacesLookupTable) { 52 for (auto& face : pair.value) 53 face->removeClient(*this); 54 } 55 } 56 57 void CSSFontFaceSet::addClient(CSSFontFaceSetClient& client) 58 { 59 m_clients.add(&client); 60 } 61 62 void CSSFontFaceSet::removeClient(CSSFontFaceSetClient& client) 63 { 64 ASSERT(m_clients.contains(&client)); 65 m_clients.remove(&client); 47 66 } 48 67 … … 52 71 if (m_activeCount == 1) { 53 72 m_status = Status::Loading; 54 m_client.startedLoading(); 73 for (auto* client : m_clients) 74 client->startedLoading(); 55 75 } 56 76 } … … 61 81 if (!m_activeCount) { 62 82 m_status = Status::Loaded; 63 m_client.completedLoading(); 83 for (auto* client : m_clients) 84 client->completedLoading(); 64 85 } 65 86 } … … 71 92 return true; 72 93 } 94 73 95 return false; 74 96 } 75 97 98 void CSSFontFaceSet::registerLocalFontFacesForFamily(const String& familyName) 99 { 100 ASSERT(!m_locallyInstalledFacesLookupTable.contains(familyName)); 101 102 Vector<FontTraitsMask> traitsMasks = FontCache::singleton().getTraitsInFamily(familyName); 103 if (traitsMasks.isEmpty()) 104 return; 105 106 Vector<Ref<CSSFontFace>> faces; 107 for (auto mask : traitsMasks) { 108 Ref<CSSFontFace> face = CSSFontFace::create(nullptr, nullptr, nullptr, true); 109 110 Ref<CSSValueList> familyList = CSSValueList::createCommaSeparated(); 111 familyList->append(CSSValuePool::singleton().createFontFamilyValue(familyName)); 112 face->setFamilies(familyList.get()); 113 face->setTraitsMask(mask); 114 face->adoptSource(std::make_unique<CSSFontFaceSource>(face.get(), familyName)); 115 ASSERT(!face->allSourcesFailed()); 116 faces.append(WTFMove(face)); 117 } 118 m_locallyInstalledFacesLookupTable.add(familyName, WTFMove(faces)); 119 } 120 121 String CSSFontFaceSet::familyNameFromPrimitive(const CSSPrimitiveValue& value) 122 { 123 if (value.isFontFamily()) 124 return value.fontFamily().familyName; 125 if (!value.isValueID()) 126 return { }; 127 128 // We need to use the raw text for all the generic family types, since @font-face is a way of actually 129 // defining what font to use for those types. 130 switch (value.getValueID()) { 131 case CSSValueSerif: 132 return serifFamily; 133 case CSSValueSansSerif: 134 return sansSerifFamily; 135 case CSSValueCursive: 136 return cursiveFamily; 137 case CSSValueFantasy: 138 return fantasyFamily; 139 case CSSValueMonospace: 140 return monospaceFamily; 141 case CSSValueWebkitPictograph: 142 return pictographFamily; 143 default: 144 return { }; 145 } 146 } 147 148 void CSSFontFaceSet::addToFacesLookupTable(CSSFontFace& face) 149 { 150 if (!face.families()) 151 return; 152 153 for (auto& item : *face.families()) { 154 String familyName = CSSFontFaceSet::familyNameFromPrimitive(downcast<CSSPrimitiveValue>(item.get())); 155 if (familyName.isEmpty()) 156 continue; 157 158 auto addResult = m_facesLookupTable.add(familyName, Vector<Ref<CSSFontFace>>()); 159 auto& familyFontFaces = addResult.iterator->value; 160 if (addResult.isNewEntry) { 161 // m_locallyInstalledFontFaces grows without bound, eventually encorporating every font installed on the system. 162 // This is by design. 163 registerLocalFontFacesForFamily(familyName); 164 familyFontFaces = { }; 165 } 166 167 familyFontFaces.append(face); 168 } 169 } 170 76 171 void CSSFontFaceSet::add(CSSFontFace& face) 77 172 { 78 173 ASSERT(!hasFace(face)); 79 174 80 m_faces.append(face); 175 for (auto* client : m_clients) 176 client->fontModified(); 177 81 178 face.addClient(*this); 179 m_cache.clear(); 180 181 if (face.cssConnection()) 182 m_faces.insert(m_facesPartitionIndex++, face); 183 else 184 m_faces.append(face); 185 186 addToFacesLookupTable(face); 187 82 188 if (face.status() == CSSFontFace::Status::Loading || face.status() == CSSFontFace::Status::TimedOut) 83 189 incrementActiveCount(); 84 190 } 85 191 192 void CSSFontFaceSet::removeFromFacesLookupTable(const CSSFontFace& face, const CSSValueList& familiesToSearchFor) 193 { 194 for (auto& item : familiesToSearchFor) { 195 String familyName = CSSFontFaceSet::familyNameFromPrimitive(downcast<CSSPrimitiveValue>(item.get())); 196 if (familyName.isEmpty()) 197 continue; 198 199 auto iterator = m_facesLookupTable.find(familyName); 200 ASSERT(iterator != m_facesLookupTable.end()); 201 bool found = false; 202 for (size_t i = 0; i < iterator->value.size(); ++i) { 203 if (iterator->value[i].ptr() == &face) { 204 found = true; 205 iterator->value.remove(i); 206 break; 207 } 208 } 209 ASSERT_UNUSED(found, found); 210 if (!iterator->value.size()) 211 m_facesLookupTable.remove(iterator); 212 } 213 } 214 86 215 void CSSFontFaceSet::remove(const CSSFontFace& face) 87 216 { 217 m_cache.clear(); 218 219 for (auto* client : m_clients) 220 client->fontModified(); 221 222 if (face.families()) 223 removeFromFacesLookupTable(face, *face.families()); 224 88 225 for (size_t i = 0; i < m_faces.size(); ++i) { 89 226 if (m_faces[i].ptr() == &face) { 227 if (i < m_facesPartitionIndex) 228 --m_facesPartitionIndex; 90 229 m_faces[i]->removeClient(*this); 91 230 m_faces.remove(i); … … 98 237 } 99 238 100 static HashSet<String> extractFamilies(const CSSValueList& list) 101 { 102 HashSet<String> result; 103 for (auto& family : list) { 104 const CSSPrimitiveValue& primitive = downcast<CSSPrimitiveValue>(family.get()); 105 if (!primitive.isFontFamily()) 106 continue; 107 result.add(primitive.fontFamily().familyName); 108 } 109 return result; 110 } 111 112 static bool familiesIntersect(const CSSFontFace& face, const CSSValueList& request) 113 { 114 if (!face.families()) 115 return false; 116 117 HashSet<String> faceFamilies = extractFamilies(*face.families()); 118 HashSet<String> requestFamilies = extractFamilies(request); 119 for (auto& family1 : faceFamilies) { 120 if (requestFamilies.contains(family1)) 121 return true; 122 } 123 return false; 239 void CSSFontFaceSet::clear() 240 { 241 m_faces.clear(); 242 m_facesLookupTable.clear(); 243 m_locallyInstalledFacesLookupTable.clear(); 244 m_cache.clear(); 245 } 246 247 CSSFontFace& CSSFontFaceSet::operator[](size_t i) 248 { 249 ASSERT(i < faceCount()); 250 return m_faces[i]; 251 } 252 253 static Optional<FontTraitsMask> computeFontTraitsMask(MutableStyleProperties& style) 254 { 255 RefPtr<CSSValue> styleValue = style.getPropertyCSSValue(CSSPropertyFontStyle).get(); 256 if (!styleValue) 257 styleValue = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal).ptr(); 258 259 FontTraitsMask styleMask; 260 if (auto styleMaskOptional = CSSFontFace::calculateStyleMask(*styleValue)) 261 styleMask = styleMaskOptional.value(); 262 else 263 return Nullopt; 264 265 RefPtr<CSSValue> weightValue = style.getPropertyCSSValue(CSSPropertyFontWeight).get(); 266 if (!weightValue) 267 weightValue = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal).ptr(); 268 269 FontTraitsMask weightMask; 270 if (auto weightMaskOptional = CSSFontFace::calculateWeightMask(*weightValue)) 271 weightMask = weightMaskOptional.value(); 272 else 273 return Nullopt; 274 275 return static_cast<FontTraitsMask>(static_cast<unsigned>(styleMask) | static_cast<unsigned>(weightMask)); 124 276 } 125 277 … … 133 285 return result; 134 286 } 135 bool desiredStyleIsNormal = true; 136 if (RefPtr<CSSValue> desiredStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) { 137 if (!is<CSSPrimitiveValue>(*desiredStyle)) { 138 ec = SYNTAX_ERR; 139 return result; 140 } 141 desiredStyleIsNormal = downcast<CSSPrimitiveValue>(*desiredStyle).getValueID() == CSSValueNormal; 142 } 287 288 FontTraitsMask fontTraitsMask; 289 if (auto maskOptional = computeFontTraitsMask(style.get())) 290 fontTraitsMask = maskOptional.value(); 291 else { 292 ec = SYNTAX_ERR; 293 return result; 294 } 295 143 296 RefPtr<CSSValue> family = style->getPropertyCSSValue(CSSPropertyFontFamily); 144 297 if (!is<CSSValueList>(family.get())) { … … 148 301 CSSValueList& familyList = downcast<CSSValueList>(*family); 149 302 150 // Match CSSFontSelector::getFontFace() 151 for (auto& face : m_faces) { 152 if (!familiesIntersect(face, familyList) || (desiredStyleIsNormal && !(face->traitsMask() & FontStyleNormalMask))) 303 HashSet<AtomicString> uniqueFamilies; 304 for (auto& family : familyList) { 305 const CSSPrimitiveValue& primitive = downcast<CSSPrimitiveValue>(family.get()); 306 if (!primitive.isFontFamily()) 153 307 continue; 154 result.append(face.get()); 155 } 308 uniqueFamilies.add(primitive.fontFamily().familyName); 309 } 310 311 for (auto& family : uniqueFamilies) { 312 CSSSegmentedFontFace* faces = getFontFace(fontTraitsMask, family); 313 if (!faces) 314 continue; 315 for (auto& constituentFace : faces->constituentFaces()) 316 result.append(constituentFace.get()); 317 } 318 156 319 return result; 157 }158 159 void CSSFontFaceSet::load(const String& font, const String& text, ExceptionCode& ec)160 {161 auto matchingFaces = this->matchingFaces(font, text, ec);162 if (ec)163 return;164 165 for (auto& face : matchingFaces)166 face.get().load();167 320 } 168 321 … … 180 333 } 181 334 182 void CSSFontFaceSet::stateChanged(CSSFontFace& face, CSSFontFace::Status oldState, CSSFontFace::Status newState) 335 static bool fontFaceComparator(FontTraitsMask desiredTraitsMaskForComparison, const CSSFontFace& first, const CSSFontFace& second) 336 { 337 FontTraitsMask firstTraitsMask = first.traitsMask(); 338 FontTraitsMask secondTraitsMask = second.traitsMask(); 339 340 bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask; 341 bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask; 342 343 if (firstHasDesiredStyle != secondHasDesiredStyle) 344 return firstHasDesiredStyle; 345 346 if ((desiredTraitsMaskForComparison & FontStyleItalicMask) && !first.isLocalFallback() && !second.isLocalFallback()) { 347 // Prefer a font that has indicated that it can only support italics to a font that claims to support 348 // all styles. The specialized font is more likely to be the one the author wants used. 349 bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask); 350 bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask); 351 if (firstRequiresItalics != secondRequiresItalics) 352 return firstRequiresItalics; 353 } 354 355 if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask) 356 return false; 357 if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask) 358 return true; 359 360 // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says : 361 // - If the desired weight is less than 400, weights below the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found. 362 // - If the desired weight is greater than 500, weights above the desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found. 363 // - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used. 364 // - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used. 365 366 static const unsigned fallbackRuleSets = 9; 367 static const unsigned rulesPerSet = 8; 368 static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = { 369 { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 370 { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 371 { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 372 { FontWeight500Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 373 { FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, 374 { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 375 { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 376 { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, 377 { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask } 378 }; 379 380 unsigned ruleSetIndex = 0; 381 for (; !(desiredTraitsMaskForComparison & (1 << (FontWeight100Bit + ruleSetIndex))); ruleSetIndex++) { } 382 383 const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex]; 384 for (unsigned i = 0; i < rulesPerSet; ++i) { 385 if (secondTraitsMask & weightFallbackRule[i]) 386 return false; 387 if (firstTraitsMask & weightFallbackRule[i]) 388 return true; 389 } 390 391 return false; 392 } 393 394 CSSSegmentedFontFace* CSSFontFaceSet::getFontFace(FontTraitsMask traitsMask, const AtomicString& family) 395 { 396 auto iterator = m_facesLookupTable.find(family); 397 if (iterator == m_facesLookupTable.end()) 398 return nullptr; 399 auto& familyFontFaces = iterator->value; 400 401 auto& segmentedFontFaceCache = m_cache.add(family, HashMap<unsigned, std::unique_ptr<CSSSegmentedFontFace>>()).iterator->value; 402 403 auto& face = segmentedFontFaceCache.add(traitsMask, nullptr).iterator->value; 404 if (face) 405 return face.get(); 406 407 face = std::make_unique<CSSSegmentedFontFace>(); 408 409 Vector<std::reference_wrapper<CSSFontFace>, 32> candidateFontFaces; 410 for (int i = familyFontFaces.size() - 1; i >= 0; --i) { 411 CSSFontFace& candidate = familyFontFaces[i]; 412 unsigned candidateTraitsMask = candidate.traitsMask(); 413 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) 414 continue; 415 candidateFontFaces.append(candidate); 416 } 417 418 auto localIterator = m_locallyInstalledFacesLookupTable.find(family); 419 if (localIterator != m_locallyInstalledFacesLookupTable.end()) { 420 for (auto& candidate : localIterator->value) { 421 unsigned candidateTraitsMask = candidate->traitsMask(); 422 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) 423 continue; 424 candidateFontFaces.append(candidate); 425 } 426 } 427 428 std::stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), [traitsMask](const CSSFontFace& first, const CSSFontFace& second) { 429 return fontFaceComparator(traitsMask, first, second); 430 }); 431 for (auto& candidate : candidateFontFaces) 432 face->appendFontFace(candidate.get()); 433 434 return face.get(); 435 } 436 437 void CSSFontFaceSet::fontStateChanged(CSSFontFace& face, CSSFontFace::Status oldState, CSSFontFace::Status newState) 183 438 { 184 439 ASSERT(hasFace(face)); … … 189 444 if (newState == CSSFontFace::Status::Success || newState == CSSFontFace::Status::Failure) { 190 445 ASSERT(oldState == CSSFontFace::Status::Loading || oldState == CSSFontFace::Status::TimedOut); 191 m_client.faceFinished(face, newState); 446 for (auto* client : m_clients) 447 client->faceFinished(face, newState); 192 448 decrementActiveCount(); 193 449 } 194 450 } 195 451 196 } 452 void CSSFontFaceSet::fontPropertyChanged(CSSFontFace& face, CSSValueList* oldFamilies) 453 { 454 m_cache.clear(); 455 456 if (oldFamilies) { 457 removeFromFacesLookupTable(face, *oldFamilies); 458 addToFacesLookupTable(face); 459 } 460 461 for (auto* client : m_clients) 462 client->fontModified(); 463 } 464 465 } -
trunk/Source/WebCore/css/CSSFontFaceSet.h
r196784 r196954 28 28 29 29 #include "CSSFontFace.h" 30 #include <wtf/HashMap.h> 30 31 #include <wtf/Vector.h> 32 #include <wtf/text/StringHash.h> 31 33 32 34 namespace WebCore { 33 35 36 class CSSPrimitiveValue; 34 37 class FontFaceSet; 35 38 … … 37 40 public: 38 41 virtual ~CSSFontFaceSetClient() { } 39 virtual void faceFinished(CSSFontFace&, CSSFontFace::Status) = 0; 40 virtual void startedLoading() = 0; 41 virtual void completedLoading() = 0; 42 virtual void faceFinished(CSSFontFace&, CSSFontFace::Status) { }; 43 virtual void fontModified() { }; 44 virtual void startedLoading() { }; 45 virtual void completedLoading() { }; 42 46 }; 43 47 44 class CSSFontFaceSet final : public CSSFontFace::Client {48 class CSSFontFaceSet final : public RefCounted<CSSFontFaceSet>, public CSSFontFace::Client { 45 49 public: 46 CSSFontFaceSet(CSSFontFaceSetClient&); 50 static Ref<CSSFontFaceSet> create() 51 { 52 return adoptRef(*new CSSFontFaceSet()); 53 } 47 54 ~CSSFontFaceSet(); 55 56 void addClient(CSSFontFaceSetClient&); 57 void removeClient(CSSFontFaceSetClient&); 48 58 49 59 bool hasFace(const CSSFontFace&) const; … … 51 61 void add(CSSFontFace&); 52 62 void remove(const CSSFontFace&); 53 const CSSFontFace& operator[](size_t i) const { return m_faces[i]; } 63 void clear(); 64 CSSFontFace& operator[](size_t i); 54 65 55 void load(const String& font, const String& text, ExceptionCode&);56 66 bool check(const String& font, const String& text, ExceptionCode&); 67 68 CSSSegmentedFontFace* getFontFace(FontTraitsMask, const AtomicString& family); 57 69 58 70 enum class Status { … … 65 77 66 78 private: 79 CSSFontFaceSet(); 80 81 void removeFromFacesLookupTable(const CSSFontFace&, const CSSValueList& familiesToSearchFor); 82 void addToFacesLookupTable(CSSFontFace&); 83 67 84 void incrementActiveCount(); 68 85 void decrementActiveCount(); 69 86 70 virtual void stateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override; 87 virtual void fontStateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override; 88 virtual void fontPropertyChanged(CSSFontFace&, CSSValueList* oldFamilies = nullptr) override; 71 89 72 Vector<Ref<CSSFontFace>> m_faces; 90 void registerLocalFontFacesForFamily(const String&); 91 92 static String familyNameFromPrimitive(const CSSPrimitiveValue&); 93 94 // m_faces should hold all the same fonts as the ones inside inside m_facesLookupTable. 95 Vector<Ref<CSSFontFace>> m_faces; // We should investigate moving m_faces to FontFaceSet and making it reference FontFaces. This may clean up the font loading design. 96 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_facesLookupTable; 97 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_locallyInstalledFacesLookupTable; 98 HashMap<String, HashMap<unsigned, std::unique_ptr<CSSSegmentedFontFace>>, ASCIICaseInsensitiveHash> m_cache; 99 size_t m_facesPartitionIndex { 0 }; // All entries in m_faces before this index are CSS-connected. 73 100 Status m_status { Status::Loaded }; 74 CSSFontFaceSetClient& m_client;101 HashSet<CSSFontFaceSetClient*> m_clients; 75 102 unsigned m_activeCount { 0 }; 76 103 }; -
trunk/Source/WebCore/css/CSSFontFaceSource.h
r196376 r196954 46 46 WTF_MAKE_FAST_ALLOCATED; 47 47 public: 48 CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* = nullptr, SVGFontFaceElement* = nullptr); 49 virtual ~CSSFontFaceSource(); 48 50 49 51 // => Success … … 58 60 Failure 59 61 }; 60 61 CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* = nullptr, SVGFontFaceElement* = nullptr);62 virtual ~CSSFontFaceSource();63 64 62 Status status() const { return m_status; } 65 63 -
trunk/Source/WebCore/css/CSSFontSelector.cpp
r196747 r196954 32 32 #include "CSSFontFaceRule.h" 33 33 #include "CSSFontFaceSource.h" 34 #include "CSSFontFaceSrcValue.h"35 34 #include "CSSFontFamily.h" 36 35 #include "CSSFontFeatureValue.h" … … 47 46 #include "Font.h" 48 47 #include "FontCache.h" 48 #include "FontFaceSet.h" 49 49 #include "FontVariantBuilder.h" 50 50 #include "Frame.h" … … 66 66 CSSFontSelector::CSSFontSelector(Document& document) 67 67 : m_document(&document) 68 , m_cssFontFaceSet(CSSFontFaceSet::create()) 68 69 , m_beginLoadingTimer(*this, &CSSFontSelector::beginLoadTimerFired) 69 70 , m_uniqueId(++fontSelectorId) … … 76 77 ASSERT(m_document); 77 78 FontCache::singleton().addClient(*this); 79 m_cssFontFaceSet->addClient(*this); 78 80 } 79 81 … … 81 83 { 82 84 clearDocument(); 85 m_cssFontFaceSet->removeClient(*this); 83 86 FontCache::singleton().removeClient(*this); 84 87 } 85 88 89 FontFaceSet& CSSFontSelector::fontFaceSet() 90 { 91 if (!m_fontFaceSet) { 92 ASSERT(m_document); 93 m_fontFaceSet = FontFaceSet::create(*m_document, m_cssFontFaceSet.get()); 94 } 95 96 return *m_fontFaceSet; 97 } 98 86 99 bool CSSFontSelector::isEmpty() const 87 100 { 88 return m_fonts.isEmpty(); 89 } 90 91 void CSSFontSelector::appendSources(CSSFontFace& fontFace, CSSValueList& srcList, Document* document, bool isInitiatingElementInUserAgentShadowTree) 92 { 93 for (auto& src : srcList) { 94 // An item in the list either specifies a string (local font name) or a URL (remote font to download). 95 CSSFontFaceSrcValue& item = downcast<CSSFontFaceSrcValue>(src.get()); 96 std::unique_ptr<CSSFontFaceSource> source; 97 SVGFontFaceElement* fontFaceElement = nullptr; 98 bool foundSVGFont = false; 99 100 #if ENABLE(SVG_FONTS) 101 foundSVGFont = item.isSVGFontFaceSrc() || item.svgFontFaceElement(); 102 fontFaceElement = item.svgFontFaceElement(); 103 #endif 104 if (!item.isLocal()) { 105 Settings* settings = document ? document->settings() : nullptr; 106 bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled()); 107 if (allowDownloading && item.isSupportedFormat() && document) { 108 if (CachedFont* cachedFont = item.cachedFont(document, foundSVGFont, isInitiatingElementInUserAgentShadowTree)) 109 source = std::make_unique<CSSFontFaceSource>(fontFace, item.resource(), cachedFont); 110 } 111 } else 112 source = std::make_unique<CSSFontFaceSource>(fontFace, item.resource(), nullptr, fontFaceElement); 113 114 if (source) 115 fontFace.adoptSource(WTFMove(source)); 116 } 117 fontFace.sourcesPopulated(); 118 } 119 120 String CSSFontSelector::familyNameFromPrimitive(const CSSPrimitiveValue& value) 121 { 122 if (value.isFontFamily()) 123 return value.fontFamily().familyName; 124 if (!value.isValueID()) 125 return { }; 126 127 // We need to use the raw text for all the generic family types, since @font-face is a way of actually 128 // defining what font to use for those types. 129 switch (value.getValueID()) { 130 case CSSValueSerif: 131 return serifFamily; 132 case CSSValueSansSerif: 133 return sansSerifFamily; 134 case CSSValueCursive: 135 return cursiveFamily; 136 case CSSValueFantasy: 137 return fantasyFamily; 138 case CSSValueMonospace: 139 return monospaceFamily; 140 case CSSValueWebkitPictograph: 141 return pictographFamily; 142 default: 143 return { }; 144 } 145 } 146 147 void CSSFontSelector::registerLocalFontFacesForFamily(const String& familyName) 148 { 149 ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); 150 151 Vector<FontTraitsMask> traitsMasks = FontCache::singleton().getTraitsInFamily(familyName); 152 if (traitsMasks.isEmpty()) 153 return; 154 155 Vector<Ref<CSSFontFace>> faces = { }; 156 for (auto mask : traitsMasks) { 157 Ref<CSSFontFace> face = CSSFontFace::create(*this, nullptr, true); 158 159 RefPtr<CSSValueList> familyList = CSSValueList::createCommaSeparated(); 160 familyList->append(CSSValuePool::singleton().createFontFamilyValue(familyName)); 161 face->setFamilies(*familyList); 162 face->setTraitsMask(mask); 163 face->adoptSource(std::make_unique<CSSFontFaceSource>(face.get(), familyName)); 164 ASSERT(!face->allSourcesFailed()); 165 faces.append(WTFMove(face)); 166 } 167 m_locallyInstalledFontFaces.add(familyName, WTFMove(faces)); 168 } 169 170 void CSSFontSelector::addFontFaceRule(const StyleRuleFontFace& fontFaceRule, bool isInitiatingElementInUserAgentShadowTree) 101 return !m_cssFontFaceSet->faceCount(); 102 } 103 104 void CSSFontSelector::addFontFaceRule(StyleRuleFontFace& fontFaceRule, bool isInitiatingElementInUserAgentShadowTree) 171 105 { 172 106 const StyleProperties& style = fontFaceRule.properties(); … … 202 136 return; 203 137 204 Ref<CSSFontFace> fontFace = CSSFontFace::create(*this); 138 m_creatingFont = true; 139 Ref<CSSFontFace> fontFace = CSSFontFace::create(this, &fontFaceRule); 205 140 206 141 if (!fontFace->setFamilies(*fontFamily)) … … 227 162 return; 228 163 229 appendSources(fontFace, srcList, m_document, isInitiatingElementInUserAgentShadowTree);164 CSSFontFace::appendSources(fontFace, srcList, m_document, isInitiatingElementInUserAgentShadowTree); 230 165 if (fontFace->allSourcesFailed()) 231 166 return; 232 167 233 for (auto& item : familyList) { 234 String familyName = familyNameFromPrimitive(downcast<CSSPrimitiveValue>(item.get())); 235 if (familyName.isEmpty()) 236 continue; 237 238 auto addResult = m_fontFaces.add(familyName, Vector<Ref<CSSFontFace>>()); 239 auto& familyFontFaces = addResult.iterator->value; 240 if (addResult.isNewEntry) { 241 registerLocalFontFacesForFamily(familyName); 242 familyFontFaces = { }; 243 } 244 245 familyFontFaces.append(fontFace.copyRef()); 246 247 ++m_version; 248 } 168 m_cssFontFaceSet->add(fontFace.get()); 169 m_creatingFont = false; 170 ++m_version; 249 171 } 250 172 … … 272 194 { 273 195 dispatchInvalidationCallbacks(); 196 } 197 198 void CSSFontSelector::fontModified() 199 { 200 if (!m_creatingFont) 201 dispatchInvalidationCallbacks(); 274 202 } 275 203 … … 305 233 } 306 234 307 class FontFaceComparator {308 public:309 FontFaceComparator(FontTraitsMask desiredTraitsMaskForComparison)310 : m_desiredTraitsMaskForComparison(desiredTraitsMaskForComparison)311 {312 ASSERT_WITH_SECURITY_IMPLICATION(m_desiredTraitsMaskForComparison & FontWeightMask);313 }314 315 bool operator()(const CSSFontFace& first, const CSSFontFace& second)316 {317 FontTraitsMask firstTraitsMask = first.traitsMask();318 FontTraitsMask secondTraitsMask = second.traitsMask();319 320 bool firstHasDesiredStyle = firstTraitsMask & m_desiredTraitsMaskForComparison & FontStyleMask;321 bool secondHasDesiredStyle = secondTraitsMask & m_desiredTraitsMaskForComparison & FontStyleMask;322 323 if (firstHasDesiredStyle != secondHasDesiredStyle)324 return firstHasDesiredStyle;325 326 if ((m_desiredTraitsMaskForComparison & FontStyleItalicMask) && !first.isLocalFallback() && !second.isLocalFallback()) {327 // Prefer a font that has indicated that it can only support italics to a font that claims to support328 // all styles. The specialized font is more likely to be the one the author wants used.329 bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask);330 bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask);331 if (firstRequiresItalics != secondRequiresItalics)332 return firstRequiresItalics;333 }334 335 if (secondTraitsMask & m_desiredTraitsMaskForComparison & FontWeightMask)336 return false;337 if (firstTraitsMask & m_desiredTraitsMaskForComparison & FontWeightMask)338 return true;339 340 // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says :341 // - If the desired weight is less than 400, weights below the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found.342 // - If the desired weight is greater than 500, weights above the desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found.343 // - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used.344 // - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used.345 346 static const unsigned fallbackRuleSets = 9;347 static const unsigned rulesPerSet = 8;348 static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {349 { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },350 { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },351 { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },352 { FontWeight500Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },353 { FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },354 { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },355 { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },356 { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },357 { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }358 };359 360 unsigned ruleSetIndex = 0;361 for (; !(m_desiredTraitsMaskForComparison & (1 << (FontWeight100Bit + ruleSetIndex))); ruleSetIndex++) { }362 363 const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];364 for (unsigned i = 0; i < rulesPerSet; ++i) {365 if (secondTraitsMask & weightFallbackRule[i])366 return false;367 if (firstTraitsMask & weightFallbackRule[i])368 return true;369 }370 371 return false;372 }373 374 private:375 FontTraitsMask m_desiredTraitsMaskForComparison;376 };377 378 235 FontRanges CSSFontSelector::fontRangesForFamily(const FontDescription& fontDescription, const AtomicString& familyName) 379 236 { … … 382 239 383 240 AtomicString familyForLookup = resolveGenericFamilyFirst ? resolveGenericFamily(m_document, fontDescription, familyName) : familyName; 384 CSSSegmentedFontFace* face = getFontFace(fontDescription, familyForLookup);241 CSSSegmentedFontFace* face = m_cssFontFaceSet->getFontFace(fontDescription.traitsMask(), familyForLookup); 385 242 if (!face) { 386 243 if (!resolveGenericFamilyFirst) … … 392 249 } 393 250 394 CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& family)395 {396 auto iterator = m_fontFaces.find(family);397 if (iterator == m_fontFaces.end())398 return nullptr;399 auto& familyFontFaces = iterator->value;400 401 auto& segmentedFontFaceCache = m_fonts.add(family, HashMap<unsigned, std::unique_ptr<CSSSegmentedFontFace>>()).iterator->value;402 403 FontTraitsMask traitsMask = fontDescription.traitsMask();404 405 auto& face = segmentedFontFaceCache.add(traitsMask, nullptr).iterator->value;406 if (face)407 return face.get();408 409 face = std::make_unique<CSSSegmentedFontFace>(*this);410 411 Vector<std::reference_wrapper<CSSFontFace>, 32> candidateFontFaces;412 for (int i = familyFontFaces.size() - 1; i >= 0; --i) {413 CSSFontFace& candidate = familyFontFaces[i];414 unsigned candidateTraitsMask = candidate.traitsMask();415 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))416 continue;417 candidateFontFaces.append(candidate);418 }419 420 auto localIterator = m_locallyInstalledFontFaces.find(family);421 if (localIterator != m_locallyInstalledFontFaces.end()) {422 for (auto& candidate : localIterator->value) {423 unsigned candidateTraitsMask = candidate->traitsMask();424 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))425 continue;426 candidateFontFaces.append(candidate);427 }428 }429 430 std::stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), FontFaceComparator(traitsMask));431 for (auto& candidate : candidateFontFaces)432 face->appendFontFace(candidate.get());433 434 return face.get();435 }436 437 251 void CSSFontSelector::clearDocument() 438 252 { … … 455 269 456 270 // FIXME: This object should outlive the Document. 457 m_fontFaces.clear(); 458 m_locallyInstalledFontFaces.clear(); 459 m_fonts.clear(); 271 m_cssFontFaceSet->clear(); 460 272 m_clients.clear(); 461 273 } -
trunk/Source/WebCore/css/CSSFontSelector.h
r196747 r196954 28 28 29 29 #include "CSSFontFace.h" 30 #include "CSSFontFaceSet.h" 30 31 #include "CachedResourceHandle.h" 31 32 #include "Font.h" … … 49 50 class StyleRuleFontFace; 50 51 51 class CSSFontSelector final : public FontSelector {52 class CSSFontSelector final : public FontSelector, public CSSFontFaceSetClient { 52 53 public: 53 54 static Ref<CSSFontSelector> create(Document& document) … … 63 64 virtual size_t fallbackFontCount() override; 64 65 virtual RefPtr<Font> fallbackFontAt(const FontDescription&, size_t) override; 65 CSSSegmentedFontFace* getFontFace(const FontDescription&, const AtomicString& family);66 66 67 67 void clearDocument(); 68 68 69 static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree); 70 void addFontFaceRule(const StyleRuleFontFace&, bool isInitiatingElementInUserAgentShadowTree); 69 void addFontFaceRule(StyleRuleFontFace&, bool isInitiatingElementInUserAgentShadowTree); 71 70 72 71 void fontLoaded(); … … 82 81 void beginLoadingFontSoon(CachedFont*); 83 82 84 static String familyNameFromPrimitive(const CSSPrimitiveValue&);83 FontFaceSet& fontFaceSet(); 85 84 86 85 private: … … 89 88 void dispatchInvalidationCallbacks(); 90 89 90 virtual void fontModified() override; 91 91 92 void beginLoadTimerFired(); 92 93 93 void registerLocalFontFacesForFamily(const String&);94 95 94 Document* m_document; 96 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_fontFaces; 97 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_locallyInstalledFontFaces; 98 HashMap<String, HashMap<unsigned, std::unique_ptr<CSSSegmentedFontFace>>, ASCIICaseInsensitiveHash> m_fonts; 95 RefPtr<FontFaceSet> m_fontFaceSet; 96 Ref<CSSFontFaceSet> m_cssFontFaceSet; 99 97 HashSet<FontSelectorClient*> m_clients; 100 98 … … 104 102 unsigned m_uniqueId; 105 103 unsigned m_version; 104 bool m_creatingFont { false }; 106 105 }; 107 106 -
trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp
r196747 r196954 38 38 namespace WebCore { 39 39 40 CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector& fontSelector) 41 : m_fontSelector(fontSelector) 40 CSSSegmentedFontFace::CSSSegmentedFontFace() 42 41 { 43 42 } -
trunk/Source/WebCore/css/CSSSegmentedFontFace.h
r196747 r196954 43 43 WTF_MAKE_FAST_ALLOCATED; 44 44 public: 45 CSSSegmentedFontFace( CSSFontSelector&);45 CSSSegmentedFontFace(); 46 46 ~CSSSegmentedFontFace(); 47 48 CSSFontSelector& fontSelector() const { return m_fontSelector; }49 47 50 48 void appendFontFace(Ref<CSSFontFace>&&); … … 52 50 FontRanges fontRanges(const FontDescription&); 53 51 52 Vector<Ref<CSSFontFace>, 1>& constituentFaces() { return m_fontFaces; } 53 54 54 private: 55 55 virtual void fontLoaded(CSSFontFace&) override; 56 56 57 CSSFontSelector& m_fontSelector;58 57 HashMap<FontDescriptionKey, FontRanges, FontDescriptionKeyHash, WTF::SimpleClassHashTraits<FontDescriptionKey>> m_cache; 59 58 Vector<Ref<CSSFontFace>, 1> m_fontFaces; -
trunk/Source/WebCore/css/FontFace.cpp
r196747 r196954 76 76 if (is<CSSValueList>(value.get())) { 77 77 CSSValueList& srcList = downcast<CSSValueList>(*value); 78 CSSFont Selector::appendSources(result->backing(), srcList, &downcast<Document>(context), false);78 CSSFontFace::appendSources(result->backing(), srcList, &downcast<Document>(context), false); 79 79 } else { 80 80 ec = SYNTAX_ERR; … … 111 111 } 112 112 113 Ref<FontFace> FontFace::create(JSC::ExecState& execState, CSSFontFace& face) 114 { 115 return adoptRef(*new FontFace(execState, face)); 116 } 117 113 118 FontFace::FontFace(JSC::ExecState& execState, CSSFontSelector& fontSelector) 114 : m_backing(CSSFontFace::create(fontSelector, this)) 119 : m_weakPtrFactory(this) 120 , m_backing(CSSFontFace::create(&fontSelector, nullptr, this)) 115 121 , m_promise(createPromise(execState)) 116 122 { … … 118 124 } 119 125 126 FontFace::FontFace(JSC::ExecState& execState, CSSFontFace& face) 127 : m_weakPtrFactory(this) 128 , m_backing(face) 129 , m_promise(createPromise(execState)) 130 { 131 m_backing->addClient(*this); 132 } 133 120 134 FontFace::~FontFace() 121 135 { 122 136 m_backing->removeClient(*this); 137 } 138 139 WeakPtr<FontFace> FontFace::createWeakPtr() const 140 { 141 return m_weakPtrFactory.createWeakPtr(); 123 142 } 124 143 … … 318 337 } 319 338 320 void FontFace:: stateChanged(CSSFontFace& face, CSSFontFace::Status, CSSFontFace::Status newState)339 void FontFace::fontStateChanged(CSSFontFace& face, CSSFontFace::Status, CSSFontFace::Status newState) 321 340 { 322 341 ASSERT_UNUSED(face, &face == m_backing.ptr()); 323 342 switch (newState) { 343 case CSSFontFace::Status::Loading: 344 // We still need to resolve promises when loading completes, even if all references to use have fallen out of scope. 345 ref(); 346 break; 324 347 case CSSFontFace::Status::TimedOut: 325 348 rejectPromise(NETWORK_ERR); 349 deref(); 326 350 return; 327 351 case CSSFontFace::Status::Success: 328 352 fulfillPromise(); 353 deref(); 329 354 return; 330 355 case CSSFontFace::Status::Failure: 331 356 rejectPromise(NETWORK_ERR); 357 deref(); 332 358 return; 333 359 default: -
trunk/Source/WebCore/css/FontFace.h
r196747 r196954 34 34 #include <wtf/RefCounted.h> 35 35 #include <wtf/RefPtr.h> 36 #include <wtf/WeakPtr.h> 36 37 #include <wtf/text/WTFString.h> 37 38 … … 49 50 public: 50 51 static RefPtr<FontFace> create(JSC::ExecState&, ScriptExecutionContext&, const String& family, const Deprecated::ScriptValue& source, const Dictionary& descriptors, ExceptionCode&); 52 static Ref<FontFace> create(JSC::ExecState&, CSSFontFace&); 51 53 virtual ~FontFace(); 52 54 … … 77 79 static RefPtr<CSSValue> parseString(const String&, CSSPropertyID); 78 80 81 virtual void fontStateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override; 82 83 WeakPtr<FontFace> createWeakPtr() const; 84 79 85 private: 80 86 FontFace(JSC::ExecState&, CSSFontSelector&); 81 82 virtual void stateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override; 87 FontFace(JSC::ExecState&, CSSFontFace&); 83 88 84 89 void fulfillPromise(); 85 90 void rejectPromise(ExceptionCode); 86 91 92 WeakPtrFactory<FontFace> m_weakPtrFactory; 87 93 Ref<CSSFontFace> m_backing; 88 94 Promise m_promise; -
trunk/Source/WebCore/css/FontFaceSet.cpp
r196900 r196954 43 43 } 44 44 45 FontFaceSet::FontFaceSet(JSC::ExecState& execState, Document& document, const Vector<RefPtr<FontFace>>& initialFaces) 45 Ref<FontFaceSet> FontFaceSet::create(Document& document, const Vector<RefPtr<FontFace>>& initialFaces) 46 { 47 Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(document, initialFaces)); 48 result->suspendIfNeeded(); 49 return result; 50 } 51 52 Ref<FontFaceSet> FontFaceSet::create(Document& document, CSSFontFaceSet& backing) 53 { 54 Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(document, backing)); 55 result->suspendIfNeeded(); 56 return result; 57 } 58 59 FontFaceSet::FontFaceSet(Document& document, const Vector<RefPtr<FontFace>>& initialFaces) 46 60 : ActiveDOMObject(&document) 47 , m_backing( *this)48 , m_promise(createPromise(execState)) 49 { 61 , m_backing(CSSFontFaceSet::create()) 62 { 63 m_backing->addClient(*this); 50 64 for (auto& face : initialFaces) 51 65 add(face.get()); 52 66 } 53 67 68 FontFaceSet::FontFaceSet(Document& document, CSSFontFaceSet& backing) 69 : ActiveDOMObject(&document) 70 , m_backing(backing) 71 { 72 m_backing->addClient(*this); 73 } 74 54 75 FontFaceSet::~FontFaceSet() 55 76 { 77 m_backing->removeClient(*this); 56 78 } 57 79 … … 61 83 } 62 84 63 bool FontFaceSet::Iterator::next( FontFace*& key, FontFace*& value)85 bool FontFaceSet::Iterator::next(JSC::ExecState& execState, RefPtr<FontFace>& key, RefPtr<FontFace>& value) 64 86 { 65 87 if (m_index == m_target->size()) 66 88 return true; 67 key = m_target-> m_backing[m_index++].wrapper();89 key = m_target->backing()[m_index++].wrapper(execState); 68 90 value = key; 69 91 return false; … … 79 101 } 80 102 81 bool FontFaceSet::has( FontFace*face) const103 bool FontFaceSet::has(RefPtr<WebCore::FontFace> face) const 82 104 { 83 105 if (!face) 84 106 return false; 85 return m_backing .hasFace(face->backing());107 return m_backing->hasFace(face->backing()); 86 108 } 87 109 88 110 size_t FontFaceSet::size() const 89 111 { 90 return m_backing .faceCount();91 } 92 93 FontFaceSet& FontFaceSet::add( FontFace*face)94 { 95 if (face && !m_backing .hasFace(face->backing()))96 m_backing .add(face->backing());112 return m_backing->faceCount(); 113 } 114 115 FontFaceSet& FontFaceSet::add(RefPtr<WebCore::FontFace> face) 116 { 117 if (face && !m_backing->hasFace(face->backing())) 118 m_backing->add(face->backing()); 97 119 return *this; 98 120 } 99 121 100 bool FontFaceSet::remove( FontFace*face)122 bool FontFaceSet::remove(RefPtr<WebCore::FontFace> face) 101 123 { 102 124 if (!face) 103 125 return false; 104 126 105 bool result = m_backing .hasFace(face->backing());127 bool result = m_backing->hasFace(face->backing()); 106 128 if (result) 107 m_backing .remove(face->backing());129 m_backing->remove(face->backing()); 108 130 return result; 109 131 } … … 111 133 void FontFaceSet::clear() 112 134 { 113 while (m_backing .faceCount())114 m_backing .remove(m_backing[0]);115 } 116 117 void FontFaceSet::load( const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode& ec)118 { 119 auto matchingFaces = m_backing .matchingFaces(font, text, ec);135 while (m_backing->faceCount()) 136 m_backing->remove(m_backing.get()[0]); 137 } 138 139 void FontFaceSet::load(JSC::ExecState& execState, const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode& ec) 140 { 141 auto matchingFaces = m_backing->matchingFaces(font, text, ec); 120 142 if (ec) 121 143 return; … … 140 162 141 163 for (auto& face : matchingFaces) { 142 pendingPromise->faces.append(face.get().wrapper( ));164 pendingPromise->faces.append(face.get().wrapper(execState)); 143 165 if (face.get().status() == CSSFontFace::Status::Success) 144 166 continue; 145 167 waiting = true; 146 auto& vector = m_pendingPromises.add(RefPtr< FontFace>(face.get().wrapper()), Vector<Ref<PendingPromise>>()).iterator->value;168 auto& vector = m_pendingPromises.add(RefPtr<CSSFontFace>(&face.get()), Vector<Ref<PendingPromise>>()).iterator->value; 147 169 vector.append(pendingPromise.copyRef()); 148 170 } … … 154 176 bool FontFaceSet::check(const String& family, const String& text, ExceptionCode& ec) 155 177 { 156 return m_backing .check(family, text, ec);178 return m_backing->check(family, text, ec); 157 179 } 158 180 … … 161 183 if (!m_promise) { 162 184 m_promise = createPromise(execState); 163 if (m_backing .status() == CSSFontFaceSet::Status::Loaded)185 if (m_backing->status() == CSSFontFaceSet::Status::Loaded) 164 186 fulfillPromise(); 165 187 } … … 169 191 String FontFaceSet::status() const 170 192 { 171 switch (m_backing .status()) {193 switch (m_backing->status()) { 172 194 case CSSFontFaceSet::Status::Loading: 173 195 return String("loading", String::ConstructFromLiteral); … … 181 203 bool FontFaceSet::canSuspendForDocumentSuspension() const 182 204 { 183 return m_backing .status() == CSSFontFaceSet::Status::Loaded;205 return m_backing->status() == CSSFontFaceSet::Status::Loaded; 184 206 } 185 207 … … 210 232 void FontFaceSet::faceFinished(CSSFontFace& face, CSSFontFace::Status newStatus) 211 233 { 212 auto iterator = m_pendingPromises.find( face.wrapper());234 auto iterator = m_pendingPromises.find(&face); 213 235 if (iterator == m_pendingPromises.end()) 214 236 return; -
trunk/Source/WebCore/css/FontFaceSet.h
r196900 r196954 39 39 #include <wtf/text/WTFString.h> 40 40 41 namespace JSC { 42 class ExecState; 43 } 44 41 45 namespace WebCore { 42 46 … … 46 50 class FontFaceSet final : public RefCounted<FontFaceSet>, public CSSFontFaceSetClient, public EventTargetWithInlineData, public ActiveDOMObject { 47 51 public: 48 static Ref<FontFaceSet> create(JSC::ExecState& execState, Document& document, const Vector<RefPtr<FontFace>>& initialFaces) 49 { 50 Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(execState, document, initialFaces)); 51 result->suspendIfNeeded(); 52 return result; 53 } 52 static Ref<FontFaceSet> create(Document&, const Vector<RefPtr<FontFace>>& initialFaces); 53 static Ref<FontFaceSet> create(Document&, CSSFontFaceSet& backing); 54 54 virtual ~FontFaceSet(); 55 55 56 bool has( FontFace*) const;56 bool has(RefPtr<WebCore::FontFace>) const; 57 57 size_t size() const; 58 FontFaceSet& add( FontFace*);59 bool remove( FontFace*);58 FontFaceSet& add(RefPtr<WebCore::FontFace>); 59 bool remove(RefPtr<WebCore::FontFace>); 60 60 void clear(); 61 61 62 void load( const String& font, DeferredWrapper&& promise, ExceptionCode& ec) { load(font, String(" ", String::ConstructFromLiteral), WTFMove(promise), ec); }63 void load( const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode&);62 void load(JSC::ExecState& execState, const String& font, DeferredWrapper&& promise, ExceptionCode& ec) { load(execState, font, String(" ", String::ConstructFromLiteral), WTFMove(promise), ec); } 63 void load(JSC::ExecState&, const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode&); 64 64 bool check(const String& font, ExceptionCode& ec) { return check(font, String(" ", String::ConstructFromLiteral), ec); } 65 65 bool check(const String& font, const String& text, ExceptionCode&); … … 70 70 Promise& promise(JSC::ExecState&); 71 71 72 CSSFontFaceSet& backing() { return m_backing; } 73 72 74 class Iterator { 73 75 public: 74 76 explicit Iterator(FontFaceSet&); 75 bool next( FontFace*& nextKey, FontFace*& nextValue);77 bool next(JSC::ExecState&, RefPtr<FontFace>& nextKey, RefPtr<FontFace>& nextValue); 76 78 77 79 private: 78 80 Ref<FontFaceSet> m_target; 79 size_t m_index { 0 }; 81 size_t m_index { 0 }; // FIXME: There needs to be a mechanism to handle when fonts are added or removed from the middle of the FontFaceSet. 80 82 }; 81 83 Iterator createIterator() { return Iterator(*this); } … … 101 103 }; 102 104 103 FontFaceSet(JSC::ExecState&, Document&, const Vector<RefPtr<FontFace>>&); 105 FontFaceSet(Document&, const Vector<RefPtr<FontFace>>&); 106 FontFaceSet(Document&, CSSFontFaceSet&); 104 107 105 108 void fulfillPromise(); … … 120 123 virtual void derefEventTarget() override { deref(); } 121 124 122 CSSFontFaceSetm_backing;123 HashMap<RefPtr< FontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;125 Ref<CSSFontFaceSet> m_backing; 126 HashMap<RefPtr<CSSFontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises; 124 127 Optional<Promise> m_promise; 125 128 }; -
trunk/Source/WebCore/css/FontFaceSet.idl
r196900 r196954 30 30 31 31 [ 32 ConstructorCallWith= ScriptState&Document,32 ConstructorCallWith=Document, 33 33 Constructor(sequence<FontFace> initialFaces) 34 34 ] interface FontFaceSet : EventTarget { … … 49 49 attribute EventHandler onloadingerror; 50 50 51 [RaisesException ] Promise load(DOMString font, optional DOMString text);51 [RaisesException, CallWith=ScriptState] Promise load(DOMString font, optional DOMString text); 52 52 [RaisesException] boolean check(DOMString font, optional DOMString text); 53 53 -
trunk/Source/WebCore/dom/Document.cpp
r196888 r196954 63 63 #include "ExtensionStyleSheets.h" 64 64 #include "FocusController.h" 65 #include "Font Loader.h"65 #include "FontFaceSet.h" 66 66 #include "FormController.h" 67 67 #include "FrameLoader.h" … … 6685 6685 #endif 6686 6686 6687 #if ENABLE(FONT_LOAD_EVENTS) 6688 RefPtr<FontLoader> Document::fonts() 6689 { 6690 if (!m_fontloader) 6691 m_fontloader = FontLoader::create(this); 6692 return m_fontloader; 6693 } 6694 #endif 6687 Ref<FontFaceSet> Document::fonts() 6688 { 6689 return fontSelector().fontFaceSet(); 6690 } 6695 6691 6696 6692 float Document::deviceScaleFactor() const -
trunk/Source/WebCore/dom/Document.h
r196888 r196954 202 202 #endif 203 203 204 #if ENABLE(FONT_LOAD_EVENTS) 205 class FontLoader; 206 #endif 204 class FontFaceSet; 207 205 208 206 typedef int ExceptionCode; … … 1268 1266 WEBCORE_EXPORT virtual SecurityOrigin* topOrigin() const override final; 1269 1267 1270 #if ENABLE(FONT_LOAD_EVENTS) 1271 RefPtr<FontLoader> fonts(); 1272 #endif 1268 Ref<FontFaceSet> fonts(); 1273 1269 1274 1270 void ensurePlugInsInjectedScript(DOMWrapperWorld&); … … 1752 1748 RefPtr<CSSFontSelector> m_fontSelector; 1753 1749 1754 #if ENABLE(FONT_LOAD_EVENTS)1755 RefPtr<FontLoader> m_fontloader;1756 #endif1757 1758 1750 #if ENABLE(WEB_REPLAY) 1759 1751 RefPtr<JSC::InputCursor> m_inputCursor; -
trunk/Source/WebCore/dom/Document.idl
r195778 r196954 266 266 267 267 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT 268 [Conditional=FONT_LOAD_EVENTS] readonly attribute FontLoaderfonts;268 readonly attribute FontFaceSet fonts; 269 269 #endif 270 270 -
trunk/Source/WebCore/svg/SVGFontFaceElement.h
r191871 r196954 51 51 void rebuildFontFace(); 52 52 53 const StyleRuleFontFace& fontFaceRule() const{ return m_fontFaceRule.get(); }53 StyleRuleFontFace& fontFaceRule() { return m_fontFaceRule.get(); } 54 54 55 55 private:
Note: See TracChangeset
for help on using the changeset viewer.