Changeset 196954 in webkit


Ignore:
Timestamp:
Feb 22, 2016 1:40:02 PM (8 years ago)
Author:
mmaxfield@apple.com
Message:

[Font Loading] Split CSSFontSelector into a FontFaceSet implementation and the rest of the class
https://bugs.webkit.org/show_bug.cgi?id=153347

Reviewed by Antti Koivisto.

Source/WebCore:

This patch implements the document.fonts Javascript object. It does so by briding the
already-existing FontFaceSet Javascript object with the CSSFontSelector WebCore object.
CSSFontSelector used to hold internal objects for each @font-face object in the
Document. These objects have been moved into CSSFontFaceSet, so CSSFontSelector simply
just owns an instance of a CSSFontFaceSet.

The lifetime of the FontFace and FontFaceSet objects is a little interesting: because
all the ownership references are inside the WebCore CSSFontFace{,Set} objects, the
higher-level Javascript FontFace{,Set} objects are held through a WeakPtr. This means
that if all the references to these higher-level objects go away, and you re-query the
document for its FontFace objects, you may get a new object (albeit with the same
state as a previous object). However, this won't occur if there are any references to
the old object, which means it is almost not observable.

This patch doesn't implement the relationship between the CSSOM and the FontFace
objects. Changing one should result in a change in the other, but that will be
implemented in a forthcoming patch.

This patch also doesn't alter the lifetime of the CSSFontSelector, which means that all
the Document's fonts may be destroyed and recreated from CSS. There are a few things
which can trigger this. A subsequent patch will make the CSSFontSelector outlive the
Document.

This patch does implement (and test) the ability to add a new FontFace to the Document
to cause a relayout, as well as changing properties of existing FontFace objects already
in the Document to cause a relayout.

Test: fast/text/font-face-set-document.html

  • Modules/fetch/FetchHeaders.cpp:

(WebCore::FetchHeaders::Iterator::next): Pass an extra argument.

  • Modules/fetch/FetchHeaders.h:
  • bindings/js/JSKeyValueIterator.h: The ExecState is necessary to build an external

wrapper from an existing CSSFontFace object.
(WebCore::JSKeyValueIterator<JSWrapper>::next):

  • css/CSSFontFace.cpp:

(WebCore::CSSFontFace::appendSources): Moved from CSSFontSelector.
(WebCore::CSSFontFace::CSSFontFace):
(WebCore::CSSFontFace::notifyClientsOfFontPropertyChange):
(WebCore::CSSFontFace::setFamilies):
(WebCore::CSSFontFace::calculateStyle): Shared code between CSSFontFaceSet and
CSSFontFace.
(WebCore::CSSFontFace::setStyle): Update to use calculateStyle().
(WebCore::CSSFontFace::calculateWeight): Ditto.
(WebCore::CSSFontFace::setWeight): Update to use caculateWeight().
(WebCore::CSSFontFace::setUnicodeRange): Notify clients.
(WebCore::CSSFontFace::setVariantLigatures): Ditto.
(WebCore::CSSFontFace::setVariantPosition): Ditto.
(WebCore::CSSFontFace::setVariantCaps): Ditto.
(WebCore::CSSFontFace::setVariantNumeric): Ditto.
(WebCore::CSSFontFace::setVariantAlternates): Ditto.
(WebCore::CSSFontFace::setVariantEastAsian): Ditto.
(WebCore::CSSFontFace::setFeatureSettings): Ditto.
(WebCore::CSSFontFace::removeClient):
(WebCore::CSSFontFace::wrapper): Build a new wrapper if one doesn't already
exist. Note that this requires an ExecState to create a promise.
(WebCore::CSSFontFace::setStatus):
(WebCore::CSSFontFace::fontLoaded):
(WebCore::CSSFontFace::pump):
(WebCore::CSSFontFace::font):

  • css/CSSFontFace.h:
  • css/CSSFontFaceSet.cpp:

(WebCore::CSSFontFaceSet::CSSFontFaceSet): Moved code from CSSFontSelector.
(WebCore::CSSFontFaceSet::~CSSFontFaceSet):
(WebCore::CSSFontFaceSet::addClient): This object can now have multiple
clients.
(WebCore::CSSFontFaceSet::removeClient):
(WebCore::CSSFontFaceSet::incrementActiveCount): Update for multiple clients.
(WebCore::CSSFontFaceSet::decrementActiveCount): Ditto.
(WebCore::CSSFontFaceSet::hasFace):
(WebCore::CSSFontFaceSet::registerLocalFontFacesForFamily): Moved from
CSSFontSelector.
(WebCore::CSSFontFaceSet::familyNameFromPrimitive): Ditto.
(WebCore::CSSFontFaceSet::addToFacesLookupTable): This helper function can
be used when a property of a FontFace is changed.
(WebCore::CSSFontFaceSet::add): Update to use addToFacesLookupTable().
(WebCore::CSSFontFaceSet::removeFromFacesLookupTable): Same as
addToFacesLookupTable().
(WebCore::CSSFontFaceSet::remove): Update to use removeFromFacesLookupTable().
(WebCore::CSSFontFaceSet::clear):
(WebCore::CSSFontFaceSet::operator[]):
(WebCore::computeFontTraitsMask): Moved from CSSFontSelector.
(WebCore::CSSFontFaceSet::matchingFaces): Update to use new data structures.
(WebCore::FontFaceComparator::FontFaceComparator): Moved from
CSSFontSelector.
(WebCore::FontFaceComparator::operator()):
(WebCore::CSSFontFaceSet::getFontFace): Update to use new data structures.
(WebCore::CSSFontFaceSet::fontStateChanged): Update to use multiple clients.
(WebCore::CSSFontFaceSet::fontPropertyChanged): We must update our internal
data structure if the family name changed.
(WebCore::extractFamilies): Deleted.
(WebCore::familiesIntersect): Deleted.
(WebCore::CSSFontFaceSet::load): Deleted.
(WebCore::CSSFontFaceSet::stateChanged): Deleted.

  • css/CSSFontFaceSet.h: Now needs to be RefCounted. New data structures are

taken from CSSFontSelector.
(WebCore::CSSFontFaceSetClient::faceFinished):
(WebCore::CSSFontFaceSetClient::fontModified):
(WebCore::CSSFontFaceSetClient::startedLoading):
(WebCore::CSSFontFaceSetClient::completedLoading):

  • css/CSSFontFaceSource.h:
  • css/CSSFontSelector.cpp: Move code into CSSFontFaceSet.

(WebCore::CSSFontSelector::CSSFontSelector):
(WebCore::CSSFontSelector::~CSSFontSelector):
(WebCore::CSSFontSelector::fontFaceSet):
(WebCore::CSSFontSelector::isEmpty):
(WebCore::CSSFontSelector::addFontFaceRule):
(WebCore::CSSFontSelector::fontModified):
(WebCore::CSSFontSelector::fontRangesForFamily):
(WebCore::CSSFontSelector::clearDocument):
(WebCore::CSSFontSelector::appendSources): Deleted.
(WebCore::CSSFontSelector::familyNameFromPrimitive): Deleted.
(WebCore::CSSFontSelector::registerLocalFontFacesForFamily): Deleted.
(WebCore::FontFaceComparator::FontFaceComparator): Deleted.
(WebCore::FontFaceComparator::operator()): Deleted.
(WebCore::CSSFontSelector::getFontFace): Deleted.

  • css/CSSFontSelector.h:
  • css/CSSSegmentedFontFace.cpp:

(WebCore::CSSSegmentedFontFace::CSSSegmentedFontFace):

  • css/CSSSegmentedFontFace.h:
  • css/FontFace.cpp:

(WebCore::FontFace::create):
(WebCore::FontFace::FontFace):
(WebCore::FontFace::createWeakPtr):
(WebCore::FontFace::fontStateChanged):
(WebCore::FontFace::stateChanged): Deleted.

  • css/FontFace.h:
  • css/FontFaceSet.cpp:

(WebCore::FontFaceSet::create):
(WebCore::FontFaceSet::FontFaceSet):
(WebCore::FontFaceSet::~FontFaceSet):
(WebCore::FontFaceSet::Iterator::next):
(WebCore::FontFaceSet::has):
(WebCore::FontFaceSet::size):
(WebCore::FontFaceSet::add):
(WebCore::FontFaceSet::remove):
(WebCore::FontFaceSet::clear):
(WebCore::FontFaceSet::load):
(WebCore::FontFaceSet::check):
(WebCore::FontFaceSet::status):
(WebCore::FontFaceSet::canSuspendForDocumentSuspension):
(WebCore::FontFaceSet::faceFinished):

  • css/FontFaceSet.h:
  • css/FontFaceSet.idl:
  • dom/Document.cpp:

(WebCore::Document::fonts):

  • dom/Document.h:
  • dom/Document.idl:
  • svg/SVGFontFaceElement.h:

LayoutTests:

  • fast/text/font-face-javascript.html:
  • fast/text/font-face-set-document-expected.txt: Added.
  • fast/text/font-face-set-document.html: Added.
Location:
trunk
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r196948 r196954  
     12016-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
    1122016-02-22  Konstantin Tokarev  <annulen@yandex.ru>
    213
  • trunk/LayoutTests/fast/text/font-face-javascript.html

    r196604 r196954  
    11<!DOCTYPE html>
     2<html>
    23<head>
    34<script src="../../resources/js-test-pre.js"></script>
  • trunk/Source/WebCore/ChangeLog

    r196947 r196954  
     12016-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
    11582016-02-22  Konstantin Tokarev  <annulen@yandex.ru>
    2159
  • trunk/Source/WebCore/Modules/fetch/FetchHeaders.cpp

    r196128 r196954  
    180180}
    181181
    182 bool FetchHeaders::Iterator::next(String& nextKey, String& nextValue)
     182bool FetchHeaders::Iterator::next(JSC::ExecState&, String& nextKey, String& nextValue)
    183183{
    184184    while (m_currentIndex < m_keys.size()) {
  • trunk/Source/WebCore/Modules/fetch/FetchHeaders.h

    r196900 r196954  
    3434#include "HTTPHeaderMap.h"
    3535
     36namespace JSC {
     37class ExecState;
     38}
     39
    3640namespace WebCore {
    3741
     
    6670    public:
    6771        explicit Iterator(FetchHeaders&);
    68         bool next(String& nextKey, String& nextValue);
     72        bool next(JSC::ExecState&, String& nextKey, String& nextValue);
    6973
    7074    private:
  • trunk/Source/WebCore/bindings/js/JSKeyValueIterator.h

    r196900 r196954  
    130130    typename JSWrapper::IteratorValue nextValue;
    131131    auto iterator = wrapper->wrapped().createIterator();
    132     while (!iterator.next(nextKey, nextValue)) {
     132    while (!iterator.next(state, nextKey, nextValue)) {
    133133        JSC::MarkedArgumentBuffer arguments;
    134134        arguments.append(toJS(&state, wrapper->globalObject(), nextValue));
     
    154154    typename JSWrapper::IteratorKey nextKey;
    155155    typename JSWrapper::IteratorValue nextValue;
    156     if (m_iterator.next(nextKey, nextValue)) {
     156    if (m_iterator.next(state, nextKey, nextValue)) {
    157157        value = JSC::jsUndefined();
    158158        return true;
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r196900 r196954  
    40404040    return "${svgNativeType}*" if $svgNativeType;
    40414041    return "RefPtr<DOMStringList>" if $type eq "DOMStringList";
     4042    return "RefPtr<FontFace>" if $type eq "FontFace";
    40424043    return "RefPtr<${type}>" if $codeGenerator->IsTypedArrayType($type) and not $type eq "ArrayBuffer";
    40434044    return $nativeType{$type} if exists $nativeType{$type};
  • trunk/Source/WebCore/css/CSSFontFace.cpp

    r196747 r196954  
    2828
    2929#include "CSSFontFaceSource.h"
     30#include "CSSFontFaceSrcValue.h"
    3031#include "CSSFontFamily.h"
    3132#include "CSSFontFeatureValue.h"
     
    3940#include "Font.h"
    4041#include "FontDescription.h"
    41 #include "FontLoader.h"
     42#include "FontFace.h"
    4243#include "FontVariantBuilder.h"
    4344#include "RuntimeEnabledFeatures.h"
     45#include "Settings.h"
    4446#include "StyleProperties.h"
     47#include "StyleRule.h"
    4548
    4649namespace WebCore {
    4750
    48 CSSFontFace::CSSFontFace(CSSFontSelector& fontSelector, FontFace* wrapper, bool isLocalFallback)
     51void 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
     80CSSFontFace::CSSFontFace(CSSFontSelector* fontSelector, StyleRuleFontFace* cssConnection, FontFace* wrapper, bool isLocalFallback)
    4981    : m_fontSelector(fontSelector)
    50     , m_wrapper(wrapper)
     82    , m_cssConnection(cssConnection)
     83    , m_wrapper(wrapper ? wrapper->createWeakPtr() : WeakPtr<FontFace>())
    5184    , m_isLocalFallback(isLocalFallback)
    5285{
     
    5588CSSFontFace::~CSSFontFace()
    5689{
     90}
     91
     92void CSSFontFace::notifyClientsOfFontPropertyChange()
     93{
     94    auto clientsCopy = m_clients;
     95    for (auto* client : clientsCopy) {
     96        if (m_clients.contains(client))
     97            client->fontPropertyChanged(*this);
     98    }
    5799}
    58100
     
    66108        return false;
    67109
     110    RefPtr<CSSValueList> oldFamilies = m_families;
    68111    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
     122Optional<FontTraitsMask> CSSFontFace::calculateStyleMask(CSSValue& style)
    73123{
    74124    if (!is<CSSPrimitiveValue>(style))
    75         return false;
    76 
    77     unsigned styleMask = 0;
     125        return Nullopt;
     126
    78127    switch (downcast<CSSPrimitiveValue>(style).getValueID()) {
    79128    case CSSValueNormal:
    80         styleMask = FontStyleNormalMask;
    81         break;
     129        return FontStyleNormalMask;
    82130    case CSSValueItalic:
    83131    case CSSValueOblique:
    84         styleMask = FontStyleItalicMask;
    85         break;
     132        return FontStyleItalicMask;
    86133    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
     140bool 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
     152Optional<FontTraitsMask> CSSFontFace::calculateWeightMask(CSSValue& weight)
    96153{
    97154    if (!is<CSSPrimitiveValue>(weight))
    98         return false;
    99 
    100     unsigned weightMask = 0;
     155        return Nullopt;
     156
    101157    switch (downcast<CSSPrimitiveValue>(weight).getValueID()) {
    102158    case CSSValueBold:
    103159    case CSSValueBolder:
    104160    case CSSValue700:
    105         weightMask = FontWeight700Mask;
    106         break;
     161        return FontWeight700Mask;
    107162    case CSSValueNormal:
    108163    case CSSValue400:
    109         weightMask = FontWeight400Mask;
    110         break;
     164        return FontWeight400Mask;
    111165    case CSSValue900:
    112         weightMask = FontWeight900Mask;
    113         break;
     166        return FontWeight900Mask;
    114167    case CSSValue800:
    115         weightMask = FontWeight800Mask;
    116         break;
     168        return FontWeight800Mask;
    117169    case CSSValue600:
    118         weightMask = FontWeight600Mask;
    119         break;
     170        return FontWeight600Mask;
    120171    case CSSValue500:
    121         weightMask = FontWeight500Mask;
    122         break;
     172        return FontWeight500Mask;
    123173    case CSSValue300:
    124         weightMask = FontWeight300Mask;
    125         break;
     174        return FontWeight300Mask;
    126175    case CSSValueLighter:
    127176    case CSSValue200:
    128         weightMask = FontWeight200Mask;
    129         break;
     177        return FontWeight200Mask;
    130178    case CSSValue100:
    131         weightMask = FontWeight100Mask;
    132         break;
     179        return FontWeight100Mask;
    133180    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
     187bool 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;
    140198}
    141199
     
    151209        m_ranges.append(UnicodeRange(range.from(), range.to()));
    152210    }
     211
     212    notifyClientsOfFontPropertyChange();
     213
    153214    return true;
    154215}
     
    161222    m_variantSettings.historicalLigatures = ligatures.historicalLigatures;
    162223    m_variantSettings.contextualAlternates = ligatures.contextualAlternates;
     224
     225    notifyClientsOfFontPropertyChange();
     226
    163227    return true;
    164228}
     
    169233        return false;
    170234    m_variantSettings.position = downcast<CSSPrimitiveValue>(variantPosition);
     235
     236    notifyClientsOfFontPropertyChange();
     237
    171238    return true;
    172239}
     
    177244        return false;
    178245    m_variantSettings.caps = downcast<CSSPrimitiveValue>(variantCaps);
     246
     247    notifyClientsOfFontPropertyChange();
     248
    179249    return true;
    180250}
     
    188258    m_variantSettings.numericOrdinal = numeric.ordinal;
    189259    m_variantSettings.numericSlashedZero = numeric.slashedZero;
     260
     261    notifyClientsOfFontPropertyChange();
     262
    190263    return true;
    191264}
     
    196269        return false;
    197270    m_variantSettings.alternates = downcast<CSSPrimitiveValue>(variantAlternates);
     271
     272    notifyClientsOfFontPropertyChange();
     273
    198274    return true;
    199275}
     
    205281    m_variantSettings.eastAsianWidth = eastAsian.width;
    206282    m_variantSettings.eastAsianRuby = eastAsian.ruby;
     283
     284    notifyClientsOfFontPropertyChange();
     285
    207286    return true;
    208287}
     
    219298        m_featureSettings.insert(FontFeature(feature.tag(), feature.value()));
    220299    }
     300
     301    notifyClientsOfFontPropertyChange();
     302
    221303    return true;
    222304}
     
    238320void CSSFontFace::removeClient(Client& client)
    239321{
     322    ASSERT(m_clients.contains(&client));
    240323    m_clients.remove(&client);
     324}
     325
     326Ref<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;
    241353}
    242354
     
    269381    }
    270382
    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);
    273385
    274386    m_status = newStatus;
     
    283395        pump();
    284396
     397    ASSERT(m_fontSelector);
    285398    m_fontSelector->fontLoaded();
    286399
    287     for (auto& client : m_clients)
     400    for (auto* client : m_clients)
    288401        client->fontLoaded(*this);
    289402}
     
    297410        if (source->status() == CSSFontFaceSource::Status::Pending) {
    298411            ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut);
     412            ASSERT(m_fontSelector);
    299413            if (m_status == Status::Pending)
    300414                setStatus(Status::Loading);
    301             source->load(m_fontSelector.get());
     415            source->load(*m_fontSelector);
    302416        }
    303417
     
    346460    for (size_t i = startIndex; i < m_sources.size(); ++i) {
    347461        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        }
    350466
    351467        switch (source->status()) {
  • trunk/Source/WebCore/css/CSSFontFace.h

    r196747 r196954  
    2828
    2929#include "CSSFontFaceRule.h"
    30 #include "CSSFontFaceSource.h"
    3130#include "FontFeatureSettings.h"
    3231#include "TextFlags.h"
     
    3736#include <wtf/RefCounted.h>
    3837#include <wtf/Vector.h>
     38#include <wtf/WeakPtr.h>
     39
     40namespace JSC {
     41class ExecState;
     42}
    3943
    4044namespace WebCore {
    4145
     46class CSSFontFaceSource;
     47class CSSFontSelector;
    4248class CSSSegmentedFontFace;
    4349class CSSValue;
    4450class CSSValueList;
     51class Document;
    4552class FontDescription;
    4653class Font;
    4754class FontFace;
    4855
    49 // FIXME: This class does not need to be reference counted.
    5056class CSSFontFace final : public RefCounted<CSSFontFace> {
    5157public:
    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)
    5359    {
    54         return adoptRef(*new CSSFontFace(fontSelector, wrapper, isLocalFallback));
     60        return adoptRef(*new CSSFontFace(fontSelector, cssConnection, wrapper, isLocalFallback));
    5561    }
    5662    virtual ~CSSFontFace();
     
    7985    bool isLocalFallback() const { return m_isLocalFallback; }
    8086    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);
    8191
    8292    class Client;
     
    94104    RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic);
    95105
     106    static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree);
     107
    96108    class Client {
    97109    public:
    98110        virtual ~Client() { }
    99111        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); };
    101114    };
    102115
     
    133146    };
    134147
    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&);
    136150
    137151#if ENABLE(SVG_FONTS)
     
    140154
    141155private:
    142     CSSFontFace(CSSFontSelector&, FontFace*, bool isLocalFallback);
     156    CSSFontFace(CSSFontSelector*, StyleRuleFontFace*, FontFace*, bool isLocalFallback);
    143157
    144158    size_t pump();
    145159    void setStatus(Status);
     160    void notifyClientsOfFontPropertyChange();
    146161
    147162    RefPtr<CSSValueList> m_families;
    148163    FontTraitsMask m_traitsMask { static_cast<FontTraitsMask>(FontStyleNormalMask | FontWeight400Mask) };
    149164    Vector<UnicodeRange> m_ranges;
    150     HashSet<Client*> m_clients;
    151     Ref<CSSFontSelector> m_fontSelector;
    152     FontFace* m_wrapper;
    153165    FontFeatureSettings m_featureSettings;
    154166    FontVariantSettings m_variantSettings;
    155167    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;
    156172    Status m_status { Status::Pending };
    157173    bool m_isLocalFallback { false };
  • trunk/Source/WebCore/css/CSSFontFaceSet.cpp

    r196747 r196954  
    2727#include "CSSFontFaceSet.h"
    2828
     29#include "CSSFontFaceSource.h"
    2930#include "CSSFontFamily.h"
    3031#include "CSSFontSelector.h"
    3132#include "CSSParser.h"
    3233#include "CSSPrimitiveValue.h"
     34#include "CSSSegmentedFontFace.h"
    3335#include "CSSValueList.h"
     36#include "CSSValuePool.h"
     37#include "FontCache.h"
    3438#include "StyleProperties.h"
    3539
    3640namespace WebCore {
    3741
    38 CSSFontFaceSet::CSSFontFaceSet(CSSFontFaceSetClient& client)
    39     : m_client(client)
     42CSSFontFaceSet::CSSFontFaceSet()
    4043{
    4144}
     
    4548    for (auto& face : m_faces)
    4649        face->removeClient(*this);
     50
     51    for (auto& pair : m_locallyInstalledFacesLookupTable) {
     52        for (auto& face : pair.value)
     53            face->removeClient(*this);
     54    }
     55}
     56
     57void CSSFontFaceSet::addClient(CSSFontFaceSetClient& client)
     58{
     59    m_clients.add(&client);
     60}
     61
     62void CSSFontFaceSet::removeClient(CSSFontFaceSetClient& client)
     63{
     64    ASSERT(m_clients.contains(&client));
     65    m_clients.remove(&client);
    4766}
    4867
     
    5271    if (m_activeCount == 1) {
    5372        m_status = Status::Loading;
    54         m_client.startedLoading();
     73        for (auto* client : m_clients)
     74            client->startedLoading();
    5575    }
    5676}
     
    6181    if (!m_activeCount) {
    6282        m_status = Status::Loaded;
    63         m_client.completedLoading();
     83        for (auto* client : m_clients)
     84            client->completedLoading();
    6485    }
    6586}
     
    7192            return true;
    7293    }
     94
    7395    return false;
    7496}
    7597
     98void 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
     121String 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
     148void 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
    76171void CSSFontFaceSet::add(CSSFontFace& face)
    77172{
    78173    ASSERT(!hasFace(face));
    79174
    80     m_faces.append(face);
     175    for (auto* client : m_clients)
     176        client->fontModified();
     177
    81178    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
    82188    if (face.status() == CSSFontFace::Status::Loading || face.status() == CSSFontFace::Status::TimedOut)
    83189        incrementActiveCount();
    84190}
    85191
     192void 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
    86215void CSSFontFaceSet::remove(const CSSFontFace& face)
    87216{
     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
    88225    for (size_t i = 0; i < m_faces.size(); ++i) {
    89226        if (m_faces[i].ptr() == &face) {
     227            if (i < m_facesPartitionIndex)
     228                --m_facesPartitionIndex;
    90229            m_faces[i]->removeClient(*this);
    91230            m_faces.remove(i);
     
    98237}
    99238
    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;
     239void CSSFontFaceSet::clear()
     240{
     241    m_faces.clear();
     242    m_facesLookupTable.clear();
     243    m_locallyInstalledFacesLookupTable.clear();
     244    m_cache.clear();
     245}
     246
     247CSSFontFace& CSSFontFaceSet::operator[](size_t i)
     248{
     249    ASSERT(i < faceCount());
     250    return m_faces[i];
     251}
     252
     253static 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));
    124276}
    125277
     
    133285        return result;
    134286    }
    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
    143296    RefPtr<CSSValue> family = style->getPropertyCSSValue(CSSPropertyFontFamily);
    144297    if (!is<CSSValueList>(family.get())) {
     
    148301    CSSValueList& familyList = downcast<CSSValueList>(*family);
    149302
    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())
    153307            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
    156319    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();
    167320}
    168321
     
    180333}
    181334
    182 void CSSFontFaceSet::stateChanged(CSSFontFace& face, CSSFontFace::Status oldState, CSSFontFace::Status newState)
     335static 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
     394CSSSegmentedFontFace* 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
     437void CSSFontFaceSet::fontStateChanged(CSSFontFace& face, CSSFontFace::Status oldState, CSSFontFace::Status newState)
    183438{
    184439    ASSERT(hasFace(face));
     
    189444    if (newState == CSSFontFace::Status::Success || newState == CSSFontFace::Status::Failure) {
    190445        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);
    192448        decrementActiveCount();
    193449    }
    194450}
    195451
    196 }
     452void 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  
    2828
    2929#include "CSSFontFace.h"
     30#include <wtf/HashMap.h>
    3031#include <wtf/Vector.h>
     32#include <wtf/text/StringHash.h>
    3133
    3234namespace WebCore {
    3335
     36class CSSPrimitiveValue;
    3437class FontFaceSet;
    3538
     
    3740public:
    3841    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() { };
    4246};
    4347
    44 class CSSFontFaceSet final : public CSSFontFace::Client {
     48class CSSFontFaceSet final : public RefCounted<CSSFontFaceSet>, public CSSFontFace::Client {
    4549public:
    46     CSSFontFaceSet(CSSFontFaceSetClient&);
     50    static Ref<CSSFontFaceSet> create()
     51    {
     52        return adoptRef(*new CSSFontFaceSet());
     53    }
    4754    ~CSSFontFaceSet();
     55
     56    void addClient(CSSFontFaceSetClient&);
     57    void removeClient(CSSFontFaceSetClient&);
    4858
    4959    bool hasFace(const CSSFontFace&) const;
     
    5161    void add(CSSFontFace&);
    5262    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);
    5465
    55     void load(const String& font, const String& text, ExceptionCode&);
    5666    bool check(const String& font, const String& text, ExceptionCode&);
     67
     68    CSSSegmentedFontFace* getFontFace(FontTraitsMask, const AtomicString& family);
    5769
    5870    enum class Status {
     
    6577
    6678private:
     79    CSSFontFaceSet();
     80
     81    void removeFromFacesLookupTable(const CSSFontFace&, const CSSValueList& familiesToSearchFor);
     82    void addToFacesLookupTable(CSSFontFace&);
     83
    6784    void incrementActiveCount();
    6885    void decrementActiveCount();
    6986
    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;
    7189
    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.
    73100    Status m_status { Status::Loaded };
    74     CSSFontFaceSetClient& m_client;
     101    HashSet<CSSFontFaceSetClient*> m_clients;
    75102    unsigned m_activeCount { 0 };
    76103};
  • trunk/Source/WebCore/css/CSSFontFaceSource.h

    r196376 r196954  
    4646    WTF_MAKE_FAST_ALLOCATED;
    4747public:
     48    CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* = nullptr, SVGFontFaceElement* = nullptr);
     49    virtual ~CSSFontFaceSource();
    4850
    4951    //                      => Success
     
    5860        Failure
    5961    };
    60 
    61     CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* = nullptr, SVGFontFaceElement* = nullptr);
    62     virtual ~CSSFontFaceSource();
    63 
    6462    Status status() const { return m_status; }
    6563
  • trunk/Source/WebCore/css/CSSFontSelector.cpp

    r196747 r196954  
    3232#include "CSSFontFaceRule.h"
    3333#include "CSSFontFaceSource.h"
    34 #include "CSSFontFaceSrcValue.h"
    3534#include "CSSFontFamily.h"
    3635#include "CSSFontFeatureValue.h"
     
    4746#include "Font.h"
    4847#include "FontCache.h"
     48#include "FontFaceSet.h"
    4949#include "FontVariantBuilder.h"
    5050#include "Frame.h"
     
    6666CSSFontSelector::CSSFontSelector(Document& document)
    6767    : m_document(&document)
     68    , m_cssFontFaceSet(CSSFontFaceSet::create())
    6869    , m_beginLoadingTimer(*this, &CSSFontSelector::beginLoadTimerFired)
    6970    , m_uniqueId(++fontSelectorId)
     
    7677    ASSERT(m_document);
    7778    FontCache::singleton().addClient(*this);
     79    m_cssFontFaceSet->addClient(*this);
    7880}
    7981
     
    8183{
    8284    clearDocument();
     85    m_cssFontFaceSet->removeClient(*this);
    8386    FontCache::singleton().removeClient(*this);
    8487}
    8588
     89FontFaceSet& 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
    8699bool CSSFontSelector::isEmpty() const
    87100{
    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
     104void CSSFontSelector::addFontFaceRule(StyleRuleFontFace& fontFaceRule, bool isInitiatingElementInUserAgentShadowTree)
    171105{
    172106    const StyleProperties& style = fontFaceRule.properties();
     
    202136        return;
    203137
    204     Ref<CSSFontFace> fontFace = CSSFontFace::create(*this);
     138    m_creatingFont = true;
     139    Ref<CSSFontFace> fontFace = CSSFontFace::create(this, &fontFaceRule);
    205140
    206141    if (!fontFace->setFamilies(*fontFamily))
     
    227162        return;
    228163
    229     appendSources(fontFace, srcList, m_document, isInitiatingElementInUserAgentShadowTree);
     164    CSSFontFace::appendSources(fontFace, srcList, m_document, isInitiatingElementInUserAgentShadowTree);
    230165    if (fontFace->allSourcesFailed())
    231166        return;
    232167
    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;
    249171}
    250172
     
    272194{
    273195    dispatchInvalidationCallbacks();
     196}
     197
     198void CSSFontSelector::fontModified()
     199{
     200    if (!m_creatingFont)
     201        dispatchInvalidationCallbacks();
    274202}
    275203
     
    305233}
    306234
    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 support
    328             // 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 
    378235FontRanges CSSFontSelector::fontRangesForFamily(const FontDescription& fontDescription, const AtomicString& familyName)
    379236{
     
    382239
    383240    AtomicString familyForLookup = resolveGenericFamilyFirst ? resolveGenericFamily(m_document, fontDescription, familyName) : familyName;
    384     CSSSegmentedFontFace* face = getFontFace(fontDescription, familyForLookup);
     241    CSSSegmentedFontFace* face = m_cssFontFaceSet->getFontFace(fontDescription.traitsMask(), familyForLookup);
    385242    if (!face) {
    386243        if (!resolveGenericFamilyFirst)
     
    392249}
    393250
    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 
    437251void CSSFontSelector::clearDocument()
    438252{
     
    455269
    456270    // FIXME: This object should outlive the Document.
    457     m_fontFaces.clear();
    458     m_locallyInstalledFontFaces.clear();
    459     m_fonts.clear();
     271    m_cssFontFaceSet->clear();
    460272    m_clients.clear();
    461273}
  • trunk/Source/WebCore/css/CSSFontSelector.h

    r196747 r196954  
    2828
    2929#include "CSSFontFace.h"
     30#include "CSSFontFaceSet.h"
    3031#include "CachedResourceHandle.h"
    3132#include "Font.h"
     
    4950class StyleRuleFontFace;
    5051
    51 class CSSFontSelector final : public FontSelector {
     52class CSSFontSelector final : public FontSelector, public CSSFontFaceSetClient {
    5253public:
    5354    static Ref<CSSFontSelector> create(Document& document)
     
    6364    virtual size_t fallbackFontCount() override;
    6465    virtual RefPtr<Font> fallbackFontAt(const FontDescription&, size_t) override;
    65     CSSSegmentedFontFace* getFontFace(const FontDescription&, const AtomicString& family);
    6666
    6767    void clearDocument();
    6868
    69     static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree);
    70     void addFontFaceRule(const StyleRuleFontFace&, bool isInitiatingElementInUserAgentShadowTree);
     69    void addFontFaceRule(StyleRuleFontFace&, bool isInitiatingElementInUserAgentShadowTree);
    7170
    7271    void fontLoaded();
     
    8281    void beginLoadingFontSoon(CachedFont*);
    8382
    84     static String familyNameFromPrimitive(const CSSPrimitiveValue&);
     83    FontFaceSet& fontFaceSet();
    8584
    8685private:
     
    8988    void dispatchInvalidationCallbacks();
    9089
     90    virtual void fontModified() override;
     91
    9192    void beginLoadTimerFired();
    9293
    93     void registerLocalFontFacesForFamily(const String&);
    94 
    9594    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;
    9997    HashSet<FontSelectorClient*> m_clients;
    10098
     
    104102    unsigned m_uniqueId;
    105103    unsigned m_version;
     104    bool m_creatingFont { false };
    106105};
    107106
  • trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp

    r196747 r196954  
    3838namespace WebCore {
    3939
    40 CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector& fontSelector)
    41     : m_fontSelector(fontSelector)
     40CSSSegmentedFontFace::CSSSegmentedFontFace()
    4241{
    4342}
  • trunk/Source/WebCore/css/CSSSegmentedFontFace.h

    r196747 r196954  
    4343    WTF_MAKE_FAST_ALLOCATED;
    4444public:
    45     CSSSegmentedFontFace(CSSFontSelector&);
     45    CSSSegmentedFontFace();
    4646    ~CSSSegmentedFontFace();
    47 
    48     CSSFontSelector& fontSelector() const { return m_fontSelector; }
    4947
    5048    void appendFontFace(Ref<CSSFontFace>&&);
     
    5250    FontRanges fontRanges(const FontDescription&);
    5351
     52    Vector<Ref<CSSFontFace>, 1>& constituentFaces() { return m_fontFaces; }
     53
    5454private:
    5555    virtual void fontLoaded(CSSFontFace&) override;
    5656
    57     CSSFontSelector& m_fontSelector;
    5857    HashMap<FontDescriptionKey, FontRanges, FontDescriptionKeyHash, WTF::SimpleClassHashTraits<FontDescriptionKey>> m_cache;
    5958    Vector<Ref<CSSFontFace>, 1> m_fontFaces;
  • trunk/Source/WebCore/css/FontFace.cpp

    r196747 r196954  
    7676        if (is<CSSValueList>(value.get())) {
    7777            CSSValueList& srcList = downcast<CSSValueList>(*value);
    78             CSSFontSelector::appendSources(result->backing(), srcList, &downcast<Document>(context), false);
     78            CSSFontFace::appendSources(result->backing(), srcList, &downcast<Document>(context), false);
    7979        } else {
    8080            ec = SYNTAX_ERR;
     
    111111}
    112112
     113Ref<FontFace> FontFace::create(JSC::ExecState& execState, CSSFontFace& face)
     114{
     115    return adoptRef(*new FontFace(execState, face));
     116}
     117
    113118FontFace::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))
    115121    , m_promise(createPromise(execState))
    116122{
     
    118124}
    119125
     126FontFace::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
    120134FontFace::~FontFace()
    121135{
    122136    m_backing->removeClient(*this);
     137}
     138
     139WeakPtr<FontFace> FontFace::createWeakPtr() const
     140{
     141    return m_weakPtrFactory.createWeakPtr();
    123142}
    124143
     
    318337}
    319338
    320 void FontFace::stateChanged(CSSFontFace& face, CSSFontFace::Status, CSSFontFace::Status newState)
     339void FontFace::fontStateChanged(CSSFontFace& face, CSSFontFace::Status, CSSFontFace::Status newState)
    321340{
    322341    ASSERT_UNUSED(face, &face == m_backing.ptr());
    323342    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;
    324347    case CSSFontFace::Status::TimedOut:
    325348        rejectPromise(NETWORK_ERR);
     349        deref();
    326350        return;
    327351    case CSSFontFace::Status::Success:
    328352        fulfillPromise();
     353        deref();
    329354        return;
    330355    case CSSFontFace::Status::Failure:
    331356        rejectPromise(NETWORK_ERR);
     357        deref();
    332358        return;
    333359    default:
  • trunk/Source/WebCore/css/FontFace.h

    r196747 r196954  
    3434#include <wtf/RefCounted.h>
    3535#include <wtf/RefPtr.h>
     36#include <wtf/WeakPtr.h>
    3637#include <wtf/text/WTFString.h>
    3738
     
    4950public:
    5051    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&);
    5153    virtual ~FontFace();
    5254
     
    7779    static RefPtr<CSSValue> parseString(const String&, CSSPropertyID);
    7880
     81    virtual void fontStateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override;
     82
     83    WeakPtr<FontFace> createWeakPtr() const;
     84
    7985private:
    8086    FontFace(JSC::ExecState&, CSSFontSelector&);
    81 
    82     virtual void stateChanged(CSSFontFace&, CSSFontFace::Status oldState, CSSFontFace::Status newState) override;
     87    FontFace(JSC::ExecState&, CSSFontFace&);
    8388
    8489    void fulfillPromise();
    8590    void rejectPromise(ExceptionCode);
    8691
     92    WeakPtrFactory<FontFace> m_weakPtrFactory;
    8793    Ref<CSSFontFace> m_backing;
    8894    Promise m_promise;
  • trunk/Source/WebCore/css/FontFaceSet.cpp

    r196900 r196954  
    4343}
    4444
    45 FontFaceSet::FontFaceSet(JSC::ExecState& execState, Document& document, const Vector<RefPtr<FontFace>>& initialFaces)
     45Ref<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
     52Ref<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
     59FontFaceSet::FontFaceSet(Document& document, const Vector<RefPtr<FontFace>>& initialFaces)
    4660    : ActiveDOMObject(&document)
    47     , m_backing(*this)
    48     , m_promise(createPromise(execState))
    49 {
     61    , m_backing(CSSFontFaceSet::create())
     62{
     63    m_backing->addClient(*this);
    5064    for (auto& face : initialFaces)
    5165        add(face.get());
    5266}
    5367
     68FontFaceSet::FontFaceSet(Document& document, CSSFontFaceSet& backing)
     69    : ActiveDOMObject(&document)
     70    , m_backing(backing)
     71{
     72    m_backing->addClient(*this);
     73}
     74
    5475FontFaceSet::~FontFaceSet()
    5576{
     77    m_backing->removeClient(*this);
    5678}
    5779
     
    6183}
    6284
    63 bool FontFaceSet::Iterator::next(FontFace*& key, FontFace*& value)
     85bool FontFaceSet::Iterator::next(JSC::ExecState& execState, RefPtr<FontFace>& key, RefPtr<FontFace>& value)
    6486{
    6587    if (m_index == m_target->size())
    6688        return true;
    67     key = m_target->m_backing[m_index++].wrapper();
     89    key = m_target->backing()[m_index++].wrapper(execState);
    6890    value = key;
    6991    return false;
     
    79101}
    80102
    81 bool FontFaceSet::has(FontFace* face) const
     103bool FontFaceSet::has(RefPtr<WebCore::FontFace> face) const
    82104{
    83105    if (!face)
    84106        return false;
    85     return m_backing.hasFace(face->backing());
     107    return m_backing->hasFace(face->backing());
    86108}
    87109
    88110size_t FontFaceSet::size() const
    89111{
    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
     115FontFaceSet& FontFaceSet::add(RefPtr<WebCore::FontFace> face)
     116{
     117    if (face && !m_backing->hasFace(face->backing()))
     118        m_backing->add(face->backing());
    97119    return *this;
    98120}
    99121
    100 bool FontFaceSet::remove(FontFace* face)
     122bool FontFaceSet::remove(RefPtr<WebCore::FontFace> face)
    101123{
    102124    if (!face)
    103125        return false;
    104126
    105     bool result = m_backing.hasFace(face->backing());
     127    bool result = m_backing->hasFace(face->backing());
    106128    if (result)
    107         m_backing.remove(face->backing());
     129        m_backing->remove(face->backing());
    108130    return result;
    109131}
     
    111133void FontFaceSet::clear()
    112134{
    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
     139void 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);
    120142    if (ec)
    121143        return;
     
    140162
    141163    for (auto& face : matchingFaces) {
    142         pendingPromise->faces.append(face.get().wrapper());
     164        pendingPromise->faces.append(face.get().wrapper(execState));
    143165        if (face.get().status() == CSSFontFace::Status::Success)
    144166            continue;
    145167        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;
    147169        vector.append(pendingPromise.copyRef());
    148170    }
     
    154176bool FontFaceSet::check(const String& family, const String& text, ExceptionCode& ec)
    155177{
    156     return m_backing.check(family, text, ec);
     178    return m_backing->check(family, text, ec);
    157179}
    158180
     
    161183    if (!m_promise) {
    162184        m_promise = createPromise(execState);
    163         if (m_backing.status() == CSSFontFaceSet::Status::Loaded)
     185        if (m_backing->status() == CSSFontFaceSet::Status::Loaded)
    164186            fulfillPromise();
    165187    }
     
    169191String FontFaceSet::status() const
    170192{
    171     switch (m_backing.status()) {
     193    switch (m_backing->status()) {
    172194    case CSSFontFaceSet::Status::Loading:
    173195        return String("loading", String::ConstructFromLiteral);
     
    181203bool FontFaceSet::canSuspendForDocumentSuspension() const
    182204{
    183     return m_backing.status() == CSSFontFaceSet::Status::Loaded;
     205    return m_backing->status() == CSSFontFaceSet::Status::Loaded;
    184206}
    185207
     
    210232void FontFaceSet::faceFinished(CSSFontFace& face, CSSFontFace::Status newStatus)
    211233{
    212     auto iterator = m_pendingPromises.find(face.wrapper());
     234    auto iterator = m_pendingPromises.find(&face);
    213235    if (iterator == m_pendingPromises.end())
    214236        return;
  • trunk/Source/WebCore/css/FontFaceSet.h

    r196900 r196954  
    3939#include <wtf/text/WTFString.h>
    4040
     41namespace JSC {
     42class ExecState;
     43}
     44
    4145namespace WebCore {
    4246
     
    4650class FontFaceSet final : public RefCounted<FontFaceSet>, public CSSFontFaceSetClient, public EventTargetWithInlineData, public ActiveDOMObject {
    4751public:
    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);
    5454    virtual ~FontFaceSet();
    5555
    56     bool has(FontFace*) const;
     56    bool has(RefPtr<WebCore::FontFace>) const;
    5757    size_t size() const;
    58     FontFaceSet& add(FontFace*);
    59     bool remove(FontFace*);
     58    FontFaceSet& add(RefPtr<WebCore::FontFace>);
     59    bool remove(RefPtr<WebCore::FontFace>);
    6060    void clear();
    6161
    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&);
    6464    bool check(const String& font, ExceptionCode& ec) { return check(font, String(" ", String::ConstructFromLiteral), ec); }
    6565    bool check(const String& font, const String& text, ExceptionCode&);
     
    7070    Promise& promise(JSC::ExecState&);
    7171
     72    CSSFontFaceSet& backing() { return m_backing; }
     73
    7274    class Iterator {
    7375    public:
    7476        explicit Iterator(FontFaceSet&);
    75         bool next(FontFace*& nextKey, FontFace*& nextValue);
     77        bool next(JSC::ExecState&, RefPtr<FontFace>& nextKey, RefPtr<FontFace>& nextValue);
    7678
    7779    private:
    7880        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.
    8082    };
    8183    Iterator createIterator() { return Iterator(*this); }
     
    101103    };
    102104
    103     FontFaceSet(JSC::ExecState&, Document&, const Vector<RefPtr<FontFace>>&);
     105    FontFaceSet(Document&, const Vector<RefPtr<FontFace>>&);
     106    FontFaceSet(Document&, CSSFontFaceSet&);
    104107
    105108    void fulfillPromise();
     
    120123    virtual void derefEventTarget() override { deref(); }
    121124
    122     CSSFontFaceSet m_backing;
    123     HashMap<RefPtr<FontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;
     125    Ref<CSSFontFaceSet> m_backing;
     126    HashMap<RefPtr<CSSFontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;
    124127    Optional<Promise> m_promise;
    125128};
  • trunk/Source/WebCore/css/FontFaceSet.idl

    r196900 r196954  
    3030
    3131[
    32     ConstructorCallWith=ScriptState&Document,
     32    ConstructorCallWith=Document,
    3333    Constructor(sequence<FontFace> initialFaces)
    3434] interface FontFaceSet : EventTarget {
     
    4949    attribute EventHandler onloadingerror;
    5050
    51     [RaisesException] Promise load(DOMString font, optional DOMString text);
     51    [RaisesException, CallWith=ScriptState] Promise load(DOMString font, optional DOMString text);
    5252    [RaisesException] boolean check(DOMString font, optional DOMString text);
    5353
  • trunk/Source/WebCore/dom/Document.cpp

    r196888 r196954  
    6363#include "ExtensionStyleSheets.h"
    6464#include "FocusController.h"
    65 #include "FontLoader.h"
     65#include "FontFaceSet.h"
    6666#include "FormController.h"
    6767#include "FrameLoader.h"
     
    66856685#endif
    66866686
    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
     6687Ref<FontFaceSet> Document::fonts()
     6688{
     6689    return fontSelector().fontFaceSet();
     6690}
    66956691
    66966692float Document::deviceScaleFactor() const
  • trunk/Source/WebCore/dom/Document.h

    r196888 r196954  
    202202#endif
    203203
    204 #if ENABLE(FONT_LOAD_EVENTS)
    205 class FontLoader;
    206 #endif
     204class FontFaceSet;
    207205
    208206typedef int ExceptionCode;
     
    12681266    WEBCORE_EXPORT virtual SecurityOrigin* topOrigin() const override final;
    12691267
    1270 #if ENABLE(FONT_LOAD_EVENTS)
    1271     RefPtr<FontLoader> fonts();
    1272 #endif
     1268    Ref<FontFaceSet> fonts();
    12731269
    12741270    void ensurePlugInsInjectedScript(DOMWrapperWorld&);
     
    17521748    RefPtr<CSSFontSelector> m_fontSelector;
    17531749
    1754 #if ENABLE(FONT_LOAD_EVENTS)
    1755     RefPtr<FontLoader> m_fontloader;
    1756 #endif
    1757 
    17581750#if ENABLE(WEB_REPLAY)
    17591751    RefPtr<JSC::InputCursor> m_inputCursor;
  • trunk/Source/WebCore/dom/Document.idl

    r195778 r196954  
    266266
    267267#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
    268     [Conditional=FONT_LOAD_EVENTS] readonly attribute FontLoader fonts;
     268    readonly attribute FontFaceSet fonts;
    269269#endif
    270270
  • trunk/Source/WebCore/svg/SVGFontFaceElement.h

    r191871 r196954  
    5151    void rebuildFontFace();
    5252   
    53     const StyleRuleFontFace& fontFaceRule() const { return m_fontFaceRule.get(); }
     53    StyleRuleFontFace& fontFaceRule() { return m_fontFaceRule.get(); }
    5454
    5555private:
Note: See TracChangeset for help on using the changeset viewer.