Changeset 216944 in webkit


Ignore:
Timestamp:
May 16, 2017 1:26:39 PM (7 years ago)
Author:
mmaxfield@apple.com
Message:

REGRESSION(r212513): LastResort is platform-dependent, so its semantics should not be required to perform font loading correctly.
https://bugs.webkit.org/show_bug.cgi?id=168487

Reviewed by Antti Koivisto.

Source/WebCore:

There are three ways a Web author can chain multiple font files together:

  1. Multiple entries in the "src" descriptor in an @font-face rule
  2. Multiple @font-face rules with the same "font-family" descriptor
  3. Multiple entries in the "font-family" property on an element

Before r212513, the code which iterated across #2 and #3 above could have
triggered each item in the chain to download. r212513 tried to solve this
by using LastResort as the interstitial font used during downloads, because
LastResort supports every character and therefore solves #3 above. However,
this change had a few problems:

  1. Previously, our code would try to avoid using the interstitial font for

layout or rendering whenever possible (because one of the chains above may
have named a local font which would be better to use). In order to use the
benefits of LastResort, I had to remove this avoidance logic and make
WebKit try to use the interstitial font as often as possible. However, due
to the large metrics of LastResort, this means that offsetWidth queries
during font loading would be wildly inaccurate, causing Google Docs to break.

  1. It also means that canvas drawing during font loading would actually draw

LastResort, causing Bing maps to break.

  1. LastResort is platform-specific, so only platforms which have it would

actually be able to load fonts correctly.

Instead, we should keep the older logic about avoiding using the
interstitial font so that loading has a better experience for the user.
We solve the unnecessary download problem by giving our loading code a
downloading policy enum, which has two values: allow downloads or forbid
downloads. Whenever our loading code returns the interstitial font, we
continue our search, but we change the policy to forbid downloads.

There is one piece of subtlety, though: It is more common for web authors
to put good fallbacks in the "font-family" property than in the "src"
descriptor inside @font-face. This means that we shouldn't exhaustively
search through the @font-face src list first. Instead, we should look
through the src list until we hit a non-local font, and then immediately
start looking through the other other chains.

Tests: fast/text/font-download-font-face-src-list.html

fast/text/font-download-font-family-property.html
fast/text/font-download-remote-fallback-all.html
fast/text/font-interstitial-invisible-width-while-loading.html
fast/text/font-weight-download-3.html
fast/text/web-font-load-fallback-during-loading-2.html
fast/text/web-font-load-invisible-during-loading.html

  • css/CSSFontFace.cpp:

(WebCore::CSSFontFace::fontLoadEventOccurred): Implement support for
the font download policy.
(WebCore::CSSFontFace::setStatus): After 3 seconds of loading, we
will start drawing the fallback font. However, for testing, we have an
internal setting to make this switch happen immediately. This patch now
requires that this internal switch happen synchronously.
(WebCore::CSSFontFace::pump): Implement support for the font download
policy.
(WebCore::CSSFontFace::load): Ditto.
(WebCore::CSSFontFace::font): Ditto.

  • css/CSSFontFace.h: Ditto.
  • css/CSSFontSelector.cpp:

(WebCore::CSSFontSelector::beginLoadingFontSoon): Implement support for
synchronous font download timeouts.

  • css/CSSSegmentedFontFace.cpp:

(WebCore::CSSSegmentedFontFace::fontRanges): Implement support for the
font download policy.

  • platform/graphics/Font.cpp: Add new flag which represents if the

interstitial font was created after the 3 second timeout or before.
Previously, we would distinguish between these two cases by knowing
that one font was LastResort and the other font was a fallback. Now that
we're using fallback fonts on both sides of the 3 second timeout, we
now no longer know which one should be invisible. This new enum solves
this problem.
(WebCore::Font::Font):
(WebCore::Font::verticalRightOrientationFont):
(WebCore::Font::uprightOrientationFont):

  • platform/graphics/Font.h: Ditto.

(WebCore::Font::create):
(WebCore::Font::origin):
(WebCore::Font::visibility):

  • platform/graphics/FontCache.h:
  • platform/graphics/FontCascade.cpp: We try to fall back to a local() font

during downloads, but there might not be one that we can use. Therefore, we
can't use the presence of the interstitial font to detect if we should paint
invisibly. Instead, we can move this logic into the font-specific part of
painting, and consult with the specific font to know if it was created from
a timed-out @font-face rule or not.
(WebCore::FontCascade::drawText):
(WebCore::shouldDrawIfLoading):
(WebCore::FontCascade::drawGlyphBuffer):
(WebCore::FontCascade::drawEmphasisMarks):

  • platform/graphics/FontCascade.h:
  • platform/graphics/FontCascadeFonts.cpp:

(WebCore::FontCascadeFonts::glyphDataForVariant): Implement the logic
described above where we switch the policy if we encounter the intestitial
font.
(WebCore::FontCascadeFonts::glyphDataForNormalVariant): Ditto.
(WebCore::glyphPageFromFontRanges): Ditto.

  • platform/graphics/FontRanges.cpp: Implement support for the font download

policy.
(WebCore::FontRanges::Range::font):
(WebCore::FontRanges::glyphDataForCharacter):
(WebCore::FontRanges::fontForCharacter):
(WebCore::FontRanges::fontForFirstRange):

  • platform/graphics/FontRanges.h:
  • platform/graphics/FontSelector.h:
  • platform/graphics/freetype/FontCacheFreeType.cpp:

(WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.

  • platform/graphics/mac/FontCacheMac.mm:

(WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.

  • platform/graphics/win/FontCacheWin.cpp:

(WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.

LayoutTests:

  • fast/text/font-download-font-face-src-list-expected.txt: Added.
  • fast/text/font-download-font-face-src-list.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
  • fast/text/font-download-font-family-property-expected.txt: Added.
  • fast/text/font-download-font-family-property.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
  • fast/text/font-download-remote-fallback-all-expected.txt: Added.
  • fast/text/font-download-remote-fallback-all.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
  • fast/text/font-interstitial-invisible-width-while-loading-expected.txt: Added.
  • fast/text/font-interstitial-invisible-width-while-loading.html: Added.
  • fast/text/font-weight-download-2.html:
  • fast/text/font-weight-download-3-expected.txt: Added.
  • fast/text/font-weight-download-3.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
  • fast/text/web-font-load-fallback-during-loading-2-expected.html: Added.
  • fast/text/web-font-load-fallback-during-loading-2.html: Added.
  • fast/text/web-font-load-fallback-during-loading-expected.html:
  • fast/text/web-font-load-fallback-during-loading.html:
  • fast/text/web-font-load-invisible-during-loading-expected.txt: Added.
  • fast/text/web-font-load-invisible-during-loading.html: Added.
  • http/tests/webfont/fallback-font-while-loading-expected.txt:
  • http/tests/webfont/fallback-font-while-loading.html:
Location:
trunk
Files:
10 added
22 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r216938 r216944  
     12017-05-16  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        REGRESSION(r212513): LastResort is platform-dependent, so its semantics should not be required to perform font loading correctly.
     4        https://bugs.webkit.org/show_bug.cgi?id=168487
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * fast/text/font-download-font-face-src-list-expected.txt: Added.
     9        * fast/text/font-download-font-face-src-list.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
     10        * fast/text/font-download-font-family-property-expected.txt: Added.
     11        * fast/text/font-download-font-family-property.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
     12        * fast/text/font-download-remote-fallback-all-expected.txt: Added.
     13        * fast/text/font-download-remote-fallback-all.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
     14        * fast/text/font-interstitial-invisible-width-while-loading-expected.txt: Added.
     15        * fast/text/font-interstitial-invisible-width-while-loading.html: Added.
     16        * fast/text/font-weight-download-2.html:
     17        * fast/text/font-weight-download-3-expected.txt: Added.
     18        * fast/text/font-weight-download-3.html: Copied from LayoutTests/fast/text/font-weight-download-2.html.
     19        * fast/text/web-font-load-fallback-during-loading-2-expected.html: Added.
     20        * fast/text/web-font-load-fallback-during-loading-2.html: Added.
     21        * fast/text/web-font-load-fallback-during-loading-expected.html:
     22        * fast/text/web-font-load-fallback-during-loading.html:
     23        * fast/text/web-font-load-invisible-during-loading-expected.txt: Added.
     24        * fast/text/web-font-load-invisible-during-loading.html: Added.
     25        * http/tests/webfont/fallback-font-while-loading-expected.txt:
     26        * http/tests/webfont/fallback-font-while-loading.html:
     27
    1282017-05-16  Eric Carlson  <eric.carlson@apple.com>
    229
  • trunk/LayoutTests/fast/text/font-download-font-face-src-list.html

    r216943 r216944  
    1515@font-face {
    1616    font-family: "WebFont";
    17     font-weight: 100;
    18     src: url("../../resources/Ahem_CJK.ttf") format("truetype");
    19 }
    20 @font-face {
    21     font-family: "WebFont";
    22     font-weight: 900;
    23     src: url("../../resources/Ahem.otf") format("opentype");
     17    src: url("../../resources/Ahem_CJK.ttf") format("truetype"), url("../../resources/Ahem.otf") format("opentype");
    2418}
    2519</style>
     
    2721<body>
    2822This test makes sure that unnecessary fonts aren't downloaded. The test fails if Ahem.otf is downloaded.
    29 <div style="font: 100 100px 'WebFont';">&#x6A2A;</div>
     23<div style="font-size: 100px; font-family: 'WebFont';">&#x6A2A;</div>
    3024</body>
    3125</html>
     26
     27
  • trunk/LayoutTests/fast/text/font-download-font-family-property.html

    r216943 r216944  
    1515@font-face {
    1616    font-family: "WebFont";
    17     font-weight: 100;
    1817    src: url("../../resources/Ahem_CJK.ttf") format("truetype");
    1918}
    2019@font-face {
    21     font-family: "WebFont";
    22     font-weight: 900;
     20    font-family: "WebFont2";
    2321    src: url("../../resources/Ahem.otf") format("opentype");
    2422}
     
    2725<body>
    2826This test makes sure that unnecessary fonts aren't downloaded. The test fails if Ahem.otf is downloaded.
    29 <div style="font: 100 100px 'WebFont';">&#x6A2A;</div>
     27<div style="font-size: 100px; font-family: 'WebFont', 'WebFont2';">&#x6A2A;</div>
    3028</body>
    3129</html>
     30
  • trunk/LayoutTests/fast/text/font-download-remote-fallback-all.html

    r216943 r216944  
    1616    font-family: "WebFont";
    1717    font-weight: 100;
    18     src: url("../../resources/Ahem_CJK.ttf") format("truetype");
     18    src: url("../../resources/Ahem_CJK.ttf"), url("garbage2");
    1919}
    2020@font-face {
    2121    font-family: "WebFont";
    2222    font-weight: 900;
    23     src: url("../../resources/Ahem.otf") format("opentype");
     23    src: url("garbage3"), url("garbage4");
     24}
     25@font-face {
     26    font-family: "WebFont2";
     27    src: url("garbage5"), url("garbage6");
    2428}
    2529</style>
    2630</head>
    2731<body>
    28 This test makes sure that unnecessary fonts aren't downloaded. The test fails if Ahem.otf is downloaded.
    29 <div style="font: 100 100px 'WebFont';">&#x6A2A;</div>
     32This test makes sure that unnecessary fonts aren't downloaded. The test fails if any of the "garbage" font names are requested.
     33<div style="font-size: 100px; font-weight: 100; font-family: 'WebFont', 'WebFont2';">&#x6A2A;</div>
    3034</body>
    3135</html>
  • trunk/LayoutTests/fast/text/font-weight-download-3.html

    r216943 r216944  
    2727<body>
    2828This test makes sure that unnecessary fonts aren't downloaded. The test fails if Ahem.otf is downloaded.
    29 <div style="font: 100 100px 'WebFont';">&#x6A2A;</div>
     29<div style="font: 100 100px 'WebFont';">&#x6A2A;&#x300;</div>
    3030</body>
    3131</html>
     32
  • trunk/LayoutTests/fast/text/web-font-load-fallback-during-loading-expected.html

    r201676 r216944  
    44</head>
    55<body>
    6 This test makes sure that fallback fonts are used during the time when fonts are loading. The test passes if the next line below reads "Test complete" and all the subsequent statements below are legible and true.
    7 <p id="console">Test complete</p>
    8 <p><span class="test" style="font-family: Helvetica">This is rendered with Helvetica.</span></p>
    9 <p><span class="test" style="font-family: Helvetica">This is rendered with Helvetica.</span></p>
    10 <p><span class="test" style="font-family: Helvetica">This is rendered with Helvetica.</span></p>
     6<div style="-webkit-text-size-adjust: none;">
     7This test makes sure that fallback fonts are used during the time when fonts are loading.
     8<p id="console">PASS: Element is not rendered with American Typewriter.</p>
     9<p><span class="test" style="font-family: 'American Typewriter';">This is a test rendering.</span></p>
     10<p><span class="test" style="font-family: 'American Typewriter';">PASS: This is rendered with American Typewriter.</span></p>
     11</div>
    1112</body>
    1213</html>
  • trunk/LayoutTests/fast/text/web-font-load-fallback-during-loading.html

    r216079 r216944  
    88    internals.invalidateFontCache();
    99}
    10 if (window.testRunner)
    11     testRunner.waitUntilDone();
    12 
    13 function computeCurrentWidths() {
    14     var result = [];
    15     var collection = document.getElementsByClassName("test");
    16     for (var i = 0; i < collection.length; ++i)
    17         result.push(collection.item(i).getBoundingClientRect().width);
    18     return result;
    19 }
    20 
    21 function testCompleted(widths, goal) {
    22     for (var i = 0; i < widths.length; ++i) {
    23         if (widths[i] != goal)
    24             return false;
    25     }
    26     return true;
    27 }
    28 
    29 var token = window.setInterval(function () {
    30     if (testCompleted(computeCurrentWidths(), expectedWidth)) {
    31         window.clearInterval(token);
    32         document.getElementById("console").appendChild(document.createTextNode("Test complete"));
    33         if (window.testRunner)
    34             testRunner.notifyDone();
    35     }
    36 }, 0);
    37 
    3810</script>
    3911<style>
    4012@font-face {
    41     font-family: WebFont;
    42     src: url("../../resources/Ahem.ttf") format("truetype"), local("Helvetica");
     13    font-family: "WebFont";
     14    src: url("../../resources/Ahem.ttf") format("truetype"), local("American Typewriter");
    4315}
    4416@font-face {
    45     font-family: WebFont2;
    46     src: local("Helvetica");
     17    font-family: "WebFont2";
     18    src: local("American Typewriter");
    4719}
    4820@font-face {
    49     font-family: WebFont2;
     21    font-family: "WebFont2";
     22    src: url("../../resources/Ahem.ttf") format("truetype");
     23}
     24@font-face {
     25    font-family: "WebFont3";
    5026    src: url("../../resources/Ahem.ttf") format("truetype");
    5127}
     
    5329</head>
    5430<body>
    55 This test makes sure that fallback fonts are used during the time when fonts are loading. The test passes if the next line below reads "Test complete" and all the subsequent statements below are legible and true.
    56 <!-- FIXME: This test is racey. The font may complete downloading before the 0-delay timer fires,
    57 in which case the "Test Complete" text will not be added. -->
    58 <p id="console"></p>
    59 <p><span id="reference" style="font-family: Helvetica">This is rendered with Helvetica.</span></p>
    60 <p><span class="test" style="font-family: WebFont">This is rendered with Helvetica.</span></p>
    61 <p><span class="test" style="font-family: WebFont2">This is rendered with Helvetica.</span></p>
     31<div style="-webkit-text-size-adjust: none;">
     32This test makes sure that fallback fonts are used during the time when fonts are loading.
     33<p id="console">Test NOT complete.</p>
     34<p><span id="americanTypewriter" style="font-family: 'American Typewriter';">This is a test rendering.</span></p>
     35<p id="container"><span id="notAmericanTypewriter" style="font-family: 'WebFont';">This is a test rendering.</span></p>
     36<p><span style="font-family: 'WebFont2';">PASS: This is rendered with American Typewriter.</span></p>
     37<!-- Because the primary font is the platform-dependent interstitial font, the baseline position of the line is calculated with this platform-specific font, which means we can't test it with a ref test because we don't know exactly where the text will end up. -->
     38<!--p><span style="font-family: 'WebFont3', 'American Typewriter';">PASS: This is rendered with American Typewriter.</span></p-->
     39</div>
    6240<script>
    63 var expectedWidth = document.getElementById("reference").getBoundingClientRect().width;
     41var console = document.getElementById("console");
     42var americanTypewriterWidth = document.getElementById("americanTypewriter").getBoundingClientRect().width;
     43var notAmericanTypewriterWidth = document.getElementById("notAmericanTypewriter").getBoundingClientRect().width;
     44if (americanTypewriterWidth == notAmericanTypewriterWidth)
     45    console.innerText = "FAIL: Element should not be rendered with American Typewriter.";
     46else
     47    console.innerText = "PASS: Element is not rendered with American Typewriter.";
     48document.getElementById("container").style.display = "none";
    6449</script>
    6550</body>
  • trunk/LayoutTests/http/tests/webfont/fallback-font-while-loading-expected.txt

    r212513 r216944  
    1 This test checks that the fallback font is not used for layout while a webfont is loading.
     1This test checks that the fallback font is used for layout while a webfont is loading.
    22
    33Target:
     
    55Reference:
    66A text to be measured.
    7 PASS: The width of target text and reference text are different.
     7PASS: The width of target text and reference text is the same.
  • trunk/LayoutTests/http/tests/webfont/fallback-font-while-loading.html

    r212513 r216944  
    66</style>
    77<p>
    8 This test checks that the fallback font is not used for layout while a webfont is loading.
     8This test checks that the fallback font is used for layout while a webfont is loading.
    99</p>
    1010Target:
     
    2727    var referenceWidth = document.getElementById('reference').offsetWidth;
    2828    var result = document.getElementById('result');
    29     if (targetWidth != referenceWidth)
    30         result.innerText = 'PASS: The width of target text and reference text are different.';
     29    if (targetWidth == referenceWidth)
     30        result.innerText = 'PASS: The width of target text and reference text is the same.';
    3131    else
    32         result.innerText = 'FAIL: The width of target text and reference text are the same.';
     32        result.innerText = 'FAIL: The width of target text and reference text is different: ' + targetWidth + ' != ' + referenceWidth;
    3333}
    3434
  • trunk/Source/WebCore/ChangeLog

    r216940 r216944  
     12017-05-16  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        REGRESSION(r212513): LastResort is platform-dependent, so its semantics should not be required to perform font loading correctly.
     4        https://bugs.webkit.org/show_bug.cgi?id=168487
     5
     6        Reviewed by Antti Koivisto.
     7
     8        There are three ways a Web author can chain multiple font files together:
     9        1. Multiple entries in the "src" descriptor in an @font-face rule
     10        2. Multiple @font-face rules with the same "font-family" descriptor
     11        3. Multiple entries in the "font-family" property on an element
     12
     13        Before r212513, the code which iterated across #2 and #3 above could have
     14        triggered each item in the chain to download. r212513 tried to solve this
     15        by using LastResort as the interstitial font used during downloads, because
     16        LastResort supports every character and therefore solves #3 above. However,
     17        this change had a few problems:
     18
     19        1. Previously, our code would try to avoid using the interstitial font for
     20        layout or rendering whenever possible (because one of the chains above may
     21        have named a local font which would be better to use). In order to use the
     22        benefits of LastResort, I had to remove this avoidance logic and make
     23        WebKit try to use the interstitial font as often as possible. However, due
     24        to the large metrics of LastResort, this means that offsetWidth queries
     25        during font loading would be wildly inaccurate, causing Google Docs to break.
     26        2. It also means that canvas drawing during font loading would actually draw
     27        LastResort, causing Bing maps to break.
     28        3. LastResort is platform-specific, so only platforms which have it would
     29        actually be able to load fonts correctly.
     30
     31        Instead, we should keep the older logic about avoiding using the
     32        interstitial font so that loading has a better experience for the user.
     33        We solve the unnecessary download problem by giving our loading code a
     34        downloading policy enum, which has two values: allow downloads or forbid
     35        downloads. Whenever our loading code returns the interstitial font, we
     36        continue our search, but we change the policy to forbid downloads.
     37
     38        There is one piece of subtlety, though: It is more common for web authors
     39        to put good fallbacks in the "font-family" property than in the "src"
     40        descriptor inside @font-face. This means that we shouldn't exhaustively
     41        search through the @font-face src list first. Instead, we should look
     42        through the src list until we hit a non-local font, and then immediately
     43        start looking through the other other chains.
     44
     45        Tests: fast/text/font-download-font-face-src-list.html
     46               fast/text/font-download-font-family-property.html
     47               fast/text/font-download-remote-fallback-all.html
     48               fast/text/font-interstitial-invisible-width-while-loading.html
     49               fast/text/font-weight-download-3.html
     50               fast/text/web-font-load-fallback-during-loading-2.html
     51               fast/text/web-font-load-invisible-during-loading.html
     52
     53        * css/CSSFontFace.cpp:
     54        (WebCore::CSSFontFace::fontLoadEventOccurred): Implement support for
     55        the font download policy.
     56        (WebCore::CSSFontFace::setStatus): After 3 seconds of loading, we
     57        will start drawing the fallback font. However, for testing, we have an
     58        internal setting to make this switch happen immediately. This patch now
     59        requires that this internal switch happen synchronously.
     60        (WebCore::CSSFontFace::pump): Implement support for the font download
     61        policy.
     62        (WebCore::CSSFontFace::load): Ditto.
     63        (WebCore::CSSFontFace::font): Ditto.
     64        * css/CSSFontFace.h: Ditto.
     65        * css/CSSFontSelector.cpp:
     66        (WebCore::CSSFontSelector::beginLoadingFontSoon): Implement support for
     67        synchronous font download timeouts.
     68        * css/CSSSegmentedFontFace.cpp:
     69        (WebCore::CSSSegmentedFontFace::fontRanges): Implement support for the
     70        font download policy.
     71        * platform/graphics/Font.cpp: Add new flag which represents if the
     72        interstitial font was created after the 3 second timeout or before.
     73        Previously, we would distinguish between these two cases by knowing
     74        that one font was LastResort and the other font was a fallback. Now that
     75        we're using fallback fonts on both sides of the 3 second timeout, we
     76        now no longer know which one should be invisible. This new enum solves
     77        this problem.
     78        (WebCore::Font::Font):
     79        (WebCore::Font::verticalRightOrientationFont):
     80        (WebCore::Font::uprightOrientationFont):
     81        * platform/graphics/Font.h: Ditto.
     82        (WebCore::Font::create):
     83        (WebCore::Font::origin):
     84        (WebCore::Font::visibility):
     85        * platform/graphics/FontCache.h:
     86        * platform/graphics/FontCascade.cpp: We try to fall back to a local() font
     87        during downloads, but there might not be one that we can use. Therefore, we
     88        can't use the presence of the interstitial font to detect if we should paint
     89        invisibly. Instead, we can move this logic into the font-specific part of
     90        painting, and consult with the specific font to know if it was created from
     91        a timed-out @font-face rule or not.
     92        (WebCore::FontCascade::drawText):
     93        (WebCore::shouldDrawIfLoading):
     94        (WebCore::FontCascade::drawGlyphBuffer):
     95        (WebCore::FontCascade::drawEmphasisMarks):
     96        * platform/graphics/FontCascade.h:
     97        * platform/graphics/FontCascadeFonts.cpp:
     98        (WebCore::FontCascadeFonts::glyphDataForVariant): Implement the logic
     99        described above where we switch the policy if we encounter the intestitial
     100        font.
     101        (WebCore::FontCascadeFonts::glyphDataForNormalVariant): Ditto.
     102        (WebCore::glyphPageFromFontRanges): Ditto.
     103        * platform/graphics/FontRanges.cpp: Implement support for the font download
     104        policy.
     105        (WebCore::FontRanges::Range::font):
     106        (WebCore::FontRanges::glyphDataForCharacter):
     107        (WebCore::FontRanges::fontForCharacter):
     108        (WebCore::FontRanges::fontForFirstRange):
     109        * platform/graphics/FontRanges.h:
     110        * platform/graphics/FontSelector.h:
     111        * platform/graphics/freetype/FontCacheFreeType.cpp:
     112        (WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.
     113        * platform/graphics/mac/FontCacheMac.mm:
     114        (WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.
     115        * platform/graphics/win/FontCacheWin.cpp:
     116        (WebCore::FontCache::lastResortFallbackFontForEveryCharacter): Deleted.
     117
    11182017-05-16  Zalan Bujtas  <zalan@apple.com>
    2119
  • trunk/Source/WebCore/css/CSSFontFace.cpp

    r216896 r216944  
    420420    // Let's not pump the state machine until we've got all our sources. font() and load() are smart enough to act correctly
    421421    // when a source is failed or succeeded before we have asked it to load.
    422     if (m_sourcesPopulated)
    423         pump();
     422    if (m_sourcesPopulated && !webFontsShouldAlwaysFallBack())
     423        pump(ExternalResourceDownloadPolicy::Forbid);
    424424
    425425    ASSERT(m_fontSelector);
     
    527527    }
    528528
    529     if (newStatus == Status::Loading)
    530         m_timeoutTimer.startOneShot(webFontsShouldAlwaysFallBack() ? 0_s : 3_s);
    531     else if (newStatus == Status::Success || newStatus == Status::Failure)
    532         m_timeoutTimer.stop();
     529    bool webFontsShouldAlwaysFallBack = this->webFontsShouldAlwaysFallBack();
     530    if (!webFontsShouldAlwaysFallBack) {
     531        if (newStatus == Status::Loading) {
     532            Seconds timeUntilInterstitialFontIsDrawnVisibly = 3_s;
     533            m_timeoutTimer.startOneShot(timeUntilInterstitialFontIsDrawnVisibly);
     534        } else if (newStatus == Status::Success || newStatus == Status::Failure)
     535            m_timeoutTimer.stop();
     536    }
    533537
    534538    iterateClients(m_clients, [&](Client& client) {
     
    537541
    538542    m_status = newStatus;
     543
     544    if (newStatus == Status::Loading && webFontsShouldAlwaysFallBack)
     545        timeoutFired();
    539546}
    540547
     
    551558}
    552559
    553 size_t CSSFontFace::pump()
     560size_t CSSFontFace::pump(ExternalResourceDownloadPolicy policy)
    554561{
    555562    size_t i;
     
    559566        if (source->status() == CSSFontFaceSource::Status::Pending) {
    560567            ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut);
    561             if (m_status == Status::Pending)
    562                 setStatus(Status::Loading);
    563             source->load(m_fontSelector.get());
     568            if (policy == ExternalResourceDownloadPolicy::Allow || !source->requiresExternalResource()) {
     569                if (m_status == Status::Pending)
     570                    setStatus(Status::Loading);
     571                source->load(m_fontSelector.get());
     572            }
    564573        }
    565574
    566575        switch (source->status()) {
    567576        case CSSFontFaceSource::Status::Pending:
    568             ASSERT_NOT_REACHED();
    569             break;
     577            ASSERT(policy == ExternalResourceDownloadPolicy::Forbid);
     578            return i;
    570579        case CSSFontFaceSource::Status::Loading:
    571580            ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut);
     
    595604void CSSFontFace::load()
    596605{
    597     pump();
    598 }
    599 
    600 RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
     606    pump(ExternalResourceDownloadPolicy::Allow);
     607}
     608
     609RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy policy)
    601610{
    602611    if (allSourcesFailed())
     
    607616    // of the sources to try to find a font to use. These subsequent tries should not affect
    608617    // our own state, though.
    609     size_t startIndex = pump();
    610     bool fontIsLoading = false;
     618    size_t startIndex = pump(policy);
    611619    for (size_t i = startIndex; i < m_sources.size(); ++i) {
    612620        auto& source = m_sources[i];
    613         if (source->status() == CSSFontFaceSource::Status::Pending) {
    614             if (fontIsLoading && source->requiresExternalResource())
    615                 continue;
     621        if (source->status() == CSSFontFaceSource::Status::Pending && (policy == ExternalResourceDownloadPolicy::Allow || !source->requiresExternalResource()))
    616622            source->load(m_fontSelector.get());
    617         }
    618623
    619624        switch (source->status()) {
    620625        case CSSFontFaceSource::Status::Pending:
    621             ASSERT_NOT_REACHED();
    622             break;
    623         case CSSFontFaceSource::Status::Loading:
    624             ASSERT(!fontIsLoading);
    625             fontIsLoading = true;
    626             if (status() == Status::TimedOut)
    627                 continue;
    628             return Font::create(FontCache::singleton().lastResortFallbackFontForEveryCharacter(fontDescription)->platformData(), Font::Origin::Remote, Font::Interstitial::Yes);
     626        case CSSFontFaceSource::Status::Loading: {
     627            Font::Visibility visibility = status() == Status::TimedOut ? Font::Visibility::Visible : Font::Visibility::Invisible;
     628            return Font::create(FontCache::singleton().lastResortFallbackFont(fontDescription)->platformData(), Font::Origin::Remote, Font::Interstitial::Yes, visibility);
     629        }
    629630        case CSSFontFaceSource::Status::Success:
    630631            if (RefPtr<Font> result = source->font(fontDescription, syntheticBold, syntheticItalic, m_featureSettings, m_variantSettings, m_fontSelectionCapabilities))
  • trunk/Source/WebCore/css/CSSFontFace.h

    r215287 r216944  
    5454class Font;
    5555class FontFace;
     56enum class ExternalResourceDownloadPolicy;
    5657
    5758class CSSFontFace final : public RefCounted<CSSFontFace> {
     
    109110
    110111    void load();
    111     RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic);
     112
     113    RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy);
    112114
    113115    static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree);
     
    159161    CSSFontFace(CSSFontSelector*, StyleRuleFontFace*, FontFace*, bool isLocalFallback);
    160162
    161     size_t pump();
     163    size_t pump(ExternalResourceDownloadPolicy);
    162164    void setStatus(Status);
    163165    void notifyClientsOfFontPropertyChange();
  • trunk/Source/WebCore/css/CSSFontSelector.cpp

    r215287 r216944  
    333333        return;
    334334
    335     m_fontsToBeginLoading.append(&font);
    336     // Increment the request count now, in order to prevent didFinishLoad from being dispatched
    337     // after this font has been requested but before it began loading. Balanced by
    338     // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
    339     m_document->cachedResourceLoader().incrementRequestCount(font);
     335    if (!m_document->settings().webFontsAlwaysFallBack()) {
     336        m_fontsToBeginLoading.append(&font);
     337        // Increment the request count now, in order to prevent didFinishLoad from being dispatched
     338        // after this font has been requested but before it began loading. Balanced by
     339        // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
     340        m_document->cachedResourceLoader().incrementRequestCount(font);
     341    }
    340342    m_beginLoadingTimer.startOneShot(0_s);
    341343}
  • trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp

    r216896 r216944  
    6767    }
    6868
    69     const Font* font() const final
     69    const Font* font(ExternalResourceDownloadPolicy policy) const final
    7070    {
    71         if (!m_result)
    72             m_result = m_fontFace->font(m_fontDescription, m_syntheticBold, m_syntheticItalic);
     71        if (!m_result || (policy == ExternalResourceDownloadPolicy::Allow
     72            && (m_fontFace->status() == CSSFontFace::Status::Pending || m_fontFace->status() == CSSFontFace::Status::Loading || m_fontFace->status() == CSSFontFace::Status::TimedOut))) {
     73            const auto result = m_fontFace->font(m_fontDescription, m_syntheticBold, m_syntheticItalic, policy);
     74            if (!m_result)
     75                m_result = result;
     76        }
    7377        return m_result.value().get();
    7478    }
     
    122126            bool syntheticItalic = (fontDescription.fontSynthesis() & FontSynthesisStyle) && !isItalic(selectionCapabilities.slope.maximum) && isItalic(desiredRequest.slope);
    123127
    124             // This doesn't trigger an unnecessary download because every element styled with this family will need font metrics in order to run layout.
    125128            // Metrics used for layout come from FontRanges::fontForFirstRange(), which assumes that the first font is non-null.
    126             // We're kicking off this necessary first download now.
    127129            auto fontAccessor = CSSFontAccessor::create(face, fontDescription, syntheticBold, syntheticItalic);
    128             if (result.isNull() && !fontAccessor->font())
     130            if (result.isNull() && !fontAccessor->font(ExternalResourceDownloadPolicy::Forbid))
    129131                continue;
    130132            appendFont(result, WTFMove(fontAccessor), face->ranges());
  • trunk/Source/WebCore/platform/graphics/Font.cpp

    r216896 r216944  
    5656const float emphasisMarkFontSizeMultiplier = 0.5f;
    5757
    58 Font::Font(const FontPlatformData& platformData, Origin origin, Interstitial interstitial, OrientationFallback orientationFallback)
     58Font::Font(const FontPlatformData& platformData, Origin origin, Interstitial interstitial, Visibility visibility, OrientationFallback orientationFallback)
    5959    : m_maxCharWidth(-1)
    6060    , m_avgCharWidth(-1)
    6161    , m_platformData(platformData)
    6262    , m_mathData(nullptr)
     63    , m_origin(origin)
     64    , m_visibility(visibility)
    6365    , m_treatAsFixedPitch(false)
    64     , m_origin(origin == Origin::Remote)
    6566    , m_isInterstitial(interstitial == Interstitial::Yes)
    66     , m_isTextOrientationFallback(orientationFallback == OrientationFallback::Fallback)
     67    , m_isTextOrientationFallback(orientationFallback == OrientationFallback::Yes)
    6768    , m_isBrokenIdeographFallback(false)
    6869    , m_hasVerticalGlyphs(false)
     
    7677    platformCharWidthInit();
    7778#if ENABLE(OPENTYPE_VERTICAL)
    78     if (platformData.orientation() == Vertical && orientationFallback == OrientationFallback::NoFallback) {
     79    if (platformData.orientation() == Vertical && orientationFallback == OrientationFallback::No) {
    7980        m_verticalData = FontCache::singleton().verticalData(platformData);
    8081        m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
     
    267268    if (!m_derivedFontData->verticalRightOrientation) {
    268269        auto verticalRightPlatformData = FontPlatformData::cloneWithOrientation(m_platformData, Horizontal);
    269         m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, origin(), Interstitial::No, OrientationFallback::Fallback);
     270        m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, origin(), Interstitial::No, Visibility::Visible, OrientationFallback::Yes);
    270271    }
    271272    ASSERT(m_derivedFontData->verticalRightOrientation != this);
     
    278279        m_derivedFontData = std::make_unique<DerivedFonts>();
    279280    if (!m_derivedFontData->uprightOrientation)
    280         m_derivedFontData->uprightOrientation = create(m_platformData, origin(), Interstitial::No, OrientationFallback::Fallback);
     281        m_derivedFontData->uprightOrientation = create(m_platformData, origin(), Interstitial::No, Visibility::Visible, OrientationFallback::Yes);
    281282    ASSERT(m_derivedFontData->uprightOrientation != this);
    282283    return *m_derivedFontData->uprightOrientation;
  • trunk/Source/WebCore/platform/graphics/Font.h

    r216896 r216944  
    8585        No
    8686    };
     87    enum class Visibility {
     88        Visible,
     89        Invisible
     90    };
    8791    enum class OrientationFallback {
    88         Fallback,
    89         NoFallback
    90     };
    91     static Ref<Font> create(const FontPlatformData& platformData, Origin origin = Origin::Local, Interstitial interstitial = Interstitial::No, OrientationFallback orientationFallback = OrientationFallback::NoFallback)
     92        Yes,
     93        No
     94    };
     95    static Ref<Font> create(const FontPlatformData& platformData, Origin origin = Origin::Local, Interstitial interstitial = Interstitial::No, Visibility visibility = Visibility::Visible, OrientationFallback orientationFallback = OrientationFallback::No)
    9296    {
    93         return adoptRef(*new Font(platformData, origin, interstitial, orientationFallback));
     97        return adoptRef(*new Font(platformData, origin, interstitial, visibility, orientationFallback));
    9498    }
    9599
     
    182186    Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
    183187
    184     Origin origin() const { return m_origin ? Origin::Remote : Origin::Local; }
     188    Origin origin() const { return m_origin; }
    185189    bool isInterstitial() const { return m_isInterstitial; }
     190    Visibility visibility() const { return m_visibility; }
    186191
    187192#ifndef NDEBUG
     
    221226
    222227private:
    223     Font(const FontPlatformData&, Origin, Interstitial, OrientationFallback);
     228    Font(const FontPlatformData&, Origin, Interstitial, Visibility, OrientationFallback);
    224229
    225230    void platformInit();
     
    304309#endif
    305310
     311    Origin m_origin; // Whether or not we are custom font loaded via @font-face
     312    Visibility m_visibility; // @font-face's internal timer can cause us to show fonts even when a font is being downloaded.
     313
    306314    unsigned m_treatAsFixedPitch : 1;
    307     unsigned m_origin : 1; // Whether or not we are custom font loaded via @font-face
    308315    unsigned m_isInterstitial : 1; // Whether or not this custom font is the last resort placeholder for a loading font
    309316
  • trunk/Source/WebCore/platform/graphics/FontCache.h

    r215287 r216944  
    203203    WEBCORE_EXPORT RefPtr<Font> fontForFamily(const FontDescription&, const AtomicString&, const FontFeatureSettings* fontFaceFeatures = nullptr, const FontVariantSettings* fontFaceVariantSettings = nullptr, FontSelectionSpecifiedCapabilities fontFaceCapabilities = { }, bool checkingAlternateName = false);
    204204    WEBCORE_EXPORT Ref<Font> lastResortFallbackFont(const FontDescription&);
    205     Ref<Font> lastResortFallbackFontForEveryCharacter(const FontDescription&);
    206205    WEBCORE_EXPORT Ref<Font> fontForPlatformData(const FontPlatformData&);
    207206    RefPtr<Font> similarFont(const FontDescription&, const AtomicString& family);
  • trunk/Source/WebCore/platform/graphics/FontCascade.cpp

    r216331 r216944  
    308308float FontCascade::drawText(GraphicsContext& context, const TextRun& run, const FloatPoint& point, unsigned from, std::optional<unsigned> to, CustomFontNotReadyAction customFontNotReadyAction) const
    309309{
    310     // Don't draw anything while we are using custom fonts that are in the process of loading,
    311     // except if the 'force' argument is set to true (in which case it will use a fallback
    312     // font).
    313     if (isLoadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
    314         return 0;
    315 
    316310    unsigned destination = to.value_or(run.length());
    317311
     
    328322    // Draw the glyph buffer now at the starting point returned in startX.
    329323    FloatPoint startPoint(startX, point.y());
    330     drawGlyphBuffer(context, glyphBuffer, startPoint);
     324    drawGlyphBuffer(context, glyphBuffer, startPoint, customFontNotReadyAction);
    331325    return startPoint.x() - startX;
    332326}
     
    14011395}
    14021396
    1403 void FontCascade::drawGlyphBuffer(GraphicsContext& context, const GlyphBuffer& glyphBuffer, FloatPoint& point) const
     1397inline bool shouldDrawIfLoading(const Font& font, FontCascade::CustomFontNotReadyAction customFontNotReadyAction)
     1398{
     1399    // Don't draw anything while we are using custom fonts that are in the process of loading,
     1400    // except if the 'customFontNotReadyAction' argument is set to UseFallbackIfFontNotReady
     1401    // (in which case "font" will be a fallback font).
     1402    return !font.isInterstitial() || font.visibility() == Font::Visibility::Visible || customFontNotReadyAction == FontCascade::CustomFontNotReadyAction::UseFallbackIfFontNotReady;
     1403}
     1404
     1405void FontCascade::drawGlyphBuffer(GraphicsContext& context, const GlyphBuffer& glyphBuffer, FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
    14041406{
    14051407    // Draw each contiguous run of glyphs that use the same font data.
     
    14161418
    14171419        if (nextFontData != fontData || nextOffset != offset) {
    1418             context.drawGlyphs(*this, *fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
     1420            if (shouldDrawIfLoading(*fontData, customFontNotReadyAction))
     1421                context.drawGlyphs(*this, *fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
    14191422
    14201423            lastFrom = nextGlyph;
     
    14291432    }
    14301433
    1431     context.drawGlyphs(*this, *fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
     1434    if (shouldDrawIfLoading(*fontData, customFontNotReadyAction))
     1435        context.drawGlyphs(*this, *fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
    14321436    point.setX(nextX);
    14331437}
     
    14741478    markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
    14751479
    1476     drawGlyphBuffer(context, markBuffer, startPoint);
     1480    drawGlyphBuffer(context, markBuffer, startPoint, CustomFontNotReadyAction::DoNotPaintIfFontNotReady);
    14771481}
    14781482
  • trunk/Source/WebCore/platform/graphics/FontCascade.h

    r215752 r216944  
    222222    float getGlyphsAndAdvancesForSimpleText(const TextRun&, unsigned from, unsigned to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
    223223    void drawEmphasisMarksForSimpleText(GraphicsContext&, const TextRun&, const AtomicString& mark, const FloatPoint&, unsigned from, unsigned to) const;
    224     void drawGlyphBuffer(GraphicsContext&, const GlyphBuffer&, FloatPoint&) const;
     224    void drawGlyphBuffer(GraphicsContext&, const GlyphBuffer&, FloatPoint&, CustomFontNotReadyAction) const;
    225225    void drawEmphasisMarks(GraphicsContext&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
    226226    float floatWidthForSimpleText(const TextRun&, HashSet<const Font*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
  • trunk/Source/WebCore/platform/graphics/FontCascadeFonts.cpp

    r214848 r216944  
    351351GlyphData FontCascadeFonts::glyphDataForVariant(UChar32 c, const FontCascadeDescription& description, FontVariant variant, unsigned fallbackIndex)
    352352{
     353    ExternalResourceDownloadPolicy policy = ExternalResourceDownloadPolicy::Allow;
     354    GlyphData loadingResult;
    353355    while (true) {
    354356        auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex++);
    355357        if (fontRanges.isNull())
    356358            break;
    357         GlyphData data = fontRanges.glyphDataForCharacter(c);
     359        GlyphData data = fontRanges.glyphDataForCharacter(c, policy);
    358360        if (!data.font)
    359361            continue;
     362        if (data.font->isInterstitial()) {
     363            policy = ExternalResourceDownloadPolicy::Forbid;
     364            if (!loadingResult.font)
     365                loadingResult = data;
     366            continue;
     367        }
    360368        // The variantFont function should not normally return 0.
    361369        // But if it does, we will just render the capital letter big.
     
    365373    }
    366374
     375    if (loadingResult.font)
     376        return loadingResult;
    367377    return glyphDataForSystemFallback(c, description, variant);
    368378}
     
    370380GlyphData FontCascadeFonts::glyphDataForNormalVariant(UChar32 c, const FontCascadeDescription& description)
    371381{
     382    ExternalResourceDownloadPolicy policy = ExternalResourceDownloadPolicy::Allow;
     383    GlyphData loadingResult;
    372384    for (unsigned fallbackIndex = 0; ; ++fallbackIndex) {
    373385        auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex);
    374386        if (fontRanges.isNull())
    375387            break;
    376         GlyphData data = fontRanges.glyphDataForCharacter(c);
     388        GlyphData data = fontRanges.glyphDataForCharacter(c, policy);
    377389        if (!data.font)
    378390            continue;
     391        if (data.font->isInterstitial()) {
     392            policy = ExternalResourceDownloadPolicy::Forbid;
     393            if (!loadingResult.font)
     394                loadingResult = data;
     395            continue;
     396        }
    379397        if (data.font->platformData().orientation() == Vertical && !data.font->isTextOrientationFallback()) {
    380398            if (!FontCascade::isCJKIdeographOrSymbol(c))
     
    390408    }
    391409
     410    if (loadingResult.font)
     411        return loadingResult;
    392412    return glyphDataForSystemFallback(c, description, NormalVariant);
    393413}
     
    398418    UChar32 pageRangeFrom = pageNumber * GlyphPage::size;
    399419    UChar32 pageRangeTo = pageRangeFrom + GlyphPage::size - 1;
     420    auto policy = ExternalResourceDownloadPolicy::Allow;
    400421    for (unsigned i = 0; i < fontRanges.size(); ++i) {
    401422        auto& range = fontRanges.rangeAt(i);
    402         if (range.to()) {
    403             if (range.from() <= pageRangeFrom && pageRangeTo <= range.to())
    404                 font = range.font();
    405             break;
    406         }
     423        if (range.from() <= pageRangeFrom && pageRangeTo <= range.to()) {
     424            font = range.font(policy);
     425            if (!font)
     426                continue;
     427            if (font->isInterstitial()) {
     428                font = nullptr;
     429                policy = ExternalResourceDownloadPolicy::Forbid;
     430                continue;
     431            }
     432        }
     433        break;
    407434    }
    408435    if (!font || font->platformData().orientation() == Vertical)
  • trunk/Source/WebCore/platform/graphics/FontRanges.cpp

    r216896 r216944  
    3434namespace WebCore {
    3535
    36 const Font* FontRanges::Range::font() const
     36const Font* FontRanges::Range::font(ExternalResourceDownloadPolicy policy) const
    3737{
    38     return m_fontAccessor->font();
     38    return m_fontAccessor->font(policy);
    3939}
    4040
     
    5656    }
    5757
    58     const Font* font() const final
     58    const Font* font(ExternalResourceDownloadPolicy) const final
    5959    {
    6060        return m_font.get();
     
    7979}
    8080
    81 GlyphData FontRanges::glyphDataForCharacter(UChar32 character) const
     81GlyphData FontRanges::glyphDataForCharacter(UChar32 character, ExternalResourceDownloadPolicy policy) const
    8282{
     83    const Font* resultFont = nullptr;
    8384    for (auto& range : m_ranges) {
    8485        if (range.from() <= character && character <= range.to()) {
    85             if (auto* font = range.font()) {
    86                 auto glyphData = font->glyphDataForCharacter(character);
    87                 if (glyphData.glyph)
    88                     return glyphData;
     86            if (auto* font = range.font(policy)) {
     87                if (font->isInterstitial()) {
     88                    policy = ExternalResourceDownloadPolicy::Forbid;
     89                    if (!resultFont)
     90                        resultFont = font;
     91                } else {
     92                    auto glyphData = font->glyphDataForCharacter(character);
     93                    if (glyphData.glyph)
     94                        return glyphData;
     95                }
    8996            }
    9097        }
     98    }
     99    if (resultFont) {
     100        // We want higher-level code to be able to differentiate between
     101        // "The interstitial font doesn't have the character" and
     102        // "The real downloaded font doesn't have the character".
     103        GlyphData result = resultFont->glyphDataForCharacter(character);
     104        if (!result.font)
     105            result.font = resultFont;
     106        return result;
    91107    }
    92108    return GlyphData();
     
    95111const Font* FontRanges::fontForCharacter(UChar32 character) const
    96112{
    97     return glyphDataForCharacter(character).font;
     113    return glyphDataForCharacter(character, ExternalResourceDownloadPolicy::Allow).font;
    98114}
    99115
    100116const Font& FontRanges::fontForFirstRange() const
    101117{
    102     auto* font = m_ranges[0].font();
     118    auto* font = m_ranges[0].font(ExternalResourceDownloadPolicy::Forbid);
    103119    ASSERT(font);
    104120    return *font;
  • trunk/Source/WebCore/platform/graphics/FontRanges.h

    r200601 r216944  
    3535class FontAccessor;
    3636
     37enum class ExternalResourceDownloadPolicy {
     38    Forbid,
     39    Allow
     40};
     41
    3742class FontRanges {
    3843public:
     
    5863        UChar32 from() const { return m_from; }
    5964        UChar32 to() const { return m_to; }
    60         const Font* font() const;
     65        const Font* font(ExternalResourceDownloadPolicy) const;
    6166        const FontAccessor& fontAccessor() const { return m_fontAccessor; }
    6267
     
    8085    const Range& rangeAt(unsigned i) const { return m_ranges[i]; }
    8186
    82     GlyphData glyphDataForCharacter(UChar32) const;
     87    GlyphData glyphDataForCharacter(UChar32, ExternalResourceDownloadPolicy) const;
    8388    WEBCORE_EXPORT const Font* fontForCharacter(UChar32) const;
    8489    WEBCORE_EXPORT const Font& fontForFirstRange() const;
  • trunk/Source/WebCore/platform/graphics/FontSelector.h

    r204466 r216944  
    4040    virtual ~FontAccessor() { }
    4141
    42     virtual const Font* font() const = 0;
     42    virtual const Font* font(ExternalResourceDownloadPolicy) const = 0;
    4343    virtual bool isLoading() const = 0;
    4444};
  • trunk/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp

    r215287 r216944  
    124124}
    125125
    126 Ref<Font> FontCache::lastResortFallbackFontForEveryCharacter(const FontDescription& fontDescription)
    127 {
    128     return lastResortFallbackFont(fontDescription);
    129 }
    130 
    131126Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
    132127{
  • trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm

    r216342 r216944  
    150150#endif // PLATFORM(MAC)
    151151
    152 Ref<Font> FontCache::lastResortFallbackFontForEveryCharacter(const FontDescription& fontDescription)
    153 {
    154     auto result = fontForFamily(fontDescription, AtomicString("LastResort", AtomicString::ConstructFromLiteral));
    155     ASSERT(result);
    156     return *result;
    157 }
    158 
    159152} // namespace WebCore
  • trunk/Source/WebCore/platform/graphics/win/FontCacheWin.cpp

    r216833 r216944  
    339339}
    340340
    341 Ref<Font> FontCache::lastResortFallbackFontForEveryCharacter(const FontDescription& fontDescription)
    342 {
    343     return lastResortFallbackFont(fontDescription);
    344 }
    345 
    346341Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription)
    347342{
Note: See TracChangeset for help on using the changeset viewer.