summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Hofmann <Johannes.Hofmann@gmx.de>2010-04-23 14:53:33 +0200
committerJohannes Hofmann <Johannes.Hofmann@gmx.de>2010-04-23 14:53:33 +0200
commit0b045d5fe5e9540ba22b2d441d4346fbd3646dd9 (patch)
treefdd30ece6f5c57c6c0fc380065db83ae2d2acd7d
parent1b40d6342a64924426642cc742849a8172e25fb2 (diff)
use CSS rule position when specificity is equal
When two CSS rules have the same specificity make sure they are applied in the order as they appear in the stylesheets (see [1]). Testcase: <html><head><style> A:link {color: red} A.foo {color: green} </style></head><body> <a class="foo" href=http://www.dillo.org>should be green</a> </body></html> Reported by: corvid [1] http://www.w3.org/TR/CSS2/cascade.html#cascading-order
-rw-r--r--src/css.cc19
-rw-r--r--src/css.hh6
2 files changed, 18 insertions, 7 deletions
diff --git a/src/css.cc b/src/css.cc
index 1b81ea7c..988d0dc6 100644
--- a/src/css.cc
+++ b/src/css.cc
@@ -287,13 +287,14 @@ void CssSimpleSelector::print () {
}
}
-CssRule::CssRule (CssSelector *selector, CssPropertyList *props) {
+CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) {
assert (selector->size () > 0);
this->selector = selector;
this->selector->ref ();
this->props = props;
this->props->ref ();
+ this->pos = pos;
spec = selector->specificity ();
};
@@ -435,17 +436,23 @@ void CssStyleSheet::apply (CssPropertyList *props,
if (ruleList[numLists])
numLists++;
- // Apply potentially matching rules from ruleList[0-3] with
- // ascending specificity. Each ruleList is sorted already.
+ // Apply potentially matching rules from ruleList[0-numLists] with
+ // ascending specificity.
+ // If specificity is equal, rules are applied in order of appearance.
+ // Each ruleList is sorted already.
while (true) {
int minSpec = 1 << 30;
+ int minPos = 1 << 30;
int minSpecIndex = -1;
for (int i = 0; i < numLists; i++) {
if (ruleList[i] && ruleList[i]->size () > index[i] &&
- ruleList[i]->get(index[i])->specificity () < minSpec) {
+ (ruleList[i]->get(index[i])->specificity () < minSpec ||
+ (ruleList[i]->get(index[i])->specificity () == minSpec &&
+ ruleList[i]->get(index[i])->position () < minPos))) {
minSpec = ruleList[i]->get(index[i])->specificity ();
+ minPos = ruleList[i]->get(index[i])->position ();
minSpecIndex = i;
}
}
@@ -465,6 +472,8 @@ CssStyleSheet *CssContext::userStyle;
CssStyleSheet *CssContext::userImportantStyle;
CssContext::CssContext () {
+ pos = 0;
+
for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
sheet[o] = NULL;
@@ -532,7 +541,7 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props,
CssPrimaryOrder order) {
if (props->size () > 0) {
- CssRule *rule = new CssRule (sel, props);
+ CssRule *rule = new CssRule (sel, props, pos++);
if (sheet[order] == NULL)
sheet[order] = new CssStyleSheet ();
diff --git a/src/css.hh b/src/css.hh
index 69573fdf..b23eb9a3 100644
--- a/src/css.hh
+++ b/src/css.hh
@@ -407,17 +407,18 @@ class CssSelector {
class CssRule {
private:
CssPropertyList *props;
- int spec;
+ int spec, pos;
public:
CssSelector *selector;
- CssRule (CssSelector *selector, CssPropertyList *props);
+ CssRule (CssSelector *selector, CssPropertyList *props, int pos);
~CssRule ();
void apply (CssPropertyList *props,
Doctree *docTree, const DoctreeNode *node);
inline int specificity () { return spec; };
+ inline int position () { return pos; };
void print ();
};
@@ -475,6 +476,7 @@ class CssContext {
static CssStyleSheet *userStyle;
static CssStyleSheet *userImportantStyle;
CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+ int pos;
void buildUserAgentStyle ();
void buildUserStyle ();