cssstyleselector.cpp
来自「将konqueror浏览器移植到ARM9 2410中」· C++ 代码 · 共 1,995 行 · 第 1/5 页
CPP
1,995 行
return; } if(!checkOneSelector(sel, elem)) return; //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl; break; } } relation = sel->relation; } // disallow *:hover if ( single && selectorDynamicState & StyleSelector::Hover ) return; usedDynamicStates |= selectorDynamicState; if ((selectorDynamicState & dynamicState) != selectorDynamicState) return; if ( dynamicPseudo != RenderStyle::NOPSEUDO ) { selectorCache[selIndex].state = AppliesPseudo; selectors[ selIndex ]->pseudoId = dynamicPseudo; } else selectorCache[ selIndex ].state = Applies; //qDebug( "selector %d applies", selIndex ); //selectors[ selIndex ]->print(); return;}// 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; while ( (pos = path.find( "//", pos )) != -1) { 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 ){ DOMString attr; if( e->id() != ID_A || (attr = e->getAttribute(ATTR_HREF)).isNull() ) { pseudoState = PseudoNone; return; } QString u = attr.string(); if ( !u.contains("://") ) { if ( u[0] == '/' ) u = encodedurl->host + u; else if ( u[0] == '#' ) u = encodedurl->file + u; else u = encodedurl->path + u; cleanpath( u ); } //completeURL( attr.string() ); pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;}bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e){ if(!e) return false; if(e->id() != sel->tag && sel->tag != -1) return false; if(sel->attr) { DOMString value = e->getAttribute(sel->attr); if(value.isNull()) return false; // attribute is not set switch(sel->match) { case CSSSelector::Exact: if( (strictParsing && strcmp(sel->value, value) ) || (!strictParsing && strcasecmp(sel->value, value))) return false; break; case CSSSelector::Set: break; case CSSSelector::List: { //kdDebug( 6080 ) << "checking for list match" << endl; QString str = value.string(); QString selStr = sel->value.string(); int pos = str.find(selStr, 0, strictParsing); if(pos == -1) return false; if(pos && str[pos-1] != ' ') return false; pos += selStr.length(); if(pos < (int)str.length() && str[pos] != ' ') return false; break; } case CSSSelector::Hyphen: { // ### still doesn't work. FIXME //kdDebug( 6080 ) << "checking for hyphen match" << endl; QString str = value.string(); if(str.find(sel->value.string(), 0, strictParsing) != 0) return false; // ### could be "bla , sdfdsf" too. Parse out spaces int pos = sel->value.length() + 1; while(pos < (int)str.length() && sel->value[pos] == ' ') pos++; if(pos < (int)str.length() && sel->value[pos] != ',') return false; break; } case CSSSelector::Pseudo: case CSSSelector::None: break; } } if(sel->match == CSSSelector::Pseudo) { // Pseudo elements. We need to check first child here. No dynamic pseudo // elements for the moment const QString& value = sel->value.string(); //kdDebug() << "CSSOrderedRule::pseudo " << value << endl; if(value == "first-child") { // first-child matches the first child that is an element! DOM::NodeImpl *n = e->parentNode()->firstChild(); while( n && !n->isElementNode() ) n = n->nextSibling(); if( n == e ) return true; } else if ( value == "first-line" && subject ) { dynamicPseudo=RenderStyle::FIRST_LINE; return true; } else if ( value == "first-letter" && subject ) { dynamicPseudo=RenderStyle::FIRST_LETTER; return true; } else if( value == "link") { if ( pseudoState == PseudoUnknown ) checkPseudoState( e ); if ( pseudoState == PseudoLink ) { return true; } } else if ( value == "visited" ) { if ( pseudoState == PseudoUnknown ) checkPseudoState( e ); if ( pseudoState == PseudoVisited ) return true; } else if ( value == "hover" ) { selectorDynamicState |= StyleSelector::Hover; // dynamic pseudos have to be sorted out in checkSelector, so we if it could in some state apply // to the element. return true; } else if ( value == "focus" ) { selectorDynamicState |= StyleSelector::Focus; return true; } else if ( value == "active" ) { if ( pseudoState == PseudoUnknown ) checkPseudoState( e ); if ( pseudoState != PseudoNone ) { selectorDynamicState |= StyleSelector::Active; return true; } } return false; } // ### add the rest of the checks... return true;}void CSSStyleSelector::clearLists(){ if ( selectors ) delete [] selectors; if ( selectorCache ) { for ( unsigned int i = 0; i < selectors_size; i++ ) if ( selectorCache[i].props ) delete [] selectorCache[i].props; delete [] selectorCache; } if ( properties ) { CSSOrderedProperty **prop = properties; while ( *prop ) { delete (*prop); prop++; } delete [] properties; } selectors = 0; properties = 0; selectorCache = 0;}void CSSStyleSelector::buildLists(){ clearLists(); // collect all selectors and Properties in lists. Then transer them to the array for faster lookup. QList<CSSSelector> selectorList; CSSOrderedPropertyList propertyList; if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList, Default, Default ); if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant ); if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant ); selectors_size = selectorList.count(); selectors = new CSSSelector *[selectors_size]; CSSSelector *s = selectorList.first(); CSSSelector **sel = selectors; while ( s ) { *sel = s; s = selectorList.next(); ++sel; } selectorCache = new SelectorCache[selectors_size]; for ( unsigned int i = 0; i < selectors_size; i++ ) { selectorCache[i].state = Unknown; selectorCache[i].props_size = 0; selectorCache[i].props = 0; } // presort properties. Should make the sort() calls in styleForElement faster. propertyList.sort(); properties_size = propertyList.count() + 1; properties = new CSSOrderedProperty *[ properties_size ]; CSSOrderedProperty *p = propertyList.first(); CSSOrderedProperty **prop = properties; while ( p ) { *prop = p; p = propertyList.next(); ++prop; } *prop = 0; unsigned int* offsets = new unsigned int[selectors_size]; if(properties[0]) offsets[properties[0]->selector] = 0; for(unsigned int p = 1; p < properties_size; ++p) { if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) { unsigned int sel = properties[p - 1]->selector; int* newprops = new int[selectorCache[sel].props_size+2]; for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ ) newprops[i] = selectorCache[sel].props[i]; newprops[selectorCache[sel].props_size] = offsets[sel]; newprops[selectorCache[sel].props_size+1] = p - offsets[sel]; delete [] selectorCache[sel].props; selectorCache[sel].props = newprops; selectorCache[sel].props_size += 2; if(properties[p]) { sel = properties[p]->selector; offsets[sel] = p; } } } delete [] offsets;#if 0 // and now the same for the selector map for ( unsigned int sel = 0; sel < selectors_size; ++sel ) { kdDebug( 6080 ) << "trying for sel: " << sel << endl; int len = 0; int offset = 0; bool matches = false; for ( unsigned int i = 0; i < selectors_size; i++ ) { int tag = selectors[i]->tag; if ( sel != tag && tag != -1 ) selectorCache[i].state = Invalid; else selectorCache[i].state = Unknown; if ( matches != ( selectorCache[i].state == Unknown ) ) { if ( matches ) { kdDebug( 6080 ) << "new: offs: " << offset << " len: " << len << endl; matches = false; } else { matches = true;// offset = p-selectors; len = 0; } } ++len; } }#endif}// ----------------------------------------------------------------------CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index){ rule = r; if(rule) r->ref(); index = _index; selector = s;}CSSOrderedRule::~CSSOrderedRule(){ if(rule) rule->deref();}// -----------------------------------------------------------------CSSStyleSelectorList::CSSStyleSelectorList() : QList<CSSOrderedRule>(){ setAutoDelete(true);}CSSStyleSelectorList::~CSSStyleSelectorList(){}void CSSStyleSelectorList::append(StyleSheetImpl *sheet){ if(!sheet || !sheet->isCSSStyleSheet()) return; int len = sheet->length(); for(int i = 0; i< len; i++) { StyleBaseImpl *item = sheet->item(i); if(item->isStyleRule()) { CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item); QList<CSSSelector> *s = r->selector(); for(int j = 0; j < (int)s->count(); j++) { CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count()); QList<CSSOrderedRule>::append(rule); //kdDebug( 6080 ) << "appending StyleRule!" << endl; } } else if(item->isImportRule()) { CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item); // ### check media type StyleSheetImpl *importedSheet = import->styleSheet(); append(importedSheet); } // ### include media, import rules and other }}void CSSStyleSelectorList::collect( QList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList, Source regular, Source important ){ CSSOrderedRule *r = first(); while( r ) { CSSSelector *sel = selectorList->first(); int selectorNum = 0; while( sel ) { if ( *sel == *(r->selector) ) break; sel = selectorList->next(); selectorNum++; } if ( !sel ) selectorList->append( r->selector );// else// qDebug("merged one selector"); propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important ); r = next(); }}// -------------------------------------------------------------------------int CSSOrderedPropertyList::compareItems(QCollection::Item i1, QCollection::Item i2){ int diff = static_cast<CSSOrderedProperty *>(i1)->priority - static_cast<CSSOrderedProperty *>(i2)->priority; return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position - static_cast<CSSOrderedProperty *>(i2)->position;}void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity, Source regular, Source important ){ QList<CSSProperty> *values = decl->values(); if(!values) return; int len = values->count(); for(int i = 0; i < len; i++)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?