⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cssstyleselector.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
class CSSRuleSet {public:    CSSRuleSet();    ~CSSRuleSet();        typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;        void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);        void addRule(CSSStyleRule* rule, CSSSelector* sel);    void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,                      CSSStyleRule* rule, CSSSelector* sel);        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); }    CSSRuleDataList* getUniversalRules() { return m_universalRules; }    public:    AtomRuleMap m_idRules;    AtomRuleMap m_classRules;    AtomRuleMap m_tagRules;    CSSRuleDataList* m_universalRules;    unsigned m_ruleCount;};static CSSRuleSet* defaultStyle;static CSSRuleSet* defaultQuirksStyle;static CSSRuleSet* defaultPrintStyle;static CSSRuleSet* defaultViewSourceStyle;static CSSStyleSheet* simpleDefaultStyleSheet;RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;static PseudoState pseudoState;static void loadFullDefaultStyle();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}";static bool elementCanUseSimpleDefaultStyle(Element* e){    return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag);}static const MediaQueryEvaluator& screenEval(){    DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));    return staticScreenEval;}static const MediaQueryEvaluator& printEval(){    DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));    return staticPrintEval;}CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, bool strictParsing, bool matchAuthorAndUserStyles)    : m_backgroundData(BackgroundFillLayer)    , m_checker(doc, strictParsing)    , m_fontSelector(CSSFontSelector::create(doc)){    init();    m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;        Element* root = doc->documentElement();    if (!defaultStyle) {        if (!root || elementCanUseSimpleDefaultStyle(root))            loadSimpleDefaultStyle();        else            loadFullDefaultStyle();    }    m_userStyle = 0;    // construct document root element default style. this is needed    // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"    // This is here instead of constructor, because when constructor is run,    // document doesn't have documentElement    // NOTE: this assumes that element that gets passed to styleForElement -call    // is always from the document that owns the style selector    FrameView* view = doc->view();    if (view)        m_medium = new MediaQueryEvaluator(view->mediaType());    else        m_medium = new MediaQueryEvaluator("all");    if (root)        m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap    if (m_rootDefaultStyle && view) {        delete m_medium;        m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get());    }    // FIXME: This sucks! The user sheet is reparsed every time!    if (!userStyleSheet.isEmpty()) {        m_userSheet = CSSStyleSheet::create(doc);        m_userSheet->parseString(userStyleSheet, strictParsing);        m_userStyle = new CSSRuleSet();        m_userStyle->addRulesFromSheet(m_userSheet.get(), *m_medium, this);    }    // add stylesheets from document    m_authorStyle = new CSSRuleSet();        // Add rules from elments like SVG's <font-face>    if (mappedElementSheet)        m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);    unsigned length = styleSheets->length();    for (unsigned i = 0; i < length; i++) {        StyleSheet* sheet = styleSheets->item(i);        if (sheet->isCSSStyleSheet() && !sheet->disabled())            m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);    }}// This is a simplified style setting function for keyframe stylesvoid CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule){    AtomicString s(rule->name());    m_keyframesRuleMap.add(s.impl(), rule);}void CSSStyleSelector::init(){    m_element = 0;    m_matchedDecls.clear();    m_ruleList = 0;    m_rootDefaultStyle = 0;    m_medium = 0;}CSSStyleSelector::~CSSStyleSelector(){    m_fontSelector->clearDocument();    delete m_medium;    delete m_authorStyle;    delete m_userStyle;    deleteAllValues(m_viewportDependentMediaQueryResults);    m_keyframesRuleMap.clear();}static CSSStyleSheet* parseUASheet(const String& str){    CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose    sheet->parseString(str);    return sheet;}static CSSStyleSheet* parseUASheet(const char* characters, unsigned size){    return parseUASheet(String(characters, size));}static void loadFullDefaultStyle(){    if (simpleDefaultStyleSheet) {        ASSERT(defaultStyle);        delete defaultStyle;        delete simpleDefaultStyleSheet;        defaultStyle = new CSSRuleSet;        simpleDefaultStyleSheet = 0;    } else {        ASSERT(!defaultStyle);        defaultStyle = new CSSRuleSet;        defaultPrintStyle = new CSSRuleSet;        defaultQuirksStyle = new CSSRuleSet;    }    // Strict-mode rules.    String defaultRules = String(html4UserAgentStyleSheet, sizeof(html4UserAgentStyleSheet)) + theme()->extraDefaultStyleSheet();    CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);    defaultStyle->addRulesFromSheet(defaultSheet, screenEval());    defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());    // Quirks-mode rules.    String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + theme()->extraQuirksStyleSheet();    CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);    defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());}static void loadSimpleDefaultStyle(){    ASSERT(!defaultStyle);    ASSERT(!simpleDefaultStyleSheet);        defaultStyle = new CSSRuleSet;    defaultPrintStyle = new CSSRuleSet;    defaultQuirksStyle = new CSSRuleSet;    simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));    defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());        // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.}    static void loadViewSourceStyle(){    ASSERT(!defaultViewSourceStyle);    defaultViewSourceStyle = new CSSRuleSet;    defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());}void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl){    if (!decl->hasVariableDependentValue()) {        m_matchedDecls.append(decl);        return;    }    // See if we have already resolved the variables in this declaration.    CSSMutableStyleDeclaration* resolvedDecl = m_resolvedVariablesDeclarations.get(decl).get();    if (resolvedDecl) {        m_matchedDecls.append(resolvedDecl);        return;    }    // If this declaration has any variables in it, then we need to make a cloned    // declaration with as many variables resolved as possible for this style selector's media.    RefPtr<CSSMutableStyleDeclaration> newDecl = CSSMutableStyleDeclaration::create(decl->parentRule());    m_matchedDecls.append(newDecl.get());    m_resolvedVariablesDeclarations.set(decl, newDecl);    HashSet<String> usedBlockVariables;    resolveVariablesForDeclaration(decl, newDecl.get(), usedBlockVariables);}void CSSStyleSelector::resolveVariablesForDeclaration(CSSMutableStyleDeclaration* decl, CSSMutableStyleDeclaration* newDecl, HashSet<String>& usedBlockVariables){    // Now iterate over the properties in the original declaration.  As we resolve variables we'll end up    // mutating the new declaration (possibly expanding shorthands).  The new declaration has no m_node    // though, so it can't mistakenly call setChanged on anything.    CSSMutableStyleDeclaration::const_iterator end = decl->end();    for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {        const CSSProperty& current = *it;        if (!current.value()->isVariableDependentValue()) {            // We can just add the parsed property directly.            newDecl->addParsedProperty(current);            continue;        }        CSSValueList* valueList = static_cast<CSSVariableDependentValue*>(current.value())->valueList();        if (!valueList)            continue;        CSSParserValueList resolvedValueList;        unsigned s = valueList->length();        bool fullyResolved = true;        for (unsigned i = 0; i < s; ++i) {            CSSValue* val = valueList->item(i);            CSSPrimitiveValue* primitiveValue = val->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(val) : 0;            if (primitiveValue && primitiveValue->isVariable()) {                CSSVariablesRule* rule = m_variablesMap.get(primitiveValue->getStringValue());                if (!rule || !rule->variables()) {                    fullyResolved = false;                    break;                }                                if (current.id() == CSSPropertyWebkitVariableDeclarationBlock && s == 1) {                    fullyResolved = false;                    if (!usedBlockVariables.contains(primitiveValue->getStringValue())) {                        CSSMutableStyleDeclaration* declBlock = rule->variables()->getParsedVariableDeclarationBlock(primitiveValue->getStringValue());                        if (declBlock) {                            usedBlockVariables.add(primitiveValue->getStringValue());                            resolveVariablesForDeclaration(declBlock, newDecl, usedBlockVariables);                        }                    }                }                CSSValueList* resolvedVariable = rule->variables()->getParsedVariable(primitiveValue->getStringValue());                if (!resolvedVariable) {                    fullyResolved = false;                    break;                }                unsigned valueSize = resolvedVariable->length();                for (unsigned j = 0; j < valueSize; ++j)                    resolvedValueList.addValue(resolvedVariable->item(j)->parserValue());            } else                resolvedValueList.addValue(val->parserValue());        }                if (!fullyResolved)            continue;        // We now have a fully resolved new value list.  We want the parser to use this value list        // and parse our new declaration.        CSSParser(m_checker.m_strictParsing).parsePropertyWithResolvedVariables(current.id(), current.isImportant(), newDecl, &resolvedValueList);    }}void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex){    m_matchedRules.clear();    if (!rules || !m_element)        return;        // We need to collect the rules for id, class, tag, and everything else into a buffer and    // then sort the buffer.    if (m_element->hasID())        matchRulesForList(rules->getIDRules(m_element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);    if (m_element->hasClass()) {        ASSERT(m_styledElement);        const ClassNames& classNames = m_styledElement->classNames();        size_t size = classNames.size();        for (size_t i = 0; i < size; ++i)            matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex);    }    matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex);    matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);        // If we didn't match any rules, we're done.    if (m_matchedRules.isEmpty())        return;        // Sort the set of matched rules.    sortMatchedRules(0, m_matchedRules.size());        // Now transfer the set of matched rules over to our list of decls.    if (!m_checker.m_collectRulesOnly) {        for (unsigned i = 0; i < m_matchedRules.size(); i++)            addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());    } else {        for (unsigned i = 0; i < m_matchedRules.size(); i++) {            if (!m_ruleList)                m_ruleList = CSSRuleList::create();            m_ruleList->append(m_matchedRules[i]->rule());        }    }}void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -