Changeset 216944 in webkit
- Timestamp:
- May 16, 2017 1:26:39 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 10 added
- 22 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r216938 r216944 1 2017-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 1 28 2017-05-16 Eric Carlson <eric.carlson@apple.com> 2 29 -
trunk/LayoutTests/fast/text/font-download-font-face-src-list.html
r216943 r216944 15 15 @font-face { 16 16 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"); 24 18 } 25 19 </style> … … 27 21 <body> 28 22 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';">横</div>23 <div style="font-size: 100px; font-family: 'WebFont';">横</div> 30 24 </body> 31 25 </html> 26 27 -
trunk/LayoutTests/fast/text/font-download-font-family-property.html
r216943 r216944 15 15 @font-face { 16 16 font-family: "WebFont"; 17 font-weight: 100;18 17 src: url("../../resources/Ahem_CJK.ttf") format("truetype"); 19 18 } 20 19 @font-face { 21 font-family: "WebFont"; 22 font-weight: 900; 20 font-family: "WebFont2"; 23 21 src: url("../../resources/Ahem.otf") format("opentype"); 24 22 } … … 27 25 <body> 28 26 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';">横</div>27 <div style="font-size: 100px; font-family: 'WebFont', 'WebFont2';">横</div> 30 28 </body> 31 29 </html> 30 -
trunk/LayoutTests/fast/text/font-download-remote-fallback-all.html
r216943 r216944 16 16 font-family: "WebFont"; 17 17 font-weight: 100; 18 src: url("../../resources/Ahem_CJK.ttf") format("truetype");18 src: url("../../resources/Ahem_CJK.ttf"), url("garbage2"); 19 19 } 20 20 @font-face { 21 21 font-family: "WebFont"; 22 22 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"); 24 28 } 25 29 </style> 26 30 </head> 27 31 <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';">横</div>32 This 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';">横</div> 30 34 </body> 31 35 </html> -
trunk/LayoutTests/fast/text/font-weight-download-3.html
r216943 r216944 27 27 <body> 28 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';">横 </div>29 <div style="font: 100 100px 'WebFont';">横̀</div> 30 30 </body> 31 31 </html> 32 -
trunk/LayoutTests/fast/text/web-font-load-fallback-during-loading-expected.html
r201676 r216944 4 4 </head> 5 5 <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;"> 7 This 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> 11 12 </body> 12 13 </html> -
trunk/LayoutTests/fast/text/web-font-load-fallback-during-loading.html
r216079 r216944 8 8 internals.invalidateFontCache(); 9 9 } 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 38 10 </script> 39 11 <style> 40 12 @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"); 43 15 } 44 16 @font-face { 45 font-family: WebFont2;46 src: local(" Helvetica");17 font-family: "WebFont2"; 18 src: local("American Typewriter"); 47 19 } 48 20 @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"; 50 26 src: url("../../resources/Ahem.ttf") format("truetype"); 51 27 } … … 53 29 </head> 54 30 <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;"> 32 This 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> 62 40 <script> 63 var expectedWidth = document.getElementById("reference").getBoundingClientRect().width; 41 var console = document.getElementById("console"); 42 var americanTypewriterWidth = document.getElementById("americanTypewriter").getBoundingClientRect().width; 43 var notAmericanTypewriterWidth = document.getElementById("notAmericanTypewriter").getBoundingClientRect().width; 44 if (americanTypewriterWidth == notAmericanTypewriterWidth) 45 console.innerText = "FAIL: Element should not be rendered with American Typewriter."; 46 else 47 console.innerText = "PASS: Element is not rendered with American Typewriter."; 48 document.getElementById("container").style.display = "none"; 64 49 </script> 65 50 </body> -
trunk/LayoutTests/http/tests/webfont/fallback-font-while-loading-expected.txt
r212513 r216944 1 This test checks that the fallback font is notused for layout while a webfont is loading.1 This test checks that the fallback font is used for layout while a webfont is loading. 2 2 3 3 Target: … … 5 5 Reference: 6 6 A text to be measured. 7 PASS: The width of target text and reference text are different.7 PASS: The width of target text and reference text is the same. -
trunk/LayoutTests/http/tests/webfont/fallback-font-while-loading.html
r212513 r216944 6 6 </style> 7 7 <p> 8 This test checks that the fallback font is notused for layout while a webfont is loading.8 This test checks that the fallback font is used for layout while a webfont is loading. 9 9 </p> 10 10 Target: … … 27 27 var referenceWidth = document.getElementById('reference').offsetWidth; 28 28 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.'; 31 31 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; 33 33 } 34 34 -
trunk/Source/WebCore/ChangeLog
r216940 r216944 1 2017-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 1 118 2017-05-16 Zalan Bujtas <zalan@apple.com> 2 119 -
trunk/Source/WebCore/css/CSSFontFace.cpp
r216896 r216944 420 420 // Let's not pump the state machine until we've got all our sources. font() and load() are smart enough to act correctly 421 421 // 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); 424 424 425 425 ASSERT(m_fontSelector); … … 527 527 } 528 528 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 } 533 537 534 538 iterateClients(m_clients, [&](Client& client) { … … 537 541 538 542 m_status = newStatus; 543 544 if (newStatus == Status::Loading && webFontsShouldAlwaysFallBack) 545 timeoutFired(); 539 546 } 540 547 … … 551 558 } 552 559 553 size_t CSSFontFace::pump( )560 size_t CSSFontFace::pump(ExternalResourceDownloadPolicy policy) 554 561 { 555 562 size_t i; … … 559 566 if (source->status() == CSSFontFaceSource::Status::Pending) { 560 567 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 } 564 573 } 565 574 566 575 switch (source->status()) { 567 576 case CSSFontFaceSource::Status::Pending: 568 ASSERT _NOT_REACHED();569 break;577 ASSERT(policy == ExternalResourceDownloadPolicy::Forbid); 578 return i; 570 579 case CSSFontFaceSource::Status::Loading: 571 580 ASSERT(m_status == Status::Pending || m_status == Status::Loading || m_status == Status::TimedOut); … … 595 604 void CSSFontFace::load() 596 605 { 597 pump( );598 } 599 600 RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic )606 pump(ExternalResourceDownloadPolicy::Allow); 607 } 608 609 RefPtr<Font> CSSFontFace::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy policy) 601 610 { 602 611 if (allSourcesFailed()) … … 607 616 // of the sources to try to find a font to use. These subsequent tries should not affect 608 617 // our own state, though. 609 size_t startIndex = pump(); 610 bool fontIsLoading = false; 618 size_t startIndex = pump(policy); 611 619 for (size_t i = startIndex; i < m_sources.size(); ++i) { 612 620 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())) 616 622 source->load(m_fontSelector.get()); 617 }618 623 619 624 switch (source->status()) { 620 625 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 } 629 630 case CSSFontFaceSource::Status::Success: 630 631 if (RefPtr<Font> result = source->font(fontDescription, syntheticBold, syntheticItalic, m_featureSettings, m_variantSettings, m_fontSelectionCapabilities)) -
trunk/Source/WebCore/css/CSSFontFace.h
r215287 r216944 54 54 class Font; 55 55 class FontFace; 56 enum class ExternalResourceDownloadPolicy; 56 57 57 58 class CSSFontFace final : public RefCounted<CSSFontFace> { … … 109 110 110 111 void load(); 111 RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic); 112 113 RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy); 112 114 113 115 static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree); … … 159 161 CSSFontFace(CSSFontSelector*, StyleRuleFontFace*, FontFace*, bool isLocalFallback); 160 162 161 size_t pump( );163 size_t pump(ExternalResourceDownloadPolicy); 162 164 void setStatus(Status); 163 165 void notifyClientsOfFontPropertyChange(); -
trunk/Source/WebCore/css/CSSFontSelector.cpp
r215287 r216944 333 333 return; 334 334 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 } 340 342 m_beginLoadingTimer.startOneShot(0_s); 341 343 } -
trunk/Source/WebCore/css/CSSSegmentedFontFace.cpp
r216896 r216944 67 67 } 68 68 69 const Font* font( ) const final69 const Font* font(ExternalResourceDownloadPolicy policy) const final 70 70 { 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 } 73 77 return m_result.value().get(); 74 78 } … … 122 126 bool syntheticItalic = (fontDescription.fontSynthesis() & FontSynthesisStyle) && !isItalic(selectionCapabilities.slope.maximum) && isItalic(desiredRequest.slope); 123 127 124 // This doesn't trigger an unnecessary download because every element styled with this family will need font metrics in order to run layout.125 128 // 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.127 129 auto fontAccessor = CSSFontAccessor::create(face, fontDescription, syntheticBold, syntheticItalic); 128 if (result.isNull() && !fontAccessor->font( ))130 if (result.isNull() && !fontAccessor->font(ExternalResourceDownloadPolicy::Forbid)) 129 131 continue; 130 132 appendFont(result, WTFMove(fontAccessor), face->ranges()); -
trunk/Source/WebCore/platform/graphics/Font.cpp
r216896 r216944 56 56 const float emphasisMarkFontSizeMultiplier = 0.5f; 57 57 58 Font::Font(const FontPlatformData& platformData, Origin origin, Interstitial interstitial, OrientationFallback orientationFallback)58 Font::Font(const FontPlatformData& platformData, Origin origin, Interstitial interstitial, Visibility visibility, OrientationFallback orientationFallback) 59 59 : m_maxCharWidth(-1) 60 60 , m_avgCharWidth(-1) 61 61 , m_platformData(platformData) 62 62 , m_mathData(nullptr) 63 , m_origin(origin) 64 , m_visibility(visibility) 63 65 , m_treatAsFixedPitch(false) 64 , m_origin(origin == Origin::Remote)65 66 , m_isInterstitial(interstitial == Interstitial::Yes) 66 , m_isTextOrientationFallback(orientationFallback == OrientationFallback:: Fallback)67 , m_isTextOrientationFallback(orientationFallback == OrientationFallback::Yes) 67 68 , m_isBrokenIdeographFallback(false) 68 69 , m_hasVerticalGlyphs(false) … … 76 77 platformCharWidthInit(); 77 78 #if ENABLE(OPENTYPE_VERTICAL) 78 if (platformData.orientation() == Vertical && orientationFallback == OrientationFallback::No Fallback) {79 if (platformData.orientation() == Vertical && orientationFallback == OrientationFallback::No) { 79 80 m_verticalData = FontCache::singleton().verticalData(platformData); 80 81 m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics(); … … 267 268 if (!m_derivedFontData->verticalRightOrientation) { 268 269 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); 270 271 } 271 272 ASSERT(m_derivedFontData->verticalRightOrientation != this); … … 278 279 m_derivedFontData = std::make_unique<DerivedFonts>(); 279 280 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); 281 282 ASSERT(m_derivedFontData->uprightOrientation != this); 282 283 return *m_derivedFontData->uprightOrientation; -
trunk/Source/WebCore/platform/graphics/Font.h
r216896 r216944 85 85 No 86 86 }; 87 enum class Visibility { 88 Visible, 89 Invisible 90 }; 87 91 enum class OrientationFallback { 88 Fallback,89 No Fallback90 }; 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) 92 96 { 93 return adoptRef(*new Font(platformData, origin, interstitial, orientationFallback));97 return adoptRef(*new Font(platformData, origin, interstitial, visibility, orientationFallback)); 94 98 } 95 99 … … 182 186 Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; } 183 187 184 Origin origin() const { return m_origin ? Origin::Remote : Origin::Local; }188 Origin origin() const { return m_origin; } 185 189 bool isInterstitial() const { return m_isInterstitial; } 190 Visibility visibility() const { return m_visibility; } 186 191 187 192 #ifndef NDEBUG … … 221 226 222 227 private: 223 Font(const FontPlatformData&, Origin, Interstitial, OrientationFallback);228 Font(const FontPlatformData&, Origin, Interstitial, Visibility, OrientationFallback); 224 229 225 230 void platformInit(); … … 304 309 #endif 305 310 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 306 314 unsigned m_treatAsFixedPitch : 1; 307 unsigned m_origin : 1; // Whether or not we are custom font loaded via @font-face308 315 unsigned m_isInterstitial : 1; // Whether or not this custom font is the last resort placeholder for a loading font 309 316 -
trunk/Source/WebCore/platform/graphics/FontCache.h
r215287 r216944 203 203 WEBCORE_EXPORT RefPtr<Font> fontForFamily(const FontDescription&, const AtomicString&, const FontFeatureSettings* fontFaceFeatures = nullptr, const FontVariantSettings* fontFaceVariantSettings = nullptr, FontSelectionSpecifiedCapabilities fontFaceCapabilities = { }, bool checkingAlternateName = false); 204 204 WEBCORE_EXPORT Ref<Font> lastResortFallbackFont(const FontDescription&); 205 Ref<Font> lastResortFallbackFontForEveryCharacter(const FontDescription&);206 205 WEBCORE_EXPORT Ref<Font> fontForPlatformData(const FontPlatformData&); 207 206 RefPtr<Font> similarFont(const FontDescription&, const AtomicString& family); -
trunk/Source/WebCore/platform/graphics/FontCascade.cpp
r216331 r216944 308 308 float FontCascade::drawText(GraphicsContext& context, const TextRun& run, const FloatPoint& point, unsigned from, std::optional<unsigned> to, CustomFontNotReadyAction customFontNotReadyAction) const 309 309 { 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 fallback312 // font).313 if (isLoadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)314 return 0;315 316 310 unsigned destination = to.value_or(run.length()); 317 311 … … 328 322 // Draw the glyph buffer now at the starting point returned in startX. 329 323 FloatPoint startPoint(startX, point.y()); 330 drawGlyphBuffer(context, glyphBuffer, startPoint );324 drawGlyphBuffer(context, glyphBuffer, startPoint, customFontNotReadyAction); 331 325 return startPoint.x() - startX; 332 326 } … … 1401 1395 } 1402 1396 1403 void FontCascade::drawGlyphBuffer(GraphicsContext& context, const GlyphBuffer& glyphBuffer, FloatPoint& point) const 1397 inline 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 1405 void FontCascade::drawGlyphBuffer(GraphicsContext& context, const GlyphBuffer& glyphBuffer, FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const 1404 1406 { 1405 1407 // Draw each contiguous run of glyphs that use the same font data. … … 1416 1418 1417 1419 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); 1419 1422 1420 1423 lastFrom = nextGlyph; … … 1429 1432 } 1430 1433 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); 1432 1436 point.setX(nextX); 1433 1437 } … … 1474 1478 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0); 1475 1479 1476 drawGlyphBuffer(context, markBuffer, startPoint );1480 drawGlyphBuffer(context, markBuffer, startPoint, CustomFontNotReadyAction::DoNotPaintIfFontNotReady); 1477 1481 } 1478 1482 -
trunk/Source/WebCore/platform/graphics/FontCascade.h
r215752 r216944 222 222 float getGlyphsAndAdvancesForSimpleText(const TextRun&, unsigned from, unsigned to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; 223 223 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; 225 225 void drawEmphasisMarks(GraphicsContext&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; 226 226 float floatWidthForSimpleText(const TextRun&, HashSet<const Font*>* fallbackFonts = 0, GlyphOverflow* = 0) const; -
trunk/Source/WebCore/platform/graphics/FontCascadeFonts.cpp
r214848 r216944 351 351 GlyphData FontCascadeFonts::glyphDataForVariant(UChar32 c, const FontCascadeDescription& description, FontVariant variant, unsigned fallbackIndex) 352 352 { 353 ExternalResourceDownloadPolicy policy = ExternalResourceDownloadPolicy::Allow; 354 GlyphData loadingResult; 353 355 while (true) { 354 356 auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex++); 355 357 if (fontRanges.isNull()) 356 358 break; 357 GlyphData data = fontRanges.glyphDataForCharacter(c );359 GlyphData data = fontRanges.glyphDataForCharacter(c, policy); 358 360 if (!data.font) 359 361 continue; 362 if (data.font->isInterstitial()) { 363 policy = ExternalResourceDownloadPolicy::Forbid; 364 if (!loadingResult.font) 365 loadingResult = data; 366 continue; 367 } 360 368 // The variantFont function should not normally return 0. 361 369 // But if it does, we will just render the capital letter big. … … 365 373 } 366 374 375 if (loadingResult.font) 376 return loadingResult; 367 377 return glyphDataForSystemFallback(c, description, variant); 368 378 } … … 370 380 GlyphData FontCascadeFonts::glyphDataForNormalVariant(UChar32 c, const FontCascadeDescription& description) 371 381 { 382 ExternalResourceDownloadPolicy policy = ExternalResourceDownloadPolicy::Allow; 383 GlyphData loadingResult; 372 384 for (unsigned fallbackIndex = 0; ; ++fallbackIndex) { 373 385 auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex); 374 386 if (fontRanges.isNull()) 375 387 break; 376 GlyphData data = fontRanges.glyphDataForCharacter(c );388 GlyphData data = fontRanges.glyphDataForCharacter(c, policy); 377 389 if (!data.font) 378 390 continue; 391 if (data.font->isInterstitial()) { 392 policy = ExternalResourceDownloadPolicy::Forbid; 393 if (!loadingResult.font) 394 loadingResult = data; 395 continue; 396 } 379 397 if (data.font->platformData().orientation() == Vertical && !data.font->isTextOrientationFallback()) { 380 398 if (!FontCascade::isCJKIdeographOrSymbol(c)) … … 390 408 } 391 409 410 if (loadingResult.font) 411 return loadingResult; 392 412 return glyphDataForSystemFallback(c, description, NormalVariant); 393 413 } … … 398 418 UChar32 pageRangeFrom = pageNumber * GlyphPage::size; 399 419 UChar32 pageRangeTo = pageRangeFrom + GlyphPage::size - 1; 420 auto policy = ExternalResourceDownloadPolicy::Allow; 400 421 for (unsigned i = 0; i < fontRanges.size(); ++i) { 401 422 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; 407 434 } 408 435 if (!font || font->platformData().orientation() == Vertical) -
trunk/Source/WebCore/platform/graphics/FontRanges.cpp
r216896 r216944 34 34 namespace WebCore { 35 35 36 const Font* FontRanges::Range::font( ) const36 const Font* FontRanges::Range::font(ExternalResourceDownloadPolicy policy) const 37 37 { 38 return m_fontAccessor->font( );38 return m_fontAccessor->font(policy); 39 39 } 40 40 … … 56 56 } 57 57 58 const Font* font( ) const final58 const Font* font(ExternalResourceDownloadPolicy) const final 59 59 { 60 60 return m_font.get(); … … 79 79 } 80 80 81 GlyphData FontRanges::glyphDataForCharacter(UChar32 character ) const81 GlyphData FontRanges::glyphDataForCharacter(UChar32 character, ExternalResourceDownloadPolicy policy) const 82 82 { 83 const Font* resultFont = nullptr; 83 84 for (auto& range : m_ranges) { 84 85 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 } 89 96 } 90 97 } 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; 91 107 } 92 108 return GlyphData(); … … 95 111 const Font* FontRanges::fontForCharacter(UChar32 character) const 96 112 { 97 return glyphDataForCharacter(character ).font;113 return glyphDataForCharacter(character, ExternalResourceDownloadPolicy::Allow).font; 98 114 } 99 115 100 116 const Font& FontRanges::fontForFirstRange() const 101 117 { 102 auto* font = m_ranges[0].font( );118 auto* font = m_ranges[0].font(ExternalResourceDownloadPolicy::Forbid); 103 119 ASSERT(font); 104 120 return *font; -
trunk/Source/WebCore/platform/graphics/FontRanges.h
r200601 r216944 35 35 class FontAccessor; 36 36 37 enum class ExternalResourceDownloadPolicy { 38 Forbid, 39 Allow 40 }; 41 37 42 class FontRanges { 38 43 public: … … 58 63 UChar32 from() const { return m_from; } 59 64 UChar32 to() const { return m_to; } 60 const Font* font( ) const;65 const Font* font(ExternalResourceDownloadPolicy) const; 61 66 const FontAccessor& fontAccessor() const { return m_fontAccessor; } 62 67 … … 80 85 const Range& rangeAt(unsigned i) const { return m_ranges[i]; } 81 86 82 GlyphData glyphDataForCharacter(UChar32 ) const;87 GlyphData glyphDataForCharacter(UChar32, ExternalResourceDownloadPolicy) const; 83 88 WEBCORE_EXPORT const Font* fontForCharacter(UChar32) const; 84 89 WEBCORE_EXPORT const Font& fontForFirstRange() const; -
trunk/Source/WebCore/platform/graphics/FontSelector.h
r204466 r216944 40 40 virtual ~FontAccessor() { } 41 41 42 virtual const Font* font( ) const = 0;42 virtual const Font* font(ExternalResourceDownloadPolicy) const = 0; 43 43 virtual bool isLoading() const = 0; 44 44 }; -
trunk/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp
r215287 r216944 124 124 } 125 125 126 Ref<Font> FontCache::lastResortFallbackFontForEveryCharacter(const FontDescription& fontDescription)127 {128 return lastResortFallbackFont(fontDescription);129 }130 131 126 Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription) 132 127 { -
trunk/Source/WebCore/platform/graphics/mac/FontCacheMac.mm
r216342 r216944 150 150 #endif // PLATFORM(MAC) 151 151 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 159 152 } // namespace WebCore -
trunk/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
r216833 r216944 339 339 } 340 340 341 Ref<Font> FontCache::lastResortFallbackFontForEveryCharacter(const FontDescription& fontDescription)342 {343 return lastResortFallbackFont(fontDescription);344 }345 346 341 Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescription) 347 342 {
Note: See TracChangeset
for help on using the changeset viewer.