📄 cssparser.cpp
字号:
CSS_PROP_BORDER_RIGHT_COLOR }; return parseShortHand(properties, 3, important); } case CSS_PROP_BORDER_BOTTOM: // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit { const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_BOTTOM_COLOR }; return parseShortHand(properties, 3, important); } case CSS_PROP_BORDER_LEFT: // [ 'border-left-width' || 'border-style' || <color> ] | inherit { const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_LEFT_COLOR }; return parseShortHand(properties, 3, important); } case CSS_PROP_OUTLINE: // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit { const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE, CSS_PROP_OUTLINE_COLOR }; return parseShortHand(properties, 3, important); } case CSS_PROP_BORDER_COLOR: // <color>{1,4} | transparent | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR, CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR }; return parse4Values(properties, important); } case CSS_PROP_BORDER_WIDTH: // <border-width>{1,4} | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH }; return parse4Values(properties, important); } case CSS_PROP_BORDER_STYLE: // <border-style>{1,4} | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE }; return parse4Values(properties, important); } case CSS_PROP_MARGIN: // <margin-width>{1,4} | inherit { const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; return parse4Values(properties, important); } case CSS_PROP_PADDING: // <padding-width>{1,4} | inherit { const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; return parse4Values(properties, important); } case CSS_PROP_FONT: // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit if ( id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR ) valid_primitive = true; else return parseFont(important); 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 ); } valueList->next(); } if ( parsedValue ) { addProperty( propId, parsedValue, important ); return true; } 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; 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 ) ) { 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 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", num ); // the order is top, right, bottom, left switch( num ) { case 1: { if( !parseValue( properties[0], important ) ) 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 ) ) return false; if( !parseValue( properties[1], important ) ) 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 ) ) return false; if( !parseValue( properties[1], important ) ) return false; if( !parseValue( properties[2], important ) ) return false; CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value(); addProperty( properties[3], value, important ); return true; } case 4: { if( !parseValue( properties[0], important ) ) return false; if( !parseValue( properties[1], important ) ) return false; if( !parseValue( properties[2], important ) ) return false; if( !parseValue( properties[3], important ) ) 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().string(), value.string()).url() ), styleElement );#ifdef CSS_DEBUG kdDebug( 6080 ) << "content, url=" << value.string() << " base=" << styleElement->baseURL().string() << endl;#endif } else if ( val->unit == Value::Function ) { // attr( X ) ValueList *args = val->function->args; QString fname = qString( val->function->name ).lower(); if ( fname != "attr(" || !args ) return false; if ( args->numValues != 1) return false; Value *a = args->current(); parsedValue = new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR); } else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) { // open-quote // close-quote // no-open-quote // no-close-quote } 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;}bool CSSParser::parseShape( int propId, bool important ){ Value *value = valueList->current(); ValueList *args = value->function->args; QString fname = qString( value->function->name ).lower(); if ( fname != "rect(" || !args ) return false; // rect( t, r, b, l ) || rect( t r b l ) if ( args->numValues != 4 && args->numValues != 7 ) return false; RectImpl *rect = new RectImpl(); bool valid = true; int i = 0; Value *a = args->current(); while ( a ) { valid = a->id == CSS_VAL_AUTO || validUnit( a, FLength, strict ); if ( !valid ) break; CSSPrimitiveValueImpl *length = a->id == CSS_VAL_AUTO ? new CSSPrimitiveValueImpl(CSS_VAL_AUTO) : new CSSPrimitiveValueImpl( a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit ); if ( i == 0 ) rect->setTop( length ); else if ( i == 1 ) rect->setRight( length ); else if ( i == 2 ) rect->setBottom( length ); else rect->setLeft( length ); a = args->next(); if ( a && args->numValues == 7 ) { if ( a->unit == Value::Operator && a->iValue == ',' ) { a = args->next(); } else { valid = false; break; } } i++; } if ( valid ) { addProperty( propId, new CSSPrimitiveValueImpl( rect ), important ); valueList->next(); return true; } delete rect; return false;}// [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'bool CSSParser::parseFont( bool important ){// kdDebug(6080) << "parsing font property current=" << valueList->currentValue << endl; bool valid = true; Value *value = valueList->current(); FontValueImpl *font = new FontValueImpl; // optional font-style, font-variant and font-weight while ( value ) {// kdDebug( 6080 ) << "got value " << value->id << " / " << (value->unit == CSSPrimitiveValue::CSS_STRING || // value->unit == CSSPrimitiveValue::CSS_IDENT ? qString( value->string ) : QString::null )// << endl; int id = value->id; if ( id ) { if ( id == CSS_VAL_NORMAL ) { // do nothing, it's the inital value for all three } /* else if ( id == CSS_VAL_INHERIT ) { // set all non set ones to inherit // This is not that simple as the inherit could also apply to the following font-size. // very ahrd to tell without looking ahead. inherit = true; } */ else if ( id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE ) { if ( font->style ) goto invalid; font->style = new CSSPrimitiveValueImpl( id ); } else if ( id == CSS_VAL_SMALL_CAPS ) { if ( font->variant ) goto invalid; font->variant = new CSSPrimitiveValueImpl( id ); } else if ( id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER ) { if ( font->weight ) goto invalid; font->weight = new CSSPrimitiveValueImpl( id ); } else { valid = false; } } else if ( !font->weight && validUnit( value, FInteger|FNonNeg, true ) ) { int weight = (int)value->fValue; int val = 0; if ( weight == 100 ) val = CSS_VAL_100; else if ( weight == 200 ) val = CSS_VAL_200; else if ( weight == 300 ) val = CSS_VAL_300; else if ( weight == 400 ) val = CSS_VAL_400; else if ( weight == 500 ) val = CSS_VAL_500; else if ( weight == 600 ) val = CSS_VAL_600; else if ( weight == 700 ) val = CSS_VAL_700; else if ( weight == 800 ) val = CSS_VAL_800; else if ( weight == 900 ) val = CSS_VAL_900; if ( val ) font->weight = new CSSPrimitiveValueImpl( val ); else valid = false; } else { valid = false; } if ( !valid )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -