2010-06-15 Dmitry Titov <dimich@chromium.org>
authoryuzo@google.com <yuzo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Jun 2010 03:23:12 +0000 (03:23 +0000)
committeryuzo@google.com <yuzo@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Jun 2010 03:23:12 +0000 (03:23 +0000)
        Not reviewed, updating Chromium test expectations.

        * platform/chromium/test_expectations.txt:
2010-06-15  Mark Rowe  <mrowe@apple.com>

        Rubber-stamped by David Harrison.

        sqlite3_prepare16_v2 is not documented as always setting "tail" during error cases.
        Explicitly initialize it to null, just to be safe.

        * platform/sql/SQLiteStatement.cpp:
        (WebCore::SQLiteStatement::prepare):
2010-06-10  Yuzo Fujishima  <yuzo@google.com>

        Reviewed by Shinichiro Hamaji.

        Implement render style selection for pages to support CSS3 Paged Media.
        https://bugs.webkit.org/show_bug.cgi?id=35961

        * Misc/WebCoreStatistics.h:
        * Misc/WebCoreStatistics.mm:
        (-[WebFrame pageProperty:propertyName:]):
2010-06-10  Yuzo Fujishima  <yuzo@google.com>

        Reviewed by Shinichiro Hamaji.

        Implement render style selection for pages to support CSS3 Paged Media.
        https://bugs.webkit.org/show_bug.cgi?id=35961

        * DumpRenderTree/LayoutTestController.cpp:
        (parsePagePropertyParameters):
        (pagePropertyCallback):
        (LayoutTestController::staticFunctions):
        * DumpRenderTree/LayoutTestController.h:
        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
        (LayoutTestController::pageProperty):
        * DumpRenderTree/mac/LayoutTestControllerMac.mm:
        (LayoutTestController::pageProperty):
        * DumpRenderTree/win/LayoutTestControllerWin.cpp:
        (LayoutTestController::pageProperty):

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

28 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/chromium/test_expectations.txt
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
LayoutTests/printing/page-rule-selection-expected.txt [new file with mode: 0644]
LayoutTests/printing/page-rule-selection.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/css/CSSGrammar.y
WebCore/css/CSSSelector.cpp
WebCore/css/CSSSelector.h
WebCore/css/CSSStyleSelector.cpp
WebCore/css/CSSStyleSelector.h
WebCore/css/html.css
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/page/PrintContext.cpp
WebCore/page/PrintContext.h
WebKit/mac/ChangeLog
WebKit/mac/Misc/WebCoreStatistics.h
WebKit/mac/Misc/WebCoreStatistics.mm
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/LayoutTestController.cpp
WebKitTools/DumpRenderTree/LayoutTestController.h
WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp

index 029280e..af524b4 100644 (file)
 
         Reviewed by Shinichiro Hamaji.
 
+        Implement render style selection for pages to support CSS3 Paged Media.
+        https://bugs.webkit.org/show_bug.cgi?id=35961
+
+        * platform/chromium/test_expectations.txt:
+        * platform/gtk/Skipped:
+        * platform/qt/Skipped:
+        * platform/win/Skipped:
+        * printing/page-rule-selection-expected.txt: Added.
+        * printing/page-rule-selection.html: Added.
+
+2010-06-10  Yuzo Fujishima  <yuzo@google.com>
+
+        Reviewed by Shinichiro Hamaji.
+
         Fix Bug 40452: REGRESSION: printing is broken if stylesheet has @page
         https://bugs.webkit.org/show_bug.cgi?id=40452
 
index c5d7ad1..f2ab17d 100644 (file)
@@ -2917,3 +2917,6 @@ BUG46603 : fast/frames/lots-of-objects.html = PASS TIMEOUT
 
 // Whitespace difference between TestShell and DRT.
 BUGDARIN : fast/history/history-back-within-subframe.html = TEXT
+
+// LayoutTestController::pageProperty is not implemented for Chromium yet.
+BUGWK35961 : printing/page-rule-selection.html = TEXT
index c919592..536fbfd 100644 (file)
@@ -5937,3 +5937,6 @@ fast/forms/slider-transformed.html
 # of the slider thumb in GTK+ themes.
 fast/forms/slider-mouse-events.html
 fast/forms/slider-zoomed.html
+
+# LayoutTestController::pageProperty is not implemented for GTK yet.
+printing/page-rule-selection.html
index 5b68c48..e30b1a9 100644 (file)
@@ -854,6 +854,10 @@ fast/ruby/rubyDOM-remove-rt2.html
 fast/ruby/rubyDOM-remove-text1.html
 fast/ruby/rubyDOM-remove-text2.html
 
+# Missing LayoutTestController::pageProperty.
+# https://bugs.webkit.org/show_bug.cgi?id=35961
+printing/page-rule-selection.html
+
 # ============================================================================= #
 # ------- failing editing/input tests
 # ============================================================================= #
index ff42b2c..7fb9aad 100644 (file)
@@ -893,3 +893,6 @@ storage/indexeddb
 # This port doesn't support DeviceOrientation.
 fast/dom/DeviceOrientation
 fast/dom/Window/window-properties-on-device-orientation.html
+
+# LayoutTestController::pageProperty is not implemented for WIN yet.
+printing/page-rule-selection.html
diff --git a/LayoutTests/printing/page-rule-selection-expected.txt b/LayoutTests/printing/page-rule-selection-expected.txt
new file mode 100644 (file)
index 0000000..c6f2abd
--- /dev/null
@@ -0,0 +1,55 @@
+This tests page style selection.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Default margin is 1in = 96px.
+PASS layoutTestController.pageProperty('margin-left', 0) is "96"
+PASS layoutTestController.pageProperty('margin-left', 1) is "96"
+PASS layoutTestController.pageProperty('margin-left', 2) is "96"
+PASS layoutTestController.pageProperty('margin-left', 3) is "96"
+PASS layoutTestController.pageProperty('margin-left', 4) is "96"
+Set margin to 200px via user style sheet.
+PASS layoutTestController.pageProperty('margin-left', 0) is "200"
+PASS layoutTestController.pageProperty('margin-left', 1) is "200"
+PASS layoutTestController.pageProperty('margin-left', 2) is "200"
+PASS layoutTestController.pageProperty('margin-left', 3) is "200"
+PASS layoutTestController.pageProperty('margin-left', 4) is "200"
+Set margin to 100px.
+PASS layoutTestController.pageProperty('margin-left', 0) is "100"
+PASS layoutTestController.pageProperty('margin-left', 1) is "100"
+PASS layoutTestController.pageProperty('margin-left', 2) is "100"
+PASS layoutTestController.pageProperty('margin-left', 3) is "100"
+PASS layoutTestController.pageProperty('margin-left', 4) is "100"
+Set margin for right pages to 50px. The first page is a right page.
+PASS layoutTestController.pageProperty('margin-left', 0) is "50"
+PASS layoutTestController.pageProperty('margin-left', 1) is "100"
+PASS layoutTestController.pageProperty('margin-left', 2) is "50"
+PASS layoutTestController.pageProperty('margin-left', 3) is "100"
+PASS layoutTestController.pageProperty('margin-left', 4) is "50"
+Set margin for left pages to 75px.
+PASS layoutTestController.pageProperty('margin-left', 0) is "50"
+PASS layoutTestController.pageProperty('margin-left', 1) is "75"
+PASS layoutTestController.pageProperty('margin-left', 2) is "50"
+PASS layoutTestController.pageProperty('margin-left', 3) is "75"
+PASS layoutTestController.pageProperty('margin-left', 4) is "50"
+Set margin for the first page to 125px.
+PASS layoutTestController.pageProperty('margin-left', 0) is "125"
+PASS layoutTestController.pageProperty('margin-left', 1) is "75"
+PASS layoutTestController.pageProperty('margin-left', 2) is "50"
+PASS layoutTestController.pageProperty('margin-left', 3) is "75"
+PASS layoutTestController.pageProperty('margin-left', 4) is "50"
+Change the document direction to RTL. This makes the first page a left page.
+PASS layoutTestController.pageProperty('margin-left', 0) is "125"
+PASS layoutTestController.pageProperty('margin-left', 1) is "50"
+PASS layoutTestController.pageProperty('margin-left', 2) is "75"
+PASS layoutTestController.pageProperty('margin-left', 3) is "50"
+PASS layoutTestController.pageProperty('margin-left', 4) is "75"
+Check font update and line height override.
+PASS layoutTestController.pageProperty('line-height', 0) is "180"
+PASS layoutTestController.pageProperty('font-family', 0) is "Arial"
+PASS layoutTestController.pageProperty('font-size', 0) is "30"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/printing/page-rule-selection.html b/LayoutTests/printing/page-rule-selection.html
new file mode 100644 (file)
index 0000000..0b5aaa0
--- /dev/null
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html id="html_element">
+<head id="head_element">
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css">
+<script src="../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+    description("This tests page style selection.");
+
+    function appendStyle(styleString)
+    {
+        var styleElement = document.createElement("style");
+        styleElement.innerHTML = styleString;
+        document.getElementById("head_element").appendChild(styleElement);
+    }
+
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+
+        debug("Default margin is 1in = 96px.");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "96");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "96");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "96");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "96");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "96");
+
+        debug("Set margin to 200px via user style sheet.");
+        layoutTestController.addUserStyleSheet("@page { margin:200px; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "200");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "200");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "200");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "200");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "200");
+
+        debug("Set margin to 100px.");
+        appendStyle("@page { margin:100px; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "100");
+
+        debug("Set margin for right pages to 50px. The first page is a right page.");
+        appendStyle("@page :right { margin:50px; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "100");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "50");
+
+        debug("Set margin for left pages to 75px.");
+        appendStyle("@page :left { margin:75px; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "75");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "75");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "50");
+
+        debug("Set margin for the first page to 125px.");
+        appendStyle("@page :first { margin:125px; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "125");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "75");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "75");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "50");
+
+        debug("Change the document direction to RTL. This makes the first page a left page.");
+        document.getElementById("html_element").setAttribute("dir", "rtl");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 0)", "125");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 1)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 2)", "75");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 3)", "50");
+        shouldBeEqualToString("layoutTestController.pageProperty('margin-left', 4)", "75");
+
+        debug("Check font update and line height override.");
+        appendStyle("@page { line-height:1em; }");
+        appendStyle("@page { font-family:Futura; }");
+        appendStyle("@page { font:15px/6em Arial; }");
+        appendStyle("@page { zoom:200%; }");
+        shouldBeEqualToString("layoutTestController.pageProperty('line-height', 0)", "180");
+        shouldBeEqualToString("layoutTestController.pageProperty('font-family', 0)", "Arial");
+        shouldBeEqualToString("layoutTestController.pageProperty('font-size', 0)", "30");
+        appendStyle("@page { zoom:100%; }");
+    } else {
+        testFailed("This test can be run only with window.layoutTestController");
+    }
+    var successfullyParsed = true;
+</script>
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index b245f52..addf32a 100644 (file)
 
         Reviewed by Shinichiro Hamaji.
 
+        Implement render style selection for pages to support CSS3 Paged Media.
+        https://bugs.webkit.org/show_bug.cgi?id=35961
+
+        Test: printing/page-rule-selection.html
+
+        * WebCore.base.exp:
+        * css/CSSGrammar.y:
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::specificity):
+        (WebCore::CSSSelector::specificityForPage):
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::CSSSelector):
+        (WebCore::CSSSelector::isForPage):
+        (WebCore::CSSSelector::setForPage):
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::styleForPage):
+        (WebCore::CSSStyleSelector::matchPageRules):
+        (WebCore::CSSStyleSelector::matchPageRulesForList):
+        (WebCore::CSSStyleSelector::isLeftPage):
+        (WebCore::CSSStyleSelector::isFirstPage):
+        (WebCore::CSSStyleSelector::pageName):
+        * css/CSSStyleSelector.h:
+        (WebCore::CSSStyleSelector::isRightPage):
+        * css/html.css:
+        (@page):
+        * dom/Document.cpp:
+        (WebCore::Document::styleForPage):
+        * dom/Document.h:
+        * page/PrintContext.cpp:
+        (WebCore::PrintContext::pageProperty):
+        * page/PrintContext.h:
+
+
+2010-06-10  Yuzo Fujishima  <yuzo@google.com>
+
+        Reviewed by Shinichiro Hamaji.
+
         Fix Bug 40452: REGRESSION: printing is broken if stylesheet has @page
         https://bugs.webkit.org/show_bug.cgi?id=40452
 
index 0cec00b..e469d1d 100644 (file)
@@ -248,6 +248,7 @@ __ZN7WebCore12IconDatabase4openERKNS_6StringE
 __ZN7WebCore12IconDatabase5closeEv
 __ZN7WebCore12IconDatabase9setClientEPNS_18IconDatabaseClientE
 __ZN7WebCore12PluginWidget14invalidateRectERKNS_7IntRectE
+__ZN7WebCore12PrintContext12pagePropertyEPNS_5FrameEPKci
 __ZN7WebCore12PrintContext13numberOfPagesEPNS_5FrameERKNS_9FloatSizeE
 __ZN7WebCore12PrintContext20pageNumberForElementEPNS_7ElementERKNS_9FloatSizeE
 __ZN7WebCore12PrintContext28computePageRectsWithPageSizeERKNS_9FloatSizeEb
index 06c6d01..26b2ba8 100644 (file)
@@ -778,19 +778,25 @@ page_selector:
         CSSParser* p = static_cast<CSSParser*>(parser);
         $$ = p->createFloatingSelector();
         $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+        $$->setForPage();
     }
     | IDENT pseudo_page {
         CSSParser* p = static_cast<CSSParser*>(parser);
         $$ = $2;
-        if ($$)
+        if ($$) {
             $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+            $$->setForPage();
+        }
     }
     | pseudo_page {
         $$ = $1;
+        if ($$)
+            $$->setForPage();
     }
     | /* empty */ {
         CSSParser* p = static_cast<CSSParser*>(parser);
         $$ = p->createFloatingSelector();
+        $$->setForPage();
     }
     ;
 
index e45bf4c..8e98a3f 100644 (file)
@@ -37,6 +37,9 @@ using namespace HTMLNames;
 
 unsigned int CSSSelector::specificity()
 {
+    if (m_isForPage)
+        return specificityForPage();
+
     // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
     // isn't quite correct.
     int s = (m_tag.localName() == starAtom ? 0 : 1);
@@ -66,6 +69,27 @@ unsigned int CSSSelector::specificity()
     return s & 0xffffff;
 }
 
+unsigned CSSSelector::specificityForPage()
+{
+    // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context
+    unsigned s = (m_tag.localName() == starAtom ? 0 : 4);
+
+    switch (pseudoType()) {
+    case PseudoFirstPage:
+        s += 2;
+        break;
+    case PseudoLeftPage:
+    case PseudoRightPage:
+        s += 1;
+        break;
+    case PseudoNotParsed:
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return s;
+}
+
 PseudoId CSSSelector::pseudoId(PseudoType type)
 {
     switch (type) {
index 11d30b1..eb07078 100644 (file)
@@ -39,6 +39,7 @@ namespace WebCore {
             , m_parsedNth(false)
             , m_isLastInSelectorList(false)
             , m_hasRareData(false)
+            , m_isForPage(false)
             , m_tag(anyQName())
         {
         }
@@ -50,6 +51,7 @@ namespace WebCore {
             , m_parsedNth(false)
             , m_isLastInSelectorList(false)
             , m_hasRareData(false)
+            , m_isForPage(false)
             , m_tag(qName)
         {
         }
@@ -253,6 +255,9 @@ namespace WebCore {
         void setLastInSelectorList() { m_isLastInSelectorList = true; }
         bool isSimple() const;
 
+        bool isForPage() const { return m_isForPage; }
+        void setForPage() { m_isForPage = true; }
+
         unsigned m_relation           : 3; // enum Relation
         mutable unsigned m_match      : 4; // enum Match
         mutable unsigned m_pseudoType : 8; // PseudoType
@@ -261,7 +266,9 @@ namespace WebCore {
         bool m_parsedNth              : 1; // Used for :nth-* 
         bool m_isLastInSelectorList   : 1;
         bool m_hasRareData            : 1;
+        bool m_isForPage              : 1;
 
+        unsigned specificityForPage();
         void extractPseudoType() const;
 
         struct RareData : Noncopyable {
index e4f28aa..bff07ba 100644 (file)
@@ -1548,6 +1548,36 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo,
     return m_style.release();
 }
 
+PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
+{
+    initForStyleResolve(m_checker.m_document->body());
+
+    m_style = RenderStyle::create();
+    m_style->inheritFrom(m_rootElementStyle);
+
+    const bool isLeft = isLeftPage(pageIndex);
+    const bool isFirst = isFirstPage(pageIndex);
+    const String page = pageName(pageIndex);
+    matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
+    matchPageRules(m_userStyle, isLeft, isFirst, page);
+    matchPageRules(m_authorStyle, isLeft, isFirst, page);
+    m_lineHeightValue = 0;
+    applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
+
+    // If our font got dirtied, go ahead and update it now.
+    if (m_fontDirty)
+        updateFont();
+
+    // Line-height is set when we are sure we decided on the font-size
+    if (m_lineHeightValue)
+        applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
+
+    applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
+
+    // Now return the style.
+    return m_style.release();
+}
+
 #if ENABLE(DATAGRID)
 
 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*)
@@ -2889,6 +2919,74 @@ void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int e
     }
 }
 
+void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+    m_matchedRules.clear();
+
+    if (!rules)
+        return;
+
+    matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName);
+
+    // If we didn't match any rules, we're done.
+    if (m_matchedRules.isEmpty())
+        return;
+
+    // Sort the set of matched rules.
+    sortMatchedRules(0, m_matchedRules.size());
+
+    // Now transfer the set of matched rules over to our list of decls.
+    for (unsigned i = 0; i < m_matchedRules.size(); i++)
+        addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
+}
+
+void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+    if (!rules)
+        return;
+
+    for (CSSRuleData* d = rules->first(); d; d = d->next()) {
+        CSSStyleRule* rule = d->rule();
+        const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
+        if (selectorLocalName != starAtom && selectorLocalName != pageName)
+            continue;
+        CSSSelector::PseudoType pseudoType = d->selector()->pseudoType();
+        if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
+            || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
+            || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
+            continue;
+
+        // If the rule has no properties to apply, then ignore it.
+        CSSMutableStyleDeclaration* decl = rule->declaration();
+        if (!decl || !decl->length())
+            continue;
+
+        // Add this rule to our list of matched rules.
+        addMatchedRule(d);
+    }
+}
+
+bool CSSStyleSelector::isLeftPage(int pageIndex) const
+{
+    bool isFirstPageLeft = false;
+    if (m_rootElementStyle->direction() == RTL)
+        isFirstPageLeft = true;
+
+    return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
+}
+
+bool CSSStyleSelector::isFirstPage(int pageIndex) const
+{
+    // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
+    return (!pageIndex);
+}
+
+String CSSStyleSelector::pageName(int /* pageIndex */) const
+{
+    // FIXME: Implement page index to page name mapping.
+    return "";
+}
+
 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
 {
     CounterDirectiveMap& map = style->accessCounterDirectives();
index fd37c85..05cd109 100644 (file)
@@ -93,6 +93,8 @@ public:
 
         PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle = 0, bool matchVisitedPseudoClass = false);
 
+        PassRefPtr<RenderStyle> styleForPage(int pageIndex);
+
         static PassRefPtr<RenderStyle> styleForDocument(Document*);
 
 #if ENABLE(DATAGRID)
@@ -180,6 +182,13 @@ public:
 
         template <bool firstPass>
         void applyDeclarations(bool important, int startIndex, int endIndex);
+
+        void matchPageRules(CSSRuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
+        void matchPageRulesForList(CSSRuleDataList*, bool isLeftPage, bool isFirstPage, const String& pageName);
+        bool isLeftPage(int pageIndex) const;
+        bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
+        bool isFirstPage(int pageIndex) const;
+        String pageName(int pageIndex) const;
         
         CSSRuleSet* m_authorStyle;
         CSSRuleSet* m_userStyle;
index b4bb05a..fe28528 100644 (file)
@@ -683,4 +683,11 @@ iframe {
     border: 2px inset
 }
 
+/* page */
+
+@page {
+    /* FIXME: Define the right default values for page properties. */
+    margin: 1in;
+}
+
 /* noscript is handled internally, as it depends on settings */
index 366fb0f..8f91571 100644 (file)
@@ -1496,6 +1496,12 @@ PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Elem
     return style.release();
 }
 
+PassRefPtr<RenderStyle> Document::styleForPage(int pageIndex)
+{
+    RefPtr<RenderStyle> style = styleSelector()->styleForPage(pageIndex);
+    return style.release();
+}
+
 void Document::createStyleSelector()
 {
     bool matchAuthorAndUserStyles = true;
index 92b3a7f..bc12da3 100644 (file)
@@ -482,6 +482,7 @@ public:
     void updateLayout();
     void updateLayoutIgnorePendingStylesheets();
     PassRefPtr<RenderStyle> styleForElementIgnoringPendingStylesheets(Element*);
+    PassRefPtr<RenderStyle> styleForPage(int pageIndex);
     static void updateStyleForAllDocuments(); // FIXME: Try to reduce the # of calls to this function.
     DocLoader* docLoader() { return m_docLoader.get(); }
 
index bc4b31a..8ff8a62 100644 (file)
@@ -199,6 +199,25 @@ int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSi
     return -1;
 }
 
+String PrintContext::pageProperty(Frame* frame, const char* propertyName, int pageNumber)
+{
+    Document* document = frame->document();
+    document->updateLayout();
+    RefPtr<RenderStyle> style = document->styleForPage(pageNumber);
+
+    // Implement formatters for properties we care about.
+    if (!strcmp(propertyName, "margin-left"))
+        return String::format("%d", style->marginLeft().rawValue());
+    if (!strcmp(propertyName, "line-height"))
+        return String::format("%d", style->lineHeight().rawValue());
+    if (!strcmp(propertyName, "font-size"))
+        return String::format("%d", style->fontDescription().computedPixelSize());
+    if (!strcmp(propertyName, "font-family"))
+        return String::format("%s", style->fontDescription().family().family().string().utf8().data());
+
+    return String::format("pageProperty() unimplemented for: %s", propertyName);
+}
+
 int PrintContext::numberOfPages(Frame* frame, const FloatSize& pageSizeInPixels)
 {
     frame->document()->updateLayout();
index 1891144..9398a6e 100644 (file)
@@ -31,6 +31,7 @@ class FloatRect;
 class FloatSize;
 class GraphicsContext;
 class IntRect;
+class String;
 
 class PrintContext {
 public:
@@ -54,6 +55,7 @@ public:
 
     // Used by layout tests.
     static int pageNumberForElement(Element*, const FloatSize& pageSizeInPixels);
+    static String pageProperty(Frame* frame, const char* propertyName, int pageNumber);
     static int numberOfPages(Frame*, const FloatSize& pageSizeInPixels);
 
 protected:
index 1e30702..b52a351 100644 (file)
@@ -1,3 +1,14 @@
+2010-06-10  Yuzo Fujishima  <yuzo@google.com>
+
+        Reviewed by Shinichiro Hamaji.
+
+        Implement render style selection for pages to support CSS3 Paged Media.
+        https://bugs.webkit.org/show_bug.cgi?id=35961
+
+        * Misc/WebCoreStatistics.h:
+        * Misc/WebCoreStatistics.mm:
+        (-[WebFrame pageProperty:propertyName:]):
+
 2010-06-15  Darin Adler  <darin@apple.com>
 
         Reviewed by Adam Barth.
index a11c064..c79c96d 100644 (file)
@@ -87,4 +87,5 @@
 - (NSString *)counterValueForElement:(DOMElement*)element;
 - (int)pageNumberForElement:(DOMElement*)element:(float)pageWidthInPixels:(float)pageHeightInPixels;
 - (int)numberOfPages:(float)pageWidthInPixels:(float)pageHeightInPixels;
+- (NSString *)pageProperty:(const char*)propertyName:(int)pageNumber;
 @end
index c3fc23e..89f70fd 100644 (file)
@@ -275,4 +275,9 @@ using namespace WebCore;
     return PrintContext::numberOfPages(_private->coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels));
 }
 
+- (NSString *)pageProperty:(const char *)propertyName:(int)pageNumber
+{
+    return PrintContext::pageProperty(_private->coreFrame, propertyName, pageNumber);
+}
+
 @end
index 4a59be2..27aeefd 100644 (file)
@@ -1,3 +1,22 @@
+2010-06-10  Yuzo Fujishima  <yuzo@google.com>
+
+        Reviewed by Shinichiro Hamaji.
+
+        Implement render style selection for pages to support CSS3 Paged Media.
+        https://bugs.webkit.org/show_bug.cgi?id=35961
+
+        * DumpRenderTree/LayoutTestController.cpp:
+        (parsePagePropertyParameters):
+        (pagePropertyCallback):
+        (LayoutTestController::staticFunctions):
+        * DumpRenderTree/LayoutTestController.h:
+        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+        (LayoutTestController::pageProperty):
+        * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+        (LayoutTestController::pageProperty):
+        * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+        (LayoutTestController::pageProperty):
+
 2010-06-15  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index b96a9c9..3564001 100644 (file)
@@ -521,6 +521,32 @@ static bool parsePageParameters(JSContextRef context, int argumentCount, const J
     return true;
 }
 
+// Caller needs to delete[] propertyName.
+static bool parsePagePropertyParameters(JSContextRef context, int argumentCount, const JSValueRef* arguments, JSValueRef* exception, char*& propertyName, int& pageNumber)
+{
+    pageNumber = 0;
+    switch (argumentCount) {
+    case 2:
+        pageNumber = static_cast<float>(JSValueToNumber(context, arguments[1], exception));
+        if (*exception)
+            return false;
+        // Fall through.
+    case 1: {
+        JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+        if (*exception)
+            return false;
+
+        size_t maxLength = JSStringGetMaximumUTF8CStringSize(propertyNameString.get());
+        propertyName = new char[maxLength + 1];
+        JSStringGetUTF8CString(propertyNameString.get(), propertyName, maxLength + 1);
+        return true;
+    }
+    case 0:
+    default:
+        return false;
+    }
+}
+
 static JSValueRef pageNumberForElementByIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     float pageWidthInPixels = 0;
@@ -548,6 +574,20 @@ static JSValueRef numberOfPagesCallback(JSContextRef context, JSObjectRef functi
     return JSValueMakeNumber(context, controller->numberOfPages(pageWidthInPixels, pageHeightInPixels));
 }
 
+static JSValueRef pagePropertyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    char* propertyName = 0;
+    int pageNumber = 0;
+    if (!parsePagePropertyParameters(context, argumentCount, arguments, exception, propertyName, pageNumber))
+        return JSValueMakeUndefined(context);
+
+    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+    JSValueRef value = JSValueMakeString(context, controller->pageProperty(propertyName, pageNumber).get());
+
+    delete[] propertyName;
+    return value;
+}
+
 static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     // Has mac & windows implementation
@@ -1601,6 +1641,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
         { "numberOfActiveAnimations", numberOfActiveAnimationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "overridePreference", overridePreferenceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "pageNumberForElementById", pageNumberForElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "pageProperty", pagePropertyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "pauseAnimationAtTimeOnElementWithId", pauseAnimationAtTimeOnElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "pauseTransitionAtTimeOnElementWithId", pauseTransitionAtTimeOnElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
index 8ff38d1..14ec130 100644 (file)
@@ -62,6 +62,7 @@ public:
     int numberOfPages(float pageWidthInPixels, float pageHeightInPixels);
     void overridePreference(JSStringRef key, JSStringRef value);
     int pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels);
+    JSRetainPtr<JSStringRef> pageProperty(const char* propertyName, int pageNumber) const;
     JSStringRef pathToLocalResource(JSContextRef, JSStringRef url);
     void queueBackNavigation(int howFarBackward);
     void queueForwardNavigation(int howFarForward);
index e8b8627..2bdd80c 100644 (file)
@@ -171,6 +171,12 @@ int LayoutTestController::numberOfPages(float pageWidth, float pageHeight)
     return webkit_web_frame_number_of_pages(mainFrame, pageWidth, pageHeight);
 }
 
+JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
+{
+    // FIXME: implement
+    return JSRetainPtr<JSStringRef>();
+}
+
 size_t LayoutTestController::webHistoryItemCount()
 {
     // FIXME: implement
index eb01090..ee10703 100644 (file)
@@ -212,6 +212,12 @@ int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWid
     return [mainFrame pageNumberForElement:element:pageWidthInPixels:pageHeightInPixels];
 }
 
+JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
+{
+    JSRetainPtr<JSStringRef> propertyValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame pageProperty:propertyName:pageNumber]));
+    return propertyValue;
+}
+
 int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeightInPixels)
 {
     return [mainFrame numberOfPages:pageWidthInPixels:pageHeightInPixels];
index c70b517..b2a345b 100644 (file)
@@ -1237,6 +1237,12 @@ int LayoutTestController::numberOfPages(float pageWidthInPixels, float pageHeigh
     return pageNumber;
 }
 
+JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char* propertyName, int pageNumber) const
+{
+    // FIXME: Implement this.
+    return JSRetainPtr<JSStringRef>();
+}
+
 void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
 {