cssparser.cpp

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 1,746 行 · 第 1/5 页

CPP
1,746
字号
    case CSS_PROP_LIST_STYLE:    {        const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,                                    CSS_PROP_LIST_STYLE_IMAGE };        return parseShortHand(properties, 3, important);    }    default:// #ifdef CSS_DEBUG//         kdDebug( 6080 ) << "illegal or CSS2 Aural property: " << val << endl;// #endif        break;    }    if ( valid_primitive ) {        if ( id != 0 ) {            // qDebug(" new value: id=%d", id );            parsedValue = new CSSPrimitiveValueImpl( id );        } else if ( value->unit == CSSPrimitiveValue::CSS_STRING )            parsedValue = new CSSPrimitiveValueImpl( domString( value->string ),                                                     (CSSPrimitiveValue::UnitTypes) value->unit );        else if ( value->unit >= CSSPrimitiveValue::CSS_NUMBER &&                  value->unit <= CSSPrimitiveValue::CSS_KHZ ) {            // qDebug(" new value: value=%.2f, unit=%d", value->fValue, value->unit );            parsedValue = new CSSPrimitiveValueImpl( value->fValue,                                                     (CSSPrimitiveValue::UnitTypes) value->unit );        } else if ( value->unit >= Value::Q_EMS ) {            // qDebug(" new quirks value: value=%.2f, unit=%d", value->fValue, value->unit );            parsedValue = new CSSQuirkPrimitiveValueImpl( value->fValue, CSSPrimitiveValue::CSS_EMS );        }        --expected;        valueList->next();        if ( valueList->current() && expected == 0)        {            delete parsedValue;            parsedValue = 0;        }    }    if ( parsedValue ) {        addProperty( propId, parsedValue, important );        return true;    }    return false;}void CSSParser::addBackgroundValue(CSSValueImpl*& lval, CSSValueImpl* rval){    if (lval) {        if (lval->isValueList())            static_cast<CSSValueListImpl*>(lval)->append(rval);        else {            CSSValueImpl* oldVal = lval;            CSSValueListImpl* list = new CSSValueListImpl();            lval = list;            list->append(oldVal);            list->append(rval);        }    }    else        lval = rval;}bool CSSParser::parseBackgroundShorthand(bool important){    // Position must come before color in this array because a plain old "0" is a legal color    // in quirks mode but it's usually the X coordinate of a position.    const int numProperties = 5;    const int properties[numProperties] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,        CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP_BACKGROUND_COLOR };    inParseShortHand = true;    bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary    CSSValueImpl* values[numProperties] = { 0 }; // compiler will repeat 0 as necessary    CSSValueImpl* positionYValue = 0;    int i;    while (valueList->current()) {        Value* val = valueList->current();        if (val->unit == Value::Operator && val->iValue == ',') {            // We hit the end.  Fill in all remaining values with the initial value.            valueList->next();            for (i = 0; i < numProperties; ++i) {                if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i])                    // Color is not allowed except as the last item in a list.  Reject the entire                    // property.                    goto fail;                if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) {                    addBackgroundValue(values[i], new CSSInitialValueImpl());                    if (properties[i] == CSS_PROP_BACKGROUND_POSITION)                        addBackgroundValue(positionYValue, new CSSInitialValueImpl());                }                parsedProperty[i] = false;            }            if (!valueList->current())                break;        }        bool found = false;        for (i = 0; !found && i < numProperties; ++i) {            if (!parsedProperty[i]) {                CSSValueImpl *val1 = 0, *val2 = 0;                int propId1, propId2;		if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) {		    parsedProperty[i] = found = true;                    addBackgroundValue(values[i], val1);                    if (properties[i] == CSS_PROP_BACKGROUND_POSITION)                        addBackgroundValue(positionYValue, val2);		}	    }	}        // if we didn't find at least one match, this is an        // invalid shorthand and we have to ignore it        if (!found)            goto fail;    }    // Fill in any remaining properties with the initial value.    for (i = 0; i < numProperties; ++i) {        if (!parsedProperty[i]) {            addBackgroundValue(values[i], new CSSInitialValueImpl());            if (properties[i] == CSS_PROP_BACKGROUND_POSITION)                addBackgroundValue(positionYValue, new CSSInitialValueImpl());        }    }    // Now add all of the properties we found.    for (i = 0; i < numProperties; i++) {        if (properties[i] == CSS_PROP_BACKGROUND_POSITION) {            addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i], important);            addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue, important);        }        else            addProperty(properties[i], values[i], important);    }    inParseShortHand = false;    return true;fail:    inParseShortHand = false;    for (int k = 0; k < numProperties; k++)        delete values[k];    delete positionYValue;    return false;}bool CSSParser::parseShortHand( const int *properties, int numProperties, bool important ){    /* We try to match as many properties as possible     * We setup an array of booleans to mark which property has been found,     * and we try to search for properties until it makes no longer any sense     */    inParseShortHand = true;    bool found = false;    int oldPropIndex = numParsedProperties;    bool fnd[6]; //Trust me ;)    for( int i = 0; i < numProperties; i++ )            fnd[i] = false;#ifdef CSS_DEBUG    kdDebug(6080) << "PSH: numProperties=" << numProperties << endl;#endif    while ( valueList->current() ) {        found = false;        // qDebug("outer loop" );        for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {            if (!fnd[propIndex]) {#ifdef CSS_DEBUG                kdDebug(6080) << "LOOKING FOR: " << getPropertyName(properties[propIndex]).string() << endl;#endif                if ( parseValue( properties[propIndex], important, numProperties ) ) {                    fnd[propIndex] = found = true;#ifdef CSS_DEBUG                    kdDebug(6080) << "FOUND: " << getPropertyName(properties[propIndex]).string() << endl;#endif                }            }        }        // if we didn't find at least one match, this is an        // invalid shorthand and we have to ignore it        if (!found) {#ifdef CSS_DEBUG            qDebug("didn't find anything" );#endif            // need to nuke the already added values            for ( int i = oldPropIndex; i < numParsedProperties; ++i )                delete parsedProperties[i];            numParsedProperties = oldPropIndex;            inParseShortHand = false;            return false;        }    }    // Fill in any remaining properties with the initial value.    for (int i = 0; i < numProperties; ++i) {        if (!fnd[i])            addProperty(properties[i], new CSSInitialValueImpl(), important);    }    inParseShortHand = false;#ifdef CSS_DEBUG    kdDebug( 6080 ) << "parsed shorthand" << endl;#endif    return true;}bool CSSParser::parse4Values( const int *properties,  bool important ){    /* From the CSS 2 specs, 8.3     * If there is only one value, it applies to all sides. If there are two values, the top and     * bottom margins are set to the first value and the right and left margins are set to the second.     * If there are three values, the top is set to the first value, the left and right are set to the     * second, and the bottom is set to the third. If there are four values, they apply to the top,     * right, bottom, and left, respectively.     */    int num = inParseShortHand ? 1 : valueList->numValues;    //qDebug("parse4Values: num=%d %d", num,  valueList->numValues );    // the order is top, right, bottom, left    switch( num ) {    case 1: {        if( !parseValue( properties[0], important, valueList->numValues ) ) return false;        CSSValueImpl *value = parsedProperties[numParsedProperties-1]->value();        addProperty( properties[1], value, important );        addProperty( properties[2], value, important );        addProperty( properties[3], value, important );        return true;    }    case 2: {        if( !parseValue( properties[0], important, valueList->numValues ) ) return false;        if( !parseValue( properties[1], important, valueList->numValues) ) return false;        CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();        addProperty( properties[2], value, important );        value = parsedProperties[numParsedProperties-2]->value();        addProperty( properties[3], value, important );        return true;    }    case 3: {        if( !parseValue( properties[0], important, valueList->numValues ) ) return false;        if( !parseValue( properties[1], important, valueList->numValues ) ) return false;        if( !parseValue( properties[2], important, valueList->numValues ) ) return false;        CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();        addProperty( properties[3], value, important );        return true;    }    case 4: {        if( !parseValue( properties[0], important, valueList->numValues ) ) return false;        if( !parseValue( properties[1], important, valueList->numValues ) ) return false;        if( !parseValue( properties[2], important, valueList->numValues ) ) return false;        if( !parseValue( properties[3], important, valueList->numValues ) ) return false;        return true;    }    default:        return false;    }}// [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit// in CSS 2.1 this got somewhat reduced:// [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inheritbool CSSParser::parseContent( int propId, bool important ){    CSSValueListImpl* values = new CSSValueListImpl();    Value *val;    CSSValueImpl *parsedValue = 0;    while ( (val = valueList->current()) ) {        if ( val->unit == CSSPrimitiveValue::CSS_URI ) {            // url            DOMString value = khtml::parseURL(domString(val->string));            parsedValue = new CSSImageValueImpl(                DOMString(KURL( styleElement->baseURL(), value.string()).url() ), styleElement );#ifdef CSS_DEBUG            kdDebug( 6080 ) << "content, url=" << value.string() << " base=" << styleElement->baseURL().url( ) << endl;#endif        } else if ( val->unit == Value::Function ) {            // attr( X ) | counter( X [,Y] ) | counters( X, Y, [,Z] )            ValueList *args = val->function->args;            QString fname = qString( val->function->name ).lower();            if (!args) return false;            if (fname == "attr(") {            if ( args->numValues != 1)                return false;            Value *a = args->current();            parsedValue = new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR);            }            else            if (fname == "counter(") {                parsedValue = parseCounterContent(args, false);                if (!parsedValue) return false;            } else            if (fname == "counters(") {                parsedValue = parseCounterContent(args, true);                if (!parsedValue) return false;            }            else                return false;        } else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) {            // open-quote | close-quote | no-open-quote | no-close-quote            if ( val->id == CSS_VAL_OPEN_QUOTE ||                 val->id == CSS_VAL_CLOSE_QUOTE ||                 val->id == CSS_VAL_NO_OPEN_QUOTE ||                 val->id == CSS_VAL_NO_CLOSE_QUOTE ) {                parsedValue = new CSSPrimitiveValueImpl(val->id);            }        } else if ( val->unit == CSSPrimitiveValue::CSS_STRING ) {            parsedValue = new CSSPrimitiveValueImpl(domString(val->string), CSSPrimitiveValue::CSS_STRING);        }        if (parsedValue)            values->append(parsedValue);        else            break;        valueList->next();    }    if ( values->length() ) {        addProperty( propId, values, important );        valueList->next();        return true;    }    delete values;    return false;}CSSValueImpl* CSSParser::parseCounterContent(ValueList *args, bool counters){    if (counters || (args->numValues != 1 && args->numValues != 3))        if (!counters || (args->numValues != 3 && args->numValues != 5))            return 0;    CounterImpl *counter = new CounterImpl;    Value *i = args->current();//    if (i->unit != CSSPrimitiveValue::CSS_IDENT) goto invalid;    counter->m_identifier = domString(i->string);    if (counters) {        i = args->next();        if (i->unit != Value::Operator || i->iValue != ',') goto invalid;        i = args->next();        if (i->unit != CSSPrimitiveValue::CSS_STRING) goto invalid;        counter->m_separator = domString(i->string);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?