diff options
-rw-r--r-- | src/css.cc | 57 | ||||
-rw-r--r-- | src/css.hh | 33 | ||||
-rw-r--r-- | src/cssparser.cc | 10 | ||||
-rw-r--r-- | src/dillo.cc | 2 | ||||
-rw-r--r-- | src/styleengine.cc | 6 | ||||
-rw-r--r-- | src/styleengine.hh | 3 |
6 files changed, 73 insertions, 38 deletions
@@ -1,7 +1,7 @@ /* * File: css.cc * - * Copyright 2008-2009 Johannes Hofmann <Johannes.Hofmann@gmx.de> + * Copyright 2008-2014 Johannes Hofmann <Johannes.Hofmann@gmx.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -108,12 +108,12 @@ CssSelector::CssSelector () { struct CombinatorAndSelector *cs; refCount = 0; + matchCacheOffset = -1; selectorList = new lout::misc::SimpleVector <struct CombinatorAndSelector> (1); selectorList->increase (); cs = selectorList->getRef (selectorList->size () - 1); - cs->notMatchingBefore = -1; cs->combinator = COMB_NONE; cs->selector = new CssSimpleSelector (); } @@ -128,7 +128,8 @@ CssSelector::~CssSelector () { * \brief Return whether selector matches at a given node in the document tree. */ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node, - int i, Combinator comb) { + int i, Combinator comb, MatchCache *matchCache) { + int *matchCacheEntry; assert (node); if (i < 0) @@ -148,14 +149,16 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node, break; case COMB_DESCENDANT: node = docTree->parent (node); + matchCacheEntry = matchCache->getRef(matchCacheOffset + i); for (const DoctreeNode *n = node; - n && n->num > cs->notMatchingBefore; n = docTree->parent (n)) - if (sel->match (n) && match (docTree, n, i - 1, cs->combinator)) + n && n->num > *matchCacheEntry; n = docTree->parent (n)) + if (sel->match (n) && + match (docTree, n, i - 1, cs->combinator, matchCache)) return true; if (node) // remember that it didn't match to avoid future tests - cs->notMatchingBefore = node->num; + *matchCacheEntry = node->num; return false; break; @@ -167,17 +170,17 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node, return false; // tail recursion should be optimized by the compiler - return match (docTree, node, i - 1, cs->combinator); + return match (docTree, node, i - 1, cs->combinator, matchCache); } void CssSelector::addSimpleSelector (Combinator c) { struct CombinatorAndSelector *cs; + assert (matchCacheOffset == -1); selectorList->increase (); cs = selectorList->getRef (selectorList->size () - 1); cs->combinator = c; - cs->notMatchingBefore = -1; cs->selector = new CssSimpleSelector (); } @@ -345,8 +348,8 @@ CssRule::~CssRule () { } void CssRule::apply (CssPropertyList *props, - Doctree *docTree, const DoctreeNode *node) { - if (selector->match (docTree, node)) + Doctree *docTree, const DoctreeNode *node, MatchCache *matchCache) { + if (selector->match (docTree, node, matchCache)) this->props->apply (props); } @@ -410,6 +413,8 @@ void CssStyleSheet::addRule (CssRule *rule) { } if (ruleList) { + rule->selector->setMatchCacheOffset (matchCacheOffset); + matchCacheOffset += rule->selector->size (); ruleList->insert (rule); } else { assert (top->getElement () == CssSimpleSelector::ELEMENT_NONE); @@ -423,8 +428,8 @@ void CssStyleSheet::addRule (CssRule *rule) { * The properties are set as defined by the rules in the stylesheet that * match at the given node in the document tree. */ -void CssStyleSheet::apply (CssPropertyList *props, - Doctree *docTree, const DoctreeNode *node) { +void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree, + const DoctreeNode *node, MatchCache *matchCache) { static const int maxLists = 32; RuleList *ruleList[maxLists]; int numLists = 0, index[maxLists] = {0}; @@ -484,8 +489,8 @@ void CssStyleSheet::apply (CssPropertyList *props, } if (minSpecIndex >= 0) { - ruleList[minSpecIndex]->get (index[minSpecIndex])->apply - (props, docTree, node); + CssRule *rule = ruleList[minSpecIndex]->get (index[minSpecIndex]); + rule->apply(props, docTree, node, matchCache); index[minSpecIndex]++; } else { break; @@ -493,8 +498,11 @@ void CssStyleSheet::apply (CssPropertyList *props, } } +CssStyleSheet CssContext::userAgentSheet; + CssContext::CssContext () { pos = 0; + matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1); } /** @@ -511,23 +519,28 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree, CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant, CssPropertyList *nonCssHints) { - sheet[CSS_PRIMARY_USER_AGENT].apply (props, docTree, node); - sheet[CSS_PRIMARY_USER].apply (props, docTree, node); + userAgentSheet.apply (props, docTree, node, + &matchCache[CSS_PRIMARY_USER_AGENT]); + sheet[CSS_PRIMARY_USER].apply (props, docTree, node, + &matchCache[CSS_PRIMARY_USER]); if (nonCssHints) nonCssHints->apply (props); - sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node); + sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node, + &matchCache[CSS_PRIMARY_AUTHOR]); if (tagStyle) tagStyle->apply (props); - sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node); + sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node, + &matchCache[CSS_PRIMARY_AUTHOR_IMPORTANT]); if (tagStyleImportant) tagStyleImportant->apply (props); - sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node); + sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node, + &matchCache[CSS_PRIMARY_USER_IMPORTANT]); } void CssContext::addRule (CssSelector *sel, CssPropertyList *props, @@ -541,8 +554,12 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props, !rule->isSafe ()) { MSG_WARN ("Ignoring unsafe author style that might reveal browsing history\n"); delete rule; - } else { + } else if (order == CSS_PRIMARY_USER_AGENT) { + userAgentSheet.addRule (rule); + matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1); + } else { sheet[order].addRule (rule); + matchCache[order].setSize (sheet[order].matchCacheOffset, -1); } } } @@ -364,6 +364,11 @@ class CssSimpleSelector { void print (); }; +class MatchCache : public lout::misc::SimpleVector <int> { + public: + MatchCache() : lout::misc::SimpleVector <int> (0) {}; +}; + /** * \brief CSS selector class. * @@ -380,15 +385,15 @@ class CssSelector { private: struct CombinatorAndSelector { - int notMatchingBefore; // used for optimizing CSS selector matching Combinator combinator; CssSimpleSelector *selector; }; - int refCount; + int refCount, matchCacheOffset; lout::misc::SimpleVector <struct CombinatorAndSelector> *selectorList; - bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb); + bool match (Doctree *dt, const DoctreeNode *node, int i, Combinator comb, + MatchCache *matchCache); public: CssSelector (); @@ -398,8 +403,13 @@ class CssSelector { return selectorList->getRef (selectorList->size () - 1)->selector; }; inline int size () { return selectorList->size (); }; - inline bool match (Doctree *dt, const DoctreeNode *node) { - return match (dt, node, selectorList->size () - 1, COMB_NONE); + inline bool match (Doctree *dt, const DoctreeNode *node, + MatchCache *matchCache) { + return match (dt, node, selectorList->size () - 1, COMB_NONE, + matchCache); + }; + inline void setMatchCacheOffset (int mo) { + matchCacheOffset = mo; }; int specificity (); bool checksPseudoClass (); @@ -424,8 +434,8 @@ class CssRule { CssRule (CssSelector *selector, CssPropertyList *props, int pos); ~CssRule (); - void apply (CssPropertyList *props, - Doctree *docTree, const DoctreeNode *node); + void apply (CssPropertyList *props, Doctree *docTree, + const DoctreeNode *node, MatchCache *matchCache); inline bool isSafe () { return !selector->checksPseudoClass () || props->isSafe (); }; @@ -475,9 +485,12 @@ class CssStyleSheet { RuleMap idTable, classTable; public: + int matchCacheOffset; + + CssStyleSheet () { matchCacheOffset = 0; } void addRule (CssRule *rule); - void apply (CssPropertyList *props, - Doctree *docTree, const DoctreeNode *node); + void apply (CssPropertyList *props, Doctree *docTree, + const DoctreeNode *node, MatchCache *matchCache); }; /** @@ -485,7 +498,9 @@ class CssStyleSheet { */ class CssContext { private: + static CssStyleSheet userAgentSheet; CssStyleSheet sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; + MatchCache matchCache[CSS_PRIMARY_USER_IMPORTANT + 1]; int pos; public: diff --git a/src/cssparser.cc b/src/cssparser.cc index 3f5f2869..fcff7688 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -275,7 +275,7 @@ typedef struct { CSS_SHORTHAND_BORDER, /* special, used for 'border' */ CSS_SHORTHAND_FONT, /* special, used for 'font' */ } type; - const CssPropertyName * properties;/* CSS_SHORTHAND_MULTIPLE: + const CssPropertyName *properties; /* CSS_SHORTHAND_MULTIPLE: * must be terminated by -1 * CSS_SHORTHAND_DIRECTIONS: * must have length 4 @@ -859,7 +859,7 @@ bool CssParser::parseRgbColor(int32_t *c) { bool CssParser::parseValue(CssPropertyName prop, CssValueType type, - CssPropertyValue * val) + CssPropertyValue *val) { CssLengthType lentype; bool found, ret = false; @@ -1187,8 +1187,8 @@ static int Css_shorthand_info_cmp(const void *a, const void *b) ((CssShorthandInfo *) b)->symbol); } -void CssParser::parseDeclaration(CssPropertyList * props, - CssPropertyList * importantProps) +void CssParser::parseDeclaration(CssPropertyList *props, + CssPropertyList *importantProps) { CssPropertyInfo pi = {NULL, {CSS_TYPE_UNUSED}, NULL}, *pip; CssShorthandInfo *sip; @@ -1703,7 +1703,7 @@ void CssParser::ignoreStatement() } } -void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context, +void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext *context, const char *buf, int buflen, CssOrigin origin) { diff --git a/src/dillo.cc b/src/dillo.cc index 5a67946b..d73b855a 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -52,6 +52,7 @@ #include "cookies.h" #include "domain.h" #include "auth.h" +#include "styleengine.hh" #include "lout/debug.hh" #include "dw/fltkcore.hh" @@ -472,6 +473,7 @@ int main(int argc, char **argv) a_Cookies_init(); a_Auth_init(); a_UIcmd_init(); + StyleEngine::init(); dw::Textblock::setPenaltyHyphen (prefs.penalty_hyphen); dw::Textblock::setPenaltyHyphen2 (prefs.penalty_hyphen_2); diff --git a/src/styleengine.cc b/src/styleengine.cc index 64861973..25e2e600 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -65,7 +65,6 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { doctree = new Doctree (); stack = new lout::misc::SimpleVector <Node> (1); cssContext = new CssContext (); - buildUserAgentStyle (); buildUserStyle (); this->layout = layout; importDepth = 0; @@ -939,7 +938,7 @@ void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf, * The user agent style defines how dillo renders HTML in the absence of * author or user styles. */ -void StyleEngine::buildUserAgentStyle () { +void StyleEngine::init () { const char *cssBuf = "body {margin: 5px}" "big {font-size: 1.17em}" @@ -996,7 +995,8 @@ void StyleEngine::buildUserAgentStyle () { */ "table, caption {font-size: medium; font-weight: normal}"; - CssParser::parse (NULL, NULL, cssContext, cssBuf, strlen (cssBuf), + CssContext context; + CssParser::parse (NULL, NULL, &context, cssBuf, strlen (cssBuf), CSS_ORIGIN_USER_AGENT); } diff --git a/src/styleengine.hh b/src/styleengine.hh index 714553ff..bec4875b 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -38,7 +38,6 @@ class StyleEngine { void stackPush (); void stackPop (); - void buildUserAgentStyle (); void buildUserStyle (); dw::core::style::Style *style0 (int i, BrowserWindow *bw, DilloUrl *url); dw::core::style::Style *wordStyle0 (BrowserWindow *bw, DilloUrl *url); @@ -64,6 +63,8 @@ class StyleEngine { dw::core::style::Font *font); public: + static void init (); + StyleEngine (dw::core::Layout *layout); ~StyleEngine (); |