?? cssstyleselector.cpp
字號:
if (!rules) return; for (CSSRuleData* d = rules->first(); d; d = d->next()) { CSSStyleRule* rule = d->rule(); const AtomicString& localName = m_element->localName(); const AtomicString& selectorLocalName = d->selector()->m_tag.localName(); if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector())) { // If the rule has no properties to apply, then ignore it. CSSMutableStyleDeclaration* decl = rule->declaration(); if (!decl || !decl->length()) continue; // If we're matching normal rules, set a pseudo bit if // we really just matched a pseudo-element. if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) { if (m_checker.m_collectRulesOnly) return; if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID) m_style->setHasPseudoStyle(m_dynamicPseudo); } else { // Update our first/last rule indices in the matched rules array. lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size(); if (firstRuleIndex == -1) firstRuleIndex = lastRuleIndex; // Add this rule to our list of matched rules. addMatchedRule(d); } } }}static bool operator >(CSSRuleData& r1, CSSRuleData& r2){ int spec1 = r1.selector()->specificity(); int spec2 = r2.selector()->specificity(); return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; } static bool operator <=(CSSRuleData& r1, CSSRuleData& r2){ return !(r1 > r2);}void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end){ if (start >= end || (end - start == 1)) return; // Sanity check. if (end - start <= 6) { // Apply a bubble sort for smaller lists. for (unsigned i = end - 1; i > start; i--) { bool sorted = true; for (unsigned j = start; j < i; j++) { CSSRuleData* elt = m_matchedRules[j]; CSSRuleData* elt2 = m_matchedRules[j + 1]; if (*elt > *elt2) { sorted = false; m_matchedRules[j] = elt2; m_matchedRules[j + 1] = elt; } } if (sorted) return; } return; } // Peform a merge sort for larger lists. unsigned mid = (start + end) / 2; sortMatchedRules(start, mid); sortMatchedRules(mid, end); CSSRuleData* elt = m_matchedRules[mid - 1]; CSSRuleData* elt2 = m_matchedRules[mid]; // Handle the fast common case (of equal specificity). The list may already // be completely sorted. if (*elt <= *elt2) return; // We have to merge sort. Ensure our merge buffer is big enough to hold // all the items. Vector<CSSRuleData*> rulesMergeBuffer; rulesMergeBuffer.reserveInitialCapacity(end - start); unsigned i1 = start; unsigned i2 = mid; elt = m_matchedRules[i1]; elt2 = m_matchedRules[i2]; while (i1 < mid || i2 < end) { if (i1 < mid && (i2 == end || *elt <= *elt2)) { rulesMergeBuffer.append(elt); if (++i1 < mid) elt = m_matchedRules[i1]; } else { rulesMergeBuffer.append(elt2); if (++i2 < end) elt2 = m_matchedRules[i2]; } } for (unsigned i = start; i < end; i++) m_matchedRules[i] = rulesMergeBuffer[i - start];}void CSSStyleSelector::initElementAndPseudoState(Element* e){ m_element = e; if (m_element && m_element->isStyledElement()) m_styledElement = static_cast<StyledElement*>(m_element); else m_styledElement = 0; pseudoState = PseudoUnknown;}void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID){ m_checker.m_pseudoStyle = pseudoID; m_parentNode = e ? e->parentNode() : 0;#if ENABLE(SVG) if (!m_parentNode && e && e->isSVGElement() && e->isShadowNode()) m_parentNode = e->shadowParentNode();#endif if (parentStyle) m_parentStyle = parentStyle; else m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0; m_style = 0; m_matchedDecls.clear(); m_ruleList = 0; m_fontDirty = false;}static inline const AtomicString* linkAttribute(Node* node){ if (!node->isLink()) return 0; ASSERT(node->isElementNode()); Element* element = static_cast<Element*>(node); if (element->isHTMLElement()) return &element->getAttribute(hrefAttr);#if ENABLE(WML) if (element->isWMLElement()) { // <anchor> elements don't have href attributes, but we still want to // appear as link, so linkAttribute() has to return a non-null value! if (element->hasTagName(WMLNames::anchorTag)) return &emptyAtom; return &element->getAttribute(hrefAttr); }#endif#if ENABLE(SVG) if (element->isSVGElement()) return &element->getAttribute(XLinkNames::hrefAttr);#endif return 0;}CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing) : m_document(document) , m_strictParsing(strictParsing) , m_collectRulesOnly(false) , m_pseudoStyle(NOPSEUDO) , m_documentIsHTML(document->isHTMLDocument()){}PseudoState CSSStyleSelector::SelectorChecker::checkPseudoState(Element* element, bool checkVisited) const{ const AtomicString* attr = linkAttribute(element); if (!attr || attr->isNull()) return PseudoNone; if (!checkVisited) return PseudoAnyLink; LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr); if (!hash) return PseudoLink; Frame* frame = m_document->frame(); if (!frame) return PseudoLink; Page* page = frame->page(); if (!page) return PseudoLink; m_linksCheckedForVisitedState.add(hash); return page->group().isLinkVisited(hash) ? PseudoVisited : PseudoLink;}bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const{ pseudoState = PseudoUnknown; PseudoId dynamicPseudo = NOPSEUDO; return checkSelector(sel, element, 0, dynamicPseudo, true, false) == SelectorMatches;}#ifdef STYLE_SHARING_STATSstatic int fraction = 0;static int total = 0;#endifstatic const unsigned cStyleSearchThreshold = 10;Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth){ 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(); } } } return 0;}bool CSSStyleSelector::canShareStyleWithElement(Node* n){ 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->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() && (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) && (s->isLink() == m_element->isLink()) && !style->affectedByAttributeSelectors() && (s->hovered() == m_element->hovered()) && (s->active() == m_element->active()) && (s->focused() == m_element->focused()) && (s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) && (s->getAttribute(typeAttr) == m_element->getAttribute(typeAttr)) && (s->getAttribute(XMLNames::langAttr) == m_element->getAttribute(XMLNames::langAttr)) && (s->getAttribute(langAttr) == m_element->getAttribute(langAttr)) && (s->getAttribute(readonlyAttr) == m_element->getAttribute(readonlyAttr)) && (s->getAttribute(cellpaddingAttr) == m_element->getAttribute(cellpaddingAttr))) { bool isControl = s->isFormControlElement(); if (isControl != m_element->isFormControlElement()) return false; if (isControl) { InputElement* thisInputElement = toInputElement(s); InputElement* otherInputElement = toInputElement(m_element); if (thisInputElement && otherInputElement) { if ((thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) || (thisInputElement->isChecked() != otherInputElement->isChecked()) || (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())) return false; } else return false; FormControlElement* thisFormControlElement = toFormControlElement(s); FormControlElement* otherFormControlElement = toFormControlElement(m_element); if (thisFormControlElement && otherFormControlElement) { if (thisFormControlElement->isEnabled() != otherFormControlElement->isEnabled()) return false; } else return false; } if (style->transitions() || style->animations()) return false; bool classesMatch = true; if (s->hasClass()) { const AtomicString& class1 = m_element->getAttribute(classAttr); const AtomicString& class2 = s->getAttribute(classAttr); classesMatch = (class1 == class2); } if (classesMatch) { bool mappedAttrsMatch = true; if (s->hasMappedAttributes()) mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes()); if (mappedAttrsMatch) { bool linksMatch = true; if (s->isLink()) { // We need to check to see if the visited state matches. if (pseudoState == PseudoUnknown) { const Color& linkColor = m_element->document()->linkColor(); const Color& visitedColor = m_element->document()->visitedLinkColor(); pseudoState = m_checker.checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor); } linksMatch = (pseudoState == style->pseudoState()); } if (linksMatch) return true; } } } } return false;}RenderStyle* CSSStyleSelector::locateSharedStyle(){ 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()) { }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -