📄 cssstyleselector.cpp
字号:
CSSRuleData* elt2 = m_matchedRules[j+1]; if (*elt > *elt2) { sorted = false; m_matchedRules[j] = elt2; m_matchedRules[j+1] = elt; } } if (sorted) return; } } else { // Peform a merge sort for larger lists. uint 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. m_tmpRules.resize(end - start); uint i1 = start; uint i2 = mid; elt = m_matchedRules[i1]; elt2 = m_matchedRules[i2]; while (i1 < mid || i2 < end) { if (i1 < mid && (i2 == end || *elt <= *elt2)) { m_tmpRules[m_tmpRuleCount++] = elt; i1++; if (i1 < mid) elt = m_matchedRules[i1]; } else { m_tmpRules[m_tmpRuleCount++] = elt2; i2++; if (i2 < end) elt2 = m_matchedRules[i2]; } } for (uint i = start; i < end; i++) m_matchedRules[i] = m_tmpRules[i-start]; m_tmpRuleCount = 0; } }void CSSStyleSelector::initElementAndPseudoState(ElementImpl* e){ element = e; if (element && element->isHTMLElement()) htmlElement = static_cast<HTMLElementImpl*>(element); else htmlElement = 0; ::encodedurl = &encodedurl; pseudoState = PseudoUnknown;}void CSSStyleSelector::initForStyleResolve(ElementImpl* e, RenderStyle* defaultParent){ // set some variables we will need pseudoStyle = RenderStyle::NOPSEUDO; parentNode = e->parentNode(); if (defaultParent) parentStyle = defaultParent; else parentStyle = (parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0; view = element->getDocument()->view(); isXMLDoc = !element->getDocument()->isHTMLDocument(); part = element->getDocument()->part(); settings = part ? part->settings() : 0; paintDeviceMetrics = element->getDocument()->paintDeviceMetrics(); style = 0; m_matchedRuleCount = 0; m_matchedDeclCount = 0; m_tmpRuleCount = 0; fontDirty = false;}// modified version of the one in kurl.cppstatic void cleanpath(QString &path){ int pos; while ( (pos = path.find( "/../" )) != -1 ) { int prev = 0; if ( pos > 0 ) prev = path.findRev( "/", pos -1 ); // don't remove the host, i.e. http://foo.org/../foo.html if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2)) path.remove( pos, 3); else // matching directory found ? path.remove( prev, pos- prev + 3 ); } pos = 0; // Don't remove "//" from an anchor identifier. -rjw // Set refPos to -2 to mean "I haven't looked for the anchor yet". // We don't want to waste a function call on the search for the the anchor // in the vast majority of cases where there is no "//" in the path. int refPos = -2; while ( (pos = path.find( "//", pos )) != -1) { if (refPos == -2) refPos = path.find("#", 0); if (refPos > 0 && pos >= refPos) break; if ( pos == 0 || path[pos-1] != ':' ) path.remove( pos, 1 ); else pos += 2; } while ( (pos = path.find( "/./" )) != -1) path.remove( pos, 2 ); //kdDebug() << "checkPseudoState " << path << endl;}static void checkPseudoState( DOM::ElementImpl *e, bool checkVisited = true ){ if (!e->hasAnchor()) { pseudoState = PseudoNone; return; } const AtomicString& attr = e->getAttribute(ATTR_HREF); if (attr.isNull()) { pseudoState = PseudoNone; return; } if (!checkVisited) { pseudoState = PseudoAnyLink; return; } QConstString cu(attr.unicode(), attr.length()); QString u = cu.string(); if ( !u.contains("://") ) { if ( u[0] == '/' ) u.prepend(encodedurl->host); else if ( u[0] == '#' ) u.prepend(encodedurl->file); else u.prepend(encodedurl->path); cleanpath( u ); } //completeURL( attr.string() ); pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;}#ifdef STYLE_SHARING_STATSstatic int fraction = 0;static int total = 0;#endifconst int siblingThreshold = 10;NodeImpl* CSSStyleSelector::locateCousinList(ElementImpl* parent){ if (parent && parent->isHTMLElement()) { HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parent); if (p->renderer() && !p->inlineStyleDecl() && !p->hasID()) { DOM::NodeImpl* r = p->previousSibling(); int subcount = 0; RenderStyle* st = p->renderer()->style(); while (r) { if (r->renderer() && r->renderer()->style() == st) return r->lastChild(); if (subcount++ == siblingThreshold) return 0; r = r->previousSibling(); } if (!r) r = locateCousinList(static_cast<ElementImpl*>(parent->parentNode())); while (r) { if (r->renderer() && r->renderer()->style() == st) return r->lastChild(); if (subcount++ == siblingThreshold) return 0; r = r->previousSibling(); } } } return 0;}bool CSSStyleSelector::canShareStyleWithElement(NodeImpl* n){ if (n->isHTMLElement()) { bool mouseInside = element->renderer() ? element->renderer()->mouseInside() : false; HTMLElementImpl* s = static_cast<HTMLElementImpl*>(n); if (s->renderer() && (s->id() == element->id()) && !s->hasID() && (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() && (s->hasMappedAttributes() == htmlElement->hasMappedAttributes()) && (s->hasAnchor() == element->hasAnchor()) && !s->renderer()->style()->affectedByAttributeSelectors() && (s->renderer()->mouseInside() == mouseInside) && (s->active() == element->active()) && (s->focused() == element->focused())) { bool classesMatch = true; if (s->hasClass()) { const AtomicString& class1 = element->getAttribute(ATTR_CLASS); const AtomicString& class2 = s->getAttribute(ATTR_CLASS); classesMatch = (class1 == class2); } if (classesMatch) { bool mappedAttrsMatch = true; if (s->hasMappedAttributes()) mappedAttrsMatch = s->htmlAttributes()->mapsEquivalent(htmlElement->htmlAttributes()); if (mappedAttrsMatch) { bool anchorsMatch = true; if (s->hasAnchor()) { // We need to check to see if the visited state matches. QColor linkColor = element->getDocument()->linkColor(); QColor visitedColor = element->getDocument()->visitedLinkColor(); if (pseudoState == PseudoUnknown) checkPseudoState(element, s->renderer()->style()->pseudoState() != PseudoAnyLink || linkColor != visitedColor); anchorsMatch = (pseudoState == s->renderer()->style()->pseudoState()); } if (anchorsMatch) {#ifdef STYLE_SHARING_STATS fraction++; total++; printf("Sharing %d out of %d\n", fraction, total);#endif return true; } } } } } return false;}RenderStyle* CSSStyleSelector::locateSharedStyle(){ //total++; if (htmlElement && !htmlElement->inlineStyleDecl() && !htmlElement->hasID() && !htmlElement->getDocument()->usesSiblingRules()) { // Check previous siblings. int count = 0; DOM::NodeImpl* n; for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); while (n) { if (canShareStyleWithElement(n)) return n->renderer()->style(); if (count++ == siblingThreshold) return 0; for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); } if (!n) n = locateCousinList(static_cast<ElementImpl*>(element->parentNode())); while (n) { if (canShareStyleWithElement(n)) return n->renderer()->style(); if (count++ == siblingThreshold) return 0; for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()); } }#ifdef STYLE_SHARING_STATS total++; printf("Sharing %d out of %d\n", fraction, total);#endif return 0;}RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent){ if (!e->getDocument()->haveStylesheetsLoaded()) { if (!styleNotYetAvailable) { styleNotYetAvailable = ::new RenderStyle(); styleNotYetAvailable->setDisplay(NONE); styleNotYetAvailable->ref(); } return styleNotYetAvailable; } initElementAndPseudoState(e); style = locateSharedStyle(); if (style) return style; initForStyleResolve(e, defaultParent); style = new (e->getDocument()->renderArena()) RenderStyle(); if (parentStyle) style->inheritFrom(parentStyle); else parentStyle = style; // 1. First we match rules from the user agent sheet. int firstUARule = -1, lastUARule = -1; matchRules(defaultStyle, firstUARule, lastUARule); // 2. In quirks mode, we match rules from the quirks user agent sheet. if (!strictParsing) matchRules(defaultQuirksStyle, firstUARule, lastUARule); // 3. If our medium is print, then we match rules from the print sheet. if (m_medium == "print") matchRules(defaultPrintStyle, firstUARule, lastUARule); // 4. Now we check user sheet rules. int firstUserRule = -1, lastUserRule = -1; matchRules(m_userStyle, firstUserRule, lastUserRule); // 5. Now check author rules, beginning first with presentational attributes // mapped from HTML. int firstAuthorRule = -1, lastAuthorRule = -1; if (htmlElement) { // Ask if the HTML element has mapped attributes. if (htmlElement->hasMappedAttributes()) { // Walk our attribute list and add in each decl. const HTMLNamedAttrMapImpl* map = htmlElement->htmlAttributes(); for (uint i = 0; i < map->length(); i++) { HTMLAttributeImpl* attr = map->attributeItem(i); if (attr->decl()) { if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount; lastAuthorRule = m_matchedDeclCount; addMatchedDeclaration(attr->decl()); } } } // Now we check additional mapped declarations. // Tables and table cells share an additional mapped rule that must be applied // after all attributes, since their mapped style depends on the values of multiple attributes. CSSStyleDeclarationImpl* attributeDecl = htmlElement->additionalAttributeStyleDecl(); if (attributeDecl) { if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount; lastAuthorRule = m_matchedDeclCount; addMatchedDeclaration(attributeDecl); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -