<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201551] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201551">201551</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2016-06-01 07:29:30 -0700 (Wed, 01 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Precache primary font in a secondary thread
https://bugs.webkit.org/show_bug.cgi?id=158243

Reviewed by Andreas Kling.

We know the font families and descriptions to use on style resolution. The actual fonts are only needed for
layout. There is often time to load and cache fonts asynchronously before they are accessed. This can substantially
reduce font related workload in the main thread.

* css/CSSFontFace.cpp:
(WebCore::CSSFontFace::font):
(WebCore::CSSFontFace::resolveFamilies):
(WebCore::CSSFontFace::hasSVGFontFaceSource):
* css/CSSFontFace.h:
* css/CSSFontFaceSource.cpp:
(WebCore::CSSFontFaceSource::font):
(WebCore::CSSFontFaceSource::url):
(WebCore::CSSFontFaceSource::isSVGFontFaceSource):
* css/CSSFontFaceSource.h:
* css/CSSFontSelector.cpp:
(WebCore::CSSFontSelector::fallbackFontAt):
(WebCore::CSSFontSelector::resolveFamilies):

    Add a function for resolving font families of a cascade to their final values.

* css/CSSFontSelector.h:
* css/CSSSegmentedFontFace.cpp:
(WebCore::CSSSegmentedFontFace::fontRanges):
(WebCore::CSSSegmentedFontFace::resolveFamilies):
* css/CSSSegmentedFontFace.h:
* platform/graphics/FontCache.cpp:
(WebCore::fontPlatformDataCache):
(WebCore::precacheTasksInProgress):
(WebCore::alternateFamilyName):
(WebCore::FontCache::getCachedFontPlatformData):
(WebCore::FontCache::invalidate):
(WebCore::FontCache::precache):

    Precache fonts by trying to load them asyncronously one by one. On success the font is cached into font platform data cache.

(WebCore::FontCache::similarFont):
* platform/graphics/FontCache.h:
* platform/graphics/FontCascade.cpp:
(WebCore::pruneSystemFallbackFonts):
(WebCore::precachePrimaryFamily):

    When initializing a new font cascade resolve any platform fonts to their actual names using FontSelector,
    then precache the primary font for the cascade.

    Web fonts are ignored for now.

(WebCore::retrieveOrAddCachedFonts):
* platform/graphics/FontSelector.h:
(WebCore::FontSelector::~FontSelector):
* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::FontCache::setFontWhitelist):
(WebCore::fontWithFamily):
(WebCore::autoActivateFont):
(WebCore::createFontPlatformDataThreadSafe):

    Factor thread safe part of createFontPlatformData to a function.

(WebCore::FontCache::createFontPlatformData):

    Do the main thread only hash lookups here then call to createFontPlatformDataThreadSafe.

(WebCore::fallbackDedupSet):
(WebCore::FontCache::systemFallbackForCharacters):
(WebCore::FontCache::platformPrecache):

    Try to initialize font asynchronously in a dispatch queue, call completion handler on success or failure.

(WebCore::FontCache::platformCancelPrecache):

    Cancel ongoing precache operation.

(WebCore::platformFontLookupWithFamily): Deleted.

    This was inlined to the only client, fontWithFamily.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFacecpp">trunk/Source/WebCore/css/CSSFontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceh">trunk/Source/WebCore/css/CSSFontFace.h</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceSourcecpp">trunk/Source/WebCore/css/CSSFontFaceSource.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceSourceh">trunk/Source/WebCore/css/CSSFontFaceSource.h</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontSelectorcpp">trunk/Source/WebCore/css/CSSFontSelector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontSelectorh">trunk/Source/WebCore/css/CSSFontSelector.h</a></li>
<li><a href="#trunkSourceWebCorecssCSSSegmentedFontFacecpp">trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSSegmentedFontFaceh">trunk/Source/WebCore/css/CSSSegmentedFontFace.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontCachecpp">trunk/Source/WebCore/platform/graphics/FontCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontCacheh">trunk/Source/WebCore/platform/graphics/FontCache.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontCascadecpp">trunk/Source/WebCore/platform/graphics/FontCascade.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsFontSelectorh">trunk/Source/WebCore/platform/graphics/FontSelector.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp">trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/ChangeLog        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -1,3 +1,85 @@
</span><ins>+2016-05-31  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Precache primary font in a secondary thread
+        https://bugs.webkit.org/show_bug.cgi?id=158243
+
+        Reviewed by Andreas Kling.
+
+        We know the font families and descriptions to use on style resolution. The actual fonts are only needed for
+        layout. There is often time to load and cache fonts asynchronously before they are accessed. This can substantially
+        reduce font related workload in the main thread.
+
+        * css/CSSFontFace.cpp:
+        (WebCore::CSSFontFace::font):
+        (WebCore::CSSFontFace::resolveFamilies):
+        (WebCore::CSSFontFace::hasSVGFontFaceSource):
+        * css/CSSFontFace.h:
+        * css/CSSFontFaceSource.cpp:
+        (WebCore::CSSFontFaceSource::font):
+        (WebCore::CSSFontFaceSource::url):
+        (WebCore::CSSFontFaceSource::isSVGFontFaceSource):
+        * css/CSSFontFaceSource.h:
+        * css/CSSFontSelector.cpp:
+        (WebCore::CSSFontSelector::fallbackFontAt):
+        (WebCore::CSSFontSelector::resolveFamilies):
+
+            Add a function for resolving font families of a cascade to their final values.
+
+        * css/CSSFontSelector.h:
+        * css/CSSSegmentedFontFace.cpp:
+        (WebCore::CSSSegmentedFontFace::fontRanges):
+        (WebCore::CSSSegmentedFontFace::resolveFamilies):
+        * css/CSSSegmentedFontFace.h:
+        * platform/graphics/FontCache.cpp:
+        (WebCore::fontPlatformDataCache):
+        (WebCore::precacheTasksInProgress):
+        (WebCore::alternateFamilyName):
+        (WebCore::FontCache::getCachedFontPlatformData):
+        (WebCore::FontCache::invalidate):
+        (WebCore::FontCache::precache):
+
+            Precache fonts by trying to load them asyncronously one by one. On success the font is cached into font platform data cache.
+
+        (WebCore::FontCache::similarFont):
+        * platform/graphics/FontCache.h:
+        * platform/graphics/FontCascade.cpp:
+        (WebCore::pruneSystemFallbackFonts):
+        (WebCore::precachePrimaryFamily):
+
+            When initializing a new font cascade resolve any platform fonts to their actual names using FontSelector,
+            then precache the primary font for the cascade.
+
+            Web fonts are ignored for now.
+
+        (WebCore::retrieveOrAddCachedFonts):
+        * platform/graphics/FontSelector.h:
+        (WebCore::FontSelector::~FontSelector):
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::FontCache::setFontWhitelist):
+        (WebCore::fontWithFamily):
+        (WebCore::autoActivateFont):
+        (WebCore::createFontPlatformDataThreadSafe):
+
+            Factor thread safe part of createFontPlatformData to a function.
+
+        (WebCore::FontCache::createFontPlatformData):
+
+            Do the main thread only hash lookups here then call to createFontPlatformDataThreadSafe.
+
+        (WebCore::fallbackDedupSet):
+        (WebCore::FontCache::systemFallbackForCharacters):
+        (WebCore::FontCache::platformPrecache):
+
+            Try to initialize font asynchronously in a dispatch queue, call completion handler on success or failure.
+
+        (WebCore::FontCache::platformCancelPrecache):
+
+            Cancel ongoing precache operation.
+
+        (WebCore::platformFontLookupWithFamily): Deleted.
+
+            This was inlined to the only client, fontWithFamily.
+
</ins><span class="cx"> 2016-06-01  Adam Bergkvist  &lt;adam.bergkvist@ericsson.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebRTC: Add RTCRtpTransceiver interface and RTCPeerConnection.addTransceiver()
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFace.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFace.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontFace.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -520,6 +520,19 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Vector&lt;ResolvedFontFamily&gt; CSSFontFace::resolveFamilies() const
+{
+    Vector&lt;ResolvedFontFamily&gt; result;
+    for (auto&amp; source : m_sources) {
+        if (source-&gt;familyNameOrURI().isEmpty())
+            continue;
+        if (source-&gt;status() == CSSFontFaceSource::Status::Failure)
+            continue;
+        result.append({ source-&gt;familyNameOrURI(), source-&gt;url() });
+    }
+    return result;
+}
+
</ins><span class="cx"> #if ENABLE(SVG_FONTS)
</span><span class="cx"> bool CSSFontFace::hasSVGFontFaceSource() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFace.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFace.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontFace.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CSSFontFaceRule.h&quot;
</span><span class="cx"> #include &quot;FontFeatureSettings.h&quot;
</span><ins>+#include &quot;FontSelector.h&quot;
</ins><span class="cx"> #include &quot;TextFlags.h&quot;
</span><span class="cx"> #include &lt;memory&gt;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="lines">@@ -135,6 +136,8 @@
</span><span class="cx">     // We don't guarantee that the FontFace wrapper will be the same every time you ask for it.
</span><span class="cx">     Ref&lt;FontFace&gt; wrapper();
</span><span class="cx"> 
</span><ins>+    Vector&lt;ResolvedFontFamily&gt; resolveFamilies() const;
+
</ins><span class="cx"> #if ENABLE(SVG_FONTS)
</span><span class="cx">     bool hasSVGFontFaceSource() const;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFaceSource.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFaceSource.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontFaceSource.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -188,6 +188,13 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Optional&lt;URL&gt; CSSFontFaceSource::url() const
+{
+    if (!m_font)
+        return Nullopt;
+    return m_font-&gt;url();
+}
+
</ins><span class="cx"> #if ENABLE(SVG_FONTS)
</span><span class="cx"> bool CSSFontFaceSource::isSVGFontFaceSource() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFaceSource.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFaceSource.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontFaceSource.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CachedFontClient.h&quot;
</span><span class="cx"> #include &quot;CachedResourceHandle.h&quot;
</span><ins>+#include &quot;URL.h&quot;
</ins><span class="cx"> #include &lt;runtime/ArrayBufferView.h&gt;
</span><span class="cx"> #include &lt;wtf/text/AtomicString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -71,6 +72,8 @@
</span><span class="cx">     bool isSVGFontFaceSource() const;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    Optional&lt;URL&gt; url() const;
+
</ins><span class="cx"> private:
</span><span class="cx">     void fontLoaded(CachedFont&amp;) override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontSelectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontSelector.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontSelector.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontSelector.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -334,4 +334,22 @@
</span><span class="cx">     return FontCache::singleton().fontForFamily(fontDescription, settings-&gt;pictographFontFamily());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Vector&lt;ResolvedFontFamily&gt; CSSFontSelector::resolveFamilies(const Vector&lt;AtomicString&gt;&amp; families, const FontDescription&amp; fontDescription, UChar32 character)
+{
+    Vector&lt;ResolvedFontFamily&gt; result;
+
+    for (auto&amp; family : families) {
+        if (family.isEmpty())
+            continue;
+        auto* segmentedFace = m_cssFontFaceSet-&gt;getFontFace(fontDescription.traitsMask(), family);
+        if (!segmentedFace) {
+            result.append({ resolveGenericFamily(m_document, fontDescription, family), { } });
+            continue;
+        }
+        result.appendVector(segmentedFace-&gt;resolveFamilies(character));
+    }
+
+    return result;
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontSelectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontSelector.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontSelector.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSFontSelector.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -64,6 +64,8 @@
</span><span class="cx">     size_t fallbackFontCount() override;
</span><span class="cx">     RefPtr&lt;Font&gt; fallbackFontAt(const FontDescription&amp;, size_t) override;
</span><span class="cx"> 
</span><ins>+    Vector&lt;ResolvedFontFamily&gt; resolveFamilies(const Vector&lt;AtomicString&gt;&amp;, const FontDescription&amp;, UChar32) override;
+
</ins><span class="cx">     void clearDocument();
</span><span class="cx"> 
</span><span class="cx">     void addFontFaceRule(StyleRuleFontFace&amp;, bool isInitiatingElementInUserAgentShadowTree);
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSSegmentedFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -138,4 +138,20 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Vector&lt;ResolvedFontFamily&gt; CSSSegmentedFontFace::resolveFamilies(UChar32 character) const
+{
+    for (auto&amp; face : m_fontFaces) {
+        bool inRange = face-&gt;ranges().isEmpty();
+        for (auto&amp; range : face-&gt;ranges()) {
+            if (character &gt;= range.from &amp;&amp; character &lt;= range.to) {
+                inRange = true;
+                break;
+            }
+        }
+        if (inRange)
+            return face-&gt;resolveFamilies();
+    }
+    return { };
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorecssCSSSegmentedFontFaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSegmentedFontFace.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSegmentedFontFace.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/css/CSSSegmentedFontFace.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CSSFontFace.h&quot;
</span><span class="cx"> #include &quot;FontCache.h&quot;
</span><ins>+#include &quot;FontSelector.h&quot;
</ins><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -57,6 +58,8 @@
</span><span class="cx">     void ref() override { RefCounted&lt;CSSSegmentedFontFace&gt;::ref(); }
</span><span class="cx">     void deref() override { RefCounted&lt;CSSSegmentedFontFace&gt;::deref(); }
</span><span class="cx"> 
</span><ins>+    Vector&lt;ResolvedFontFamily&gt; resolveFamilies(UChar32 character) const;
+
</ins><span class="cx"> private:
</span><span class="cx">     CSSSegmentedFontFace();
</span><span class="cx">     void fontLoaded(CSSFontFace&amp;) override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontCache.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontCache.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/platform/graphics/FontCache.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -106,6 +106,7 @@
</span><span class="cx">         , m_fontFaceFeatures(fontFaceFeatures ? *fontFaceFeatures : FontFeatureSettings())
</span><span class="cx">         , m_fontFaceVariantSettings(fontFaceVariantSettings ? *fontFaceVariantSettings : FontVariantSettings())
</span><span class="cx">     { }
</span><ins>+    FontPlatformDataCacheKey(const FontPlatformDataCacheKey&amp;) = default;
</ins><span class="cx"> 
</span><span class="cx">     explicit FontPlatformDataCacheKey(HashTableDeletedValueType t)
</span><span class="cx">         : m_fontDescriptionKey(t)
</span><span class="lines">@@ -159,6 +160,16 @@
</span><span class="cx">     return cache;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA) &amp;&amp; ENABLE(PLATFORM_FONT_LOOKUP)
+using PrecacheMap = HashMap&lt;FontPlatformDataCacheKey, FontCache::PrecacheTask*, FontPlatformDataCacheKeyHash, WTF::SimpleClassHashTraits&lt;FontPlatformDataCacheKey&gt;&gt;;
+
+static PrecacheMap&amp; precacheTasksInProgress()
+{
+    static NeverDestroyed&lt;PrecacheMap&gt; map;
+    return map;
+}
+#endif
+
</ins><span class="cx"> static AtomicString alternateFamilyName(const AtomicString&amp; familyName)
</span><span class="cx"> {
</span><span class="cx">     switch (familyName.length()) {
</span><span class="lines">@@ -243,6 +254,12 @@
</span><span class="cx"> 
</span><span class="cx">     FontPlatformDataCacheKey key(familyName, fontDescription, fontFaceFeatures, fontFaceVariantSettings);
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA) &amp;&amp; ENABLE(PLATFORM_FONT_LOOKUP)
+    auto* precacheTask = precacheTasksInProgress().get(key);
+    if (precacheTask)
+        platformCancelPrecache(*precacheTask);
+#endif
+
</ins><span class="cx">     auto addResult = fontPlatformDataCache().add(key, nullptr);
</span><span class="cx">     FontPlatformDataCache::iterator it = addResult.iterator;
</span><span class="cx">     if (addResult.isNewEntry) {
</span><span class="lines">@@ -489,6 +506,67 @@
</span><span class="cx">     purgeInactiveFontData();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA) &amp;&amp; ENABLE(PLATFORM_FONT_LOOKUP)
+void FontCache::precache(const Vector&lt;AtomicString&gt;&amp; resolvedFamilies, const FontDescription&amp; fontDescription)
+{
+    if (resolvedFamilies.isEmpty())
+        return;
+    auto&amp; family = resolvedFamilies.first();
+
+    FontPlatformDataCacheKey key(family, fontDescription, nullptr, nullptr);
+
+    // Maybe we have it already?
+    auto it = fontPlatformDataCache().find(key);
+    if (it != fontPlatformDataCache().end()) {
+        if (it-&gt;value)
+            return;
+
+        // We already know this font isn't available. Try the next.
+        Vector&lt;AtomicString&gt; remainingFamilies;
+        remainingFamilies.appendRange(resolvedFamilies.begin() + 1, resolvedFamilies.end());
+        precache(remainingFamilies, fontDescription);
+        return;
+    }
+
+    auto taskAdd = precacheTasksInProgress().add(key, nullptr);
+    if (!taskAdd.isNewEntry)
+        return;
+
+    auto&amp; task = platformPrecache(family, fontDescription, [key, resolvedFamilies, fontDescription] (auto platformData, bool wasCanceled) {
+        precacheTasksInProgress().remove(key);
+
+        if (wasCanceled)
+            return;
+
+        if (platformData) {
+            auto r = fontPlatformDataCache().add(key, WTFMove(platformData));
+            fprintf(stderr, &quot;success %d\n&quot;, r.isNewEntry);
+            return;
+        }
+
+        // Didn't find the font. Try the next one.
+        Vector&lt;AtomicString&gt; remainingFamilies;
+
+        auto alternateName = alternateFamilyName(resolvedFamilies.first());
+        if (!alternateName.isNull()) {
+            remainingFamilies = resolvedFamilies;
+            remainingFamilies.first() = alternateName;
+        } else {
+            fontPlatformDataCache().add(key, nullptr);
+            remainingFamilies.appendRange(resolvedFamilies.begin() + 1, resolvedFamilies.end());
+        }
+
+        singleton().precache(remainingFamilies, fontDescription);
+    });
+
+    taskAdd.iterator-&gt;value = &amp;task;
+}
+#else
+void FontCache::precache(const Vector&lt;AtomicString&gt;&amp;, const FontDescription&amp;)
+{
+}
+#endif
+
</ins><span class="cx"> #if !PLATFORM(COCOA)
</span><span class="cx"> RefPtr&lt;Font&gt; FontCache::similarFont(const FontDescription&amp;, const AtomicString&amp;)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontCache.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontCache.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/platform/graphics/FontCache.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -193,6 +193,8 @@
</span><span class="cx">     WEBCORE_EXPORT Ref&lt;Font&gt; fontForPlatformData(const FontPlatformData&amp;);
</span><span class="cx">     RefPtr&lt;Font&gt; similarFont(const FontDescription&amp;, const AtomicString&amp; family);
</span><span class="cx"> 
</span><ins>+    void precache(const Vector&lt;AtomicString&gt;&amp; resolvedFamilies, const FontDescription&amp;);
+
</ins><span class="cx">     void addClient(FontSelector&amp;);
</span><span class="cx">     void removeClient(FontSelector&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -212,6 +214,8 @@
</span><span class="cx">     RefPtr&lt;OpenTypeVerticalData&gt; verticalData(const FontPlatformData&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    struct PrecacheTask;
+
</ins><span class="cx"> private:
</span><span class="cx">     FontCache();
</span><span class="cx">     ~FontCache() = delete;
</span><span class="lines">@@ -227,6 +231,12 @@
</span><span class="cx"> #endif
</span><span class="cx">     std::unique_ptr&lt;FontPlatformData&gt; createFontPlatformData(const FontDescription&amp;, const AtomicString&amp; family, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings);
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA) &amp;&amp; ENABLE(PLATFORM_FONT_LOOKUP)
+    using PrecacheCompletionHandler = std::function&lt;void (std::unique_ptr&lt;FontPlatformData&gt;, bool wasCanceled)&gt;;
+    PrecacheTask&amp; platformPrecache(const AtomicString&amp; family, const FontDescription&amp;, PrecacheCompletionHandler&amp;&amp;);
+    void platformCancelPrecache(PrecacheTask&amp;);
+#endif
+
</ins><span class="cx">     Timer m_purgeTimer;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontCascadecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontCascade.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontCascade.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -261,6 +261,29 @@
</span><span class="cx">         entry-&gt;fonts-&gt;pruneSystemFallbacks();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void precachePrimaryFamily(const FontCascadeDescription&amp; fontDescription, FontSelector&amp; fontSelector)
+{
+    Vector&lt;AtomicString&gt; families;
+    for (unsigned i = 0; i &lt; fontDescription.familyCount(); ++i)
+        families.append(fontDescription.familyAt(i));
+
+    // Primary family lookup falls back to the standard family.
+    families.append(standardFamily);
+
+    auto resolvedPrimaryFamilies = fontSelector.resolveFamilies(families, fontDescription, ' ');
+
+    Vector&lt;AtomicString&gt; resolvedPrimaryFamilyNames;
+    for (auto&amp; family : resolvedPrimaryFamilies) {
+        // This doesn't handle web fonts for now.
+        if (family.url)
+            break;
+        resolvedPrimaryFamilyNames.append(family.name);
+    }
+
+    // Asynchronously find first available font and precache it so it is likely to be available when needed.
+    FontCache::singleton().precache(resolvedPrimaryFamilyNames, fontDescription);
+}
+
</ins><span class="cx"> static Ref&lt;FontCascadeFonts&gt; retrieveOrAddCachedFonts(const FontCascadeDescription&amp; fontDescription, RefPtr&lt;FontSelector&gt;&amp;&amp; fontSelector)
</span><span class="cx"> {
</span><span class="cx">     auto key = makeFontCascadeCacheKey(fontDescription, fontSelector.get());
</span><span class="lines">@@ -270,6 +293,9 @@
</span><span class="cx">     if (!addResult.isNewEntry &amp;&amp; keysMatch(addResult.iterator-&gt;value-&gt;key, key))
</span><span class="cx">         return addResult.iterator-&gt;value-&gt;fonts.get();
</span><span class="cx"> 
</span><ins>+    if (fontSelector)
+        precachePrimaryFamily(fontDescription, *fontSelector);
+
</ins><span class="cx">     auto&amp; newEntry = addResult.iterator-&gt;value;
</span><span class="cx">     newEntry = std::make_unique&lt;FontCascadeCacheEntry&gt;(WTFMove(key), FontCascadeFonts::create(WTFMove(fontSelector)));
</span><span class="cx">     Ref&lt;FontCascadeFonts&gt; glyphs = newEntry-&gt;fonts.get();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsFontSelectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/FontSelector.h (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/FontSelector.h        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/platform/graphics/FontSelector.h        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &quot;FontRanges.h&quot;
</span><ins>+#include &quot;URL.h&quot;
</ins><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="lines">@@ -44,6 +45,11 @@
</span><span class="cx">     virtual bool isLoading() const = 0;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct ResolvedFontFamily {
+    AtomicString name;
+    Optional&lt;URL&gt; url;
+};
+
</ins><span class="cx"> class FontSelector : public RefCounted&lt;FontSelector&gt; {
</span><span class="cx"> public:
</span><span class="cx">     virtual ~FontSelector() { }
</span><span class="lines">@@ -58,6 +64,8 @@
</span><span class="cx">     virtual void registerForInvalidationCallbacks(FontSelectorClient&amp;) = 0;
</span><span class="cx">     virtual void unregisterForInvalidationCallbacks(FontSelectorClient&amp;) = 0;
</span><span class="cx"> 
</span><ins>+    virtual Vector&lt;ResolvedFontFamily&gt; resolveFamilies(const Vector&lt;AtomicString&gt;&amp; families, const FontDescription&amp;, UChar32 character) = 0;
+
</ins><span class="cx">     virtual unsigned uniqueId() const = 0;
</span><span class="cx">     virtual unsigned version() const = 0;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscocoaFontCacheCoreTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp (201550 => 201551)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2016-06-01 11:57:55 UTC (rev 201550)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp        2016-06-01 14:29:30 UTC (rev 201551)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/MainThread.h&gt;
</span><span class="cx"> #include &lt;wtf/NeverDestroyed.h&gt;
</span><ins>+#include &lt;wtf/RunLoop.h&gt;
+#include &lt;wtf/WorkQueue.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -660,27 +662,19 @@
</span><span class="cx">         whitelist.add(item);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(PLATFORM_FONT_LOOKUP)
-static RetainPtr&lt;CTFontRef&gt; platformFontLookupWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits requestedTraits, FontWeight weight, float size)
</del><ins>+static RetainPtr&lt;CTFontRef&gt; fontWithFamily(const String&amp; family, CTFontSymbolicTraits desiredTraits, FontWeight weight, const FontFeatureSettings&amp; featureSettings, const FontVariantSettings&amp; variantSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode&amp; textRenderingMode, float size, bool isWhitelisted)
</ins><span class="cx"> {
</span><del>-    const auto&amp; whitelist = fontWhitelist();
-    if (whitelist.size() &amp;&amp; !whitelist.contains(family))
-        return nullptr;
-
-    return adoptCF(CTFontCreateForCSS(family.string().createCFString().get(), toCoreTextFontWeight(weight), requestedTraits, size));
-}
-#endif
-
-static RetainPtr&lt;CTFontRef&gt; fontWithFamily(const AtomicString&amp; family, CTFontSymbolicTraits desiredTraits, FontWeight weight, const FontFeatureSettings&amp; featureSettings, const FontVariantSettings&amp; variantSettings, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, const TextRenderingMode&amp; textRenderingMode, float size)
-{
</del><span class="cx">     if (family.isEmpty())
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CTFontRef&gt; foundFont = platformFontWithFamilySpecialCase(family, weight, desiredTraits, size);
</span><span class="cx">     if (!foundFont) {
</span><span class="cx"> #if ENABLE(PLATFORM_FONT_LOOKUP)
</span><del>-        foundFont = platformFontLookupWithFamily(family, desiredTraits, weight, size);
</del><ins>+        if (!isWhitelisted)
+            return nullptr;
+        foundFont = adoptCF(CTFontCreateForCSS(family.createCFString().get(), toCoreTextFontWeight(weight), desiredTraits, size));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(isWhitelisted);
</ins><span class="cx">         foundFont = platformFontWithFamily(family, desiredTraits, weight, textRenderingMode, size);
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="lines">@@ -719,24 +713,24 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;FontPlatformData&gt; FontCache::createFontPlatformData(const FontDescription&amp; fontDescription, const AtomicString&amp; family, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings)
</del><ins>+// This is only thread safe with ENABLE(PLATFORM_FONT_LOOKUP) due to fontWithFamily() implementation
+static std::unique_ptr&lt;FontPlatformData&gt; createFontPlatformDataThreadSafe(const FontDescription&amp; fontDescription, const String&amp; family, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings, bool isWhitelisted, bool shouldAutoActivateIfNeeded)
</ins><span class="cx"> {
</span><span class="cx">     CTFontSymbolicTraits traits = computeTraits(fontDescription);
</span><span class="cx">     float size = fontDescription.computedPixelSize();
</span><span class="cx"> 
</span><del>-    RetainPtr&lt;CTFontRef&gt; font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size);
</del><ins>+    RetainPtr&lt;CTFontRef&gt; font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size, isWhitelisted);
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>-    if (!font) {
-        if (!shouldAutoActivateFontIfNeeded(family))
-            return nullptr;
-
</del><ins>+    if (!font &amp;&amp; shouldAutoActivateIfNeeded) {
</ins><span class="cx">         // Auto activate the font before looking for it a second time.
</span><span class="cx">         // Ignore the result because we want to use our own algorithm to actually find the font.
</span><del>-        autoActivateFont(family.string(), size);
</del><ins>+        autoActivateFont(family, size);
</ins><span class="cx"> 
</span><del>-        font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size);
</del><ins>+        font = fontWithFamily(family, traits, fontDescription.weight(), fontDescription.featureSettings(), fontDescription.variantSettings(), fontFaceFeatures, fontFaceVariantSettings, fontDescription.textRenderingMode(), size, isWhitelisted);
</ins><span class="cx">     }
</span><ins>+#else
+    UNUSED_PARAM(shouldAutoActivateIfNeeded);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     if (!font)
</span><span class="lines">@@ -748,6 +742,19 @@
</span><span class="cx">     return std::make_unique&lt;FontPlatformData&gt;(font.get(), size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.textRenderingMode());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+std::unique_ptr&lt;FontPlatformData&gt; FontCache::createFontPlatformData(const FontDescription&amp; fontDescription, const AtomicString&amp; family, const FontFeatureSettings* fontFaceFeatures, const FontVariantSettings* fontFaceVariantSettings)
+{
+    const auto&amp; whitelist = fontWhitelist();
+    bool isWhitelisted = whitelist.isEmpty() || whitelist.contains(family);
+
+    bool shouldAutoActivateIfNeeded = false;
+#if PLATFORM(MAC)
+    shouldAutoActivateIfNeeded = shouldAutoActivateFontIfNeeded(family);
+#endif
+
+    return createFontPlatformDataThreadSafe(fontDescription, family, fontFaceFeatures, fontFaceVariantSettings, isWhitelisted, shouldAutoActivateIfNeeded);
+}
+
</ins><span class="cx"> typedef HashSet&lt;RetainPtr&lt;CTFontRef&gt;, WTF::RetainPtrObjectHash&lt;CTFontRef&gt;, WTF::RetainPtrObjectHashTraits&lt;CTFontRef&gt;&gt; FallbackDedupSet;
</span><span class="cx"> static FallbackDedupSet&amp; fallbackDedupSet()
</span><span class="cx"> {
</span><span class="lines">@@ -796,4 +803,53 @@
</span><span class="cx">     return fontForPlatformData(alternateFont);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(PLATFORM_FONT_LOOKUP)
+struct FontCache::PrecacheTask {
+    String family;
+    FontDescription fontDescription;
+    bool shouldAutoActivateIfNeeded { false };
+    bool isWhitelisted { true };
+    PrecacheCompletionHandler completionHandler;
+
+    std::unique_ptr&lt;FontPlatformData&gt; result;
+    std::atomic_bool isCanceled { false };
+};
+
+FontCache::PrecacheTask&amp; FontCache::platformPrecache(const AtomicString&amp; family, const FontDescription&amp; fontDescription, PrecacheCompletionHandler&amp;&amp; completionHandler)
+{
+    static WorkQueue&amp; queue = WorkQueue::create(&quot;org.webkit.font-precache&quot;, WorkQueue::Type::Serial, WorkQueue::QOS::UserInitiated).leakRef();
+
+    auto task = std::make_unique&lt;PrecacheTask&gt;();
+    task-&gt;family = family;
+    task-&gt;fontDescription = fontDescription;
+    const auto&amp; whitelist = fontWhitelist();
+    task-&gt;isWhitelisted = whitelist.isEmpty() || whitelist.contains(family);
+#if PLATFORM(MAC)
+    task-&gt;shouldAutoActivateIfNeeded = shouldAutoActivateFontIfNeeded(family);
+#endif
+    task-&gt;completionHandler = WTFMove(completionHandler);
+
+    auto&amp; resultTask = *task;
+
+    queue.dispatch([task = task.release()] {
+        if (!task-&gt;isCanceled) {
+            auto family = task-&gt;family.isolatedCopy();
+            task-&gt;result = createFontPlatformDataThreadSafe(task-&gt;fontDescription, family, nullptr, nullptr, task-&gt;isWhitelisted, task-&gt;shouldAutoActivateIfNeeded);
+        }
+
+        RunLoop::main().dispatch([task] {
+            std::unique_ptr&lt;PrecacheTask&gt; deleter(task);
+            task-&gt;completionHandler(WTFMove(task-&gt;result), task-&gt;isCanceled);
+        });
+    });
+
+    return resultTask;
</ins><span class="cx"> }
</span><ins>+
+void FontCache::platformCancelPrecache(FontCache::PrecacheTask&amp; task)
+{
+    task.isCanceled = true;
+}
+#endif
+
+}
</ins></span></pre>
</div>
</div>

</body>
</html>