LayoutTests:
authorweinig <weinig@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Jul 2007 17:51:28 +0000 (17:51 +0000)
committerweinig <weinig@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 8 Jul 2007 17:51:28 +0000 (17:51 +0000)
        Reviewed by Darin.

        - test for http://bugs.webkit.org/show_bug.cgi?id=12384
          getComputedStyle with td.style.display='none' reports '' for all properties except display

        * fast/css/computed-style-without-renderer-expected.txt: Added.
        * fast/css/computed-style-without-renderer.html: Added.

WebCore:

        Reviewed by Darin.

        - fix http://bugs.webkit.org/show_bug.cgi?id=12384
          getComputedStyle with td.style.display='none' reports '' for all properties except display

        Test: fast/css/computed-style-without-renderer.html

        Implement rich computed style for elements that do not have a renderer.

        * css/CSSComputedStyleDeclaration.cpp:
        (WebCore::getPositionOffsetValue): Changed to take a RenderStyle instead of
        a RenderObject.
        (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Changed to
        use the computed style returned by the node instead of going through the
        renderer. Changed properties that compute by measuring the renderer to
        fall back on returning the length from the RenderStyle if a renderer does
        not exist.
        (WebCore::CSSComputedStyleDeclaration::length): Changed to return the number
        of properties we can compute even if the element has no renderer.
        (WebCore::CSSComputedStyleDeclaration::copyInheritableProperties): Changed
        to use the computed style returned by the node instead of going through the
        renderer.
        * dom/Element.cpp:
        (WebCore::ElementRareData::ElementRareData): Added a computed style member,
        used to cache computed style for elements that do not have a renderer.
        (WebCore::ElementRareData::resetComputedStyle): Added.
        (WebCore::Element::~Element): Delete the cached computed style.
        (WebCore::Element::recalcStyle): Added code to delete the cached computed
        style when necessary.
        (WebCore::Element::computedStyle): Added. Returns the style used in rendering
        the element, if available. Otherwise uses the style selector to compute style
        for the element.
        * dom/Element.h:
        * dom/Node.cpp:
        (WebCore::Node::computedStyle): Added. This method returns either the style
        used in rendering the node, or the style that would be used if the node
        had a renderer.
        * dom/Node.h:

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

LayoutTests/ChangeLog
LayoutTests/fast/css/computed-style-without-renderer-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/computed-style-without-renderer.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/css/CSSComputedStyleDeclaration.cpp
WebCore/dom/Element.cpp
WebCore/dom/Element.h
WebCore/dom/Node.cpp
WebCore/dom/Node.h

index a0484eef1f9fc87041024d0f9af375e59065cc4a..9444544cbc162f5ceed7c12f9acfc84547457bfa 100644 (file)
@@ -1,3 +1,13 @@
+2007-07-08  Mitz Pettel  <mitz@webkit.org>
+
+        Reviewed by Darin.
+
+        - test for http://bugs.webkit.org/show_bug.cgi?id=12384
+          getComputedStyle with td.style.display='none' reports '' for all properties except display
+
+        * fast/css/computed-style-without-renderer-expected.txt: Added.
+        * fast/css/computed-style-without-renderer.html: Added.
+
 2007-07-08  Rob Buis  <buis@kde.org>
 
         Reviewed by Mitz.
diff --git a/LayoutTests/fast/css/computed-style-without-renderer-expected.txt b/LayoutTests/fast/css/computed-style-without-renderer-expected.txt
new file mode 100644 (file)
index 0000000..c14204b
--- /dev/null
@@ -0,0 +1,150 @@
+Computed style of an element whose parent's 'display' value is 'none':
+    background-attachment: scroll
+    background-color: rgb(0, 128, 0)
+    background-image: none
+    background-position-x: auto
+    background-position-y: auto
+    background-repeat: repeat
+    border-bottom-color: rgb(0, 0, 0)
+    border-bottom-style: none
+    border-bottom-width: 0px
+    border-collapse: separate
+    border-left-color: rgb(0, 0, 0)
+    border-left-style: none
+    border-left-width: 0px
+    border-right-color: rgb(0, 0, 0)
+    border-right-style: none
+    border-right-width: 0px
+    border-top-color: rgb(0, 0, 0)
+    border-top-style: solid
+    border-top-width: 16px
+    bottom: auto
+    caption-side: top
+    clear: none
+    color: rgb(0, 0, 0)
+    cursor: auto
+    direction: ltr
+    display: block
+    empty-cells: show
+    float: none
+    font-family: Times
+    font-size: 16px
+    font-style: normal
+    font-variant: normal
+    font-weight: normal
+    height: 100px
+    left: auto
+    letter-spacing: normal
+    line-height: normal
+    list-style-image: none
+    list-style-position: outside
+    list-style-type: disc
+    margin-bottom: 0px
+    margin-left: auto
+    margin-right: 0px
+    margin-top: 0px
+    max-height: none
+    max-width: none
+    min-height: 0px
+    min-width: 0px
+    opacity: 1
+    orphans: 2
+    outline-color: rgb(0, 0, 0)
+    outline-style: none
+    outline-width: 0px
+    overflow-x: visible
+    overflow-y: visible
+    padding-bottom: auto
+    padding-left: auto
+    padding-right: auto
+    padding-top: auto
+    page-break-after: auto
+    page-break-before: auto
+    page-break-inside: auto
+    position: static
+    resize: none
+    right: auto
+    table-layout: auto
+    text-align: auto
+    text-decoration: none
+    text-indent: 0px
+    text-shadow: none
+    text-transform: none
+    top: auto
+    unicode-bidi: normal
+    vertical-align: baseline
+    visibility: visible
+    white-space: normal
+    widows: 2
+    width: 50%
+    word-spacing: 0px
+    word-wrap: normal
+    z-index: auto
+    -webkit-appearance: none
+    -webkit-background-clip: border
+    -webkit-background-composite: source-over
+    -webkit-background-origin: padding
+    -webkit-background-size: auto auto
+    -webkit-border-fit: border
+    -webkit-border-horizontal-spacing: 0px
+    -webkit-border-vertical-spacing: 0px
+    -webkit-box-align: stretch
+    -webkit-box-direction: normal
+    -webkit-box-flex: 0
+    -webkit-box-flex-group: 1
+    -webkit-box-lines: single
+    -webkit-box-ordinal-group: 1
+    -webkit-box-orient: horizontal
+    -webkit-box-pack: start
+    -webkit-box-shadow: none
+    -webkit-box-sizing: content-box
+    -webkit-column-break-after: auto
+    -webkit-column-break-before: auto
+    -webkit-column-break-inside: auto
+    -webkit-column-count: auto
+    -webkit-column-gap: normal
+    -webkit-column-rule-color: rgb(0, 0, 0)
+    -webkit-column-rule-style: none
+    -webkit-column-rule-width: 0px
+    -webkit-column-width: auto
+    -webkit-highlight: none
+    -webkit-line-break: normal
+    -webkit-line-clamp: none
+    -webkit-margin-bottom-collapse: collapse
+    -webkit-margin-top-collapse: collapse
+    -webkit-marquee-direction: auto
+    -webkit-marquee-increment: 6px
+    -webkit-marquee-repetition: infinite
+    -webkit-marquee-style: scroll
+    -webkit-nbsp-mode: normal
+    -webkit-rtl-ordering: logical
+    -webkit-text-decorations-in-effect: none
+    -webkit-text-fill-color: rgb(0, 0, 0)
+    -webkit-text-security: none
+    -webkit-text-stroke-color: rgb(0, 0, 0)
+    -webkit-text-stroke-width: 0
+    -webkit-user-drag: auto
+    -webkit-user-modify: read-only
+    -webkit-user-select: auto
+    -webkit-dashboard-region: null
+    background-position: '0 0'
+    border-spacing: '0px 0px'
+    overflow: visible
+    -webkit-match-nearest-mail-blockquote-color: normal
+    -webkit-text-size-adjust: auto
+
+After changing grandparent's 'color' and the parent's 'font-size' inherited properties:
+    border-top-width: 18px
+    color: rgb(0, 0, 255)
+
+After changing the parent's 'display' property to 'block', so that the child gets a renderer:
+    height: 100px
+    margin-left: 385px
+    width: 384px
+
+After changing the parent's 'display' property back to 'none':
+    height: 100px
+    margin-left: auto
+    width: 50%
+
+
diff --git a/LayoutTests/fast/css/computed-style-without-renderer.html b/LayoutTests/fast/css/computed-style-without-renderer.html
new file mode 100644 (file)
index 0000000..fc853e1
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+<head>
+    <script>
+        var others = [
+            "background-position",
+            "border-spacing",
+            "overflow",
+            "-webkit-match-nearest-mail-blockquote-color",
+            "-webkit-text-size-adjust",
+        ];
+
+        if (window.layoutTestController)
+            layoutTestController.dumpAsText();
+
+        function log(message)
+        {
+            var console = document.getElementById("console");
+            console.appendChild(document.createTextNode(message + "\n"));
+        }
+
+        function dumpComputedStyle(element, properties)
+        {
+            var style = getComputedStyle(element);
+
+            if (!properties) {
+                for (var i = 0; i != style.length; ++i) {
+                    var name = style.item(i);
+                    log("    " + name + ": " + style.getPropertyValue(name));
+                }
+                properties = others;
+            }
+
+            for (var i = 0; i != properties.length; ++i) {
+                var name = properties[i];
+                log("    " + name + ": " + style.getPropertyValue(name));
+            }
+            log("");
+        }
+
+        function test()
+        {
+            var outerDiv = document.getElementById("outer");
+            var middleDiv = document.getElementById("middle");
+            var innerDiv = document.getElementById("inner");
+
+            log("Computed style of an element whose parent's 'display' value is 'none':");
+            dumpComputedStyle(innerDiv);
+
+            outerDiv.style.color = "blue";
+            middleDiv.style.fontSize = "large";
+            log("After changing grandparent's 'color' and the parent's 'font-size' inherited properties:");
+            dumpComputedStyle(innerDiv, ["border-top-width", "color"]);
+
+            middleDiv.style.display = "block";
+            log("After changing the parent's 'display' property to 'block', so that the child gets a renderer:");
+            dumpComputedStyle(innerDiv, ["height", "margin-left", "width"]);
+
+            middleDiv.style.display = "";
+            log("After changing the parent's 'display' property back to 'none':");
+            dumpComputedStyle(innerDiv, ["height", "margin-left", "width"]);
+        }
+    </script>
+    <style>
+        div#middle { display: none; }
+        div#inner { background: green; border-top: 1em solid; height: 100px; margin-left: auto; width: 50%; }
+    </style>
+</head>
+<body onload="test()">
+    <pre id="console"></pre>
+    <div id="outer">
+        <div id="middle">
+            <div id="inner">
+            </div>
+        </div>
+    </div>
+</body>
+</html>
index dfb6c7be492835a80424c8ceeb390e4f0261de03..ecc2e2847c37edbdddd755c54ca9a69f724f9733 100644 (file)
@@ -1,3 +1,44 @@
+2007-07-08  Mitz Pettel  <mitz@webkit.org>
+
+        Reviewed by Darin.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=12384
+          getComputedStyle with td.style.display='none' reports '' for all properties except display
+
+        Test: fast/css/computed-style-without-renderer.html
+
+        Implement rich computed style for elements that do not have a renderer.
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::getPositionOffsetValue): Changed to take a RenderStyle instead of
+        a RenderObject.
+        (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Changed to
+        use the computed style returned by the node instead of going through the
+        renderer. Changed properties that compute by measuring the renderer to
+        fall back on returning the length from the RenderStyle if a renderer does
+        not exist.
+        (WebCore::CSSComputedStyleDeclaration::length): Changed to return the number
+        of properties we can compute even if the element has no renderer.
+        (WebCore::CSSComputedStyleDeclaration::copyInheritableProperties): Changed
+        to use the computed style returned by the node instead of going through the
+        renderer.
+        * dom/Element.cpp:
+        (WebCore::ElementRareData::ElementRareData): Added a computed style member,
+        used to cache computed style for elements that do not have a renderer.
+        (WebCore::ElementRareData::resetComputedStyle): Added.
+        (WebCore::Element::~Element): Delete the cached computed style.
+        (WebCore::Element::recalcStyle): Added code to delete the cached computed
+        style when necessary.
+        (WebCore::Element::computedStyle): Added. Returns the style used in rendering
+        the element, if available. Otherwise uses the style selector to compute style
+        for the element.
+        * dom/Element.h:
+        * dom/Node.cpp:
+        (WebCore::Node::computedStyle): Added. This method returns either the style
+        used in rendering the node, or the style that would be used if the node
+        had a renderer.
+        * dom/Node.h:
+
 2007-07-08  Mitz Pettel  <mitz@webkit.org>
 
         Reviewed by Darin.
index 0adca558d4ede45d8f89759054d92d54bc5bea48..3314243fc68ccc29227f205c9f00e70954802cf1 100644 (file)
@@ -361,12 +361,8 @@ static PassRefPtr<CSSValue> valueForShadow(const ShadowData* shadow)
     return list.release();
 }
 
-static PassRefPtr<CSSValue> getPositionOffsetValue(RenderObject* renderer, int propertyID)
+static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int propertyID)
 {
-    if (!renderer)
-        return 0;
-
-    RenderStyle* style = renderer->style();
     if (!style)
         return 0;
 
@@ -388,10 +384,10 @@ static PassRefPtr<CSSValue> getPositionOffsetValue(RenderObject* renderer, int p
             return 0;
     }
 
-    if (renderer->isPositioned())
+    if (style->position() == AbsolutePosition || style->position() == FixedPosition)
         return valueForLength(l);
 
-    if (renderer->isRelPositioned())
+    if (style->position() == RelativePosition)
         // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
         // In other words if left is auto and right is not auto, then left's computed value is negative right.
         // So we should get the opposite length unit and see if it is auto.
@@ -478,17 +474,9 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
     if (updateLayout)
         node->document()->updateLayout();
 
-    // FIXME: This should work even if we do not have a renderer for all properties.
     RenderObject* renderer = node->renderer();
-    if (!renderer) {
-        // Handle display:none at the very least.  By definition if we don't have a renderer
-        // we are considered to have no display.
-        if (propertyID == CSS_PROP_DISPLAY)
-            return new CSSPrimitiveValue(CSS_VAL_NONE);
-        return 0;
-    }
 
-    RenderStyle* style = renderer->style();
+    RenderStyle* style = node->computedStyle();
     if (!style)
         return 0;
 
@@ -574,14 +562,18 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             Length length(style->backgroundXPosition());
             if (length.isPercent())
                 string = numberAsString(length.percent()) + "%";
-            else
+            else if (renderer)
                 string = numberAsString(length.calcMinValue(renderer->contentWidth()));
+            else
+                string = numberAsString(length.value());
             string += " ";
             length = style->backgroundYPosition();
             if (length.isPercent())
                 string += numberAsString(length.percent()) + "%";
-            else
+            else if (renderer)
                 string += numberAsString(length.calcMinValue(renderer->contentWidth()));
+            else
+                string += numberAsString(length.value());
             return new CSSPrimitiveValue(string, CSSPrimitiveValue::CSS_STRING);
         }
         case CSS_PROP_BACKGROUND_POSITION_X:
@@ -624,7 +616,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
         case CSS_PROP_BORDER_LEFT_WIDTH:
             return new CSSPrimitiveValue(style->borderLeftWidth(), CSSPrimitiveValue::CSS_PX);
         case CSS_PROP_BOTTOM:
-            return getPositionOffsetValue(renderer, CSS_PROP_BOTTOM);
+            return getPositionOffsetValue(style, CSS_PROP_BOTTOM);
         case CSS_PROP__WEBKIT_BOX_ALIGN:
             switch (style->boxAlign()) {
                 case BSTRETCH:
@@ -986,7 +978,9 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
                 return new CSSPrimitiveValue(CSS_VAL_BOLD);
             return new CSSPrimitiveValue(CSS_VAL_NORMAL);
         case CSS_PROP_HEIGHT:
-            return new CSSPrimitiveValue(renderer->contentHeight(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->contentHeight(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->height());
         case CSS_PROP__WEBKIT_HIGHLIGHT:
             if (style->highlight() == nullAtom)
                 return new CSSPrimitiveValue(CSS_VAL_NONE);
@@ -996,7 +990,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
                 return new CSSPrimitiveValue(CSS_VAL_BORDER);
             return new CSSPrimitiveValue(CSS_VAL_LINES);
         case CSS_PROP_LEFT:
-            return getPositionOffsetValue(renderer, CSS_PROP_LEFT);
+            return getPositionOffsetValue(style, CSS_PROP_LEFT);
         case CSS_PROP_LETTER_SPACING:
             if (!style->letterSpacing())
                 return new CSSPrimitiveValue(CSS_VAL_NORMAL);
@@ -1078,17 +1072,25 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             ASSERT_NOT_REACHED();
             return 0;
         case CSS_PROP_MARGIN_TOP:
-            // FIXME: Supposed to return the percentage if percentage was specified.
-            return new CSSPrimitiveValue(renderer->marginTop(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                // FIXME: Supposed to return the percentage if percentage was specified.
+                return new CSSPrimitiveValue(renderer->marginTop(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->marginTop());
         case CSS_PROP_MARGIN_RIGHT:
-            // FIXME: Supposed to return the percentage if percentage was specified.
-            return new CSSPrimitiveValue(renderer->marginRight(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                // FIXME: Supposed to return the percentage if percentage was specified.
+                return new CSSPrimitiveValue(renderer->marginRight(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->marginRight());
         case CSS_PROP_MARGIN_BOTTOM:
-            // FIXME: Supposed to return the percentage if percentage was specified.
-            return new CSSPrimitiveValue(renderer->marginBottom(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                // FIXME: Supposed to return the percentage if percentage was specified.
+                return new CSSPrimitiveValue(renderer->marginBottom(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->marginBottom());
         case CSS_PROP_MARGIN_LEFT:
-            // FIXME: Supposed to return the percentage if percentage was specified.
-            return new CSSPrimitiveValue(renderer->marginLeft(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                // FIXME: Supposed to return the percentage if percentage was specified.
+                return new CSSPrimitiveValue(renderer->marginLeft(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->marginLeft());
         case CSS_PROP__WEBKIT_MARQUEE_DIRECTION:
             switch (style->marqueeDirection()) {
                 case MFORWARD:
@@ -1190,13 +1192,21 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             return 0;
         }
         case CSS_PROP_PADDING_TOP:
-            return new CSSPrimitiveValue(renderer->paddingTop(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->paddingTop(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->paddingTop());
         case CSS_PROP_PADDING_RIGHT:
-            return new CSSPrimitiveValue(renderer->paddingRight(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->paddingRight(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->paddingRight());
         case CSS_PROP_PADDING_BOTTOM:
-            return new CSSPrimitiveValue(renderer->paddingBottom(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->paddingBottom(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->paddingBottom());
         case CSS_PROP_PADDING_LEFT:
-            return new CSSPrimitiveValue(renderer->paddingLeft(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->paddingLeft(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->paddingLeft());
         case CSS_PROP_PAGE_BREAK_AFTER:
             switch (style->pageBreakAfter()) {
                 case PBAUTO:
@@ -1244,7 +1254,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             ASSERT_NOT_REACHED();
             return 0;
         case CSS_PROP_RIGHT:
-            return getPositionOffsetValue(renderer, CSS_PROP_RIGHT);
+            return getPositionOffsetValue(style, CSS_PROP_RIGHT);
         case CSS_PROP_TABLE_LAYOUT:
             switch (style->tableLayout()) {
                 case TAUTO:
@@ -1343,7 +1353,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             ASSERT_NOT_REACHED();
             return 0;
         case CSS_PROP_TOP:
-            return getPositionOffsetValue(renderer, CSS_PROP_TOP);
+            return getPositionOffsetValue(style, CSS_PROP_TOP);
         case CSS_PROP_UNICODE_BIDI:
             switch (style->unicodeBidi()) {
                 case UBNormal:
@@ -1411,7 +1421,9 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
         case CSS_PROP_WIDOWS:
             return new CSSPrimitiveValue(style->widows(), CSSPrimitiveValue::CSS_NUMBER);
         case CSS_PROP_WIDTH:
-            return new CSSPrimitiveValue(renderer->contentWidth(), CSSPrimitiveValue::CSS_PX);
+            if (renderer)
+                return new CSSPrimitiveValue(renderer->contentWidth(), CSSPrimitiveValue::CSS_PX);
+            return valueForLength(style->width());
         case CSS_PROP_WORD_BREAK:
             switch (style->wordBreak()) {
                 case NormalWordBreak:
@@ -1644,11 +1656,7 @@ unsigned CSSComputedStyleDeclaration::length() const
     if (!node)
         return 0;
 
-    RenderObject* renderer = node->renderer();
-    if (!renderer)
-        return 0;
-
-    RenderStyle* style = renderer->style();
+    RenderStyle* style = node->computedStyle();
     if (!style)
         return 0;
 
@@ -1702,14 +1710,14 @@ void CSSComputedStyleDeclaration::removeComputedInheritablePropertiesFrom(CSSMut
 PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copyInheritableProperties() const
 {
     RefPtr<CSSMutableStyleDeclaration> style = copyPropertiesInSet(inheritableProperties, numInheritableProperties);
-    if (style && m_node && m_node->renderer()) {
+    if (style && m_node && m_node->computedStyle()) {
         // If a node's text fill color is invalid, then its children use 
         // their font-color as their text fill color (they don't
         // inherit it).  Likewise for stroke color.
         ExceptionCode ec = 0;
-        if (!m_node->renderer()->style()->textFillColor().isValid())
+        if (!m_node->computedStyle()->textFillColor().isValid())
             style->removeProperty(CSS_PROP__WEBKIT_TEXT_FILL_COLOR, ec);
-        if (!m_node->renderer()->style()->textStrokeColor().isValid())
+        if (!m_node->computedStyle()->textStrokeColor().isValid())
             style->removeProperty(CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, ec);
         ASSERT(ec == 0);
     }
index ae9ea994d1472c39dd6a435b24644b328bbcac73..c39fe7666d2a79a97d750cf249d35c21ffc5ec36 100644 (file)
@@ -50,7 +50,10 @@ using namespace XMLNames;
 class ElementRareData {
 public:
     ElementRareData(Element*);
+    void resetComputedStyle(Element*);
+
     IntSize m_minimumSizeForResizing;
+    RenderStyle* m_computedStyle;
 };
 
 typedef HashMap<const Element*, ElementRareData*> ElementRareDataMap;
@@ -73,7 +76,16 @@ static inline IntSize defaultMinimumSizeForResizing()
 
 inline ElementRareData::ElementRareData(Element* element)
     : m_minimumSizeForResizing(defaultMinimumSizeForResizing())
+    , m_computedStyle(0)
+{
+}
+
+void ElementRareData::resetComputedStyle(Element* element)
 {
+    if (!m_computedStyle)
+        return;
+    m_computedStyle->deref(element->document()->renderArena());
+    m_computedStyle = 0;
 }
 
 Element::Element(const QualifiedName& qName, Document *doc)
@@ -95,6 +107,7 @@ Element::~Element()
         ElementRareDataMap& dataMap = rareDataMap();
         ElementRareDataMap::iterator it = dataMap.find(this);
         ASSERT(it != dataMap.end());
+        it->second->resetComputedStyle(this);
         delete it->second;
         dataMap.remove(it);
     }
@@ -671,6 +684,10 @@ void Element::recalcStyle(StyleChange change)
         hasParentStyle = true;
 #endif
 
+    if ((change > NoChange || changed())) {
+        if (ElementRareData* rd = rareData())
+            rd->resetComputedStyle(this);
+    }
     if (hasParentStyle && (change >= Inherit || changed())) {
         RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
         StyleChange ch = diff(_style, newStyle);
@@ -1067,4 +1084,17 @@ void Element::setMinimumSizeForResizing(const IntSize& size)
     createRareData()->m_minimumSizeForResizing = size;
 }
 
+RenderStyle* Element::computedStyle()
+{
+    if (RenderStyle* usedStyle = renderStyle())
+        return usedStyle;
+
+    ElementRareData* rd = createRareData();
+    if (!rd->m_computedStyle) {
+        rd->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
+        rd->m_computedStyle->ref();
+    }
+    return rd->m_computedStyle;
+}
+
 }
index f22ab6f7a59b908b63ccece667e6c3dfc13556ca..5f728bfb5395cedbfb05d071b85c1f1dfebdb74f 100644 (file)
@@ -142,6 +142,8 @@ public:
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual void recalcStyle(StyleChange = NoChange);
 
+    virtual RenderStyle* computedStyle();
+
     virtual bool childTypeAllowed(NodeType);
 
     virtual Attribute* createAttribute(const QualifiedName& name, StringImpl* value);
index 30dbb9622112ed15796d28481019778fde7ad4b0..92ade9007ecd7b0e15592acd2fa17e5350180d0e 100644 (file)
@@ -1052,6 +1052,11 @@ void Node::setRenderStyle(RenderStyle* s)
         m_renderer->setStyle(s); 
 }
 
+RenderStyle* Node::computedStyle()
+{
+    return parent() ? parent()->computedStyle() : 0;
+}
+
 int Node::maxOffset() const
 {
     return 1;
index b306432699ae0291914711f9ce46d5a4cf63ca0a..20180ef9cad0271bc536b7273c7a95e2c029a496 100644 (file)
@@ -394,6 +394,8 @@ public:
     virtual RenderStyle* renderStyle() const;
     virtual void setRenderStyle(RenderStyle*);
 
+    virtual RenderStyle* computedStyle();
+
     // -----------------------------------------------------------------------------
     // Notification of document structure changes