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 + -
显示快捷键?