Attribute styles should be created lazily.
authorkling@webkit.org <kling@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 11 Feb 2012 19:29:49 +0000 (19:29 +0000)
committerkling@webkit.org <kling@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 11 Feb 2012 19:29:49 +0000 (19:29 +0000)
<http://webkit.org/b/78381>

Reviewed by Antti Koivisto.

TL;DR summary: Lazily construct the StyledElement::attributeStyle() instead of
moving properties in/out of it in parseAttribute(). This allows us to enable
the matched declaration cache for elements with presentation attributes.

The matched declaration cache has been disabled for elements with presentation
attributes because attributeStyle() was mutable, and (simply put) the cache maps
a set of StylePropertySet pointers to a resulting RenderStyle. This requires
that the StylePropertySets are immutable.

To make them immutable, we now construct the attribute style lazily by adding
a flag (to Node) that gets set in parseAttribute() when a presentation attribute
respected by the element changes. A subsequent call to attributeStyle() checks
the flag and rebuilds the style by looping over the attributes and calling the
new virtual StyledElement::collectStyleForAttribute() on each one. Any dangling
references to the previous attribute style will be garbage collected by the
cache in CSSStyleSelector::sweepMatchedDeclarationCache().

* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::matchAllRules):

    Enable matched declaration cache for elements with attribute style.

* dom/Node.h:
(WebCore::Node::attributeStyleDirty):
(WebCore::Node::setAttributeStyleDirty):
(WebCore::Node::clearAttributeStyleDirty):

    Add a Node flag to signify that a presentation attribute has changed and
    the attribute style needs to be rebuilt.

* dom/ElementAttributeData.h:
* dom/ElementAttributeData.cpp:
(WebCore::ElementAttributeData::setAttributeStyle):

    Added a setter for the attribute style, called by updateAttributeStyle().

* dom/StyledElement.cpp:
(WebCore::StyledElement::addHTMLLengthToStyle):
(WebCore::StyledElement::addHTMLColorToStyle):

    Moved and renamed two of the old addCSS* helpers from StyledElement.

(WebCore::StyledElement::updateAttributeStyle):

    Called by attributeStyle() in case the "attribute style dirty" flag is
    set. Rebuilds the attribute style from scratch by looping over the
    attribute map and calling collectStyleForAttribute() on each attribute.

* dom/StyledElement.h:
(WebCore::StyledElement::collectStyleForAttribute):
(WebCore::StyledElement::attributeStyle):
(WebCore::StyledElement::setNeedsAttributeStyleUpdate):

    Helper, sets the attribute style dirty flag and marks the element for
    full style recalc. This is what parseAttribute() calls in subclasses
    when they encounter a presentation attribute.

* html/HTMLBRElement.cpp:
(WebCore::HTMLBRElement::collectStyleForAttribute):
(WebCore::HTMLBRElement::parseAttribute):
* html/HTMLBRElement.h:
* html/HTMLBodyElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLBodyElement::collectStyleForAttribute):
(WebCore::HTMLBodyElement::parseAttribute):
* html/HTMLBodyElement.h:
* html/HTMLDivElement.cpp:
(WebCore::HTMLDivElement::collectStyleForAttribute):
(WebCore::HTMLDivElement::parseAttribute):
* html/HTMLDivElement.h:
* html/HTMLElement.cpp:
(WebCore::HTMLElement::applyBorderAttributeToStyle):
(WebCore::HTMLElement::mapLanguageAttributeToLocale):
(WebCore::HTMLElement::collectStyleForAttribute):
(WebCore::HTMLElement::parseAttribute):
(WebCore::HTMLElement::applyAlignmentAttributeToStyle):
* html/HTMLElement.h:
* html/HTMLEmbedElement.cpp:
(WebCore::HTMLEmbedElement::collectStyleForAttribute):
(WebCore::HTMLEmbedElement::parseAttribute):
* html/HTMLEmbedElement.h:
* html/HTMLFontElement.cpp:
(WebCore::HTMLFontElement::collectStyleForAttribute):
(WebCore::HTMLFontElement::parseAttribute):
* html/HTMLFontElement.h:
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::collectStyleForAttribute):
(WebCore::HTMLFrameSetElement::parseAttribute):
* html/HTMLFrameSetElement.h:
* html/HTMLHRElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLHRElement::collectStyleForAttribute):
(WebCore::HTMLHRElement::parseAttribute):
* html/HTMLHRElement.h:
* html/HTMLIFrameElement.cpp:
(WebCore::HTMLIFrameElement::collectStyleForAttribute):
(WebCore::HTMLIFrameElement::parseAttribute):
* html/HTMLIFrameElement.h:
* html/HTMLImageElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLImageElement::collectStyleForAttribute):
(WebCore::HTMLImageElement::parseAttribute):
* html/HTMLImageElement.h:
* html/HTMLInputElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLInputElement::collectStyleForAttribute):
(WebCore::HTMLInputElement::parseAttribute):
* html/HTMLInputElement.h:
* html/HTMLLIElement.cpp:
(WebCore::HTMLLIElement::collectStyleForAttribute):
(WebCore::HTMLLIElement::parseAttribute):
* html/HTMLLIElement.h:
* html/HTMLMarqueeElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLMarqueeElement::collectStyleForAttribute):
(WebCore::HTMLMarqueeElement::parseAttribute):
* html/HTMLMarqueeElement.h:
* html/HTMLOListElement.cpp:
(WebCore::HTMLOListElement::collectStyleForAttribute):
(WebCore::HTMLOListElement::parseAttribute):
* html/HTMLOListElement.h:
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::collectStyleForAttribute):
(WebCore::HTMLObjectElement::parseAttribute):
* html/HTMLObjectElement.h:
* html/HTMLParagraphElement.cpp:
(WebCore::HTMLParagraphElement::collectStyleForAttribute):
(WebCore::HTMLParagraphElement::parseAttribute):
* html/HTMLParagraphElement.h:
* html/HTMLPlugInElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLPlugInElement::collectStyleForAttribute):
(WebCore::HTMLPlugInElement::parseAttribute):
* html/HTMLPlugInElement.h:
* html/HTMLPreElement.cpp:
(WebCore::HTMLPreElement::collectStyleForAttribute):
(WebCore::HTMLPreElement::parseAttribute):
* html/HTMLPreElement.h:
* html/HTMLTableCaptionElement.cpp:
(WebCore::HTMLTableCaptionElement::collectStyleForAttribute):
(WebCore::HTMLTableCaptionElement::parseAttribute):
* html/HTMLTableCaptionElement.h:
* html/HTMLTableCellElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLTableCellElement::collectStyleForAttribute):
(WebCore::HTMLTableCellElement::parseAttribute):
* html/HTMLTableCellElement.h:
* html/HTMLTableColElement.cpp:
(WebCore::HTMLTableColElement::collectStyleForAttribute):
(WebCore::HTMLTableColElement::parseAttribute):
* html/HTMLTableColElement.h:
* html/HTMLTableElement.cpp:
(WebCore::getBordersFromFrameAttributeValue):
(WebCore::HTMLTableElement::collectStyleForAttribute):
(WebCore::HTMLTableElement::parseAttribute):
* html/HTMLTableElement.h:
* html/HTMLTablePartElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::HTMLTablePartElement::collectStyleForAttribute):
(WebCore::HTMLTablePartElement::parseAttribute):
* html/HTMLTablePartElement.h:
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::collectStyleForAttribute):
(WebCore::HTMLTextAreaElement::parseAttribute):
* html/HTMLTextAreaElement.h:
* html/HTMLUListElement.cpp:
(WebCore::HTMLUListElement::collectStyleForAttribute):
(WebCore::HTMLUListElement::parseAttribute):
* html/HTMLUListElement.h:
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::collectStyleForAttribute):
(WebCore::HTMLVideoElement::parseAttribute):
* html/HTMLVideoElement.h:
* mathml/MathMLElement.cpp:
(WebCore::isRespectedPresentationAttribute):
(WebCore::MathMLElement::collectStyleForAttribute):
(WebCore::MathMLElement::parseAttribute):
* mathml/MathMLElement.h:
* svg/SVGImageElement.cpp:
(WebCore::SVGImageElement::collectStyleForAttribute):
(WebCore::SVGImageElement::parseAttribute):
* svg/SVGImageElement.h:
* svg/SVGStyledElement.cpp:
(WebCore::SVGStyledElement::collectStyleForAttribute):
(WebCore::SVGStyledElement::parseAttribute):
* svg/SVGStyledElement.h:
* svg/SVGTextContentElement.cpp:
(WebCore::SVGTextContentElement::collectStyleForAttribute):
(WebCore::SVGTextContentElement::parseAttribute):
* svg/SVGTextContentElement.h:

    Split handling of presentation attributes between parseAttribute() and
    collectStyleForAttribute() as appropriate. Some minor refactorings here and
    there (mostly in HTMLTableElement) to avoid excessive code duplication.
    Also sprinkled FIXMEs about inefficiencies we should clean up.

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

67 files changed:
Source/WebCore/ChangeLog
Source/WebCore/css/CSSStyleSelector.cpp
Source/WebCore/dom/ElementAttributeData.cpp
Source/WebCore/dom/ElementAttributeData.h
Source/WebCore/dom/Node.h
Source/WebCore/dom/StyledElement.cpp
Source/WebCore/dom/StyledElement.h
Source/WebCore/html/HTMLBRElement.cpp
Source/WebCore/html/HTMLBRElement.h
Source/WebCore/html/HTMLBodyElement.cpp
Source/WebCore/html/HTMLBodyElement.h
Source/WebCore/html/HTMLDivElement.cpp
Source/WebCore/html/HTMLDivElement.h
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLElement.h
Source/WebCore/html/HTMLEmbedElement.cpp
Source/WebCore/html/HTMLEmbedElement.h
Source/WebCore/html/HTMLFontElement.cpp
Source/WebCore/html/HTMLFontElement.h
Source/WebCore/html/HTMLFrameSetElement.cpp
Source/WebCore/html/HTMLFrameSetElement.h
Source/WebCore/html/HTMLHRElement.cpp
Source/WebCore/html/HTMLHRElement.h
Source/WebCore/html/HTMLIFrameElement.cpp
Source/WebCore/html/HTMLIFrameElement.h
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/HTMLImageElement.h
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/HTMLLIElement.cpp
Source/WebCore/html/HTMLLIElement.h
Source/WebCore/html/HTMLMarqueeElement.cpp
Source/WebCore/html/HTMLMarqueeElement.h
Source/WebCore/html/HTMLOListElement.cpp
Source/WebCore/html/HTMLOListElement.h
Source/WebCore/html/HTMLObjectElement.cpp
Source/WebCore/html/HTMLObjectElement.h
Source/WebCore/html/HTMLParagraphElement.cpp
Source/WebCore/html/HTMLParagraphElement.h
Source/WebCore/html/HTMLPlugInElement.cpp
Source/WebCore/html/HTMLPlugInElement.h
Source/WebCore/html/HTMLPreElement.cpp
Source/WebCore/html/HTMLPreElement.h
Source/WebCore/html/HTMLTableCaptionElement.cpp
Source/WebCore/html/HTMLTableCaptionElement.h
Source/WebCore/html/HTMLTableCellElement.cpp
Source/WebCore/html/HTMLTableCellElement.h
Source/WebCore/html/HTMLTableColElement.cpp
Source/WebCore/html/HTMLTableColElement.h
Source/WebCore/html/HTMLTableElement.cpp
Source/WebCore/html/HTMLTableElement.h
Source/WebCore/html/HTMLTablePartElement.cpp
Source/WebCore/html/HTMLTablePartElement.h
Source/WebCore/html/HTMLTextAreaElement.cpp
Source/WebCore/html/HTMLTextAreaElement.h
Source/WebCore/html/HTMLUListElement.cpp
Source/WebCore/html/HTMLUListElement.h
Source/WebCore/html/HTMLVideoElement.cpp
Source/WebCore/html/HTMLVideoElement.h
Source/WebCore/mathml/MathMLElement.cpp
Source/WebCore/mathml/MathMLElement.h
Source/WebCore/svg/SVGImageElement.cpp
Source/WebCore/svg/SVGImageElement.h
Source/WebCore/svg/SVGStyledElement.cpp
Source/WebCore/svg/SVGStyledElement.h
Source/WebCore/svg/SVGTextContentElement.cpp
Source/WebCore/svg/SVGTextContentElement.h

index 6e75b1f..9fd5d29 100644 (file)
@@ -1,3 +1,206 @@
+2012-02-11  Andreas Kling  <awesomekling@apple.com>
+
+        Attribute styles should be created lazily.
+        <http://webkit.org/b/78381>
+
+        Reviewed by Antti Koivisto.
+
+        TL;DR summary: Lazily construct the StyledElement::attributeStyle() instead of
+        moving properties in/out of it in parseAttribute(). This allows us to enable
+        the matched declaration cache for elements with presentation attributes.
+
+        The matched declaration cache has been disabled for elements with presentation
+        attributes because attributeStyle() was mutable, and (simply put) the cache maps
+        a set of StylePropertySet pointers to a resulting RenderStyle. This requires
+        that the StylePropertySets are immutable.
+
+        To make them immutable, we now construct the attribute style lazily by adding
+        a flag (to Node) that gets set in parseAttribute() when a presentation attribute
+        respected by the element changes. A subsequent call to attributeStyle() checks
+        the flag and rebuilds the style by looping over the attributes and calling the
+        new virtual StyledElement::collectStyleForAttribute() on each one. Any dangling
+        references to the previous attribute style will be garbage collected by the
+        cache in CSSStyleSelector::sweepMatchedDeclarationCache().
+
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::matchAllRules):
+
+            Enable matched declaration cache for elements with attribute style.
+
+        * dom/Node.h:
+        (WebCore::Node::attributeStyleDirty):
+        (WebCore::Node::setAttributeStyleDirty):
+        (WebCore::Node::clearAttributeStyleDirty):
+
+            Add a Node flag to signify that a presentation attribute has changed and
+            the attribute style needs to be rebuilt.
+
+        * dom/ElementAttributeData.h:
+        * dom/ElementAttributeData.cpp:
+        (WebCore::ElementAttributeData::setAttributeStyle):
+
+            Added a setter for the attribute style, called by updateAttributeStyle().
+
+        * dom/StyledElement.cpp:
+        (WebCore::StyledElement::addHTMLLengthToStyle):
+        (WebCore::StyledElement::addHTMLColorToStyle):
+
+            Moved and renamed two of the old addCSS* helpers from StyledElement.
+
+        (WebCore::StyledElement::updateAttributeStyle):
+
+            Called by attributeStyle() in case the "attribute style dirty" flag is
+            set. Rebuilds the attribute style from scratch by looping over the
+            attribute map and calling collectStyleForAttribute() on each attribute.
+
+        * dom/StyledElement.h:
+        (WebCore::StyledElement::collectStyleForAttribute):
+        (WebCore::StyledElement::attributeStyle):
+        (WebCore::StyledElement::setNeedsAttributeStyleUpdate):
+
+            Helper, sets the attribute style dirty flag and marks the element for
+            full style recalc. This is what parseAttribute() calls in subclasses
+            when they encounter a presentation attribute.
+
+        * html/HTMLBRElement.cpp:
+        (WebCore::HTMLBRElement::collectStyleForAttribute):
+        (WebCore::HTMLBRElement::parseAttribute):
+        * html/HTMLBRElement.h:
+        * html/HTMLBodyElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLBodyElement::collectStyleForAttribute):
+        (WebCore::HTMLBodyElement::parseAttribute):
+        * html/HTMLBodyElement.h:
+        * html/HTMLDivElement.cpp:
+        (WebCore::HTMLDivElement::collectStyleForAttribute):
+        (WebCore::HTMLDivElement::parseAttribute):
+        * html/HTMLDivElement.h:
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::applyBorderAttributeToStyle):
+        (WebCore::HTMLElement::mapLanguageAttributeToLocale):
+        (WebCore::HTMLElement::collectStyleForAttribute):
+        (WebCore::HTMLElement::parseAttribute):
+        (WebCore::HTMLElement::applyAlignmentAttributeToStyle):
+        * html/HTMLElement.h:
+        * html/HTMLEmbedElement.cpp:
+        (WebCore::HTMLEmbedElement::collectStyleForAttribute):
+        (WebCore::HTMLEmbedElement::parseAttribute):
+        * html/HTMLEmbedElement.h:
+        * html/HTMLFontElement.cpp:
+        (WebCore::HTMLFontElement::collectStyleForAttribute):
+        (WebCore::HTMLFontElement::parseAttribute):
+        * html/HTMLFontElement.h:
+        * html/HTMLFrameSetElement.cpp:
+        (WebCore::HTMLFrameSetElement::collectStyleForAttribute):
+        (WebCore::HTMLFrameSetElement::parseAttribute):
+        * html/HTMLFrameSetElement.h:
+        * html/HTMLHRElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLHRElement::collectStyleForAttribute):
+        (WebCore::HTMLHRElement::parseAttribute):
+        * html/HTMLHRElement.h:
+        * html/HTMLIFrameElement.cpp:
+        (WebCore::HTMLIFrameElement::collectStyleForAttribute):
+        (WebCore::HTMLIFrameElement::parseAttribute):
+        * html/HTMLIFrameElement.h:
+        * html/HTMLImageElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLImageElement::collectStyleForAttribute):
+        (WebCore::HTMLImageElement::parseAttribute):
+        * html/HTMLImageElement.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLInputElement::collectStyleForAttribute):
+        (WebCore::HTMLInputElement::parseAttribute):
+        * html/HTMLInputElement.h:
+        * html/HTMLLIElement.cpp:
+        (WebCore::HTMLLIElement::collectStyleForAttribute):
+        (WebCore::HTMLLIElement::parseAttribute):
+        * html/HTMLLIElement.h:
+        * html/HTMLMarqueeElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLMarqueeElement::collectStyleForAttribute):
+        (WebCore::HTMLMarqueeElement::parseAttribute):
+        * html/HTMLMarqueeElement.h:
+        * html/HTMLOListElement.cpp:
+        (WebCore::HTMLOListElement::collectStyleForAttribute):
+        (WebCore::HTMLOListElement::parseAttribute):
+        * html/HTMLOListElement.h:
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::collectStyleForAttribute):
+        (WebCore::HTMLObjectElement::parseAttribute):
+        * html/HTMLObjectElement.h:
+        * html/HTMLParagraphElement.cpp:
+        (WebCore::HTMLParagraphElement::collectStyleForAttribute):
+        (WebCore::HTMLParagraphElement::parseAttribute):
+        * html/HTMLParagraphElement.h:
+        * html/HTMLPlugInElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLPlugInElement::collectStyleForAttribute):
+        (WebCore::HTMLPlugInElement::parseAttribute):
+        * html/HTMLPlugInElement.h:
+        * html/HTMLPreElement.cpp:
+        (WebCore::HTMLPreElement::collectStyleForAttribute):
+        (WebCore::HTMLPreElement::parseAttribute):
+        * html/HTMLPreElement.h:
+        * html/HTMLTableCaptionElement.cpp:
+        (WebCore::HTMLTableCaptionElement::collectStyleForAttribute):
+        (WebCore::HTMLTableCaptionElement::parseAttribute):
+        * html/HTMLTableCaptionElement.h:
+        * html/HTMLTableCellElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLTableCellElement::collectStyleForAttribute):
+        (WebCore::HTMLTableCellElement::parseAttribute):
+        * html/HTMLTableCellElement.h:
+        * html/HTMLTableColElement.cpp:
+        (WebCore::HTMLTableColElement::collectStyleForAttribute):
+        (WebCore::HTMLTableColElement::parseAttribute):
+        * html/HTMLTableColElement.h:
+        * html/HTMLTableElement.cpp:
+        (WebCore::getBordersFromFrameAttributeValue):
+        (WebCore::HTMLTableElement::collectStyleForAttribute):
+        (WebCore::HTMLTableElement::parseAttribute):
+        * html/HTMLTableElement.h:
+        * html/HTMLTablePartElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::HTMLTablePartElement::collectStyleForAttribute):
+        (WebCore::HTMLTablePartElement::parseAttribute):
+        * html/HTMLTablePartElement.h:
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::collectStyleForAttribute):
+        (WebCore::HTMLTextAreaElement::parseAttribute):
+        * html/HTMLTextAreaElement.h:
+        * html/HTMLUListElement.cpp:
+        (WebCore::HTMLUListElement::collectStyleForAttribute):
+        (WebCore::HTMLUListElement::parseAttribute):
+        * html/HTMLUListElement.h:
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::collectStyleForAttribute):
+        (WebCore::HTMLVideoElement::parseAttribute):
+        * html/HTMLVideoElement.h:
+        * mathml/MathMLElement.cpp:
+        (WebCore::isRespectedPresentationAttribute):
+        (WebCore::MathMLElement::collectStyleForAttribute):
+        (WebCore::MathMLElement::parseAttribute):
+        * mathml/MathMLElement.h:
+        * svg/SVGImageElement.cpp:
+        (WebCore::SVGImageElement::collectStyleForAttribute):
+        (WebCore::SVGImageElement::parseAttribute):
+        * svg/SVGImageElement.h:
+        * svg/SVGStyledElement.cpp:
+        (WebCore::SVGStyledElement::collectStyleForAttribute):
+        (WebCore::SVGStyledElement::parseAttribute):
+        * svg/SVGStyledElement.h:
+        * svg/SVGTextContentElement.cpp:
+        (WebCore::SVGTextContentElement::collectStyleForAttribute):
+        (WebCore::SVGTextContentElement::parseAttribute):
+        * svg/SVGTextContentElement.h:
+
+            Split handling of presentation attributes between parseAttribute() and
+            collectStyleForAttribute() as appropriate. Some minor refactorings here and
+            there (mostly in HTMLTableElement) to avoid excessive code duplication.
+            Also sprinkled FIXMEs about inefficiencies we should clean up.
+
 2012-02-11   Arko Saha  <arko@motorola.com>
 
         HTML 5: Support click() method on HTMLElement.
index 5568835..4cf2494 100644 (file)
@@ -1002,7 +1002,6 @@ void CSSStyleSelector::matchAllRules(MatchResult& result)
                 if (result.ranges.firstAuthorRule == -1)
                     result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
                 addMatchedDeclaration(attributeStyle);
-                result.isCacheable = false;
             }
         }
 
index cea62f3..4d1b639 100644 (file)
@@ -53,11 +53,4 @@ void ElementAttributeData::destroyInlineStyleDecl()
     m_inlineStyleDecl = 0;
 }
 
-StylePropertySet* ElementAttributeData::ensureAttributeStyle(StyledElement* element)
-{
-    if (!m_attributeStyle)
-        m_attributeStyle = StylePropertySet::createAttributeStyle(element);
-    return m_attributeStyle.get();
-}
-
 }
index 4080659..8203d2f 100644 (file)
@@ -47,7 +47,7 @@ public:
     void destroyInlineStyleDecl();
 
     StylePropertySet* attributeStyle() const { return m_attributeStyle.get(); }
-    StylePropertySet* ensureAttributeStyle(StyledElement*);
+    void setAttributeStyle(PassRefPtr<StylePropertySet> style) { m_attributeStyle = style; }
 
 private:
     friend class NamedNodeMap;
index b1981d7..e1bbea5 100644 (file)
@@ -300,6 +300,7 @@ public:
     virtual bool sheetLoaded() { return true; }
     virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); }
 
+    bool attributeStyleDirty() const { return getFlag(AttributeStyleDirtyFlag); }
     bool hasName() const { return getFlag(HasNameFlag); }
     bool hasID() const { return getFlag(HasIDFlag); }
     bool hasClass() const { return getFlag(HasClassFlag); }
@@ -315,6 +316,9 @@ public:
     bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
     bool isLink() const { return getFlag(IsLinkFlag); }
 
+    void setAttributeStyleDirty() { setFlag(AttributeStyleDirtyFlag); }
+    void clearAttributeStyleDirty() { clearFlag(AttributeStyleDirtyFlag); }
+
     void setHasName(bool f) { setFlag(f, HasNameFlag); }
     void setHasID(bool f) { setFlag(f, HasIDFlag); }
     void setHasClass(bool f) { setFlag(f, HasClassFlag); }
@@ -676,6 +680,8 @@ private:
 
         HasNameFlag = 1 << 30,
 
+        AttributeStyleDirtyFlag = 1 << 31,
+
 #if ENABLE(SVG)
         DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag | AreSVGAttributesValidFlag
 #else
index 5260526..8d3d8fa 100644 (file)
@@ -105,192 +105,21 @@ void StyledElement::parseAttribute(Attribute* attr)
     }
 }
 
-void StyledElement::removeCSSProperties(int id1, int id2, int id3, int id4, int id5, int id6, int id7, int id8)
-{
-    StylePropertySet* style = attributeStyle();
-    if (!style)
-        return;
-
-    ASSERT(id1 != CSSPropertyInvalid);
-    style->removeProperty(id1);
-
-    if (id2 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id2);
-    if (id3 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id3);
-    if (id4 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id4);
-    if (id5 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id5);
-    if (id6 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id6);
-    if (id7 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id7);
-    if (id8 == CSSPropertyInvalid)
-        return;
-    style->removeProperty(id8);
-}
-
-void StyledElement::addCSSProperty(int id, const String &value)
-{
-    if (!ensureAttributeStyle()->setProperty(id, value))
-        removeCSSProperty(id);
-}
-
-void StyledElement::addCSSProperty(int propertyID, int identifier)
-{
-    ensureAttributeStyle()->setProperty(CSSProperty(propertyID, document()->cssValuePool()->createIdentifierValue(identifier)));
-    setNeedsStyleRecalc();
-}
-
-void StyledElement::addCSSImageProperty(int id, const String& url)
-{
-    ensureAttributeStyle()->setProperty(CSSProperty(id, CSSImageValue::create(url)));
-    setNeedsStyleRecalc();
-}
-
-void StyledElement::addCSSLength(int id, const String &value)
-{
-    // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
-    // length unit and make the appropriate parsed value.
-
-    // strip attribute garbage..
-    StringImpl* v = value.impl();
-    if (v) {
-        unsigned int l = 0;
-        
-        while (l < v->length() && (*v)[l] <= ' ')
-            l++;
-        
-        for (; l < v->length(); l++) {
-            UChar cc = (*v)[l];
-            if (cc > '9')
-                break;
-            if (cc < '0') {
-                if (cc == '%' || cc == '*')
-                    l++;
-                if (cc != '.')
-                    break;
-            }
-        }
-
-        if (l != v->length()) {
-            addCSSProperty(id, v->substring(0, l));
-            return;
-        }
-    }
-
-    addCSSProperty(id, value);
-}
-
-static String parseColorStringWithCrazyLegacyRules(const String& colorString)
+void StyledElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
 {
-    // Per spec, only look at the first 128 digits of the string.
-    const size_t maxColorLength = 128;
-    // We'll pad the buffer with two extra 0s later, so reserve two more than the max.
-    Vector<char, maxColorLength+2> digitBuffer;
-    
-    size_t i = 0;
-    // Skip a leading #.
-    if (colorString[0] == '#')
-        i = 1;
-    
-    // Grab the first 128 characters, replacing non-hex characters with 0.
-    // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String.
-    for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) {
-        if (!isASCIIHexDigit(colorString[i]))
-            digitBuffer.append('0');
-        else
-            digitBuffer.append(colorString[i]);
-    }
-
-    if (!digitBuffer.size())
-        return "#000000";
-
-    // Pad the buffer out to at least the next multiple of three in size.
-    digitBuffer.append('0');
-    digitBuffer.append('0');
-
-    if (digitBuffer.size() < 6)
-        return String::format("#0%c0%c0%c", digitBuffer[0], digitBuffer[1], digitBuffer[2]);
-    
-    // Split the digits into three components, then search the last 8 digits of each component.
-    ASSERT(digitBuffer.size() >= 6);
-    size_t componentLength = digitBuffer.size() / 3;
-    size_t componentSearchWindowLength = min<size_t>(componentLength, 8);
-    size_t redIndex = componentLength - componentSearchWindowLength;
-    size_t greenIndex = componentLength * 2 - componentSearchWindowLength;
-    size_t blueIndex = componentLength * 3 - componentSearchWindowLength;
-    // Skip digits until one of them is non-zero, or we've only got two digits left in the component.
-    while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) {
-        redIndex++;
-        greenIndex++;
-        blueIndex++;
-    }
-    ASSERT(redIndex + 1 < componentLength);
-    ASSERT(greenIndex >= componentLength);
-    ASSERT(greenIndex + 1 < componentLength * 2);
-    ASSERT(blueIndex >= componentLength * 2);
-    ASSERT(blueIndex + 1 < digitBuffer.size());
-    return String::format("#%c%c%c%c%c%c", digitBuffer[redIndex], digitBuffer[redIndex + 1], digitBuffer[greenIndex], digitBuffer[greenIndex + 1], digitBuffer[blueIndex], digitBuffer[blueIndex + 1]);   
+    if (StylePropertySet* inlineStyle = inlineStyleDecl())
+        inlineStyle->addSubresourceStyleURLs(urls);
 }
 
-// Color parsing that matches HTML's "rules for parsing a legacy color value"
-void StyledElement::addCSSColor(int id, const String& attributeValue)
+void StyledElement::updateAttributeStyle()
 {
-    // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.)
-    if (attributeValue.isEmpty()) {
-        removeCSSProperty(id);
-        return;
+    RefPtr<StylePropertySet> style = StylePropertySet::createAttributeStyle(this);
+    for (unsigned i = 0; i < attributeCount(); ++i) {
+        Attribute* attribute = attributeItem(i);
+        collectStyleForAttribute(attribute, style.get());
     }
-
-    String colorString = attributeValue.stripWhiteSpace();
-
-    // "transparent" doesn't apply a color either.
-    if (equalIgnoringCase(colorString, "transparent")) {
-        removeCSSProperty(id);
-        return;
-    }
-
-    // If the string is a named CSS color or a 3/6-digit hex color, use that.
-    Color parsedColor(colorString);
-    if (parsedColor.isValid()) {
-        addCSSProperty(id, colorString);
-        return;
-    }
-
-    addCSSProperty(id, parseColorStringWithCrazyLegacyRules(colorString));
-}
-
-void StyledElement::copyNonAttributeProperties(const Element* sourceElement)
-{
-    ASSERT(sourceElement);
-    ASSERT(sourceElement->isStyledElement());
-
-    const StyledElement* source = static_cast<const StyledElement*>(sourceElement);
-    if (!source->inlineStyleDecl())
-        return;
-
-    StylePropertySet* inlineStyle = ensureInlineStyleDecl();
-    inlineStyle->copyPropertiesFrom(*source->inlineStyleDecl());
-    inlineStyle->setStrictParsing(source->inlineStyleDecl()->useStrictParsing());
-
-    setIsStyleAttributeValid(source->isStyleAttributeValid());
-    setIsSynchronizingStyleAttribute(source->isSynchronizingStyleAttribute());
-    
-    Element::copyNonAttributeProperties(sourceElement);
-}
-
-void StyledElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
-{
-    if (StylePropertySet* inlineStyle = inlineStyleDecl())
-        inlineStyle->addSubresourceStyleURLs(urls);
+    clearAttributeStyleDirty();
+    ensureAttributeDataWithoutUpdate()->setAttributeStyle(style.release());
 }
 
 }
index 2a6d392..3fa2669 100644 (file)
@@ -36,14 +36,6 @@ class StyledElement : public Element {
 public:
     virtual ~StyledElement();
 
-    void addCSSLength(int id, const String& value);
-    void addCSSProperty(int id, const String& value);
-    void addCSSProperty(int id, int value);
-    void addCSSImageProperty(int propertyID, const String& url);
-    void addCSSColor(int id, const String& color);
-    void removeCSSProperties(int id1, int id2 = CSSPropertyInvalid, int id3 = CSSPropertyInvalid, int id4 = CSSPropertyInvalid, int id5 = CSSPropertyInvalid, int id6 = CSSPropertyInvalid, int id7 = CSSPropertyInvalid, int id8 = CSSPropertyInvalid);
-    void removeCSSProperty(int id) { removeCSSProperties(id); }
-
     virtual StylePropertySet* additionalAttributeStyle() { return 0; }
     void invalidateStyleAttribute();
 
@@ -51,8 +43,7 @@ public:
     StylePropertySet* ensureInlineStyleDecl() { return ensureAttributeDataWithoutUpdate()->ensureInlineStyleDecl(this); }
     virtual CSSStyleDeclaration* style() OVERRIDE { return ensureInlineStyleDecl()->ensureCSSStyleDeclaration(); }
 
-    StylePropertySet* attributeStyle() const { return attributeData() ? attributeData()->attributeStyle() : 0; }
-    StylePropertySet* ensureAttributeStyle() { return ensureAttributeDataWithoutUpdate()->ensureAttributeStyle(this); }
+    StylePropertySet* attributeStyle();
 
     const SpaceSplitString& classNames() const;
 
@@ -62,10 +53,14 @@ protected:
     {
     }
 
+    void setNeedsAttributeStyleUpdate();
+
     virtual void attributeChanged(Attribute*) OVERRIDE;
     virtual void parseAttribute(Attribute*);
     virtual void copyNonAttributeProperties(const Element*);
 
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) { }
+
     virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
 
     // classAttributeChanged() exists to share code between
@@ -76,6 +71,8 @@ protected:
 private:
     virtual void updateStyleAttribute() const;
 
+    void updateAttributeStyle();
+
     void destroyInlineStyleDecl()
     {
         if (attributeData())
@@ -95,6 +92,19 @@ inline void StyledElement::invalidateStyleAttribute()
     clearIsStyleAttributeValid();
 }
 
+inline StylePropertySet* StyledElement::attributeStyle()
+{
+    if (attributeStyleDirty())
+        updateAttributeStyle();
+    return attributeData() ? attributeData()->attributeStyle() : 0;
+}
+
+inline void StyledElement::setNeedsAttributeStyleUpdate()
+{
+    setAttributeStyleDirty();
+    setNeedsStyleRecalc();
+}
+
 } //namespace
 
 #endif
index 5efe637..84ea107 100644 (file)
@@ -48,20 +48,26 @@ PassRefPtr<HTMLBRElement> HTMLBRElement::create(const QualifiedName& tagName, Do
     return adoptRef(new HTMLBRElement(tagName, document));
 }
 
-void HTMLBRElement::parseAttribute(Attribute* attr)
+void HTMLBRElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == clearAttr) {
-        // If the string is empty, then don't add the clear property. 
+        // If the string is empty, then don't add the clear property.
         // <br clear> and <br clear=""> are just treated like <br> by Gecko, Mac IE, etc. -dwh
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyClear);
-        else if (!attr->value().isEmpty()) {
+        if (!attr->isEmpty()) {
             if (equalIgnoringCase(attr->value(), "all"))
-                addCSSProperty(CSSPropertyClear, "both");
+                style->setProperty(CSSPropertyClear, "both");
             else
-                addCSSProperty(CSSPropertyClear, attr->value());
+                style->setProperty(CSSPropertyClear, attr->value());
         }
     } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLBRElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == clearAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index 10a6432..cb8c29c 100644 (file)
@@ -39,7 +39,8 @@ private:
     HTMLBRElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
-    
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
+
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 };
 
index a769a2c..91f566d 100644 (file)
@@ -25,6 +25,7 @@
 #include "HTMLBodyElement.h"
 
 #include "Attribute.h"
+#include "CSSImageValue.h"
 #include "CSSParser.h"
 #include "CSSValueKeywords.h"
 #include "EventNames.h"
@@ -60,46 +61,42 @@ HTMLBodyElement::~HTMLBodyElement()
 {
 }
 
-void HTMLBodyElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == backgroundAttr || attr->name() == marginwidthAttr || attr->name() == leftmarginAttr || attr->name() == marginheightAttr || attr->name() == topmarginAttr || attr->name() == bgcolorAttr || attr->name() == textAttr || attr->name() == bgpropertiesAttr;
+
+}
+
+void HTMLBodyElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == backgroundAttr) {
         String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
         if (!url.isEmpty())
-            addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string());
-        else
-            removeCSSProperty(CSSPropertyBackgroundImage);
+            style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string())));
     } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyMarginRight, CSSPropertyMarginLeft);
-        else {
-            addCSSLength(CSSPropertyMarginRight, attr->value());
-            addCSSLength(CSSPropertyMarginLeft, attr->value());
-        }
+        addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
     } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyMarginBottom, CSSPropertyMarginTop);
-        else {
-            addCSSLength(CSSPropertyMarginBottom, attr->value());
-            addCSSLength(CSSPropertyMarginTop, attr->value());
-        }
+        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
     } else if (attr->name() == bgcolorAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyBackgroundColor);
-        else
-            addCSSColor(CSSPropertyBackgroundColor, attr->value());
+        addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value());
     } else if (attr->name() == textAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyColor);
-        else
-            addCSSColor(CSSPropertyColor, attr->value());
+        addHTMLColorToStyle(style, CSSPropertyColor, attr->value());
     } else if (attr->name() == bgpropertiesAttr) {
         if (equalIgnoringCase(attr->value(), "fixed"))
-            addCSSProperty(CSSPropertyBackgroundAttachment, CSSValueFixed);
-        else
-            removeCSSProperty(CSSPropertyBackgroundAttachment);
-    } else if (attr->name() == vlinkAttr ||
-               attr->name() == alinkAttr ||
-               attr->name() == linkAttr) {
+           style->setProperty(CSSPropertyBackgroundAttachment, CSSValueFixed);
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLBodyElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == vlinkAttr || attr->name() == alinkAttr || attr->name() == linkAttr) {
         if (attr->isNull()) {
             if (attr->name() == linkAttr)
                 document()->resetLinkColor();
index 8004b10..32cba8a 100644 (file)
@@ -71,6 +71,7 @@ private:
     HTMLBodyElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void insertedIntoDocument();
     
index da2785c..0ac4c5c 100644 (file)
@@ -48,20 +48,26 @@ PassRefPtr<HTMLDivElement> HTMLDivElement::create(const QualifiedName& tagName,
     return adoptRef(new HTMLDivElement(tagName, document));
 }
 
-void HTMLDivElement::parseAttribute(Attribute* attr)
+void HTMLDivElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == alignAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyTextAlign);
         if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center"))
-           addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
         else if (equalIgnoringCase(attr->value(), "left"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
         else if (equalIgnoringCase(attr->value(), "right"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
         else
-            addCSSProperty(CSSPropertyTextAlign, attr->value());
+            style->setProperty(CSSPropertyTextAlign, attr->value());
     } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLDivElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == alignAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index cd90d87..615774f 100644 (file)
@@ -37,6 +37,7 @@ protected:
 
 private:
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace WebCore
index a018fe2..3319350 100644 (file)
@@ -140,51 +140,81 @@ static unsigned parseBorderWidthAttribute(Attribute* attr)
     return borderWidth;
 }
 
-void HTMLElement::applyBorderAttribute(Attribute* attr)
+void HTMLElement::applyBorderAttributeToStyle(Attribute* attr, StylePropertySet* style)
 {
-    addCSSLength(CSSPropertyBorderWidth, String::number(parseBorderWidthAttribute(attr)));
-    addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
-    addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
-    addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
-    addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
+    style->setProperty(CSSPropertyBorderWidth, String::number(parseBorderWidthAttribute(attr)));
+    style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
+    style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
+    style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
+    style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
 }
 
-void HTMLElement::mapLanguageAttributeToLocale(Attribute* attribute)
+void HTMLElement::mapLanguageAttributeToLocale(Attribute* attribute, StylePropertySet* style)
 {
     ASSERT(attribute && (attribute->name() == langAttr || attribute->name().matches(XMLNames::langAttr)));
-    const AtomicString& value = attribute->value();
-    if (value.isNull())
-        removeCSSProperty(CSSPropertyWebkitLocale);
-    else if (!value.isEmpty()) {
+    if (!attribute->isEmpty()) {
         // Have to quote so the locale id is treated as a string instead of as a CSS keyword.
-        addCSSProperty(CSSPropertyWebkitLocale, quoteCSSString(value));
+        style->setProperty(CSSPropertyWebkitLocale, quoteCSSString(attribute->value()));
     } else {
         // The empty string means the language is explicitly unknown.
-        addCSSProperty(CSSPropertyWebkitLocale, CSSValueAuto);
+        style->setProperty(CSSPropertyWebkitLocale, CSSValueAuto);
     }
-    setNeedsStyleRecalc();
 }
 
-void HTMLElement::parseAttribute(Attribute* attr)
+void HTMLElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
-    if (isIdAttributeName(attr->name()) || attr->name() == classAttr || attr->name() == styleAttr)
-        return StyledElement::parseAttribute(attr);
-
     if (attr->name() == alignAttr) {
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyTextAlign);
-        else if (equalIgnoringCase(attr->value(), "middle"))
-            addCSSProperty(CSSPropertyTextAlign, "center");
+        if (equalIgnoringCase(attr->value(), "middle"))
+            style->setProperty(CSSPropertyTextAlign, "center");
         else
-            addCSSProperty(CSSPropertyTextAlign, attr->value());
+            style->setProperty(CSSPropertyTextAlign, attr->value());
     } else if (attr->name() == contenteditableAttr) {
-        setContentEditable(attr);
+        if (attr->isEmpty() || equalIgnoringCase(attr->value(), "true")) {
+            style->setProperty(CSSPropertyWebkitUserModify, CSSValueReadWrite);
+            style->setProperty(CSSPropertyWordWrap, CSSValueBreakWord);
+            style->setProperty(CSSPropertyWebkitNbspMode, CSSValueSpace);
+            style->setProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
+        } else if (equalIgnoringCase(attr->value(), "plaintext-only")) {
+            style->setProperty(CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
+            style->setProperty(CSSPropertyWordWrap, CSSValueBreakWord);
+            style->setProperty(CSSPropertyWebkitNbspMode, CSSValueSpace);
+            style->setProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
+        } else if (equalIgnoringCase(attr->value(), "false"))
+            style->setProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly);
     } else if (attr->name() == hiddenAttr) {
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyDisplay);
-        else
-            addCSSProperty(CSSPropertyDisplay, CSSValueNone);
-    } else if (attr->name() == tabindexAttr) {
+        style->setProperty(CSSPropertyDisplay, CSSValueNone);
+    } else if (attr->name() == draggableAttr) {
+        if (equalIgnoringCase(attr->value(), "true")) {
+            style->setProperty(CSSPropertyWebkitUserDrag, CSSValueElement);
+            style->setProperty(CSSPropertyWebkitUserSelect, CSSValueNone);
+        } else if (equalIgnoringCase(attr->value(), "false"))
+            style->setProperty(CSSPropertyWebkitUserDrag, CSSValueNone);
+    } else if (attr->name() == dirAttr) {
+        if (equalIgnoringCase(attr->value(), "auto"))
+            style->setProperty(CSSPropertyUnicodeBidi, unicodeBidiAttributeForDirAuto(this));
+        else {
+            style->setProperty(CSSPropertyDirection, attr->value());
+            if (!hasTagName(bdiTag) && !hasTagName(bdoTag) && !hasTagName(outputTag))
+                style->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed);
+        }
+    } else if (attr->name().matches(XMLNames::langAttr)) {
+        mapLanguageAttributeToLocale(attr, style);
+    } else if (attr->name() == langAttr) {
+        // xml:lang has a higher priority than lang.
+        if (!fastHasAttribute(XMLNames::langAttr))
+            mapLanguageAttributeToLocale(attr, style);
+    } else
+        StyledElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLElement::parseAttribute(Attribute* attr)
+{
+    if (isIdAttributeName(attr->name()) || attr->name() == classAttr || attr->name() == styleAttr)
+        return StyledElement::parseAttribute(attr);
+
+    if (attr->name() == alignAttr || attr->name() == contenteditableAttr || attr->name() == hiddenAttr || attr->name() == langAttr || attr->name().matches(XMLNames::langAttr) || attr->name() == draggableAttr)
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == tabindexAttr) {
         int tabindex = 0;
         if (attr->isEmpty())
             clearTabIndexExplicitly();
@@ -192,40 +222,9 @@ void HTMLElement::parseAttribute(Attribute* attr)
             // Clamp tabindex to the range of 'short' to match Firefox's behavior.
             setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
         }
-    } else if (attr->name().matches(XMLNames::langAttr)) {
-        mapLanguageAttributeToLocale(attr);
-    } else if (attr->name() == langAttr) {
-        // xml:lang has a higher priority than lang.
-        if (!fastHasAttribute(XMLNames::langAttr))
-            mapLanguageAttributeToLocale(attr);
     } else if (attr->name() == dirAttr) {
-        if (attr->isNull())
-            removeCSSProperties(CSSPropertyDirection, CSSPropertyUnicodeBidi);
-        else {
-            bool dirIsAuto = equalIgnoringCase(attr->value(), "auto");
-            if (!dirIsAuto)
-                addCSSProperty(CSSPropertyDirection, attr->value());
-            else
-                removeCSSProperty(CSSPropertyDirection);
-
-            dirAttributeChanged(attr);
-            if (dirIsAuto)
-                addCSSProperty(CSSPropertyUnicodeBidi, unicodeBidiAttributeForDirAuto(this));
-            else if (!hasTagName(bdiTag) && !hasTagName(bdoTag) && !hasTagName(outputTag))
-                addCSSProperty(CSSPropertyUnicodeBidi, CSSValueEmbed);
-            else
-                removeCSSProperty(CSSPropertyUnicodeBidi);
-        }
-    } else if (attr->name() == draggableAttr) {
-        const AtomicString& value = attr->value();
-        if (equalIgnoringCase(value, "true")) {
-            addCSSProperty(CSSPropertyWebkitUserDrag, CSSValueElement);
-            addCSSProperty(CSSPropertyWebkitUserSelect, CSSValueNone);
-        } else if (equalIgnoringCase(value, "false")) {
-            addCSSProperty(CSSPropertyWebkitUserDrag, CSSValueNone);
-            removeCSSProperty(CSSPropertyWebkitUserSelect);
-        } else
-            removeCSSProperties(CSSPropertyWebkitUserDrag, CSSPropertyWebkitUserSelect);
+        setNeedsAttributeStyleUpdate();
+        dirAttributeChanged(attr);
 #if ENABLE(MICRODATA)
     } else if (attr->name() == itempropAttr) {
         setItemProp(attr->value());
@@ -678,17 +677,7 @@ void HTMLElement::insertAdjacentText(const String& where, const String& text, Ex
     insertAdjacent(where, textNode.get(), ec);
 }
 
-void HTMLElement::addHTMLAlignment(Attribute* attr)
-{
-    addHTMLAlignmentToStyledElement(this, attr);
-}
-
-void HTMLElement::removeHTMLAlignment()
-{
-    removeCSSProperties(CSSPropertyFloat, CSSPropertyVerticalAlign);
-}
-
-void HTMLElement::addHTMLAlignmentToStyledElement(StyledElement* element, Attribute* attr)
+void HTMLElement::applyAlignmentAttributeToStyle(Attribute* attr, StylePropertySet* style)
 {
     // Vertical alignment with respect to the current baseline of the text
     // right or left means floating images.
@@ -718,14 +707,10 @@ void HTMLElement::addHTMLAlignmentToStyledElement(StyledElement* element, Attrib
         verticalAlignValue = CSSValueTextTop;
 
     if (floatValue != CSSValueInvalid)
-        element->addCSSProperty(CSSPropertyFloat, floatValue);
-    else
-        element->removeCSSProperty(CSSPropertyFloat);
+        style->setProperty(CSSPropertyFloat, floatValue);
 
     if (verticalAlignValue != CSSValueInvalid)
-        element->addCSSProperty(CSSPropertyVerticalAlign, verticalAlignValue);
-    else
-        element->removeCSSProperty(CSSPropertyVerticalAlign);
+        style->setProperty(CSSPropertyVerticalAlign, verticalAlignValue);
 }
 
 bool HTMLElement::supportsFocus() const
@@ -749,27 +734,6 @@ String HTMLElement::contentEditable() const
     return "inherit";
 }
 
-void HTMLElement::setContentEditable(Attribute* attr) 
-{
-    const AtomicString& enabled = attr->value();
-    if (enabled.isNull())
-        removeCSSProperties(CSSPropertyWebkitUserModify, CSSPropertyWordWrap, CSSPropertyWebkitNbspMode, CSSPropertyWebkitLineBreak);
-    else if (enabled.isEmpty() || equalIgnoringCase(enabled, "true")) {
-        addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadWrite);
-        addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord);
-        addCSSProperty(CSSPropertyWebkitNbspMode, CSSValueSpace);
-        addCSSProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
-    } else if (equalIgnoringCase(enabled, "false")) {
-        addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly);
-        removeCSSProperties(CSSPropertyWordWrap, CSSPropertyWebkitNbspMode, CSSPropertyWebkitLineBreak);
-    } else if (equalIgnoringCase(enabled, "plaintext-only")) {
-        addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
-        addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord);
-        addCSSProperty(CSSPropertyWebkitNbspMode, CSSValueSpace);
-        addCSSProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
-    }
-}
-
 void HTMLElement::setContentEditable(const String& enabled, ExceptionCode& ec)
 {
     if (equalIgnoringCase(enabled, "true"))
@@ -1065,6 +1029,135 @@ void HTMLElement::setItemValueText(const String& value, ExceptionCode& ec)
 }
 #endif
 
+void HTMLElement::addHTMLLengthToStyle(StylePropertySet* style, int propertyID, const String& value)
+{
+    // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
+    // length unit and make the appropriate parsed value.
+
+    // strip attribute garbage..
+    StringImpl* v = value.impl();
+    if (v) {
+        unsigned int l = 0;
+
+        while (l < v->length() && (*v)[l] <= ' ')
+            l++;
+
+        for (; l < v->length(); l++) {
+            UChar cc = (*v)[l];
+            if (cc > '9')
+                break;
+            if (cc < '0') {
+                if (cc == '%' || cc == '*')
+                    l++;
+                if (cc != '.')
+                    break;
+            }
+        }
+
+        if (l != v->length()) {
+            style->setProperty(propertyID, v->substring(0, l));
+            return;
+        }
+    }
+
+    style->setProperty(propertyID, value);
+}
+
+static String parseColorStringWithCrazyLegacyRules(const String& colorString)
+{
+    // Per spec, only look at the first 128 digits of the string.
+    const size_t maxColorLength = 128;
+    // We'll pad the buffer with two extra 0s later, so reserve two more than the max.
+    Vector<char, maxColorLength+2> digitBuffer;
+
+    size_t i = 0;
+    // Skip a leading #.
+    if (colorString[0] == '#')
+        i = 1;
+
+    // Grab the first 128 characters, replacing non-hex characters with 0.
+    // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String.
+    for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) {
+        if (!isASCIIHexDigit(colorString[i]))
+            digitBuffer.append('0');
+        else
+            digitBuffer.append(colorString[i]);
+    }
+
+    if (!digitBuffer.size())
+        return "#000000";
+
+    // Pad the buffer out to at least the next multiple of three in size.
+    digitBuffer.append('0');
+    digitBuffer.append('0');
+
+    if (digitBuffer.size() < 6)
+        return String::format("#0%c0%c0%c", digitBuffer[0], digitBuffer[1], digitBuffer[2]);
+
+    // Split the digits into three components, then search the last 8 digits of each component.
+    ASSERT(digitBuffer.size() >= 6);
+    size_t componentLength = digitBuffer.size() / 3;
+    size_t componentSearchWindowLength = min<size_t>(componentLength, 8);
+    size_t redIndex = componentLength - componentSearchWindowLength;
+    size_t greenIndex = componentLength * 2 - componentSearchWindowLength;
+    size_t blueIndex = componentLength * 3 - componentSearchWindowLength;
+    // Skip digits until one of them is non-zero, or we've only got two digits left in the component.
+    while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) {
+        redIndex++;
+        greenIndex++;
+        blueIndex++;
+    }
+    ASSERT(redIndex + 1 < componentLength);
+    ASSERT(greenIndex >= componentLength);
+    ASSERT(greenIndex + 1 < componentLength * 2);
+    ASSERT(blueIndex >= componentLength * 2);
+    ASSERT(blueIndex + 1 < digitBuffer.size());
+    return String::format("#%c%c%c%c%c%c", digitBuffer[redIndex], digitBuffer[redIndex + 1], digitBuffer[greenIndex], digitBuffer[greenIndex + 1], digitBuffer[blueIndex], digitBuffer[blueIndex + 1]);
+}
+
+// Color parsing that matches HTML's "rules for parsing a legacy color value"
+void HTMLElement::addHTMLColorToStyle(StylePropertySet* style, int propertyID, const String& attributeValue)
+{
+    // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.)
+    if (attributeValue.isEmpty())
+        return;
+
+    String colorString = attributeValue.stripWhiteSpace();
+
+    // "transparent" doesn't apply a color either.
+    if (equalIgnoringCase(colorString, "transparent"))
+        return;
+
+    // If the string is a named CSS color or a 3/6-digit hex color, use that.
+    Color parsedColor(colorString);
+    if (parsedColor.isValid()) {
+        style->setProperty(propertyID, colorString);
+        return;
+    }
+
+    style->setProperty(propertyID, parseColorStringWithCrazyLegacyRules(colorString));
+}
+
+void StyledElement::copyNonAttributeProperties(const Element* sourceElement)
+{
+    ASSERT(sourceElement);
+    ASSERT(sourceElement->isStyledElement());
+
+    const StyledElement* source = static_cast<const StyledElement*>(sourceElement);
+    if (!source->inlineStyleDecl())
+        return;
+
+    StylePropertySet* inlineStyle = ensureInlineStyleDecl();
+    inlineStyle->copyPropertiesFrom(*source->inlineStyleDecl());
+    inlineStyle->setStrictParsing(source->inlineStyleDecl()->useStrictParsing());
+
+    setIsStyleAttributeValid(source->isStyleAttributeValid());
+    setIsSynchronizingStyleAttribute(source->isSynchronizingStyleAttribute());
+    
+    Element::copyNonAttributeProperties(sourceElement);
+}
+
+
 } // namespace WebCore
 
 #ifndef NDEBUG
index 4719726..81e7767 100644 (file)
@@ -79,8 +79,6 @@ public:
 
     HTMLFormElement* form() const { return virtualForm(); }
 
-    static void addHTMLAlignmentToStyledElement(StyledElement*, Attribute*);
-
     HTMLFormElement* findFormAncestor() const;
 
     TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const;
@@ -93,11 +91,14 @@ public:
 protected:
     HTMLElement(const QualifiedName& tagName, Document*);
 
-    void addHTMLAlignment(Attribute*);
-    void removeHTMLAlignment();
+    static void addHTMLLengthToStyle(StylePropertySet*, int propertyID, const String& value);
+    static void addHTMLColorToStyle(StylePropertySet*, int propertyID, const String& color);
+
+    void applyAlignmentAttributeToStyle(Attribute*, StylePropertySet*);
+    void applyBorderAttributeToStyle(Attribute*, StylePropertySet*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
-    void applyBorderAttribute(Attribute*);
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
     void calculateAndAdjustDirectionality();
@@ -107,9 +108,7 @@ protected:
 private:
     virtual String nodeName() const;
 
-    void mapLanguageAttributeToLocale(Attribute*);
-
-    void setContentEditable(Attribute*);
+    void mapLanguageAttributeToLocale(Attribute*, StylePropertySet*);
 
     virtual HTMLFormElement* virtualForm() const;
 
index 748c09b..064e1b0 100644 (file)
@@ -74,6 +74,17 @@ RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings()
     return findWidgetRenderer(this);
 }
 
+void HTMLEmbedElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == hiddenAttr) {
+        if (equalIgnoringCase(attr->value(), "yes") || equalIgnoringCase(attr->value(), "true")) {
+            addHTMLLengthToStyle(style, CSSPropertyWidth, "0"); // FIXME: Pass as integer.
+            addHTMLLengthToStyle(style, CSSPropertyHeight, "0"); // FIXME: Pass as integer.
+        }
+    } else
+        HTMLPlugInImageElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLEmbedElement::parseAttribute(Attribute* attr)
 {
     const AtomicString& value = attr->value();
@@ -94,15 +105,9 @@ void HTMLEmbedElement::parseAttribute(Attribute* attr)
                 m_imageLoader = adoptPtr(new HTMLImageLoader(this));
             m_imageLoader->updateFromElementIgnoringPreviousError();
         }
-    } else if (attr->name() == hiddenAttr) {
-        if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) {
-            // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now
-            // that this rarely-used attribute won't work properly if you remove it.
-            addCSSLength(CSSPropertyWidth, "0");
-            addCSSLength(CSSPropertyHeight, "0");
-        } else
-            removeCSSProperties(CSSPropertyWidth, CSSPropertyHeight);
-    } else
+    } else if (attr->name() == hiddenAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLPlugInImageElement::parseAttribute(attr);
 }
 
index f377603..a8b680f 100644 (file)
@@ -35,6 +35,7 @@ private:
     HTMLEmbedElement(const QualifiedName&, Document*, bool createdByParser);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual bool rendererIsNeeded(const NodeRenderingContext&);
     virtual void insertedIntoDocument();
index 86f5298..cbde05d 100644 (file)
@@ -158,25 +158,25 @@ bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, int& size)
     return true;
 }
 
-void HTMLFontElement::parseAttribute(Attribute* attr)
+void HTMLFontElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == sizeAttr) {
         int size = 0;
         if (cssValueFromFontSizeNumber(attr->value(), size))
-            addCSSProperty(CSSPropertyFontSize, size);
-        else
-            removeCSSProperty(CSSPropertyFontSize);
-    } else if (attr->name() == colorAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyColor);
-        else
-            addCSSColor(CSSPropertyColor, attr->value());
-    } else if (attr->name() == faceAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyFontFamily);
-        else
-            addCSSProperty(CSSPropertyFontFamily, attr->value());
-    else
+            style->setProperty(CSSPropertyFontSize, size);
+    } else if (attr->name() == colorAttr)
+        addHTMLColorToStyle(style, CSSPropertyColor, attr->value());
+    else if (attr->name() == faceAttr)
+        style->setProperty(CSSPropertyFontFamily, attr->value());
+    else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLFontElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == sizeAttr || attr->name() == colorAttr || attr->name() == faceAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index eea8b44..5fe9af8 100644 (file)
@@ -38,6 +38,7 @@ private:
     HTMLFontElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace
index 4af6342..6d80710 100644 (file)
@@ -64,6 +64,14 @@ PassRefPtr<HTMLFrameSetElement> HTMLFrameSetElement::create(const QualifiedName&
     return adoptRef(new HTMLFrameSetElement(tagName, document));
 }
 
+void HTMLFrameSetElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == bordercolorAttr)
+        addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value());
+    else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLFrameSetElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == rowsAttr) {
@@ -100,10 +108,7 @@ void HTMLFrameSetElement::parseAttribute(Attribute* attr)
             m_borderSet = false;
     } else if (attr->name() == bordercolorAttr) {
         m_borderColorSet = !attr->isEmpty();
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyBorderColor);
-        else
-            addCSSColor(CSSPropertyBorderColor, attr->value());
+        setNeedsAttributeStyleUpdate();
     } else if (attr->name() == onloadAttr)
         document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr));
     else if (attr->name() == onbeforeunloadAttr)
index 1879023..f8baf72 100644 (file)
@@ -68,6 +68,7 @@ private:
     HTMLFrameSetElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void attach();
     virtual bool rendererIsNeeded(const NodeRenderingContext&);
index 5534b92..f377efd 100644 (file)
@@ -48,69 +48,63 @@ PassRefPtr<HTMLHRElement> HTMLHRElement::create(const QualifiedName& tagName, Do
     return adoptRef(new HTMLHRElement(tagName, document));
 }
 
-void HTMLHRElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == alignAttr || attr->name() == widthAttr || attr->name() == colorAttr || attr->name() == noshadeAttr || attr->name() == sizeAttr;
+}
+
+void HTMLHRElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == alignAttr) {
-        if (attr->value().isNull()) {
-            removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight);
-        } else if (equalIgnoringCase(attr->value(), "left")) {
-            addCSSProperty(CSSPropertyMarginLeft, "0");
-            addCSSProperty(CSSPropertyMarginRight, CSSValueAuto);
+        if (equalIgnoringCase(attr->value(), "left")) {
+            style->setProperty(CSSPropertyMarginLeft, "0"); // FIXME: Pass as integer.
+            style->setProperty(CSSPropertyMarginRight, CSSValueAuto);
         } else if (equalIgnoringCase(attr->value(), "right")) {
-            addCSSProperty(CSSPropertyMarginLeft, CSSValueAuto);
-            addCSSProperty(CSSPropertyMarginRight, "0");
+            style->setProperty(CSSPropertyMarginLeft, CSSValueAuto);
+            style->setProperty(CSSPropertyMarginRight, "0"); // FIXME: Pass as integer.
         } else {
-            addCSSProperty(CSSPropertyMarginLeft, CSSValueAuto);
-            addCSSProperty(CSSPropertyMarginRight, CSSValueAuto);
+            style->setProperty(CSSPropertyMarginLeft, CSSValueAuto);
+            style->setProperty(CSSPropertyMarginRight, CSSValueAuto);
         }
     } else if (attr->name() == widthAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyWidth);
-        else {
-            bool ok;
-            int v = attr->value().toInt(&ok);
-            if (ok && !v)
-                addCSSLength(CSSPropertyWidth, "1");
-            else
-                addCSSLength(CSSPropertyWidth, attr->value());
-        }
+        bool ok;
+        int v = attr->value().toInt(&ok);
+        if (ok && !v)
+            addHTMLLengthToStyle(style, CSSPropertyWidth, "1"); // FIXME: Pass as integer.
+        else
+            addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
     } else if (attr->name() == colorAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderColor, CSSPropertyBackgroundColor);
-        else {
-            addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
-            addCSSColor(CSSPropertyBorderColor, attr->value());
-            addCSSColor(CSSPropertyBackgroundColor, attr->value());
-        }
+        style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
+        addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value());
+        addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value());
     } else if (attr->name() == noshadeAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderColor, CSSPropertyBackgroundColor);
-        else {
-            addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
-            addCSSColor(CSSPropertyBorderColor, String("grey"));
-            addCSSColor(CSSPropertyBackgroundColor, String("grey"));
-        }
+        style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
+        style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
+        addHTMLColorToStyle(style, CSSPropertyBorderColor, String("grey")); // FIXME: Pass as rgb() value.
+        addHTMLColorToStyle(style, CSSPropertyBackgroundColor, String("grey")); // FIXME: Pass as rgb() value.
     } else if (attr->name() == sizeAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyBorderBottomWidth, CSSPropertyHeight);
-        else {
-            StringImpl* si = attr->value().impl();
-            int size = si->toInt();
-            if (size <= 1) {
-                addCSSProperty(CSSPropertyBorderBottomWidth, String("0"));
-                removeCSSProperty(CSSPropertyHeight);
-            } else {
-                addCSSLength(CSSPropertyHeight, String::number(size-2));
-                removeCSSProperty(CSSPropertyBorderBottomWidth);
-            }
-        }
-    } else
+        StringImpl* si = attr->value().impl();
+        int size = si->toInt();
+        if (size <= 1)
+            style->setProperty(CSSPropertyBorderBottomWidth, String("0")); // FIXME: Pass as integer.
+        else
+            addHTMLLengthToStyle(style, CSSPropertyHeight, String::number(size - 2)); // FIXME: Pass as integer.
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLHRElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index f05085b..c9a08d1 100644 (file)
@@ -38,6 +38,7 @@ private:
     HTMLHRElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace WebCore
index 5cba888..55da445 100644 (file)
@@ -48,14 +48,36 @@ PassRefPtr<HTMLIFrameElement> HTMLIFrameElement::create(const QualifiedName& tag
     return adoptRef(new HTMLIFrameElement(tagName, document));
 }
 
-void HTMLIFrameElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == alignAttr || attr->name() == frameborderAttr;
+}
+
+void HTMLIFrameElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == widthAttr)
-        addCSSLength(CSSPropertyWidth, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
     else if (attr->name() == heightAttr)
-        addCSSLength(CSSPropertyHeight, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
     else if (attr->name() == alignAttr)
-        addHTMLAlignment(attr);
+        applyAlignmentAttributeToStyle(attr, style);
+    else if (attr->name() == frameborderAttr) {
+        // Frame border doesn't really match the HTML4 spec definition for iframes. It simply adds
+        // a presentational hint that the border should be off if set to zero.
+        if (!attr->isNull() && !attr->value().toInt()) {
+            // Add a rule that nulls out our border width.
+            addHTMLLengthToStyle(style, CSSPropertyBorderWidth, "0"); // FIXME: Pass as integer.
+        }
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLFrameElementBase::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLIFrameElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
     else if (attr->name() == nameAttr) {
         const AtomicString& newName = attr->value();
         if (inDocument() && document()->isHTMLDocument()) {
@@ -64,14 +86,6 @@ void HTMLIFrameElement::parseAttribute(Attribute* attr)
             document->addExtraNamedItem(newName);
         }
         m_name = newName;
-    } else if (attr->name() == frameborderAttr) {
-        // Frame border doesn't really match the HTML4 spec definition for iframes.  It simply adds
-        // a presentational hint that the border should be off if set to zero.
-        if (!attr->isNull() && !attr->value().toInt()) {
-            // Add a rule that nulls out our border width.
-            addCSSLength(CSSPropertyBorderWidth, "0");
-        } else
-            removeCSSProperty(CSSPropertyBorderWidth);
     } else if (attr->name() == sandboxAttr)
         setSandboxFlags(attr->isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(attr->value()));
     else
index bcba2a2..d89b028 100644 (file)
@@ -36,6 +36,7 @@ private:
     HTMLIFrameElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void insertedIntoDocument();
     virtual void removedFromDocument();
index 6c22edc..b6e286c 100644 (file)
@@ -78,48 +78,45 @@ PassRefPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document*
     return image.release();
 }
 
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == borderAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == valignAttr;
+}
+
+void HTMLImageElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == widthAttr)
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+    else if (attr->name() == heightAttr)
+        addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+    else if (attr->name() == borderAttr)
+        applyBorderAttributeToStyle(attr, style);
+    else if (attr->name() == vspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
+    } else if (attr->name() == hspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
+    } else if (attr->name() == alignAttr)
+        applyAlignmentAttributeToStyle(attr, style);
+    else if (attr->name() == valignAttr)
+        style->setProperty(CSSPropertyVerticalAlign, attr->value());
+    else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLElement::collectStyleForAttribute(attr, style);
+    }
+}
+
 void HTMLImageElement::parseAttribute(Attribute* attr)
 {
     const QualifiedName& attrName = attr->name();
-    if (attrName == altAttr) {
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else if (attrName == altAttr) {
         if (renderer() && renderer()->isImage())
             toRenderImage(renderer())->updateAltText();
     } else if (attrName == srcAttr)
         m_imageLoader.updateFromElementIgnoringPreviousError();
-    else if (attrName == widthAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyWidth);
-        else
-            addCSSLength(CSSPropertyWidth, attr->value());
-    else if (attrName == heightAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyHeight);
-        else
-            addCSSLength(CSSPropertyHeight, attr->value());
-    else if (attrName == borderAttr) {
-        // border="noborder" -> border="0"
-        applyBorderAttribute(attr);
-    } else if (attrName == vspaceAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom);
-        else {
-            addCSSLength(CSSPropertyMarginTop, attr->value());
-            addCSSLength(CSSPropertyMarginBottom, attr->value());
-        }
-    } else if (attrName == hspaceAttr) {
-        if (attr->value().isNull())
-            removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight);
-        else {
-            addCSSLength(CSSPropertyMarginLeft, attr->value());
-            addCSSLength(CSSPropertyMarginRight, attr->value());
-        }
-    } else if (attrName == alignAttr)
-        addHTMLAlignment(attr);
-    else if (attrName == valignAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyVerticalAlign);
-        else
-            addCSSProperty(CSSPropertyVerticalAlign, attr->value());
     else if (attrName == usemapAttr)
         setIsLink(!attr->isNull());
     else if (attrName == onabortAttr)
index b24d348..a8bba34 100644 (file)
@@ -84,6 +84,7 @@ protected:
 
 private:
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void attach();
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
index 960040f..c575b2b 100644 (file)
@@ -658,9 +658,41 @@ void HTMLInputElement::accessKeyAction(bool sendMouseEvents)
     m_inputType->accessKeyAction(sendMouseEvents);
 }
 
+static inline bool isRespectedPresentationAttribute(HTMLInputElement* element, Attribute* attr)
+{
+    return attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == widthAttr || attr->name() == heightAttr || (attr->name() == borderAttr && element->isImageButton());
+}
+
+void HTMLInputElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == vspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
+    } else if (attr->name() == hspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
+    } else if (attr->name() == alignAttr) {
+        if (m_inputType->shouldRespectAlignAttribute())
+            applyAlignmentAttributeToStyle(attr, style);
+    } else if (attr->name() == widthAttr) {
+        if (m_inputType->shouldRespectHeightAndWidthAttributes())
+            addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+    } else if (attr->name() == heightAttr) {
+        if (m_inputType->shouldRespectHeightAndWidthAttributes())
+            addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+    } else if (attr->name() == borderAttr && isImageButton())
+        applyBorderAttributeToStyle(attr, style);
+    else {
+        ASSERT(!isRespectedPresentationAttribute(this, attr));
+        return HTMLTextFormControlElement::collectStyleForAttribute(attr, style);
+    }
+}
+
 void HTMLInputElement::parseAttribute(Attribute* attr)
 {
-    if (attr->name() == nameAttr) {
+    if (isRespectedPresentationAttribute(this, attr))
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == nameAttr) {
         checkedRadioButtons().removeButton(this);
         m_name = attr->value();
         checkedRadioButtons().addButton(this);
@@ -713,29 +745,6 @@ void HTMLInputElement::parseAttribute(Attribute* attr)
         m_inputType->srcAttributeChanged();
     else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) {
         // FIXME: ignore for the moment
-    } else if (attr->name() == vspaceAttr) {
-        addCSSLength(CSSPropertyMarginTop, attr->value());
-        addCSSLength(CSSPropertyMarginBottom, attr->value());
-    } else if (attr->name() == hspaceAttr) {
-        addCSSLength(CSSPropertyMarginLeft, attr->value());
-        addCSSLength(CSSPropertyMarginRight, attr->value());
-    } else if (attr->name() == alignAttr) {
-        if (m_inputType->shouldRespectAlignAttribute())
-            addHTMLAlignment(attr);
-        else
-            removeHTMLAlignment();
-    } else if (attr->name() == widthAttr) {
-        if (m_inputType->shouldRespectHeightAndWidthAttributes())
-            addCSSLength(CSSPropertyWidth, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWidth);
-    } else if (attr->name() == heightAttr) {
-        if (m_inputType->shouldRespectHeightAndWidthAttributes())
-            addCSSLength(CSSPropertyHeight, attr->value());
-        else
-            removeCSSProperty(CSSPropertyHeight);
-    } else if (attr->name() == borderAttr && isImageButton()) {
-        applyBorderAttribute(attr);
     } else if (attr->name() == onsearchAttr) {
         // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
index b6fa0f6..a512313 100644 (file)
@@ -276,6 +276,7 @@ private:
     virtual void accessKeyAction(bool sendMouseEvents);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual void finishParsingChildren();
 
     virtual void copyNonAttributeProperties(const Element* source);
index f789d32..5fc6b27 100644 (file)
@@ -49,27 +49,33 @@ PassRefPtr<HTMLLIElement> HTMLLIElement::create(const QualifiedName& tagName, Do
     return adoptRef(new HTMLLIElement(tagName, document));
 }
 
-void HTMLLIElement::parseAttribute(Attribute* attr)
+void HTMLLIElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
-    if (attr->name() == valueAttr) {
-        if (renderer() && renderer()->isListItem())
-            parseValue(attr->value());
-    } else if (attr->name() == typeAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyListStyleType);
-        else if (attr->value() == "a")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueLowerAlpha);
+    if (attr->name() == typeAttr) {
+        if (attr->value() == "a")
+            style->setProperty(CSSPropertyListStyleType, CSSValueLowerAlpha);
         else if (attr->value() == "A")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueUpperAlpha);
+            style->setProperty(CSSPropertyListStyleType, CSSValueUpperAlpha);
         else if (attr->value() == "i")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueLowerRoman);
+            style->setProperty(CSSPropertyListStyleType, CSSValueLowerRoman);
         else if (attr->value() == "I")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueUpperRoman);
+            style->setProperty(CSSPropertyListStyleType, CSSValueUpperRoman);
         else if (attr->value() == "1")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueDecimal);
+            style->setProperty(CSSPropertyListStyleType, CSSValueDecimal);
         else
-            addCSSProperty(CSSPropertyListStyleType, attr->value());
+            style->setProperty(CSSPropertyListStyleType, attr->value());
     } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLLIElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == valueAttr) {
+        if (renderer() && renderer()->isListItem())
+            parseValue(attr->value());
+    } else if (attr->name() == typeAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index 77a90e8..03f165e 100644 (file)
@@ -36,6 +36,7 @@ private:
     HTMLLIElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual void attach();
 
index c77c985..e7200d2 100644 (file)
@@ -53,64 +53,62 @@ PassRefPtr<HTMLMarqueeElement> HTMLMarqueeElement::create(const QualifiedName& t
     return marqueeElement.release();
 }
 
-void HTMLMarqueeElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == bgcolorAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == scrollamountAttr || attr->name() == scrolldelayAttr || attr->name() == loopAttr || attr->name() == behaviorAttr || attr->name() == directionAttr;
+}
+
+void HTMLMarqueeElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == widthAttr) {
-        if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyWidth, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWidth);
+        if (!attr->isEmpty())
+            addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
     } else if (attr->name() == heightAttr) {
         if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyHeight, attr->value());
-        else
-            removeCSSProperty(CSSPropertyHeight);
+            addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
     } else if (attr->name() == bgcolorAttr) {
         if (!attr->value().isEmpty())
-            addCSSColor(CSSPropertyBackgroundColor, attr->value());
-        else
-            removeCSSProperty(CSSPropertyBackgroundColor);
+            addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value());
     } else if (attr->name() == vspaceAttr) {
         if (!attr->value().isEmpty()) {
-            addCSSLength(CSSPropertyMarginTop, attr->value());
-            addCSSLength(CSSPropertyMarginBottom, attr->value());
-        } else
-            removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom);
+            addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
+            addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
+        }
     } else if (attr->name() == hspaceAttr) {
         if (!attr->value().isEmpty()) {
-            addCSSLength(CSSPropertyMarginLeft, attr->value());
-            addCSSLength(CSSPropertyMarginRight, attr->value());
-        } else
-            removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight);
+            addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
+            addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
+        }
     } else if (attr->name() == scrollamountAttr) {
         if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyWebkitMarqueeIncrement, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWebkitMarqueeIncrement);
+            addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeIncrement, attr->value());
     } else if (attr->name() == scrolldelayAttr) {
         if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyWebkitMarqueeSpeed, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWebkitMarqueeSpeed);
+            addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeSpeed, attr->value());
     } else if (attr->name() == loopAttr) {
         if (!attr->value().isEmpty()) {
             if (attr->value() == "-1" || equalIgnoringCase(attr->value(), "infinite"))
-                addCSSProperty(CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite);
+                style->setProperty(CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite);
             else
-                addCSSLength(CSSPropertyWebkitMarqueeRepetition, attr->value());
-        } else
-            removeCSSProperty(CSSPropertyWebkitMarqueeRepetition);
+                addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeRepetition, attr->value());
+        }
     } else if (attr->name() == behaviorAttr) {
         if (!attr->value().isEmpty())
-            addCSSProperty(CSSPropertyWebkitMarqueeStyle, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWebkitMarqueeStyle);
+            style->setProperty(CSSPropertyWebkitMarqueeStyle, attr->value());
     } else if (attr->name() == directionAttr) {
         if (!attr->value().isEmpty())
-            addCSSProperty(CSSPropertyWebkitMarqueeDirection, attr->value());
-        else
-            removeCSSProperty(CSSPropertyWebkitMarqueeDirection);
-    } else if (attr->name() == truespeedAttr)
+            style->setProperty(CSSPropertyWebkitMarqueeDirection, attr->value());
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLMarqueeElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == truespeedAttr)
         m_minimumDelay = !attr->isEmpty() ? 0 : defaultMinimumDelay;
     else
         HTMLElement::parseAttribute(attr);
index d1e3070..09aef55 100644 (file)
@@ -54,6 +54,7 @@ private:
     HTMLMarqueeElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     // ActiveDOMObject
     virtual bool canSuspend() const;
index 2bfa2ff..ba2e266 100644 (file)
@@ -54,22 +54,28 @@ PassRefPtr<HTMLOListElement> HTMLOListElement::create(const QualifiedName& tagNa
     return adoptRef(new HTMLOListElement(tagName, document));
 }
 
-void HTMLOListElement::parseAttribute(Attribute* attr)
+void HTMLOListElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == typeAttr) {
         if (attr->value() == "a")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueLowerAlpha);
+            style->setProperty(CSSPropertyListStyleType, CSSValueLowerAlpha);
         else if (attr->value() == "A")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueUpperAlpha);
+            style->setProperty(CSSPropertyListStyleType, CSSValueUpperAlpha);
         else if (attr->value() == "i")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueLowerRoman);
+            style->setProperty(CSSPropertyListStyleType, CSSValueLowerRoman);
         else if (attr->value() == "I")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueUpperRoman);
+            style->setProperty(CSSPropertyListStyleType, CSSValueUpperRoman);
         else if (attr->value() == "1")
-            addCSSProperty(CSSPropertyListStyleType, CSSValueDecimal);
-        else
-            removeCSSProperty(CSSPropertyListStyleType);
-    } else if (attr->name() == startAttr) {
+            style->setProperty(CSSPropertyListStyleType, CSSValueDecimal);
+    } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLOListElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == typeAttr)
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == startAttr) {
         int oldStart = start();
         bool canParse;
         int parsedStart = attr->value().toInt(&canParse);
index 0731fb0..0efebea 100644 (file)
@@ -54,6 +54,7 @@ private:
     void recalculateItemCount();
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     int m_start;
     unsigned m_itemCount;
index 9803f4d..017fd7e 100644 (file)
@@ -77,6 +77,14 @@ RenderWidget* HTMLObjectElement::renderWidgetForJSBindings()
     return renderPart(); // This will return 0 if the renderer is not a RenderPart.
 }
 
+void HTMLObjectElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == borderAttr)
+        applyBorderAttributeToStyle(attr, style);
+    else
+        HTMLPlugInImageElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLObjectElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == formAttr)
@@ -109,7 +117,7 @@ void HTMLObjectElement::parseAttribute(Attribute* attr)
     else if (attr->name() == onbeforeloadAttr)
         setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr));
     else if (attr->name() == borderAttr)
-        applyBorderAttribute(attr);
+        setNeedsAttributeStyleUpdate();
     else
         HTMLPlugInImageElement::parseAttribute(attr);
 }
index 85bf16f..eefed24 100644 (file)
@@ -67,6 +67,8 @@ private:
     HTMLObjectElement(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
+
     virtual void insertedIntoTree(bool deep);
     virtual void removedFromTree(bool deep);
 
index 6cc9f51..8cf1c46 100644 (file)
@@ -44,20 +44,26 @@ PassRefPtr<HTMLParagraphElement> HTMLParagraphElement::create(const QualifiedNam
     return adoptRef(new HTMLParagraphElement(tagName, document));
 }
 
-void HTMLParagraphElement::parseAttribute(Attribute* attr)
+void HTMLParagraphElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == alignAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyTextAlign);
-        else if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
+        if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center"))
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
         else if (equalIgnoringCase(attr->value(), "left"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
         else if (equalIgnoringCase(attr->value(), "right"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
         else
-            addCSSProperty(CSSPropertyTextAlign, attr->value());
+            style->setProperty(CSSPropertyTextAlign, attr->value());
     } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
+void HTMLParagraphElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == alignAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index 0c8c290..d5ceb69 100644 (file)
@@ -35,6 +35,7 @@ private:
     HTMLParagraphElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace WebCore
index 66d6092..83e1602 100644 (file)
@@ -140,34 +140,35 @@ Widget* HTMLPlugInElement::pluginWidget()
     return renderWidget->widget();
 }
 
-void HTMLPlugInElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr;
+}
+
+void HTMLPlugInElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == widthAttr)
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyWidth);
-        else
-            addCSSLength(CSSPropertyWidth, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
     else if (attr->name() == heightAttr)
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyHeight);
-        else
-            addCSSLength(CSSPropertyHeight, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
     else if (attr->name() == vspaceAttr) {
-        if (attr->isNull())
-            removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom);
-        else {
-            addCSSLength(CSSPropertyMarginTop, attr->value());
-            addCSSLength(CSSPropertyMarginBottom, attr->value());
-        }
+        addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
     } else if (attr->name() == hspaceAttr) {
-        if (attr->isNull())
-            removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight);
-        else {
-            addCSSLength(CSSPropertyMarginLeft, attr->value());
-            addCSSLength(CSSPropertyMarginRight, attr->value());
-        }
+        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
     } else if (attr->name() == alignAttr)
-        addHTMLAlignment(attr);
+        applyAlignmentAttributeToStyle(attr, style);
+    else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLFrameOwnerElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLPlugInElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
     else
         HTMLFrameOwnerElement::parseAttribute(attr);
 }
index 8c22141..270177b 100644 (file)
@@ -59,6 +59,7 @@ protected:
     virtual void detach();
     virtual void removedFromDocument();
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     bool m_inBeforeLoadEventHandler;
     // Subclasses should use guardedDispatchBeforeLoadEvent instead of calling dispatchBeforeLoadEvent directly.
index 7ed85fc..5a97747 100644 (file)
@@ -42,6 +42,14 @@ PassRefPtr<HTMLPreElement> HTMLPreElement::create(const QualifiedName& tagName,
     return adoptRef(new HTMLPreElement(tagName, document));
 }
 
+void HTMLPreElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == wrapAttr)
+        style->setProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
+    else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLPreElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == widthAttr) {
@@ -49,12 +57,9 @@ void HTMLPreElement::parseAttribute(Attribute* attr)
         // we should size the pre to.  We basically need to take the width of a space,
         // multiply by the value of the attribute and then set that as the width CSS
         // property.
-    } else if (attr->name() == wrapAttr) {
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyWhiteSpace);
-        else
-            addCSSProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
-    } else
+    } else if (attr->name() == wrapAttr)
+        setNeedsAttributeStyleUpdate();
+    else
         return HTMLElement::parseAttribute(attr);
 }
 
index 3ad3152..862dc63 100644 (file)
@@ -35,6 +35,7 @@ private:
     HTMLPreElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace WebCore
index 88450d4..ec53161 100644 (file)
@@ -44,15 +44,21 @@ PassRefPtr<HTMLTableCaptionElement> HTMLTableCaptionElement::create(const Qualif
     return adoptRef(new HTMLTableCaptionElement(tagName, document));
 }
 
-void HTMLTableCaptionElement::parseAttribute(Attribute* attr)
+void HTMLTableCaptionElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == alignAttr) {
-        if (!attr->value().isEmpty())
-            addCSSProperty(CSSPropertyCaptionSide, attr->value());
-        else
-            removeCSSProperty(CSSPropertyCaptionSide);
+        if (!attr->isEmpty())
+            style->setProperty(CSSPropertyCaptionSide, attr->value());
     } else
-        HTMLElement::parseAttribute(attr);
+        HTMLElement::collectStyleForAttribute(attr, style); // Note that we are bypassing HTMLTablePartElement here.
+}
+
+void HTMLTableCaptionElement::parseAttribute(Attribute* attr)
+{
+    if (attr->name() == alignAttr)
+        setNeedsAttributeStyleUpdate();
+    else
+        HTMLElement::parseAttribute(attr); // Note that we are bypassing HTMLTablePartElement here.
 }
 
 }
index da40e82..827cc00 100644 (file)
@@ -38,6 +38,7 @@ private:
     HTMLTableCaptionElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } // namespace
index 5e59f12..557eff3 100644 (file)
@@ -75,34 +75,43 @@ int HTMLTableCellElement::cellIndex() const
     return index;
 }
 
-void HTMLTableCellElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
 {
-    if (attr->name() == rowspanAttr) {
-        if (renderer() && renderer()->isTableCell())
-            toRenderTableCell(renderer())->colSpanOrRowSpanChanged();
-    } else if (attr->name() == colspanAttr) {
-        if (renderer() && renderer()->isTableCell())
-            toRenderTableCell(renderer())->colSpanOrRowSpanChanged();
-    } else if (attr->name() == nowrapAttr) {
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyWhiteSpace);
-        else
-            addCSSProperty(CSSPropertyWhiteSpace, CSSValueWebkitNowrap);
+    return attr->name() == nowrapAttr || attr->name() == widthAttr || attr->name() == heightAttr;
+}
 
+void HTMLTableCellElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == nowrapAttr) {
+        style->setProperty(CSSPropertyWhiteSpace, CSSValueWebkitNowrap);
     } else if (attr->name() == widthAttr) {
         if (!attr->value().isEmpty()) {
             int widthInt = attr->value().toInt();
             if (widthInt > 0) // width="0" is ignored for compatibility with WinIE.
-                addCSSLength(CSSPropertyWidth, attr->value());
-        } else
-            removeCSSProperty(CSSPropertyWidth);
+                addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+        }
     } else if (attr->name() == heightAttr) {
         if (!attr->value().isEmpty()) {
             int heightInt = attr->value().toInt();
             if (heightInt > 0) // height="0" is ignored for compatibility with WinIE.
-                addCSSLength(CSSPropertyHeight, attr->value());
-        } else
-            removeCSSProperty(CSSPropertyHeight);
+                addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+        }
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLTablePartElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLTableCellElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else if (attr->name() == rowspanAttr) {
+        if (renderer() && renderer()->isTableCell())
+            toRenderTableCell(renderer())->colSpanOrRowSpanChanged();
+    } else if (attr->name() == colspanAttr) {
+        if (renderer() && renderer()->isTableCell())
+            toRenderTableCell(renderer())->colSpanOrRowSpanChanged();
     } else
         HTMLTablePartElement::parseAttribute(attr);
 }
index 5c32d6a..fcdf0e3 100644 (file)
@@ -54,6 +54,7 @@ private:
     HTMLTableCellElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
 
index 9912172..584de3e 100644 (file)
@@ -47,6 +47,14 @@ PassRefPtr<HTMLTableColElement> HTMLTableColElement::create(const QualifiedName&
     return adoptRef(new HTMLTableColElement(tagName, document));
 }
 
+void HTMLTableColElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == widthAttr)
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+    else
+        HTMLTablePartElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLTableColElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == spanAttr) {
@@ -54,16 +62,15 @@ void HTMLTableColElement::parseAttribute(Attribute* attr)
         if (renderer() && renderer()->isTableCol())
             renderer()->updateFromElement();
     } else if (attr->name() == widthAttr) {
+        setNeedsAttributeStyleUpdate();
         if (!attr->value().isEmpty()) {
-            addCSSLength(CSSPropertyWidth, attr->value());
             if (renderer() && renderer()->isTableCol()) {
                 RenderTableCol* col = toRenderTableCol(renderer());
                 int newWidth = width().toInt();
                 if (newWidth != col->width())
                     col->setNeedsLayoutAndPrefWidthsRecalc();
             }
-        } else
-            removeCSSProperty(CSSPropertyWidth);
+        }
     } else
         HTMLTablePartElement::parseAttribute(attr);
 }
index 01cea8e..17f0b60 100644 (file)
@@ -43,6 +43,7 @@ private:
     HTMLTableColElement(const QualifiedName& tagName, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual StylePropertySet* additionalAttributeStyle() OVERRIDE;
 
     int m_span;
index be3aaa2..84835dc 100644 (file)
@@ -26,6 +26,7 @@
 #include "HTMLTableElement.h"
 
 #include "Attribute.h"
+#include "CSSImageValue.h"
 #include "CSSPropertyNames.h"
 #include "CSSStyleSheet.h"
 #include "CSSValueKeywords.h"
@@ -266,102 +267,119 @@ static bool setTableCellsChanged(Node* n)
     return cellChanged;
 }
 
+static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft)
+{
+    borderTop = false;
+    borderRight = false;
+    borderBottom = false;
+    borderLeft = false;
+
+    if (equalIgnoringCase(value, "above"))
+        borderTop = true;
+    else if (equalIgnoringCase(value, "below"))
+        borderBottom = true;
+    else if (equalIgnoringCase(value, "hsides"))
+        borderTop = borderBottom = true;
+    else if (equalIgnoringCase(value, "vsides"))
+        borderLeft = borderRight = true;
+    else if (equalIgnoringCase(value, "lhs"))
+        borderLeft = true;
+    else if (equalIgnoringCase(value, "rhs"))
+        borderRight = true;
+    else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border"))
+        borderTop = borderBottom = borderLeft = borderRight = true;
+    else if (!equalIgnoringCase(value, "void"))
+        return false;
+    return true;
+}
+
+void HTMLTableElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == widthAttr)
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+    else if (attr->name() == heightAttr)
+        addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+    else if (attr->name() == borderAttr) {
+        int border = attr->isEmpty() ? 1 : attr->value().toInt();
+        addHTMLLengthToStyle(style, CSSPropertyBorderWidth, String::number(border)); // FIXME: Pass as integer.
+    } else if (attr->name() == bordercolorAttr) {
+        if (!attr->isEmpty())
+            addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value());
+    } else if (attr->name() == bgcolorAttr)
+        addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value());
+    else if (attr->name() == backgroundAttr) {
+        String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
+        if (!url.isEmpty())
+            style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string())));
+    } else if (attr->name() == valignAttr) {
+        if (!attr->isEmpty())
+            style->setProperty(CSSPropertyVerticalAlign, attr->value());
+    } else if (attr->name() == cellspacingAttr) {
+        if (!attr->isEmpty())
+            addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, attr->value());
+    } else if (attr->name() == vspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value());
+    } else if (attr->name() == hspaceAttr) {
+        addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value());
+        addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value());
+    } else if (attr->name() == alignAttr) {
+        if (!attr->value().isEmpty()) {
+            if (equalIgnoringCase(attr->value(), "center")) {
+                style->setProperty(CSSPropertyWebkitMarginStart, CSSValueAuto);
+                style->setProperty(CSSPropertyWebkitMarginEnd, CSSValueAuto);
+            } else
+                style->setProperty(CSSPropertyFloat, attr->value());
+        }
+    } else if (attr->name() == rulesAttr) {
+        // The presence of a valid rules attribute causes border collapsing to be enabled.
+        if (m_rulesAttr != UnsetRules)
+            style->setProperty(CSSPropertyBorderCollapse, CSSValueCollapse);
+    } else if (attr->name() == frameAttr) {
+        bool borderTop;
+        bool borderRight;
+        bool borderBottom;
+        bool borderLeft;
+        if (getBordersFromFrameAttributeValue(attr->value(), borderTop, borderRight, borderBottom, borderLeft)) {
+            style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin);
+            style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
+            style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
+            style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin);
+            style->setProperty(CSSPropertyBorderTopStyle, borderTop ? CSSValueSolid : CSSValueHidden);
+            style->setProperty(CSSPropertyBorderBottomStyle, borderBottom ? CSSValueSolid : CSSValueHidden);
+            style->setProperty(CSSPropertyBorderLeftStyle, borderLeft ? CSSValueSolid : CSSValueHidden);
+            style->setProperty(CSSPropertyBorderRightStyle, borderRight ? CSSValueSolid : CSSValueHidden);
+        }
+    } else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLTableElement::parseAttribute(Attribute* attr)
 {
     CellBorders bordersBefore = cellBorders();
     unsigned short oldPadding = m_padding;
 
-    if (attr->name() == widthAttr)
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyWidth);
-        else
-            addCSSLength(CSSPropertyWidth, attr->value());
-    else if (attr->name() == heightAttr)
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyHeight);
-        else
-            addCSSLength(CSSPropertyHeight, attr->value());
+    if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == bgcolorAttr || attr->name() == backgroundAttr || attr->name() == valignAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == cellspacingAttr)
+        setNeedsAttributeStyleUpdate();
     else if (attr->name() == borderAttr)  {
+        // FIXME: This attribute is a mess.
         m_borderAttr = true;
-
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyBorderWidth);
-        else {
-            int border = 0;
-            if (attr->isEmpty())
-                border = 1;
-            else
-                border = attr->value().toInt();
+        if (!attr->isNull()) {
+            int border = attr->isEmpty() ? 1 : attr->value().toInt();
             m_borderAttr = border;
-            addCSSLength(CSSPropertyBorderWidth, String::number(border));
         }
-    } else if (attr->name() == bgcolorAttr)
-        if (attr->isNull())
-            removeCSSProperty(CSSPropertyBackgroundColor);
-        else
-            addCSSColor(CSSPropertyBackgroundColor, attr->value());
-    else if (attr->name() == bordercolorAttr) {
+        setNeedsAttributeStyleUpdate();
+    } else if (attr->name() == bordercolorAttr) {
         m_borderColorAttr = !attr->isEmpty();
-        if (!attr->isEmpty())
-            addCSSColor(CSSPropertyBorderColor, attr->value());
-        else
-            removeCSSProperty(CSSPropertyBorderColor);
-    } else if (attr->name() == backgroundAttr) {
-        String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
-        if (!url.isEmpty())
-            addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string());
-        else
-            removeCSSProperty(CSSPropertyBackgroundImage);
+        setNeedsAttributeStyleUpdate();
     } else if (attr->name() == frameAttr) {
-        // Cache the value of "frame" so that the table can examine it later.
-        m_frameAttr = false;
-        
-        // Whether or not to hide the top/right/bottom/left borders.
-        const int cTop = 0;
-        const int cRight = 1;
-        const int cBottom = 2;
-        const int cLeft = 3;
-        bool borders[4] = { false, false, false, false };
-        
-        // void, above, below, hsides, vsides, lhs, rhs, box, border
-        if (equalIgnoringCase(attr->value(), "void"))
-            m_frameAttr = true;
-        else if (equalIgnoringCase(attr->value(), "above")) {
-            m_frameAttr = true;
-            borders[cTop] = true;
-        } else if (equalIgnoringCase(attr->value(), "below")) {
-            m_frameAttr = true;
-            borders[cBottom] = true;
-        } else if (equalIgnoringCase(attr->value(), "hsides")) {
-            m_frameAttr = true;
-            borders[cTop] = borders[cBottom] = true;
-        } else if (equalIgnoringCase(attr->value(), "vsides")) {
-            m_frameAttr = true;
-            borders[cLeft] = borders[cRight] = true;
-        } else if (equalIgnoringCase(attr->value(), "lhs")) {
-            m_frameAttr = true;
-            borders[cLeft] = true;
-        } else if (equalIgnoringCase(attr->value(), "rhs")) {
-            m_frameAttr = true;
-            borders[cRight] = true;
-        } else if (equalIgnoringCase(attr->value(), "box") ||
-                   equalIgnoringCase(attr->value(), "border")) {
-            m_frameAttr = true;
-            borders[cTop] = borders[cBottom] = borders[cLeft] = borders[cRight] = true;
-        }
-        
-        // Now map in the border styles of solid and hidden respectively.
-        if (m_frameAttr) {
-            addCSSProperty(CSSPropertyBorderTopWidth, CSSValueThin);
-            addCSSProperty(CSSPropertyBorderBottomWidth, CSSValueThin);
-            addCSSProperty(CSSPropertyBorderLeftWidth, CSSValueThin);
-            addCSSProperty(CSSPropertyBorderRightWidth, CSSValueThin);
-            addCSSProperty(CSSPropertyBorderTopStyle, borders[cTop] ? CSSValueSolid : CSSValueHidden);
-            addCSSProperty(CSSPropertyBorderBottomStyle, borders[cBottom] ? CSSValueSolid : CSSValueHidden);
-            addCSSProperty(CSSPropertyBorderLeftStyle, borders[cLeft] ? CSSValueSolid : CSSValueHidden);
-            addCSSProperty(CSSPropertyBorderRightStyle, borders[cRight] ? CSSValueSolid : CSSValueHidden);
-        } else
-            removeCSSProperties(CSSPropertyBorderTopWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderTopStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderRightStyle);
+        // FIXME: This attribute is a mess.
+        bool borderTop;
+        bool borderRight;
+        bool borderBottom;
+        bool borderLeft;
+        m_frameAttr = getBordersFromFrameAttributeValue(attr->value(), borderTop, borderRight, borderBottom, borderLeft);
+        setNeedsAttributeStyleUpdate();
     } else if (attr->name() == rulesAttr) {
         m_rulesAttr = UnsetRules;
         if (equalIgnoringCase(attr->value(), "none"))
@@ -374,17 +392,8 @@ void HTMLTableElement::parseAttribute(Attribute* attr)
             m_rulesAttr = ColsRules;
         if (equalIgnoringCase(attr->value(), "all"))
             m_rulesAttr = AllRules;
-        
-        // The presence of a valid rules attribute causes border collapsing to be enabled.
-        if (m_rulesAttr != UnsetRules)
-            addCSSProperty(CSSPropertyBorderCollapse, CSSValueCollapse);
-        else
-            removeCSSProperty(CSSPropertyBorderCollapse);
-    } else if (attr->name() == cellspacingAttr) {
-        if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyBorderSpacing, attr->value());
-        else
-            removeCSSProperty(CSSPropertyBorderSpacing);
+
+        setNeedsAttributeStyleUpdate();
     } else if (attr->name() == cellpaddingAttr) {
         if (!attr->value().isEmpty())
             m_padding = max(0, attr->value().toInt());
@@ -392,34 +401,6 @@ void HTMLTableElement::parseAttribute(Attribute* attr)
             m_padding = 1;
     } else if (attr->name() == colsAttr) {
         // ###
-    } else if (attr->name() == vspaceAttr) {
-        if (attr->isNull())
-            removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom);
-        else {
-            addCSSLength(CSSPropertyMarginTop, attr->value());
-            addCSSLength(CSSPropertyMarginBottom, attr->value());
-        }
-    } else if (attr->name() == hspaceAttr) {
-        if (attr->isNull())
-            removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight);
-        else {
-            addCSSLength(CSSPropertyMarginLeft, attr->value());
-            addCSSLength(CSSPropertyMarginRight, attr->value());
-        }
-    } else if (attr->name() == alignAttr) {
-        if (!attr->value().isEmpty()) {
-            if (equalIgnoringCase(attr->value(), "center")) {
-                addCSSProperty(CSSPropertyWebkitMarginStart, CSSValueAuto);
-                addCSSProperty(CSSPropertyWebkitMarginEnd, CSSValueAuto);
-            } else
-                addCSSProperty(CSSPropertyFloat, attr->value());
-        } else
-            removeCSSProperties(CSSPropertyWebkitMarginStart, CSSPropertyWebkitMarginEnd, CSSPropertyFloat);
-    } else if (attr->name() == valignAttr) {
-        if (!attr->value().isEmpty())
-            addCSSProperty(CSSPropertyVerticalAlign, attr->value());
-        else
-            removeCSSProperty(CSSPropertyVerticalAlign);
     } else
         HTMLElement::parseAttribute(attr);
 
index ef8ccde..ee08101 100644 (file)
@@ -73,6 +73,7 @@ private:
     HTMLTableElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual bool isURLAttribute(Attribute*) const;
 
     // Used to obtain either a solid or outset border decl and to deal with the frame and rules attributes.
index 362439f..ca32dc1 100644 (file)
@@ -26,6 +26,7 @@
 #include "HTMLTablePartElement.h"
 
 #include "Attribute.h"
+#include "CSSImageValue.h"
 #include "CSSPropertyNames.h"
 #include "CSSValueKeywords.h"
 #include "Document.h"
@@ -37,53 +38,55 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-void HTMLTablePartElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == bgcolorAttr || attr->name() == backgroundAttr || attr->name() == bordercolorAttr || attr->name() == valignAttr || attr->name() == alignAttr || attr->name() == heightAttr;
+}
+
+void HTMLTablePartElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == bgcolorAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyBackgroundColor);
-        else
-            addCSSColor(CSSPropertyBackgroundColor, attr->value());
+        addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value());
     else if (attr->name() == backgroundAttr) {
         String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
         if (!url.isEmpty())
-            addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string());
-        else
-            removeCSSProperty(CSSPropertyBackgroundImage);
+            style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string())));
     } else if (attr->name() == bordercolorAttr) {
         if (!attr->value().isEmpty()) {
-            addCSSColor(CSSPropertyBorderColor, attr->value());
-            addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
-            addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
-        } else
-            removeCSSProperties(CSSPropertyBorderColor, CSSPropertyBorderTopStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderRightStyle);
+            addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value());
+            style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid);
+            style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid);
+            style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid);
+            style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid);
+        }
     } else if (attr->name() == valignAttr) {
         if (!attr->value().isEmpty())
-            addCSSProperty(CSSPropertyVerticalAlign, attr->value());
-        else
-            removeCSSProperty(CSSPropertyVerticalAlign);
+            style->setProperty(CSSPropertyVerticalAlign, attr->value());
     } else if (attr->name() == alignAttr) {
-        const AtomicString& v = attr->value();
-        if (v.isNull())
-            removeCSSProperty(CSSPropertyTextAlign);
-        else if (equalIgnoringCase(v, "middle") || equalIgnoringCase(v, "center"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
-        else if (equalIgnoringCase(v, "absmiddle"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueCenter);
-        else if (equalIgnoringCase(v, "left"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
-        else if (equalIgnoringCase(v, "right"))
-            addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
+        if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center"))
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitCenter);
+        else if (equalIgnoringCase(attr->value(), "absmiddle"))
+            style->setProperty(CSSPropertyTextAlign, CSSValueCenter);
+        else if (equalIgnoringCase(attr->value(), "left"))
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitLeft);
+        else if (equalIgnoringCase(attr->value(), "right"))
+            style->setProperty(CSSPropertyTextAlign, CSSValueWebkitRight);
         else
-            addCSSProperty(CSSPropertyTextAlign, v);
+            style->setProperty(CSSPropertyTextAlign, attr->value());
     } else if (attr->name() == heightAttr) {
         if (!attr->value().isEmpty())
-            addCSSLength(CSSPropertyHeight, attr->value());
-        else
-            removeCSSProperty(CSSPropertyHeight);
-    } else
+            addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+    } else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        HTMLElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void HTMLTablePartElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
+    else
         HTMLElement::parseAttribute(attr);
 }
 
index 0736d4c..98e7b7a 100644 (file)
@@ -38,8 +38,8 @@ protected:
         : HTMLElement(tagName, document)
     {
     }
-
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 
     HTMLTableElement* findParentTable() const;
 };
index bff7574..091f61c 100644 (file)
@@ -117,7 +117,21 @@ void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChan
     setInnerTextValue(value());
     HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
 }
-    
+
+void HTMLTextAreaElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == wrapAttr) {
+        if (shouldWrapText()) {
+            style->setProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
+            style->setProperty(CSSPropertyWordWrap, CSSValueBreakWord);
+        } else {
+            style->setProperty(CSSPropertyWhiteSpace, CSSValuePre);
+            style->setProperty(CSSPropertyWordWrap, CSSValueNormal);
+        }
+    } else
+        HTMLTextFormControlElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLTextAreaElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == rowsAttr) {
@@ -150,14 +164,7 @@ void HTMLTextAreaElement::parseAttribute(Attribute* attr)
             wrap = SoftWrap;
         if (wrap != m_wrap) {
             m_wrap = wrap;
-
-            if (shouldWrapText()) {
-                addCSSProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
-                addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord);
-            } else {
-                addCSSProperty(CSSPropertyWhiteSpace, CSSValuePre);
-                addCSSProperty(CSSPropertyWordWrap, CSSValueNormal);
-            }
+            setNeedsAttributeStyleUpdate();
 
             if (renderer())
                 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
index c2bbc71..9d73496 100644 (file)
@@ -94,6 +94,7 @@ private:
 
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual bool appendFormData(FormDataList&, bool);
     virtual void reset();
index cc3c069..1099490 100644 (file)
@@ -47,13 +47,18 @@ PassRefPtr<HTMLUListElement> HTMLUListElement::create(const QualifiedName& tagNa
     return adoptRef(new HTMLUListElement(tagName, document));
 }
 
+void HTMLUListElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == typeAttr)
+        style->setProperty(CSSPropertyListStyleType, attr->value());
+    else
+        HTMLElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLUListElement::parseAttribute(Attribute* attr)
 {
     if (attr->name() == typeAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyListStyleType);
-        else
-            addCSSProperty(CSSPropertyListStyleType, attr->value());
+        setNeedsAttributeStyleUpdate();
     else
         HTMLElement::parseAttribute(attr);
 }
index c786746..abb2192 100644 (file)
@@ -36,6 +36,7 @@ private:
     HTMLUListElement(const QualifiedName&, Document*);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
 
 } //namespace
index 6b3fc5b..2cf83a7 100644 (file)
@@ -95,6 +95,16 @@ void HTMLVideoElement::detach()
         m_imageLoader.clear();
 }
 
+void HTMLVideoElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (attr->name() == widthAttr)
+        addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value());
+    else if (attr->name() == heightAttr)
+        addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value());
+    else
+        HTMLMediaElement::collectStyleForAttribute(attr, style);
+}
+
 void HTMLVideoElement::parseAttribute(Attribute* attr)
 {
     const QualifiedName& attrName = attr->name();
@@ -115,16 +125,8 @@ void HTMLVideoElement::parseAttribute(Attribute* attr)
                 toRenderImage(renderer())->imageResource()->setCachedImage(0); 
         }
 #endif
-    } else if (attrName == widthAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyWidth);
-        else
-            addCSSLength(CSSPropertyWidth, attr->value());
-    else if (attrName == heightAttr)
-        if (attr->value().isNull())
-            removeCSSProperty(CSSPropertyHeight);
-        else
-            addCSSLength(CSSPropertyHeight, attr->value());
+    } else if (attrName == widthAttr || attrName == heightAttr)
+        setNeedsAttributeStyleUpdate();
     else
         HTMLMediaElement::parseAttribute(attr);
 }
index e8f6331..fe88ab0 100644 (file)
@@ -76,6 +76,7 @@ private:
     virtual void attach();
     virtual void detach();
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual bool isVideo() const { return true; }
     virtual bool hasVideo() const { return player() && player()->hasVideo(); }
     virtual bool supportsFullscreen() const;
index 830ad45..035a10b 100644 (file)
@@ -48,29 +48,44 @@ PassRefPtr<MathMLElement> MathMLElement::create(const QualifiedName& tagName, Do
     return adoptRef(new MathMLElement(tagName, document));
 }
 
-void MathMLElement::parseAttribute(Attribute* attr)
+static inline bool isRespectedPresentationAttribute(Attribute* attr)
+{
+    return attr->name() == mathbackgroundAttr || attr->name() == mathsizeAttr || attr->name() == mathcolorAttr || attr->name() == fontsizeAttr || attr->name() == backgroundAttr || attr->name() == colorAttr || attr->name() == fontstyleAttr || attr->name() == fontweightAttr || attr->name() == fontfamilyAttr;
+}
+
+void MathMLElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
 {
     if (attr->name() == mathbackgroundAttr)
-        addCSSProperty(CSSPropertyBackgroundColor, attr->value());
+        style->setProperty(CSSPropertyBackgroundColor, attr->value());
     else if (attr->name() == mathsizeAttr) {
         // The following three values of mathsize are handled in WebCore/css/mathml.css
         if (attr->value() != "normal" && attr->value() != "small" && attr->value() != "big")
-            addCSSProperty(CSSPropertyFontSize, attr->value());
+            style->setProperty(CSSPropertyFontSize, attr->value());
     } else if (attr->name() == mathcolorAttr)
-        addCSSProperty(CSSPropertyColor, attr->value());
+        style->setProperty(CSSPropertyColor, attr->value());
     // FIXME: deprecated attributes that should loose in a conflict with a non deprecated attribute
     else if (attr->name() == fontsizeAttr)
-        addCSSProperty(CSSPropertyFontSize, attr->value());
+        style->setProperty(CSSPropertyFontSize, attr->value());
     else if (attr->name() == backgroundAttr)
-        addCSSProperty(CSSPropertyBackgroundColor, attr->value());
+        style->setProperty(CSSPropertyBackgroundColor, attr->value());
     else if (attr->name() == colorAttr)
-        addCSSProperty(CSSPropertyColor, attr->value());
+        style->setProperty(CSSPropertyColor, attr->value());
     else if (attr->name() == fontstyleAttr)
-        addCSSProperty(CSSPropertyFontStyle, attr->value());
+        style->setProperty(CSSPropertyFontStyle, attr->value());
     else if (attr->name() == fontweightAttr)
-        addCSSProperty(CSSPropertyFontWeight, attr->value());
+        style->setProperty(CSSPropertyFontWeight, attr->value());
     else if (attr->name() == fontfamilyAttr)
-        addCSSProperty(CSSPropertyFontFamily, attr->value());
+        style->setProperty(CSSPropertyFontFamily, attr->value());
+    else {
+        ASSERT(!isRespectedPresentationAttribute(attr));
+        StyledElement::collectStyleForAttribute(attr, style);
+    }
+}
+
+void MathMLElement::parseAttribute(Attribute* attr)
+{
+    if (isRespectedPresentationAttribute(attr))
+        setNeedsAttributeStyleUpdate();
     else
         StyledElement::parseAttribute(attr);
 }
index 201f083..bc4a968 100644 (file)
@@ -43,6 +43,7 @@ protected:
 private:    
     virtual bool isMathMLElement() const { return true; }
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
 };
     
 }
index bf10a1e..b93580d 100644 (file)
@@ -91,6 +91,16 @@ bool SVGImageElement::isSupportedAttribute(const QualifiedName& attrName)
     return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
 }
 
+void SVGImageElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (!isSupportedAttribute(attr->name()))
+        SVGStyledTransformableElement::collectStyleForAttribute(attr, style);
+    else if (attr->name() == SVGNames::widthAttr)
+        style->setProperty(CSSPropertyWidth, attr->value());
+    else if (attr->name() == SVGNames::heightAttr)
+        style->setProperty(CSSPropertyHeight, attr->value());
+}
+
 void SVGImageElement::parseAttribute(Attribute* attr)
 {
     SVGParsingError parseError = NoError;
@@ -105,10 +115,10 @@ void SVGImageElement::parseAttribute(Attribute* attr)
         SVGPreserveAspectRatio::parsePreserveAspectRatio(this, attr->value());
     else if (attr->name() == SVGNames::widthAttr) {
         setWidthBaseValue(SVGLength::construct(LengthModeWidth, attr->value(), parseError, ForbidNegativeLengths));
-        addCSSProperty(CSSPropertyWidth, attr->value());
+        setNeedsAttributeStyleUpdate();
     } else if (attr->name() == SVGNames::heightAttr) {
         setHeightBaseValue(SVGLength::construct(LengthModeHeight, attr->value(), parseError, ForbidNegativeLengths));
-        addCSSProperty(CSSPropertyHeight, attr->value());
+        setNeedsAttributeStyleUpdate();
     } else if (SVGTests::parseAttribute(attr)
              || SVGLangSpace::parseAttribute(attr)
              || SVGExternalResourcesRequired::parseAttribute(attr)
index 1fbbb0f..4edd00d 100644 (file)
@@ -50,6 +50,7 @@ private:
 
     bool isSupportedAttribute(const QualifiedName&);
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual void svgAttributeChanged(const QualifiedName&);
 
     virtual void attach();
index 518b5b3..ee795f4 100644 (file)
@@ -292,12 +292,17 @@ bool SVGStyledElement::isAnimatableCSSProperty(const QualifiedName& attrName)
     return cssPropertyToTypeMap().contains(attrName);
 }
 
+void SVGStyledElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    int propertyID = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name());
+    if (propertyID > 0)
+        style->setProperty(propertyID, attr->value());
+}
+
 void SVGStyledElement::parseAttribute(Attribute* attr)
 {
-    int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name());
-    if (propId > 0) {
-        addCSSProperty(propId, attr->value());
-        setNeedsStyleRecalc();
+    if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name()) > 0) {
+        setNeedsAttributeStyleUpdate();
         return;
     }
     
index 3df4c93..08498d9 100644 (file)
@@ -66,6 +66,7 @@ protected:
     virtual bool rendererIsNeeded(const NodeRenderingContext&);
 
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual void svgAttributeChanged(const QualifiedName&);
 
     virtual void attach();
index c8dfdc5..61dfc8e 100644 (file)
@@ -228,6 +228,20 @@ bool SVGTextContentElement::isSupportedAttribute(const QualifiedName& attrName)
     return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
 }
 
+void SVGTextContentElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style)
+{
+    if (!isSupportedAttribute(attr->name()))
+        SVGStyledElement::collectStyleForAttribute(attr, style);
+    else if (attr->name().matches(XMLNames::spaceAttr)) {
+        DEFINE_STATIC_LOCAL(const AtomicString, preserveString, ("preserve"));
+
+        if (attr->value() == preserveString)
+            style->setProperty(CSSPropertyWhiteSpace, CSSValuePre);
+        else
+            style->setProperty(CSSPropertyWhiteSpace, CSSValueNowrap);
+    }
+}
+
 void SVGTextContentElement::parseAttribute(Attribute* attr)
 {
     SVGParsingError parseError = NoError;
@@ -243,14 +257,8 @@ void SVGTextContentElement::parseAttribute(Attribute* attr)
     } else if (SVGTests::parseAttribute(attr)
                || SVGExternalResourcesRequired::parseAttribute(attr)) {
     } else if (SVGLangSpace::parseAttribute(attr)) {
-        if (attr->name().matches(XMLNames::spaceAttr)) {
-            DEFINE_STATIC_LOCAL(const AtomicString, preserveString, ("preserve"));
-
-            if (attr->value() == preserveString)
-                addCSSProperty(CSSPropertyWhiteSpace, CSSValuePre);
-            else
-                addCSSProperty(CSSPropertyWhiteSpace, CSSValueNowrap);
-        }
+        if (attr->name().matches(XMLNames::spaceAttr))
+            setNeedsAttributeStyleUpdate();
     } else
         ASSERT_NOT_REACHED();
 
index d45bea6..76d2826 100644 (file)
@@ -104,6 +104,7 @@ protected:
 
     bool isSupportedAttribute(const QualifiedName&);
     virtual void parseAttribute(Attribute*) OVERRIDE;
+    virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE;
     virtual void svgAttributeChanged(const QualifiedName&);
 
     virtual bool selfHasRelativeLengths() const;