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

📄 cssstyleselector.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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 + -