<rdar://problem/10520670> REGRESSION (r91738): didFinishLoad is called before custom...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Dec 2011 22:49:53 +0000 (22:49 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Dec 2011 22:49:53 +0000 (22:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=73688

Reviewed by Darin Adler.

Source/WebCore:

The problem was that after CSSFontFaceSource::getFontData() had scheduled a 0-delay timer to
begin loading the font, but before that timer fired, the subresource loader appeared to have
had no resources waiting to be loaded, and therefore didFinishLoad could be called. This change
reworks the fix for <http://webkit.org/b/65123> so that while the load is still started on a
0-dealy timer, the subresource loader’s request count is incremented immediately, preventing
it from hitting 0 while the font load is scheduled to begin. The delayed load mechanism is
moved from CSSFontFaceSource into CSSFontSelector in order to safely handle the possibility of
the latter being decommissioned while waiting for font loading to begin.

* css/CSSFontFaceSource.cpp:
(WebCore::CSSFontFaceSource::CSSFontFaceSource): Removed initializer for m_loadStartTimer.
(WebCore::CSSFontFaceSource::~CSSFontFaceSource): Removed stopping of m_loadStartTimer.
(WebCore::CSSFontFaceSource::getFontData): Replaced code to schedule loading on a timer with
a call to CSSFontSelector::beginLoadingFontSoon.
* css/CSSFontFaceSource.h: Removed m_loadStartTimer and m_fontSelector member variables.
* css/CSSFontSelector.cpp:
(WebCore::CSSFontSelector::CSSFontSelector): Added initialized for m_beginLoadingTimer.
(WebCore::CSSFontSelector::~CSSFontSelector): Added call to clearDocument(), to deal with
anything remaining in m_fontsToBeginLoading at this time.
(WebCore::CSSFontSelector::clearDocument): Now stops m_beginLoadingTimer and balances
incrementRequestCount() calls for anything remaining in m_fontsToBeginLoading.
(WebCore::CSSFontSelector::beginLoadingFontSoon): Added. Schedules the actual call to
CachedFont::beginLoadingIfNeeded on a 0-delay timer, and meanwhile increments the request count
on the CachedResourceLoader, which ensures that didFinishLoad will not be called while waiting
for the timer to fire.
(WebCore::CSSFontSelector::beginLoadTimerFired): Added. Actually calls
CachedFont::beginLoadIfNeeded and balances the incrementRequestCount() made when the timer was
scheduled.
* css/CSSFontSelector.h:

LayoutTests:

Reverted test chnages from r91738. These tests were made to wait for the fonts to finish loading
using a DOM. Now again they do not need to.

* fast/css/color-leakage.html:
* fast/css/custom-font-xheight.html:
* fast/css/font-face-multiple-faces.html:
* fast/css/font-face-multiple-remote-sources.html:
* fast/css/font-face-remote.html:
* fast/css/font-face-woff.html:
* fast/writing-mode/broken-ideograph-small-caps.html:
* svg/W3C-SVG-1.1-SE/text-intro-09-b.svg:
* svg/W3C-SVG-1.1/fonts-elem-07-b.svg:
* svg/custom/svg-fonts-fallback.xhtml:
* svg/custom/svg-fonts-in-html.html:
* svg/custom/svg-fonts-segmented.xhtml:
* svg/custom/svg-fonts-with-no-element-reference.html:
* svg/custom/svg-fonts-without-missing-glyph.xhtml:
* svg/text/text-overflow-ellipsis-svgfont.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@101858 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/color-leakage.html
LayoutTests/fast/css/custom-font-xheight.html
LayoutTests/fast/css/font-face-multiple-faces.html
LayoutTests/fast/css/font-face-multiple-remote-sources.html
LayoutTests/fast/css/font-face-remote.html
LayoutTests/fast/css/font-face-woff.html
LayoutTests/fast/writing-mode/broken-ideograph-small-caps.html
LayoutTests/svg/W3C-SVG-1.1-SE/text-intro-09-b.svg
LayoutTests/svg/W3C-SVG-1.1/fonts-elem-07-b.svg
LayoutTests/svg/custom/svg-fonts-fallback.xhtml
LayoutTests/svg/custom/svg-fonts-in-html.html
LayoutTests/svg/custom/svg-fonts-segmented.xhtml
LayoutTests/svg/custom/svg-fonts-with-no-element-reference.html
LayoutTests/svg/custom/svg-fonts-without-missing-glyph.xhtml
LayoutTests/svg/text/text-overflow-ellipsis-svgfont.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSFontFaceSource.cpp
Source/WebCore/css/CSSFontFaceSource.h
Source/WebCore/css/CSSFontSelector.cpp
Source/WebCore/css/CSSFontSelector.h

index 490089375c462cf2f7176a9443b7f612d355d99c..c77fc6213090848988277b120188b2d40913cdd0 100644 (file)
@@ -1,3 +1,29 @@
+2011-12-02  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10520670> REGRESSION (r91738): didFinishLoad is called before custom fonts have finished loading
+        https://bugs.webkit.org/show_bug.cgi?id=73688
+
+        Reviewed by Darin Adler.
+
+        Reverted test chnages from r91738. These tests were made to wait for the fonts to finish loading
+        using a DOM. Now again they do not need to.
+
+        * fast/css/color-leakage.html:
+        * fast/css/custom-font-xheight.html:
+        * fast/css/font-face-multiple-faces.html:
+        * fast/css/font-face-multiple-remote-sources.html:
+        * fast/css/font-face-remote.html:
+        * fast/css/font-face-woff.html:
+        * fast/writing-mode/broken-ideograph-small-caps.html:
+        * svg/W3C-SVG-1.1-SE/text-intro-09-b.svg:
+        * svg/W3C-SVG-1.1/fonts-elem-07-b.svg:
+        * svg/custom/svg-fonts-fallback.xhtml:
+        * svg/custom/svg-fonts-in-html.html:
+        * svg/custom/svg-fonts-segmented.xhtml:
+        * svg/custom/svg-fonts-with-no-element-reference.html:
+        * svg/custom/svg-fonts-without-missing-glyph.xhtml:
+        * svg/text/text-overflow-ellipsis-svgfont.html:
+
 2011-12-02  David Tseng  <dtseng@google.com>
 
         Send an AXCheckedStateChanged notification when the aria-checked attribute changes.
index 22642629d8f43aa563821048249f167b560bcf59..0e591d1426b7fa53719ba37b59e4f07c9999e468 100644 (file)
@@ -2,6 +2,10 @@
   <head>
   <!-- The Ahem font rendered in this test should be displayed black, not blue. -->
     <style>
+      @font-face {
+        font-family: 'Ahem';
+        src: url('resources/Ahem.ttf');
+      }
       div {
         display: block;
         font-family: Ahem;
index b108eb5939ded7c12cae91e0d410d02a74748265..c3e7a76bde4ef3cb9890d0ee64f8585f576eb82f 100644 (file)
@@ -37,25 +37,17 @@ WebKit nightly adding insane height to div at random.</p>
 </div>
 
 <script>
-if (window.layoutTestController) {
+if (window.layoutTestController)
     layoutTestController.dumpAsText();
-    layoutTestController.waitUntilDone();
-}
 
 function test()
 {
-    document.body.offsetTop;
-    setTimeout(function() {
-        var totalHeight = document.defaultView.getComputedStyle(document.getElementById("test"), null).getPropertyCSSValue("height");
-        totalHeight = totalHeight.getFloatValue(CSSPrimitiveValue.CSS_PX);
-        if (totalHeight > 150 && totalHeight < 300)
-            document.getElementById("result").innerHTML = "PASS";
-        else
-            document.getElementById("result").innerHTML = "FAIL: " + totalHeight + "px";
-
-        if (window.layoutTestController)
-            layoutTestController.notifyDone();
-    }, 100);
+    var totalHeight = document.defaultView.getComputedStyle(document.getElementById("test"), null).getPropertyCSSValue("height");
+    totalHeight = totalHeight.getFloatValue(CSSPrimitiveValue.CSS_PX);
+    if (totalHeight > 150 && totalHeight < 300)
+        document.getElementById("result").innerHTML = "PASS";
+    else
+        document.getElementById("result").innerHTML = "FAIL: " + totalHeight + "px";
 }
 </script>
 </body>
index f072a14a0f4a767acbea0da9c99525d6ffc0a639..bd580a2450d34b4c19d1e02dc98d784572974282 100644 (file)
 <div style="font-family: webkit-four;">
     AHEM <i>AHEM</i>
 </div>
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.body.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
index 0183da1bacaa6862dd919559353b1c9224a369a8..c678f5567eb8cabb98ff7a704dce444398f4f59b 100644 (file)
         _fail
     </div>
     <script>
-        if (window.layoutTestController) {
-            layoutTestController.waitUntilDone();
-            document.body.offsetTop;
-            setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-        }
+        document.body.offsetTop;
     </script>
 </body>
index 31a5aec123ea1e068d1d91216590abe93a76bb39..da413cb0844490f4f1a9ec8aca4476aacd161a9e 100644 (file)
@@ -8,7 +8,7 @@
         div { width: 100px; height: 100px; background-color: red; font-family: 'remote'; font-size: 20px; color: green; }
     </style>
 </head>
-<body>
+<body onload="finished()">
     <div>
         FAIL_<br>
         XXXXX<br>
         _FAIL<br>
     </div>
     <script>
-        if (window.layoutTestController) {
+        if (window.layoutTestController)
             layoutTestController.waitUntilDone();
-            document.body.offsetTop;
-            setTimeout(function() { layoutTestController.notifyDone(); }, 100);
+
+        // Kick off loading of the font
+        document.body.offsetTop;
+
+        function finished()
+        {
+            if (window.layoutTestController)
+                layoutTestController.notifyDone();
         }
     </script>
 </body>
index bee473eea51005893630a427ada243fab3f64375..f1f83ca09b5b3b6ef72d3625abc749fe7030973b 100644 (file)
@@ -8,10 +8,3 @@
 <p>This test tries to render the following text with Ahem, loaded from a WOFF file. The text below should be a series of black boxes.</p>
 
 <p style="font-family: family1; font-size: 4em;">Failure</p>
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.body.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
index cb0641d1769c5d3303967d7e86ff4a357c686679..314c0c59b910b9d3e1d5d1d8764956acab1c03fa 100644 (file)
@@ -57,6 +57,10 @@ p {
 
 </style>
   
+<script type="text/javascript">
+
+</script>
+
 </head>
 <body>
 
@@ -65,12 +69,5 @@ p {
 <div class="basic d1 vert"><p>第一段落 Paragraph 1</p><p>第二段落 Paragraph 2</p></div>
 </div>
 
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.body.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
 </body>
 </html>
index 5ec28d89b134aab1495d5af43c1a39be78eeeeff..d12210214ec7599e0d0f15e46d9b6059031a492c 100644 (file)
     <text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
       text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
   </g>-->
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.documentElement.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
 </svg>
index 085bd19fdbcdf5a056db8c01cf2da35754780ba2..f3f996e5d5030c14fa29b65d4128d192f75d677d 100644 (file)
        </g>
        <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.7 $</text>
        <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
-        <script>
-            if (window.layoutTestController) {
-                layoutTestController.waitUntilDone();
-                document.documentElement.offsetTop;
-                setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-            }
-        </script>
 </svg>
index 2718aa82b43ee21fa909d0c271b4d67de9df7175..cd9f8c4f924c146cdb96b8c92082bae04f67c0ec 100644 (file)
     <!-- 'a', ' ', 'o' from TestFont2, '&#xbe2;' can't be rendered, as none of the default fonts defines it -->
     <span style='font-family: TestFont2; font-size: 40px; '>a &#xbe2; o</span><br/>
 </p>
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.documentElement.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
+
 </body>
 </html>
index 74705a671ac6ed6e7ea6fdc2856fc4c206afb226..13c01fac8f41eb53313c54becf6d4cd88e1a4f64 100644 (file)
 <!-- Add a background image to each and use width and height to control sizing, place with absolute positioning -->\r
 <div id="extraDiv1"><span></span></div><div id="extraDiv2"><span></span></div><div id="extraDiv3"><span></span></div>\r
 <div id="extraDiv4"><span></span></div><div id="extraDiv5"><span></span></div><div id="extraDiv6"><span></span></div>\r
-<script>\r
-    if (window.layoutTestController) {\r
-        layoutTestController.waitUntilDone();\r
-        document.documentElement.offsetTop;\r
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);\r
-    }\r
-</script>\r
+\r
 </body>\r
 </html>\r
index 7d8244f3e7983541834213b0d57cc4a7362319e2..4288964d960bb37b7674f308a0cc279ad6c8db9a 100644 (file)
 
 <!-- 'ABC' should be rendered using Times, 'def' using Courier, 'o' using the SVG Font, and 'O' again by Times -->
 <p style='font-family: TestFont; font-size: 40px; '>ABCdefoooO</p>
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.documentElement.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
+
 </body>
 </html>
index 8ea400aee797d3d8c6ad0ebd59713a0f586ef4fa..9aa030393b535bf5827c382058b0f33191179cfc 100644 (file)
 <body>\r
 <p class="first">This text should be rendered with a first font.</p>\r
 <p class="second">This text should be rendered with a second font.</p>\r
-<script>\r
-    if (window.layoutTestController) {\r
-        layoutTestController.waitUntilDone();\r
-        document.documentElement.offsetTop;\r
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);\r
-    }\r
-</script>\r
 </body>\r
 \r
 </html>\r
index b304f0fd363c8a54ded7ae3c89379ca93d19ba5c..b7cc4fc694c6461a1b75cbf14cd265c73f925bb3 100644 (file)
 <p class="target">AXX</p>
 <p class="target">XXX</p>
 <p class="target">AAA</p>
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.documentElement.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
+
 </body>
 </html>
index 1cc58ab8c3d43e608ae412674131ce5773b39c2a..a141441452547af7b683e75dff123ddaa4e89915 100644 (file)
@@ -36,12 +36,5 @@ Pass if some text is shown followed by an ellipsis (NOT just the ellipsis by its
        abc abc abc abc abc abc abc abc abc abc
 </div>
 
-<script>
-    if (window.layoutTestController) {
-        layoutTestController.waitUntilDone();
-        document.documentElement.offsetTop;
-        setTimeout(function() { layoutTestController.notifyDone(); }, 100);
-    }
-</script>
 </body>
 </html>
index 7c382a211a18d2239541e84e04862192aaaf13f3..ea2ef9adc217b23d88efa833d0fa2684f3d3a29e 100644 (file)
@@ -1,3 +1,40 @@
+2011-12-02  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10520670> REGRESSION (r91738): didFinishLoad is called before custom fonts have finished loading
+        https://bugs.webkit.org/show_bug.cgi?id=73688
+
+        Reviewed by Darin Adler.
+
+        The problem was that after CSSFontFaceSource::getFontData() had scheduled a 0-delay timer to
+        begin loading the font, but before that timer fired, the subresource loader appeared to have
+        had no resources waiting to be loaded, and therefore didFinishLoad could be called. This change
+        reworks the fix for <http://webkit.org/b/65123> so that while the load is still started on a
+        0-dealy timer, the subresource loader’s request count is incremented immediately, preventing
+        it from hitting 0 while the font load is scheduled to begin. The delayed load mechanism is
+        moved from CSSFontFaceSource into CSSFontSelector in order to safely handle the possibility of
+        the latter being decommissioned while waiting for font loading to begin.
+
+        * css/CSSFontFaceSource.cpp:
+        (WebCore::CSSFontFaceSource::CSSFontFaceSource): Removed initializer for m_loadStartTimer.
+        (WebCore::CSSFontFaceSource::~CSSFontFaceSource): Removed stopping of m_loadStartTimer.
+        (WebCore::CSSFontFaceSource::getFontData): Replaced code to schedule loading on a timer with
+        a call to CSSFontSelector::beginLoadingFontSoon.
+        * css/CSSFontFaceSource.h: Removed m_loadStartTimer and m_fontSelector member variables.
+        * css/CSSFontSelector.cpp:
+        (WebCore::CSSFontSelector::CSSFontSelector): Added initialized for m_beginLoadingTimer.
+        (WebCore::CSSFontSelector::~CSSFontSelector): Added call to clearDocument(), to deal with
+        anything remaining in m_fontsToBeginLoading at this time.
+        (WebCore::CSSFontSelector::clearDocument): Now stops m_beginLoadingTimer and balances
+        incrementRequestCount() calls for anything remaining in m_fontsToBeginLoading.
+        (WebCore::CSSFontSelector::beginLoadingFontSoon): Added. Schedules the actual call to
+        CachedFont::beginLoadingIfNeeded on a 0-delay timer, and meanwhile increments the request count
+        on the CachedResourceLoader, which ensures that didFinishLoad will not be called while waiting
+        for the timer to fire.
+        (WebCore::CSSFontSelector::beginLoadTimerFired): Added. Actually calls
+        CachedFont::beginLoadIfNeeded and balances the incrementRequestCount() made when the timer was
+        scheduled.
+        * css/CSSFontSelector.h:
+
 2011-12-02  David Tseng  <dtseng@google.com>
 
         Send an AXCheckedStateChanged notification when the aria-checked attribute changes.
index 5d1b12aebdc563eedcff9cee60a832a6c3974873..ac05d68ca74842e6c2e64dbf7298517250635811 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2010, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -51,7 +51,6 @@ CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
     : m_string(str)
     , m_font(font)
     , m_face(0)
-    , m_loadStartTimer(this, &CSSFontFaceSource::startLoadingTimerFired)
 #if ENABLE(SVG_FONTS)
     , m_hasExternalSVGFont(false)
 #endif
@@ -62,7 +61,6 @@ CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
 
 CSSFontFaceSource::~CSSFontFaceSource()
 {
-    m_loadStartTimer.stop();
     if (m_font)
         m_font->removeClient(this);
     pruneTable();
@@ -177,11 +175,9 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
 #endif
         }
     } else {
-        // Kick off the load now. Do it on a zero-delay timer rather than synchronously, because we may be in
-        // the middle of layout, and the loader may invoke arbitrary delegate or event handler code.
-        m_fontSelector = fontSelector;
-        if (!m_loadStartTimer.isActive())
-            m_loadStartTimer.startOneShot(0);
+        // Kick off the load. Do it soon rather than now, because we may be in the middle of layout,
+        // and the loader may invoke arbitrary delegate or event handler code.
+        fontSelector->beginLoadingFontSoon(m_font.get());
 
         // This temporary font is not retained and should not be returned.
         FontCachePurgePreventer fontCachePurgePreventer;
@@ -198,17 +194,6 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
     return fontDataRawPtr;
 }
 
-void CSSFontFaceSource::startLoadingTimerFired(Timer<WebCore::CSSFontFaceSource>*)
-{
-    ASSERT(m_font);
-    ASSERT(m_fontSelector);
-
-    if (CachedResourceLoader* cachedResourceLoader = m_fontSelector->cachedResourceLoader())
-        m_font->beginLoadIfNeeded(cachedResourceLoader);
-
-    m_fontSelector = nullptr;
-}
-
 #if ENABLE(SVG_FONTS)
 SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
 {
index 99db592158af4d8f7d90f9191f57b6eccc2b8f28..e36fe45429a886fdf678b63f40a0f30583dee449 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -78,9 +78,6 @@ private:
     CSSFontFace* m_face; // Our owning font face.
     HashMap<unsigned, SimpleFontData*> m_fontDataTable; // The hash key is composed of size synthetic styles.
 
-    Timer<CSSFontFaceSource> m_loadStartTimer;
-    RefPtr<CSSFontSelector> m_fontSelector;
-
 #if ENABLE(SVG_FONTS)
     RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
     RefPtr<SVGFontElement> m_externalSVGFontElement;
index daa19321cc0e7a35f87c6ad615fc983904a19edf..4f4349979e24665598506a2430e506b659d6dde2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,7 @@ namespace WebCore {
 
 CSSFontSelector::CSSFontSelector(Document* document)
     : m_document(document)
+    , m_beginLoadingTimer(this, &CSSFontSelector::beginLoadTimerFired)
 {
     // FIXME: An old comment used to say there was no need to hold a reference to m_document
     // because "we are guaranteed to be destroyed before the document". But there does not
@@ -71,6 +72,7 @@ CSSFontSelector::CSSFontSelector(Document* document)
 
 CSSFontSelector::~CSSFontSelector()
 {
+    clearDocument();
     fontCache()->removeClient(this);
     deleteAllValues(m_fontFaces);
     deleteAllValues(m_locallyInstalledFontFaces);
@@ -82,11 +84,6 @@ bool CSSFontSelector::isEmpty() const
     return m_fonts.isEmpty();
 }
 
-CachedResourceLoader* CSSFontSelector::cachedResourceLoader() const
-{
-    return m_document ? m_document->cachedResourceLoader() : 0;
-}
-
 void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule)
 {
     // Obtain the font-family property and the src property.  Both must be defined.
@@ -580,4 +577,51 @@ FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, c
     return face->getFontData(fontDescription);
 }
 
+void CSSFontSelector::clearDocument()
+{
+    if (!m_document) {
+        ASSERT(!m_beginLoadingTimer.isActive());
+        ASSERT(m_fontsToBeginLoading.isEmpty());
+        return;
+    }
+
+    m_beginLoadingTimer.stop();
+
+    CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
+    for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) {
+        // Balances incrementRequestCount() in beginLoadingFontSoon().
+        cachedResourceLoader->decrementRequestCount(m_fontsToBeginLoading[i].get());
+    }
+
+    m_fontsToBeginLoading.clear();
+
+    m_document = 0;
+}
+
+void CSSFontSelector::beginLoadingFontSoon(CachedFont* font)
+{
+    if (!m_document)
+        return;
+
+    m_fontsToBeginLoading.append(font);
+    // Increment the request count now, in order to prevent didFinishLoad from being dispatched
+    // after this font has been requested but before it began loading. Balanced by
+    // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
+    m_document->cachedResourceLoader()->incrementRequestCount(font);
+    m_beginLoadingTimer.startOneShot(0);
+}
+
+void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
+{
+    Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading;
+    fontsToBeginLoading.swap(m_fontsToBeginLoading);
+
+    CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
+    for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
+        fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader);
+        // Balances incrementRequestCount() in beginLoadingFontSoon().
+        cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get());
+    }
+}
+
 }
index e7ea02b158c72f480d6bd13f254666017742c9db..a42062afe9a4c8ab6680726cd43726f4fbfb0a58 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,7 +26,9 @@
 #ifndef CSSFontSelector_h
 #define CSSFontSelector_h
 
+#include "CachedResourceHandle.h"
 #include "FontSelector.h"
+#include "Timer.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -38,8 +40,8 @@ namespace WebCore {
 class CSSFontFace;
 class CSSFontFaceRule;
 class CSSSegmentedFontFace;
+class CachedFont;
 class Document;
-class CachedResourceLoader;
 class FontDescription;
 
 class CSSFontSelector : public FontSelector {
@@ -52,7 +54,7 @@ public:
 
     virtual FontData* getFontData(const FontDescription& fontDescription, const AtomicString& familyName);
 
-    void clearDocument() { m_document = 0; }
+    void clearDocument();
 
     void addFontFaceRule(const CSSFontFaceRule*);
 
@@ -61,23 +63,28 @@ public:
 
     bool isEmpty() const;
 
-    CachedResourceLoader* cachedResourceLoader() const;
-
     virtual void registerForInvalidationCallbacks(FontSelectorClient*);
     virtual void unregisterForInvalidationCallbacks(FontSelectorClient*);
 
     Document* document() const { return m_document; }
 
+    void beginLoadingFontSoon(CachedFont*);
+
 private:
     CSSFontSelector(Document*);
 
     void dispatchInvalidationCallbacks();
 
+    void beginLoadTimerFired(Timer<CSSFontSelector>*);
+
     Document* m_document;
     HashMap<String, Vector<RefPtr<CSSFontFace> >*, CaseFoldingHash> m_fontFaces;
     HashMap<String, Vector<RefPtr<CSSFontFace> >*, CaseFoldingHash> m_locallyInstalledFontFaces;
     HashMap<String, HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >*, CaseFoldingHash> m_fonts;
     HashSet<FontSelectorClient*> m_clients;
+
+    Vector<CachedResourceHandle<CachedFont> > m_fontsToBeginLoading;
+    Timer<CSSFontSelector> m_beginLoadingTimer;
 };
 
 } // namespace WebCore