?? cssstyleselector.cpp
字號:
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){
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -