Commit 84c087a0 authored by antti@apple.com's avatar antti@apple.com
Browse files

Source/WebCore: 2011-01-18 Antti Koivisto <antti@apple.com>

Reviewed by Dave Hyatt.

https://bugs.webkit.org/show_bug.cgi?id=52370
<rdar://problem/8856808>
Style sharing optimization no longer works on major web sites
        
The code in CSSStyleSelector::locateSharedStyle() that tries to share style information between element has been defeated 
by widespread use of certain CSS selectors (:first-child pseudo class and similar). The current implementation disables
the sharing optimization for the whole page if one of these constructs is seen in any style sheet used by the page.  
        
This patch gets the style sharing back to 25-40% range on most web sites.

* css/CSSMutableStyleDeclaration.h:
(WebCore::CSSMutableStyleDeclaration::propertiesEqual):
            
    Needed to improve equality checking in NamedNodeMap::mappedMapsEquivalent.
        
* css/CSSSelector.h:
(WebCore::CSSSelector::isSiblingSelector):
        
    Test for selectors that are affected by the sibling elements.
        
* css/CSSStyleSelector.cpp:
(WebCore::elementCanUseSimpleDefaultStyle):
(WebCore::collectSiblingRulesInDefaultStyle):
(WebCore::assertNoSiblingRulesInDefaultStyle):
            
    Extract sibling rules from the MathML default stylesheet. 
    Assert that no other default stylesheet has them.
            
(WebCore::CSSStyleSelector::CSSStyleSelector):
(WebCore::CSSStyleSelector::locateCousinList):
(WebCore::CSSStyleSelector::matchesSiblingRules):
(WebCore::CSSStyleSelector::canShareStyleWithElement):
(WebCore::CSSStyleSelector::locateSharedStyle):
(WebCore::CSSStyleSelector::styleForElement):
(WebCore::collectIdsAndSiblingRulesFromList):
(WebCore::CSSRuleSet::collectIdsAndSiblingRules):

    Track sibling rules and ids used in the stylesheets to allow much more fine-grained rejection of cases
    where style sharing can't be used.

* css/CSSStyleSelector.h:
* dom/NamedNodeMap.cpp:
(WebCore::NamedNodeMap::mappedMapsEquivalent):
            
    Check also for CSSValue mutation from DOM. 
            
* mathml/MathMLMathElement.cpp:
(WebCore::MathMLMathElement::insertedIntoDocument):
* mathml/MathMLMathElement.h:
        
    MathML default style sheet has sibling rules which don't get noticed by the normal document
    stylesheet parsing.
        
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::setFirstChildState):
(WebCore::InheritedFlags::setLastChildState):
(WebCore::InheritedFlags::setChildIndex):
        
    These all make style non-shareable (unique).

LayoutTests: https://bugs.webkit.org/show_bug.cgi?id=52370
Style sharing optimization no longer works on major web sites
        
Reviewed by Dave Hyatt.

These are progressions (with no noticable visual change). 
MathML code was improperly sharing style.

* platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt:
* platform/mac/mathml/presentation/subsup-expected.txt:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76012 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6d5597a4
2011-01-18 Antti Koivisto <antti@apple.com>
Reviewed by Dave Hyatt.
https://bugs.webkit.org/show_bug.cgi?id=52370
Style sharing optimization no longer works on major web sites
These are progressions (with no noticable visual change).
MathML code was improperly sharing style.
* platform/mac/mathml/presentation/fractions-vertical-alignment-expected.txt:
* platform/mac/mathml/presentation/subsup-expected.txt:
2011-01-18 Philippe Normand <pnormand@igalia.com>
 
Unreviewed, rolling out r76002.
......
......@@ -83,13 +83,13 @@ layer at (0,0) size 800x106
RenderBlock {math:mo} at (0,0) size 9x16
RenderText {math:mo} at (0,0) size 9x16
text run at (0,0) width 9: "+"
RenderBlock {math:mfrac} at (164,36) size 71x70
RenderBlock {math:mfrac} at (0,0) size 53x16
RenderBlock {math:mfrac} at (164,36) size 73x70
RenderBlock {math:mfrac} at (0,0) size 55x16
RenderInline {math:mi} at (0,0) size 10x16
RenderText {#text} at (21,0) size 10x16
text run at (21,0) width 10: "B"
RenderBlock {math:mfrac} at (0,16) size 53x54
RenderBlock {math:mrow} at (3,2) size 65x52
RenderText {#text} at (22,0) size 10x16
text run at (22,0) width 10: "B"
RenderBlock {math:mfrac} at (0,16) size 55x54
RenderBlock {math:mrow} at (4,2) size 66x52
RenderInline {math:mi} at (0,0) size 11x16
RenderText {#text} at (0,10) size 11x16
text run at (0,10) width 11: "C"
......@@ -97,13 +97,13 @@ layer at (0,0) size 800x106
RenderBlock {math:mo} at (0,0) size 9x16
RenderText {math:mo} at (0,0) size 9x16
text run at (0,0) width 9: "+"
RenderBlock {math:mfrac} at (21,0) size 44x52
RenderBlock {math:mfrac} at (0,0) size 35x16
RenderBlock {math:mfrac} at (21,0) size 45x52
RenderBlock {math:mfrac} at (0,0) size 36x16
RenderInline {math:mi} at (0,0) size 12x16
RenderText {#text} at (11,0) size 12x16
text run at (11,0) width 12: "D"
RenderBlock {math:mfrac} at (0,16) size 35x36
RenderBlock {math:mrow} at (3,2) size 38x34
RenderText {#text} at (12,0) size 12x16
text run at (12,0) width 12: "D"
RenderBlock {math:mfrac} at (0,16) size 36x36
RenderBlock {math:mrow} at (4,2) size 38x34
RenderInline {math:mi} at (0,0) size 10x16
RenderText {#text} at (0,10) size 10x16
text run at (0,10) width 10: "E"
......
......@@ -94,7 +94,7 @@ layer at (0,0) size 800x256
text run at (0,8) width 9: "Z"
RenderBlock {msubsup} at (10,0) size 32x32
RenderBlock {msubsup} at (0,0) size 18x16
RenderBlock {mrow} at (1,3) size 16x12
RenderBlock {mrow} at (0,3) size 16x12
RenderInline {mi} at (0,0) size 5x12
RenderText {#text} at (0,0) size 5x12
text run at (0,0) width 5: "k"
......
2011-01-18 Antti Koivisto <antti@apple.com>
Reviewed by Dave Hyatt.
https://bugs.webkit.org/show_bug.cgi?id=52370
<rdar://problem/8856808>
Style sharing optimization no longer works on major web sites
The code in CSSStyleSelector::locateSharedStyle() that tries to share style information between element has been defeated
by widespread use of certain CSS selectors (:first-child pseudo class and similar). The current implementation disables
the sharing optimization for the whole page if one of these constructs is seen in any style sheet used by the page.
This patch gets the style sharing back to 25-40% range on most web sites.
* css/CSSMutableStyleDeclaration.h:
(WebCore::CSSMutableStyleDeclaration::propertiesEqual):
Needed to improve equality checking in NamedNodeMap::mappedMapsEquivalent.
* css/CSSSelector.h:
(WebCore::CSSSelector::isSiblingSelector):
Test for selectors that are affected by the sibling elements.
* css/CSSStyleSelector.cpp:
(WebCore::elementCanUseSimpleDefaultStyle):
(WebCore::collectSiblingRulesInDefaultStyle):
(WebCore::assertNoSiblingRulesInDefaultStyle):
Extract sibling rules from the MathML default stylesheet.
Assert that no other default stylesheet has them.
(WebCore::CSSStyleSelector::CSSStyleSelector):
(WebCore::CSSStyleSelector::locateCousinList):
(WebCore::CSSStyleSelector::matchesSiblingRules):
(WebCore::CSSStyleSelector::canShareStyleWithElement):
(WebCore::CSSStyleSelector::locateSharedStyle):
(WebCore::CSSStyleSelector::styleForElement):
(WebCore::collectIdsAndSiblingRulesFromList):
(WebCore::CSSRuleSet::collectIdsAndSiblingRules):
Track sibling rules and ids used in the stylesheets to allow much more fine-grained rejection of cases
where style sharing can't be used.
* css/CSSStyleSelector.h:
* dom/NamedNodeMap.cpp:
(WebCore::NamedNodeMap::mappedMapsEquivalent):
Check also for CSSValue mutation from DOM.
* mathml/MathMLMathElement.cpp:
(WebCore::MathMLMathElement::insertedIntoDocument):
* mathml/MathMLMathElement.h:
MathML default style sheet has sibling rules which don't get noticed by the normal document
stylesheet parsing.
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::setFirstChildState):
(WebCore::InheritedFlags::setLastChildState):
(WebCore::InheritedFlags::setChildIndex):
These all make style non-shareable (unique).
2011-01-18 MORITA Hajime <morrita@google.com>
 
Unreviewed crash fix on release builds.
......@@ -135,6 +135,8 @@ public:
bool useStrictParsing() const { return m_strictParsing; }
void addSubresourceStyleURLs(ListHashSet<KURL>&);
bool propertiesEqual(const CSSMutableStyleDeclaration* o) const { return m_properties == o->m_properties; }
protected:
CSSMutableStyleDeclaration(CSSRule* parentRule);
......
......@@ -278,6 +278,7 @@ namespace WebCore {
return m_match == PseudoElement;
}
bool isUnknownPseudoElement() const;
bool isSiblingSelector() const;
Relation relation() const { return static_cast<Relation>(m_relation); }
......@@ -350,6 +351,24 @@ inline bool CSSSelector::isUnknownPseudoElement() const
return m_match == PseudoElement && m_pseudoType == PseudoUnknown;
}
inline bool CSSSelector::isSiblingSelector() const
{
PseudoType type = pseudoType();
return m_relation == DirectAdjacent
|| m_relation == IndirectAdjacent
|| type == PseudoEmpty
|| type == PseudoFirstChild
|| type == PseudoFirstOfType
|| type == PseudoLastChild
|| type == PseudoLastOfType
|| type == PseudoOnlyChild
|| type == PseudoOnlyOfType
|| type == PseudoNthChild
|| type == PseudoNthOfType
|| type == PseudoNthLastChild
|| type == PseudoNthLastOfType;
}
} // namespace WebCore
#endif // CSSSelector_h
......@@ -400,8 +400,8 @@ public:
}
}
CSSRuleData* first() { return m_first; }
CSSRuleData* last() { return m_last; }
CSSRuleData* first() const { return m_first; }
CSSRuleData* last() const { return m_last; }
void append(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) { m_last = new CSSRuleData(pos, rule, sel, m_last); }
......@@ -425,6 +425,8 @@ public:
void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
CSSStyleRule* rule, CSSSelector* sel);
void collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const;
CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
......@@ -448,6 +450,8 @@ static CSSRuleSet* defaultQuirksStyle;
static CSSRuleSet* defaultPrintStyle;
static CSSRuleSet* defaultViewSourceStyle;
static CSSStyleSheet* simpleDefaultStyleSheet;
static CSSRuleSet* siblingRulesInDefaultStyle;
RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
......@@ -459,11 +463,31 @@ static void loadSimpleDefaultStyle();
// FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
static bool elementCanUseSimpleDefaultStyle(Element* e)
static inline bool elementCanUseSimpleDefaultStyle(Element* e)
{
return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
}
static inline void collectSiblingRulesInDefaultStyle()
{
OwnPtr<CSSRuleSet> siblingRules;
HashSet<AtomicStringImpl*> ids;
defaultStyle->collectIdsAndSiblingRules(ids, siblingRules);
ASSERT(ids.isEmpty());
delete siblingRulesInDefaultStyle;
siblingRulesInDefaultStyle = siblingRules.leakPtr();
}
static inline void assertNoSiblingRulesInDefaultStyle()
{
#ifndef NDEBUG
if (siblingRulesInDefaultStyle)
return;
collectSiblingRulesInDefaultStyle();
ASSERT(!siblingRulesInDefaultStyle);
#endif
}
static const MediaQueryEvaluator& screenEval()
{
DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
......@@ -549,6 +573,16 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
if (sheet->isCSSStyleSheet() && !sheet->disabled())
m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
}
// Collect all ids and rules using sibling selectors (:first-child and similar)
// in the current set of stylesheets. Style sharing code uses this information to reject
// sharing candidates.
// Usually there are no sibling rules in the default style but the MathML sheet has some.
if (siblingRulesInDefaultStyle)
siblingRulesInDefaultStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
m_authorStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
if (m_userStyle)
m_userStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
if (document->renderer() && document->renderer()->style())
document->renderer()->style()->font().update(fontSelector());
......@@ -944,40 +978,52 @@ static const unsigned cStyleSearchThreshold = 10;
Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) const
{
if (parent && parent->isStyledElement()) {
StyledElement* p = static_cast<StyledElement*>(parent);
if (!p->inlineStyleDecl() && !p->hasID()) {
Node* r = p->previousSibling();
unsigned subcount = 0;
RenderStyle* st = p->renderStyle();
while (r) {
if (r->renderStyle() == st)
return r->lastChild();
if (subcount++ == cStyleSearchThreshold)
return 0;
r = r->previousSibling();
}
if (!r && depth < cStyleSearchThreshold)
r = locateCousinList(parent->parentElement(), depth + 1);
while (r) {
if (r->renderStyle() == st)
return r->lastChild();
if (subcount++ == cStyleSearchThreshold)
return 0;
r = r->previousSibling();
}
}
if (!parent || !parent->isStyledElement())
return 0;
StyledElement* p = static_cast<StyledElement*>(parent);
if (p->inlineStyleDecl())
return 0;
if (p->hasID() && m_idsInRules.contains(p->idForStyleResolution().impl()))
return 0;
Node* r = p->previousSibling();
unsigned subcount = 0;
RenderStyle* st = p->renderStyle();
while (r) {
if (r->renderStyle() == st)
return r->lastChild();
if (subcount++ == cStyleSearchThreshold)
return 0;
r = r->previousSibling();
}
if (!r && depth < cStyleSearchThreshold)
r = locateCousinList(parent->parentElement(), depth + 1);
while (r) {
if (r->renderStyle() == st)
return r->lastChild();
if (subcount++ == cStyleSearchThreshold)
return 0;
r = r->previousSibling();
}
return 0;
}
bool CSSStyleSelector::matchesSiblingRules()
{
int firstSiblingRule = -1, lastSiblingRule = -1;
matchRules(m_siblingRules.get(), firstSiblingRule, lastSiblingRule, false);
if (m_matchedDecls.isEmpty())
return false;
m_matchedDecls.clear();
return true;
}
bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
{
if (n->isStyledElement()) {
StyledElement* s = static_cast<StyledElement*>(n);
RenderStyle* style = s->renderStyle();
if (style && !style->unique() &&
(s->tagQName() == m_element->tagQName()) && !s->hasID() &&
(s->tagQName() == m_element->tagQName()) &&
(s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
(s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
(s->isLink() == m_element->isLink()) &&
......@@ -992,6 +1038,10 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
(s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) &&
(s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) &&
(s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) {
if (s->hasID() && m_idsInRules.contains(s->idForStyleResolution().impl()))
return 0;
bool isControl = s->isFormControlElement();
if (isControl != m_element->isFormControlElement())
return false;
......@@ -1062,32 +1112,46 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
}
return false;
}
ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() const
inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
{
if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
// Check previous siblings.
unsigned count = 0;
Node* n;
for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
while (n) {
if (canShareStyleWithElement(n))
return n->renderStyle();
if (count++ == cStyleSearchThreshold)
return 0;
for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
}
if (!n)
n = locateCousinList(m_element->parentElement());
while (n) {
if (canShareStyleWithElement(n))
return n->renderStyle();
if (count++ == cStyleSearchThreshold)
return 0;
for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
}
for (; node; node = node->previousSibling()) {
if (!node->isElementNode())
continue;
if (canShareStyleWithElement(node))
break;
if (count++ == cStyleSearchThreshold)
return 0;
}
return 0;
return node;
}
ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
{
if (!m_styledElement || !m_parentStyle)
return 0;
// If the element has inline style it is probably unique.
if (m_styledElement->inlineStyleDecl())
return 0;
// Ids stop style sharing if they show up in the stylesheets.
if (m_styledElement->hasID() && m_idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
return 0;
// Check previous siblings.
unsigned count = 0;
Node* shareNode = findSiblingForStyleSharing(m_styledElement->previousSibling(), count);
if (!shareNode) {
Node* cousinList = locateCousinList(m_styledElement->parentElement());
shareNode = findSiblingForStyleSharing(cousinList, count);
if (!shareNode)
return 0;
}
// Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
if (matchesSiblingRules())
return 0;
// Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
if (m_parentStyle->childrenAffectedByPositionalRules())
return 0;
return shareNode->renderStyle();
}
void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
......@@ -1180,12 +1244,12 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
}
initElement(e);
initForStyleResolve(e, defaultParent);
if (allowSharing) {
RenderStyle* sharedStyle = locateSharedStyle();
if (sharedStyle)
return sharedStyle;
}
initForStyleResolve(e, defaultParent);
// Compute our style allowing :visited to match first.
RefPtr<RenderStyle> visitedStyle;
......@@ -1227,6 +1291,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
#if ENABLE(FULLSCREEN_API)
loadFullScreenRulesIfNeeded(e->document());
#endif
assertNoSiblingRulesInDefaultStyle();
}
#if ENABLE(SVG)
......@@ -1237,6 +1302,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
defaultStyle->addRulesFromSheet(svgSheet, screenEval());
defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
assertNoSiblingRulesInDefaultStyle();
}
#endif
......@@ -1248,6 +1314,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
// There are some sibling rules here.
collectSiblingRulesInDefaultStyle();
}
#endif
......@@ -1259,6 +1327,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
assertNoSiblingRulesInDefaultStyle();
}
#endif
......@@ -1270,6 +1339,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl
CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
assertNoSiblingRulesInDefaultStyle();
}
#endif
......@@ -2927,6 +2997,47 @@ void CSSRuleSet::addStyleRule(CSSStyleRule* rule)
}
}
static void collectIdsAndSiblingRulesFromList(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules, const CSSRuleDataList* rules)
{
for (CSSRuleData* data = rules->first(); data; data = data->next()) {
bool foundSiblingSelector = false;
for (CSSSelector* selector = data->selector(); selector; selector = selector->tagHistory()) {
if (selector->m_match == CSSSelector::Id && !selector->m_value.isEmpty())
ids.add(selector->m_value.impl());
if (CSSSelector* simpleSelector = selector->simpleSelector()) {
ASSERT(!simpleSelector->simpleSelector());
if (simpleSelector->m_match == CSSSelector::Id && !simpleSelector->m_value.isEmpty())
ids.add(simpleSelector->m_value.impl());
}
if (selector->isSiblingSelector())
foundSiblingSelector = true;
}
if (foundSiblingSelector) {
if (!siblingRules)
siblingRules = adoptPtr(new CSSRuleSet);
siblingRules->addRule(data->rule(), data->selector());
}
}
}
void CSSRuleSet::collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const
{
AtomRuleMap::const_iterator end = m_idRules.end();
for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
end = m_classRules.end();
for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
end = m_tagRules.end();
for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
end = m_pseudoRules.end();
for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it)
collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
if (m_universalRules)
collectIdsAndSiblingRulesFromList(ids, siblingRules, m_universalRules.get());
}
// -------------------------------------------------------------------------------------
// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
......
......@@ -108,8 +108,10 @@ public:
private:
void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO);
void initElement(Element*);
ALWAYS_INLINE RenderStyle* locateSharedStyle() const;
RenderStyle* locateSharedStyle();
bool matchesSiblingRules();
Node* locateCousinList(Element* parent, unsigned depth = 1) const;
Node* findSiblingForStyleSharing(Node*, unsigned& count) const;
bool canShareStyleWithElement(Node*) const;
RenderStyle* style() const { return m_style.get(); }
......@@ -197,6 +199,9 @@ public:
OwnPtr<CSSRuleSet> m_authorStyle;
OwnPtr<CSSRuleSet> m_userStyle;
OwnPtr<CSSRuleSet> m_siblingRules;
HashSet<AtomicStringImpl*> m_idsInRules;
bool m_hasUAAppearance;
BorderData m_borderData;
......
......@@ -359,6 +359,8 @@ bool NamedNodeMap::mappedMapsEquivalent(const NamedNodeMap* otherMap) const
Attribute* otherAttr = otherMap->getAttributeItem(attr->name());
if (!otherAttr || attr->value() != otherAttr->value())
return false;
if (!attr->decl()->propertiesEqual(otherAttr->decl()))
return false;
}
}
return true;
......
......@@ -44,6 +44,14 @@ PassRefPtr<MathMLMathElement> MathMLMathElement::create(const QualifiedName& tag
return adoptRef(new MathMLMathElement(tagName, document));
}
void MathMLMathElement::insertedIntoDocument()
{
// There are sibling rules in the MathML default style.
document()->setUsesSiblingRules(true);
MathMLInlineContainerElement::insertedIntoDocument();
}
RenderObject* MathMLMathElement::createRenderer(RenderArena* arena, RenderStyle*)
{
return new (arena) RenderMathMLMath(this);
......
......@@ -39,6 +39,7 @@ public:
private:
MathMLMathElement(const QualifiedName& tagName, Document*);
virtual void insertedIntoDocument();
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
};
......
......@@ -1176,11 +1176,11 @@ public:
bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
void setChildrenAffectedByBackwardPositionalRules() { m_childrenAffectedByBackwardPositionalRules = true; }
bool firstChildState() const { return m_firstChildState; }
void setFirstChildState() { m_firstChildState = true; }
void setFirstChildState() { m_unique = true; m_firstChildState = true; }
bool lastChildState() const { return m_lastChildState; }
void setLastChildState() { m_lastChildState = true; }
void setLastChildState() { m_unique = true; m_lastChildState = true; }
unsigned childIndex() const { return m_childIndex; }
void setChildIndex(unsigned index) { m_childIndex = index; }
void setChildIndex(unsigned index) { m_unique = true; m_childIndex = index; }
const Color visitedDependentColor(int colorProperty) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment