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