Changeset 196322 in webkit


Ignore:
Timestamp:
Feb 9, 2016 11:50:05 AM (8 years ago)
Author:
mmaxfield@apple.com
Message:

Decouple font creation from font loading
https://bugs.webkit.org/show_bug.cgi?id=153414

Reviewed by Darin Adler.

Previously, CSSFontFaceSource never triggered a font download until that font was actually used. This means
that the function which triggers the download also has the goal of returning a font to use. However,
the CSS Font Loading JavaScript API requires being able to trigger a font download without this extra font
creation overhead.

In addition, this patch adds an explicit (and enforced) state transition diagram. The diagram looks like
this:

=> Success


Pending => Loading


=> Failure

Therefore, the API for CSSFontFaceSource has changed to expose the concept of these new states. This means
that its user (CSSSegmentedFontFaceSource) has been updated to handle each possible state that its constituent
CSSFontFaceSources may be in.

No new tests because there is no behavior change.

  • css/CSSFontFace.cpp:

(WebCore::CSSFontFace::allSourcesFailed): Renamed to make the name clearer.
(WebCore::CSSFontFace::addedToSegmentedFontFace): Use references instead of pointers.
(WebCore::CSSFontFace::removedFromSegmentedFontFace): Ditto.
(WebCore::CSSFontFace::adoptSource): Renamed to make the name clearer.
(WebCore::CSSFontFace::fontLoaded): Use references instead of pointers. Also, remove old dead code.
(WebCore::CSSFontFace::font): Adapt to the new API of CSSFontFaceSource.
(WebCore::CSSFontFace::isValid): Deleted.
(WebCore::CSSFontFace::addSource): Deleted.
(WebCore::CSSFontFace::notifyFontLoader): Deleted. Old dead code.
(WebCore::CSSFontFace::notifyLoadingDone): Deleted. Old dead code.

  • css/CSSFontFace.h:

(WebCore::CSSFontFace::create): Remove old dead code.
(WebCore::CSSFontFace::CSSFontFace): Use references instead of pointers.
(WebCore::CSSFontFace::loadState): Deleted. Remove old dead code.

  • css/CSSFontFaceSource.cpp:

(WebCore::CSSFontFaceSource::setStatus): Enforce state transitions.
(WebCore::CSSFontFaceSource::CSSFontFaceSource): Explicitly handle new state transitions.
(WebCore::CSSFontFaceSource::fontLoaded): Update for new states.
(WebCore::CSSFontFaceSource::load): Pulled out code from font().
(WebCore::CSSFontFaceSource::font): Moved code into load().
(WebCore::CSSFontFaceSource::isValid): Deleted.
(WebCore::CSSFontFaceSource::isDecodeError): Deleted.
(WebCore::CSSFontFaceSource::ensureFontData): Deleted.

  • css/CSSFontFaceSource.h: Much cleaner API.
  • css/CSSFontSelector.cpp:

(WebCore::createFontFace): Migrate to references instead of pointers. This requires a little
reorganization.
(WebCore::registerLocalFontFacesForFamily): Update to new CSSFontFaceSource API.
(WebCore::CSSFontSelector::addFontFaceRule): Ditto.
(WebCore::CSSFontSelector::getFontFace): Ditto.

  • css/CSSSegmentedFontFace.cpp:

(WebCore::CSSSegmentedFontFace::CSSSegmentedFontFace): Migrate to references instead of pointers.
(WebCore::CSSSegmentedFontFace::~CSSSegmentedFontFace): Ditto.
(WebCore::CSSSegmentedFontFace::fontLoaded): Remove old dead code.
(WebCore::CSSSegmentedFontFace::appendFontFace): Cleanup.
(WebCore::CSSSegmentedFontFace::fontRanges): Adopt to new API.
(WebCore::CSSSegmentedFontFace::pruneTable): Deleted.
(WebCore::CSSSegmentedFontFace::isLoading): Deleted. Old dead code.
(WebCore::CSSSegmentedFontFace::checkFont): Deleted. Ditto.
(WebCore::CSSSegmentedFontFace::loadFont): Deleted. Ditto.

  • css/CSSSegmentedFontFace.h:

(WebCore::CSSSegmentedFontFace::create): Migrate to references instead of pointers.
(WebCore::CSSSegmentedFontFace::fontSelector): Ditto.
(WebCore::CSSSegmentedFontFace::LoadFontCallback::~LoadFontCallback): Deleted.

  • loader/cache/CachedFont.cpp:

(WebCore::CachedFont::didAddClient): Migrate to references instead of pointers.
(WebCore::CachedFont::checkNotify): Ditto.

  • loader/cache/CachedFontClient.h:

(WebCore::CachedFontClient::fontLoaded): Ditto.

Location:
trunk/Source/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r196313 r196322  
     12016-02-09  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        Decouple font creation from font loading
     4        https://bugs.webkit.org/show_bug.cgi?id=153414
     5
     6        Reviewed by Darin Adler.
     7
     8        Previously, CSSFontFaceSource never triggered a font download until that font was actually used. This means
     9        that the function which triggers the download also has the goal of returning a font to use. However,
     10        the CSS Font Loading JavaScript API requires being able to trigger a font download without this extra font
     11        creation overhead.
     12
     13        In addition, this patch adds an explicit (and enforced) state transition diagram. The diagram looks like
     14        this:
     15                            => Success
     16                          //
     17        Pending => Loading
     18                          \\
     19                            => Failure
     20
     21        Therefore, the API for CSSFontFaceSource has changed to expose the concept of these new states. This means
     22        that its user (CSSSegmentedFontFaceSource) has been updated to handle each possible state that its constituent
     23        CSSFontFaceSources may be in.
     24
     25        No new tests because there is no behavior change.
     26
     27        * css/CSSFontFace.cpp:
     28        (WebCore::CSSFontFace::allSourcesFailed): Renamed to make the name clearer.
     29        (WebCore::CSSFontFace::addedToSegmentedFontFace): Use references instead of pointers.
     30        (WebCore::CSSFontFace::removedFromSegmentedFontFace): Ditto.
     31        (WebCore::CSSFontFace::adoptSource): Renamed to make the name clearer.
     32        (WebCore::CSSFontFace::fontLoaded): Use references instead of pointers. Also, remove old dead code.
     33        (WebCore::CSSFontFace::font): Adapt to the new API of CSSFontFaceSource.
     34        (WebCore::CSSFontFace::isValid): Deleted.
     35        (WebCore::CSSFontFace::addSource): Deleted.
     36        (WebCore::CSSFontFace::notifyFontLoader): Deleted. Old dead code.
     37        (WebCore::CSSFontFace::notifyLoadingDone): Deleted. Old dead code.
     38        * css/CSSFontFace.h:
     39        (WebCore::CSSFontFace::create): Remove old dead code.
     40        (WebCore::CSSFontFace::CSSFontFace): Use references instead of pointers.
     41        (WebCore::CSSFontFace::loadState): Deleted. Remove old dead code.
     42        * css/CSSFontFaceSource.cpp:
     43        (WebCore::CSSFontFaceSource::setStatus): Enforce state transitions.
     44        (WebCore::CSSFontFaceSource::CSSFontFaceSource): Explicitly handle new state transitions.
     45        (WebCore::CSSFontFaceSource::fontLoaded): Update for new states.
     46        (WebCore::CSSFontFaceSource::load): Pulled out code from font().
     47        (WebCore::CSSFontFaceSource::font): Moved code into load().
     48        (WebCore::CSSFontFaceSource::isValid): Deleted.
     49        (WebCore::CSSFontFaceSource::isDecodeError): Deleted.
     50        (WebCore::CSSFontFaceSource::ensureFontData): Deleted.
     51        * css/CSSFontFaceSource.h: Much cleaner API.
     52        * css/CSSFontSelector.cpp:
     53        (WebCore::createFontFace): Migrate to references instead of pointers. This requires a little
     54        reorganization.
     55        (WebCore::registerLocalFontFacesForFamily): Update to new CSSFontFaceSource API.
     56        (WebCore::CSSFontSelector::addFontFaceRule): Ditto.
     57        (WebCore::CSSFontSelector::getFontFace): Ditto.
     58        * css/CSSSegmentedFontFace.cpp:
     59        (WebCore::CSSSegmentedFontFace::CSSSegmentedFontFace): Migrate to references instead of pointers.
     60        (WebCore::CSSSegmentedFontFace::~CSSSegmentedFontFace): Ditto.
     61        (WebCore::CSSSegmentedFontFace::fontLoaded): Remove old dead code.
     62        (WebCore::CSSSegmentedFontFace::appendFontFace): Cleanup.
     63        (WebCore::CSSSegmentedFontFace::fontRanges): Adopt to new API.
     64        (WebCore::CSSSegmentedFontFace::pruneTable): Deleted.
     65        (WebCore::CSSSegmentedFontFace::isLoading): Deleted. Old dead code.
     66        (WebCore::CSSSegmentedFontFace::checkFont): Deleted. Ditto.
     67        (WebCore::CSSSegmentedFontFace::loadFont): Deleted. Ditto.
     68        * css/CSSSegmentedFontFace.h:
     69        (WebCore::CSSSegmentedFontFace::create): Migrate to references instead of pointers.
     70        (WebCore::CSSSegmentedFontFace::fontSelector): Ditto.
     71        (WebCore::CSSSegmentedFontFace::LoadFontCallback::~LoadFontCallback): Deleted.
     72        * loader/cache/CachedFont.cpp:
     73        (WebCore::CachedFont::didAddClient): Migrate to references instead of pointers.
     74        (WebCore::CachedFont::checkNotify): Ditto.
     75        * loader/cache/CachedFontClient.h:
     76        (WebCore::CachedFontClient::fontLoaded): Ditto.
     77
    1782016-02-09  Brady Eidson  <beidson@apple.com>
    279
  • trunk/Source/WebCore/css/CSSFontFace.cpp

    r194923 r196322  
    3838namespace WebCore {
    3939
    40 bool CSSFontFace::isValid() const
     40bool CSSFontFace::allSourcesFailed() const
    4141{
    42     size_t size = m_sources.size();
    43     for (size_t i = 0; i < size; i++) {
    44         if (m_sources[i]->isValid())
    45             return true;
     42    for (auto& source : m_sources) {
     43        if (source->status() != CSSFontFaceSource::Status::Failure)
     44            return false;
    4645    }
    47     return false;
     46    return true;
    4847}
    4948
    50 void CSSFontFace::addedToSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace)
     49void CSSFontFace::addedToSegmentedFontFace(CSSSegmentedFontFace& segmentedFontFace)
    5150{
    52     m_segmentedFontFaces.add(segmentedFontFace);
     51    m_segmentedFontFaces.add(&segmentedFontFace);
    5352}
    5453
    55 void CSSFontFace::removedFromSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace)
     54void CSSFontFace::removedFromSegmentedFontFace(CSSSegmentedFontFace& segmentedFontFace)
    5655{
    57     m_segmentedFontFaces.remove(segmentedFontFace);
     56    m_segmentedFontFaces.remove(&segmentedFontFace);
    5857}
    5958
    60 void CSSFontFace::addSource(std::unique_ptr<CSSFontFaceSource> source)
     59void CSSFontFace::adoptSource(std::unique_ptr<CSSFontFaceSource>&& source)
    6160{
    62     source->setFontFace(this);
    6361    m_sources.append(WTFMove(source));
    6462}
    6563
    66 void CSSFontFace::fontLoaded(CSSFontFaceSource* source)
     64void CSSFontFace::fontLoaded(CSSFontFaceSource&)
    6765{
    68     if (source != m_activeSource)
    69         return;
    70 
    7166    // FIXME: Can we assert that m_segmentedFontFaces is not empty? That may
    7267    // require stopping in-progress font loading when the last
     
    7570        return;
    7671
    77     // Use one of the CSSSegmentedFontFaces' font selector. They all have
    78     // the same font selector, so it's wasteful to store it in the CSSFontFace.
    79     CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector();
    80     fontSelector->fontLoaded();
    81 
    82 #if ENABLE(FONT_LOAD_EVENTS)
    83     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && m_loadState == Loading) {
    84         if (source->ensureFontData())
    85             notifyFontLoader(Loaded);
    86         else if (!isValid())
    87             notifyFontLoader(Error);
    88     }
    89 #endif
     72    (*m_segmentedFontFaces.begin())->fontSelector().fontLoaded();
    9073
    9174    for (auto* face : m_segmentedFontFaces)
    92         face->fontLoaded(this);
    93 
    94 #if ENABLE(FONT_LOAD_EVENTS)
    95     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled())
    96         notifyLoadingDone();
    97 #endif
     75        face->fontLoaded(*this);
    9876}
    9977
    10078RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
    10179{
    102     m_activeSource = 0;
    103     if (!isValid())
    104         return 0;
     80    if (allSourcesFailed())
     81        return nullptr;
    10582
    10683    ASSERT(!m_segmentedFontFaces.isEmpty());
    107     CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector();
     84    CSSFontSelector& fontSelector = (*m_segmentedFontFaces.begin())->fontSelector();
    10885
    109 #if ENABLE(FONT_LOAD_EVENTS)
    110     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && m_loadState == NotLoaded)
    111         notifyFontLoader(Loading);
    112 #endif
     86    for (auto& source : m_sources) {
     87        if (source->status() == CSSFontFaceSource::Status::Pending)
     88            source->load(fontSelector);
    11389
    114     size_t size = m_sources.size();
    115     for (size_t i = 0; i < size; ++i) {
    116         if (RefPtr<Font> result = m_sources[i]->font(fontDescription, syntheticBold, syntheticItalic, fontSelector, m_featureSettings, m_variantSettings)) {
    117             m_activeSource = m_sources[i].get();
    118 #if ENABLE(FONT_LOAD_EVENTS)
    119             if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && m_loadState == Loading && m_sources[i]->isLoaded()) {
    120                 notifyFontLoader(Loaded);
    121                 notifyLoadingDone();
    122             }
    123 #endif
    124             return result.release();
     90        switch (source->status()) {
     91        case CSSFontFaceSource::Status::Pending:
     92            ASSERT_NOT_REACHED();
     93            break;
     94        case CSSFontFaceSource::Status::Loading:
     95            return Font::create(FontCache::singleton().lastResortFallbackFont(fontDescription)->platformData(), true, true);
     96        case CSSFontFaceSource::Status::Success:
     97            if (RefPtr<Font> result = source->font(fontDescription, syntheticBold, syntheticItalic, m_featureSettings, m_variantSettings))
     98                return WTFMove(result);
     99            break;
     100        case CSSFontFaceSource::Status::Failure:
     101            break;
    125102        }
    126103    }
    127104
    128 #if ENABLE(FONT_LOAD_EVENTS)
    129     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && m_loadState == Loading) {
    130         notifyFontLoader(Error);
    131         notifyLoadingDone();
    132     }
    133 #endif
    134105    return nullptr;
    135106}
    136 
    137 #if ENABLE(FONT_LOAD_EVENTS)
    138 void CSSFontFace::notifyFontLoader(LoadState newState)
    139 {
    140     m_loadState = newState;
    141 
    142     Document* document = (*m_segmentedFontFaces.begin())->fontSelector()->document();
    143     if (!document)
    144         return;
    145 
    146     switch (newState) {
    147     case Loading:
    148         document->fonts()->beginFontLoading(m_rule.get());
    149         break;
    150     case Loaded:
    151         document->fonts()->fontLoaded(m_rule.get());
    152         break;
    153     case Error:
    154         document->fonts()->loadError(m_rule.get(), m_activeSource);
    155         break;
    156     default:
    157         break;
    158     }
    159 }
    160 
    161 void CSSFontFace::notifyLoadingDone()
    162 {
    163     Document* document = (*m_segmentedFontFaces.begin())->fontSelector()->document();
    164     if (document)
    165         document->fonts()->loadingDone();
    166 }
    167 #endif
    168107
    169108#if ENABLE(SVG_FONTS)
  • trunk/Source/WebCore/css/CSSFontFace.h

    r194923 r196322  
    4646class CSSFontFace : public RefCounted<CSSFontFace> {
    4747public:
    48     static Ref<CSSFontFace> create(FontTraitsMask traitsMask, RefPtr<CSSFontFaceRule>&& rule, bool isLocalFallback = false) { return adoptRef(*new CSSFontFace(traitsMask, WTFMove(rule), isLocalFallback)); }
     48    static Ref<CSSFontFace> create(FontTraitsMask traitsMask, bool isLocalFallback = false) { return adoptRef(*new CSSFontFace(traitsMask, isLocalFallback)); }
    4949
    5050    FontTraitsMask traitsMask() const { return m_traitsMask; }
     
    7373    void setVariantEastAsianRuby(FontVariantEastAsianRuby ruby) { m_variantSettings.eastAsianRuby = ruby; }
    7474
    75     void addedToSegmentedFontFace(CSSSegmentedFontFace*);
    76     void removedFromSegmentedFontFace(CSSSegmentedFontFace*);
     75    void addedToSegmentedFontFace(CSSSegmentedFontFace&);
     76    void removedFromSegmentedFontFace(CSSSegmentedFontFace&);
    7777
    78     bool isValid() const;
     78    bool allSourcesFailed() const;
    7979
    8080    bool isLocalFallback() const { return m_isLocalFallback; }
    8181
    82     void addSource(std::unique_ptr<CSSFontFaceSource>);
     82    void adoptSource(std::unique_ptr<CSSFontFaceSource>&&);
    8383
    84     void fontLoaded(CSSFontFaceSource*);
     84    void fontLoaded(CSSFontFaceSource&);
    8585
    8686    RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic);
     
    105105#endif
    106106
    107 #if ENABLE(FONT_LOAD_EVENTS)
    108     enum LoadState { NotLoaded, Loading, Loaded, Error };
    109     LoadState loadState() const { return m_loadState; }
    110 #endif
    111 
    112107private:
    113     CSSFontFace(FontTraitsMask traitsMask, RefPtr<CSSFontFaceRule>&& rule, bool isLocalFallback)
     108    CSSFontFace(FontTraitsMask traitsMask, bool isLocalFallback)
    114109        : m_traitsMask(traitsMask)
    115         , m_activeSource(0)
    116110        , m_isLocalFallback(isLocalFallback)
    117 #if ENABLE(FONT_LOAD_EVENTS)
    118         , m_loadState(isLocalFallback ? Loaded : NotLoaded)
    119         , m_rule(rule)
    120 #endif
    121111    {
    122         UNUSED_PARAM(rule);
    123112    }
    124113
     
    129118    FontVariantSettings m_variantSettings;
    130119    Vector<std::unique_ptr<CSSFontFaceSource>> m_sources;
    131     CSSFontFaceSource* m_activeSource;
    132120    bool m_isLocalFallback;
    133 #if ENABLE(FONT_LOAD_EVENTS)
    134     LoadState m_loadState;
    135     RefPtr<CSSFontFaceRule> m_rule;
    136     void notifyFontLoader(LoadState);
    137     void notifyLoadingDone();
    138 #endif
    139121};
    140122
  • trunk/Source/WebCore/css/CSSFontFaceSource.cpp

    r195567 r196322  
    5454namespace WebCore {
    5555
    56 CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
    57     : m_string(str)
     56inline void CSSFontFaceSource::setStatus(Status newStatus)
     57{
     58    switch (newStatus) {
     59    case Status::Pending:
     60        ASSERT_NOT_REACHED();
     61        break;
     62    case Status::Loading:
     63        ASSERT(status() == Status::Pending);
     64        break;
     65    case Status::Success:
     66        ASSERT(status() == Status::Loading);
     67        break;
     68    case Status::Failure:
     69        ASSERT(status() == Status::Loading);
     70        break;
     71    }
     72    m_status = newStatus;
     73}
     74
     75CSSFontFaceSource::CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* font, SVGFontFaceElement* fontFace)
     76    : m_familyNameOrURI(familyNameOrURI)
    5877    , m_font(font)
    59     , m_face(0)
     78    , m_face(owner)
     79    , m_svgFontFaceElement(fontFace)
    6080{
     81    // This may synchronously call fontLoaded().
    6182    if (m_font)
    6283        m_font->addClient(this);
     84
     85    if (status() == Status::Pending && (!m_font || m_font->isLoaded())) {
     86        setStatus(Status::Loading);
     87        if (m_font && m_font->errorOccurred())
     88            setStatus(Status::Failure);
     89        else
     90            setStatus(Status::Success);
     91    }
    6392}
    6493
     
    6998}
    7099
    71 bool CSSFontFaceSource::isValid() const
     100void CSSFontFaceSource::fontLoaded(CachedFont& loadedFont)
    72101{
    73     if (m_font)
    74         return !m_font->errorOccurred();
    75     return true;
     102    ASSERT_UNUSED(loadedFont, &loadedFont == m_font.get());
     103
     104    // If the font is in the cache, this will be synchronously called from CachedFont::addClient().
     105    if (m_status == Status::Pending)
     106        setStatus(Status::Loading);
     107
     108    if (m_font->errorOccurred())
     109        setStatus(Status::Failure);
     110    else
     111        setStatus(Status::Success);
     112    m_face.fontLoaded(*this);
    76113}
    77114
    78 void CSSFontFaceSource::fontLoaded(CachedFont*)
     115void CSSFontFaceSource::load(CSSFontSelector& fontSelector)
    79116{
    80     if (m_face)
    81         m_face->fontLoaded(this);
     117    setStatus(Status::Loading);
     118
     119    fontSelector.beginLoadingFontSoon(m_font.get());
    82120}
    83121
    84 RefPtr<Font> CSSFontFaceSource::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
     122RefPtr<Font> CSSFontFaceSource::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
    85123{
    86     // If the font hasn't loaded or an error occurred, then we've got nothing.
    87     if (!isValid())
     124    ASSERT(status() == Status::Success);
     125
     126    SVGFontFaceElement* fontFaceElement = nullptr;
     127#if ENABLE(SVG_FONTS)
     128    fontFaceElement = m_svgFontFaceElement.get();
     129#endif
     130
     131    if (!m_font && !fontFaceElement) {
     132        // We're local. Just return a Font from the normal cache.
     133        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
     134        return FontCache::singleton().fontForFamily(fontDescription, m_familyNameOrURI, true);
     135    }
     136
     137    if (m_font) {
     138        if (!m_font->ensureCustomFontData(m_familyNameOrURI))
     139            return nullptr;
     140
     141        return m_font->createFont(fontDescription, m_familyNameOrURI, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings);
     142    }
     143
     144    // In-Document SVG Fonts
     145    if (!fontFaceElement)
    88146        return nullptr;
    89147
    90     if (!m_font
    91148#if ENABLE(SVG_FONTS)
    92             && !m_svgFontFaceElement
     149#if ENABLE(SVG_OTF_CONVERTER)
     150    if (!m_svgFontFaceElement->parentNode() || !is<SVGFontElement>(m_svgFontFaceElement->parentNode()))
     151        return nullptr;
     152    SVGFontElement& fontElement = downcast<SVGFontElement>(*m_svgFontFaceElement->parentNode());
     153    // FIXME: Re-run this when script modifies the element or any of its descendents
     154    // FIXME: We might have already converted this font. Make existing conversions discoverable.
     155    if (auto otfFont = convertSVGToOTFFont(fontElement))
     156        m_generatedOTFBuffer = SharedBuffer::adoptVector(otfFont.value());
     157    if (!m_generatedOTFBuffer)
     158        return nullptr;
     159    m_inDocumentCustomPlatformData = createFontCustomPlatformData(*m_generatedOTFBuffer);
     160    if (!m_inDocumentCustomPlatformData)
     161        return nullptr;
     162    return Font::create(m_inDocumentCustomPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings), true, false);
     163#else
     164    return Font::create(std::make_unique<SVGFontData>(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic);
    93165#endif
    94     ) {
    95         // We're local. Just return a Font from the normal cache.
    96         // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
    97         return FontCache::singleton().fontForFamily(fontDescription, m_string, true);
    98     }
     166#endif
    99167
    100     if (!m_font || m_font->isLoaded()) {
    101         if (m_font) {
    102             if (!m_font->ensureCustomFontData(m_string))
    103                 return nullptr;
    104 
    105             return m_font->createFont(fontDescription, m_string, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings);
    106         } else {
    107 #if ENABLE(SVG_FONTS)
    108             // In-Document SVG Fonts
    109             if (m_svgFontFaceElement) {
    110 #if ENABLE(SVG_OTF_CONVERTER)
    111                 if (!m_svgFontFaceElement->parentNode() || !is<SVGFontElement>(m_svgFontFaceElement->parentNode()))
    112                     return nullptr;
    113                 SVGFontElement& fontElement = downcast<SVGFontElement>(*m_svgFontFaceElement->parentNode());
    114                 // FIXME: Re-run this when script modifies the element or any of its descendents
    115                 // FIXME: We might have already converted this font. Make existing conversions discoverable.
    116                 if (auto otfFont = convertSVGToOTFFont(fontElement))
    117                     m_generatedOTFBuffer = SharedBuffer::adoptVector(otfFont.value());
    118                 if (!m_generatedOTFBuffer)
    119                     return nullptr;
    120                 auto customPlatformData = createFontCustomPlatformData(*m_generatedOTFBuffer);
    121                 if (!customPlatformData)
    122                     return nullptr;
    123                 return Font::create(customPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings), true, false);
    124 #else
    125                 return Font::create(std::make_unique<SVGFontData>(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic);
    126 #endif
    127             }
    128 #endif
    129             return nullptr;
    130         }
    131     } else {
    132         // Kick off the load. Do it soon rather than now, because we may be in the middle of layout,
    133         // and the loader may invoke arbitrary delegate or event handler code.
    134         fontSelector->beginLoadingFontSoon(m_font.get());
    135 
    136         return Font::create(FontCache::singleton().lastResortFallbackFont(fontDescription)->platformData(), true, true);
    137     }
     168    ASSERT_NOT_REACHED();
     169    return nullptr;
    138170}
    139171
     
    145177#endif
    146178
    147 #if ENABLE(FONT_LOAD_EVENTS)
    148 bool CSSFontFaceSource::isDecodeError() const
    149 {
    150     if (m_font)
    151         return m_font->status() == CachedResource::DecodeError;
    152     return false;
    153179}
    154 
    155 bool CSSFontFaceSource::ensureFontData()
    156 {
    157     if (!m_font)
    158         return false;
    159     return m_font->ensureCustomFontData(m_hasExternalSVGFont, m_string);
    160 }
    161 #endif
    162 
    163 }
  • trunk/Source/WebCore/css/CSSFontFaceSource.h

    r195567 r196322  
    2929#include "CachedFontClient.h"
    3030#include "CachedResourceHandle.h"
    31 #include "SharedBuffer.h"
    32 #if ENABLE(SVG_FONTS)
    33 #include "SVGFontElement.h"
    34 #include "SVGFontFaceElement.h"
    35 #endif
    36 #include "Timer.h"
    3731#include <wtf/text/AtomicString.h>
    3832
     
    4236class CSSFontSelector;
    4337class Font;
     38struct FontCustomPlatformData;
    4439class FontDescription;
    4540class FontFeatureSettings;
    4641struct FontVariantSettings;
     42class SVGFontFaceElement;
     43class SharedBuffer;
    4744
    4845class CSSFontFaceSource final : public CachedFontClient {
    4946    WTF_MAKE_FAST_ALLOCATED;
    5047public:
    51     CSSFontFaceSource(const String&, CachedFont* = nullptr);
     48
     49    //                      => Succeeded
     50    //                    //
     51    // Pending => Loading
     52    //                    \\.
     53    //                      => Failed
     54    enum class Status {
     55        Pending,
     56        Loading,
     57        Success,
     58        Failure
     59    };
     60
     61    CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* = nullptr, SVGFontFaceElement* = nullptr);
    5262    virtual ~CSSFontFaceSource();
    5363
    54     bool isValid() const;
     64    Status status() const { return m_status; }
    5565
    56     const AtomicString& string() const { return m_string; }
     66    const AtomicString& familyNameOrURI() const { return m_familyNameOrURI; }
    5767
    58     void setFontFace(CSSFontFace* face) { m_face = face; }
    59 
    60     virtual void fontLoaded(CachedFont*) override;
    61 
    62     RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic, CSSFontSelector*, const FontFeatureSettings&, const FontVariantSettings&);
    63 
    64     void pruneTable();
     68    void load(CSSFontSelector&);
     69    RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic, const FontFeatureSettings&, const FontVariantSettings&);
    6570
    6671#if ENABLE(SVG_FONTS)
    67     SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement.get(); }
    68     void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element) { m_svgFontFaceElement = element; }
    6972    bool isSVGFontFaceSource() const;
    7073#endif
    7174
    72 #if ENABLE(FONT_LOAD_EVENTS)
    73     bool isDecodeError() const;
    74     bool ensureFontData();
    75 #endif
     75private:
     76    virtual void fontLoaded(CachedFont&) override;
    7677
    77 private:
    78     void startLoadingTimerFired();
     78    void setStatus(Status);
    7979
    80     AtomicString m_string; // URI for remote, built-in font name for local.
     80    AtomicString m_familyNameOrURI; // URI for remote, built-in font name for local.
    8181    CachedResourceHandle<CachedFont> m_font; // For remote fonts, a pointer to our cached resource.
    82     CSSFontFace* m_face; // Our owning font face.
     82    CSSFontFace& m_face; // Our owning font face.
    8383
    8484#if ENABLE(SVG_OTF_CONVERTER)
     
    8888#if ENABLE(SVG_FONTS) || ENABLE(SVG_OTF_CONVERTER)
    8989    RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
     90    std::unique_ptr<FontCustomPlatformData> m_inDocumentCustomPlatformData;
    9091#endif
     92
     93    Status m_status { Status::Pending };
    9194};
    9295
  • trunk/Source/WebCore/css/CSSFontSelector.cpp

    r195928 r196322  
    153153}
    154154
    155 static Ref<CSSFontFace> createFontFace(CSSValueList& srcList, FontTraitsMask traitsMask, Document* document, const StyleRuleFontFace& fontFaceRule, bool isInitiatingElementInUserAgentShadowTree)
    156 {
    157     RefPtr<CSSFontFaceRule> rule;
    158 #if ENABLE(FONT_LOAD_EVENTS)
    159     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=112116 - This CSSFontFaceRule has no parent.
    160     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled())
    161         rule = static_pointer_cast<CSSFontFaceRule>(fontFaceRule.createCSSOMWrapper());
    162 #else
    163     UNUSED_PARAM(fontFaceRule);
    164 #endif
    165     Ref<CSSFontFace> fontFace = CSSFontFace::create(traitsMask, WTFMove(rule));
    166 
    167     int srcLength = srcList.length();
    168 
    169     bool foundSVGFont = false;
    170 
    171     for (int i = 0; i < srcLength; i++) {
     155static Ref<CSSFontFace> createFontFace(CSSValueList& srcList, FontTraitsMask traitsMask, Document* document, bool isInitiatingElementInUserAgentShadowTree)
     156{
     157    Ref<CSSFontFace> fontFace = CSSFontFace::create(traitsMask);
     158
     159    for (auto& src : srcList) {
    172160        // An item in the list either specifies a string (local font name) or a URL (remote font to download).
    173         CSSFontFaceSrcValue& item = downcast<CSSFontFaceSrcValue>(*srcList.itemWithoutBoundsCheck(i));
     161        CSSFontFaceSrcValue& item = downcast<CSSFontFaceSrcValue>(src.get());
    174162        std::unique_ptr<CSSFontFaceSource> source;
     163        SVGFontFaceElement* fontFaceElement = nullptr;
     164        bool foundSVGFont = false;
    175165
    176166#if ENABLE(SVG_FONTS)
    177167        foundSVGFont = item.isSVGFontFaceSrc() || item.svgFontFaceElement();
     168        fontFaceElement = item.svgFontFaceElement();
    178169#endif
    179170        if (!item.isLocal()) {
     
    182173            if (allowDownloading && item.isSupportedFormat() && document) {
    183174                if (CachedFont* cachedFont = item.cachedFont(document, foundSVGFont, isInitiatingElementInUserAgentShadowTree))
    184                     source = std::make_unique<CSSFontFaceSource>(item.resource(), cachedFont);
     175                    source = std::make_unique<CSSFontFaceSource>(fontFace.get(), item.resource(), cachedFont);
    185176            }
    186177        } else
    187             source = std::make_unique<CSSFontFaceSource>(item.resource());
    188 
    189         if (source) {
    190 #if ENABLE(SVG_FONTS)
    191             source->setSVGFontFaceElement(item.svgFontFaceElement());
    192 #endif
    193             fontFace->addSource(WTFMove(source));
    194         }
     178            source = std::make_unique<CSSFontFaceSource>(fontFace.get(), item.resource(), nullptr, fontFaceElement);
     179
     180        if (source)
     181            fontFace->adoptSource(WTFMove(source));
    195182    }
    196183
     
    235222    Vector<Ref<CSSFontFace>> faces = { };
    236223    for (auto mask : traitsMasks) {
    237         Ref<CSSFontFace> face = CSSFontFace::create(mask, nullptr, true);
    238         face->addSource(std::make_unique<CSSFontFaceSource>(familyName));
    239         ASSERT(face->isValid());
     224        Ref<CSSFontFace> face = CSSFontFace::create(mask, true);
     225        face->adoptSource(std::make_unique<CSSFontFaceSource>(face.get(), familyName));
     226        ASSERT(!face->allSourcesFailed());
    240227        faces.append(WTFMove(face));
    241228    }
     
    274261    auto traitsMask = computedTraitsMask.value();
    275262
    276     Ref<CSSFontFace> fontFace = createFontFace(srcList, traitsMask, m_document, fontFaceRule, isInitiatingElementInUserAgentShadowTree);
    277     if (!fontFace->isValid())
     263    Ref<CSSFontFace> fontFace = createFontFace(srcList, traitsMask, m_document, isInitiatingElementInUserAgentShadowTree);
     264    if (fontFace->allSourcesFailed())
    278265        return;
    279266
     
    487474        return face.get();
    488475
    489     face = CSSSegmentedFontFace::create(this);
     476    face = CSSSegmentedFontFace::create(*this);
    490477
    491478    Vector<std::reference_wrapper<CSSFontFace>, 32> candidateFontFaces;
  • trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp

    r194923 r196322  
    3838namespace WebCore {
    3939
    40 CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector)
     40CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector& fontSelector)
    4141    : m_fontSelector(fontSelector)
    4242{
     
    4545CSSSegmentedFontFace::~CSSSegmentedFontFace()
    4646{
    47     pruneTable();
    4847    for (auto& face : m_fontFaces)
    49         face->removedFromSegmentedFontFace(this);
     48        face->removedFromSegmentedFontFace(*this);
    5049}
    5150
    52 void CSSSegmentedFontFace::pruneTable()
     51void CSSSegmentedFontFace::fontLoaded(CSSFontFace&)
    5352{
    54     m_descriptionToRangesMap.clear();
    55 }
    56 
    57 void CSSSegmentedFontFace::fontLoaded(CSSFontFace*)
    58 {
    59     pruneTable();
    60 
    61 #if ENABLE(FONT_LOAD_EVENTS)
    62     if (RuntimeEnabledFeatures::sharedFeatures().fontLoadEventsEnabled() && !isLoading()) {
    63         Vector<RefPtr<LoadFontCallback>> callbacks;
    64         m_callbacks.swap(callbacks);
    65         for (size_t index = 0; index < callbacks.size(); ++index) {
    66             if (checkFont())
    67                 callbacks[index]->notifyLoaded();
    68             else
    69                 callbacks[index]->notifyError();
    70         }
    71     }
    72 #endif
     53    m_cache.clear();
    7354}
    7455
    7556void CSSSegmentedFontFace::appendFontFace(Ref<CSSFontFace>&& fontFace)
    7657{
    77     pruneTable();
    78     fontFace->addedToSegmentedFontFace(this);
     58    m_cache.clear();
     59    fontFace->addedToSegmentedFontFace(*this);
    7960    m_fontFaces.append(WTFMove(fontFace));
    8061}
     
    10182    FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
    10283
    103     auto addResult = m_descriptionToRangesMap.add(FontDescriptionKey(fontDescription), FontRanges());
     84    auto addResult = m_cache.add(FontDescriptionKey(fontDescription), FontRanges());
    10485    auto& fontRanges = addResult.iterator->value;
    10586
    10687    if (addResult.isNewEntry) {
    10788        for (auto& face : m_fontFaces) {
    108             if (!face->isValid())
     89            if (face->allSourcesFailed())
    10990                continue;
    11091
     
    120101}
    121102
    122 #if ENABLE(FONT_LOAD_EVENTS)
    123 bool CSSSegmentedFontFace::isLoading() const
    124 {
    125     for (auto& face : m_fontFaces) {
    126         if (face->loadState() == CSSFontFace::Loading)
    127             return true;
    128     }
    129     return false;
    130103}
    131 
    132 bool CSSSegmentedFontFace::checkFont() const
    133 {
    134     for (auto& face : m_fontFaces) {
    135         if (face->loadState() != CSSFontFace::Loaded)
    136             return false;
    137     }
    138     return true;
    139 }
    140 
    141 void CSSSegmentedFontFace::loadFont(const FontDescription& fontDescription, PassRefPtr<LoadFontCallback> callback)
    142 {
    143     fontRanges(fontDescription); // Kick off the load.
    144 
    145     if (callback) {
    146         if (isLoading())
    147             m_callbacks.append(callback);
    148         else if (checkFont())
    149             callback->notifyLoaded();
    150         else
    151             callback->notifyError();
    152     }
    153 }
    154 #endif
    155 
    156 }
  • trunk/Source/WebCore/css/CSSSegmentedFontFace.h

    r194923 r196322  
    4242class CSSSegmentedFontFace : public RefCounted<CSSSegmentedFontFace> {
    4343public:
    44     static Ref<CSSSegmentedFontFace> create(CSSFontSelector* selector) { return adoptRef(*new CSSSegmentedFontFace(selector)); }
     44    static Ref<CSSSegmentedFontFace> create(CSSFontSelector& selector) { return adoptRef(*new CSSSegmentedFontFace(selector)); }
    4545    ~CSSSegmentedFontFace();
    4646
    47     CSSFontSelector* fontSelector() const { return m_fontSelector; }
     47    CSSFontSelector& fontSelector() const { return m_fontSelector; }
    4848
    49     void fontLoaded(CSSFontFace*);
     49    void fontLoaded(CSSFontFace&);
    5050
    5151    void appendFontFace(Ref<CSSFontFace>&&);
     
    5353    FontRanges fontRanges(const FontDescription&);
    5454
    55 #if ENABLE(FONT_LOAD_EVENTS)
    56     class LoadFontCallback : public RefCounted<LoadFontCallback> {
    57     public:
    58         virtual ~LoadFontCallback() { }
    59         virtual void notifyLoaded() = 0;
    60         virtual void notifyError() = 0;
    61     };
     55private:
     56    CSSSegmentedFontFace(CSSFontSelector&);
    6257
    63     bool checkFont() const;
    64     void loadFont(const FontDescription&, PassRefPtr<LoadFontCallback> loadCallback);
    65 #endif
    66 
    67 private:
    68     CSSSegmentedFontFace(CSSFontSelector*);
    69 
    70     void pruneTable();
    71 #if ENABLE(FONT_LOAD_EVENTS)
    72     bool isLoading() const;
    73 #endif
    74 
    75     CSSFontSelector* m_fontSelector;
    76     HashMap<FontDescriptionKey, FontRanges, FontDescriptionKeyHash, WTF::SimpleClassHashTraits<FontDescriptionKey>> m_descriptionToRangesMap;
     58    CSSFontSelector& m_fontSelector;
     59    HashMap<FontDescriptionKey, FontRanges, FontDescriptionKeyHash, WTF::SimpleClassHashTraits<FontDescriptionKey>> m_cache;
    7760    Vector<Ref<CSSFontFace>, 1> m_fontFaces;
    78 #if ENABLE(FONT_LOAD_EVENTS)
    79     Vector<RefPtr<LoadFontCallback>> m_callbacks;
    80 #endif
    8161};
    8262
  • trunk/Source/WebCore/loader/cache/CachedFont.cpp

    r195523 r196322  
    7070}
    7171
    72 void CachedFont::didAddClient(CachedResourceClient* c)
     72void CachedFont::didAddClient(CachedResourceClient* client)
    7373{
    74     ASSERT(c->resourceClientType() == CachedFontClient::expectedType());
     74    ASSERT(client->resourceClientType() == CachedFontClient::expectedType());
    7575    if (!isLoading())
    76         static_cast<CachedFontClient*>(c)->fontLoaded(this);
     76        static_cast<CachedFontClient*>(client)->fontLoaded(*this);
    7777}
    7878
     
    149149        return;
    150150   
    151     CachedResourceClientWalker<CachedFontClient> w(m_clients);
    152     while (CachedFontClient* c = w.next())
    153          c->fontLoaded(this);
     151    CachedResourceClientWalker<CachedFontClient> walker(m_clients);
     152    while (CachedFontClient* client = walker.next())
     153        client->fontLoaded(*this);
    154154}
    155155
  • trunk/Source/WebCore/loader/cache/CachedFontClient.h

    r162139 r196322  
    3838    static CachedResourceClientType expectedType() { return FontType; }
    3939    virtual CachedResourceClientType resourceClientType() const override { return expectedType(); }
    40     virtual void fontLoaded(CachedFont*) { }
     40    virtual void fontLoaded(CachedFont&) { }
    4141};
    4242
Note: See TracChangeset for help on using the changeset viewer.