📄 cssparser.cpp
字号:
break;
case CSS_PROP_TEXT_LINE_THROUGH_STYLE:
case CSS_PROP_TEXT_OVERLINE_STYLE:
case CSS_PROP_TEXT_UNDERLINE_STYLE:
if (id == CSS_VAL_NONE || id == CSS_VAL_SOLID || id == CSS_VAL_DOUBLE ||
id == CSS_VAL_DASHED || id == CSS_VAL_DOT_DASH || id == CSS_VAL_DOT_DOT_DASH ||
id == CSS_VAL_WAVE)
valid_primitive = true;
break;
case CSS_PROP_TEXT_LINE_THROUGH_WIDTH:
case CSS_PROP_TEXT_OVERLINE_WIDTH:
case CSS_PROP_TEXT_UNDERLINE_WIDTH:
if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL || id == CSS_VAL_THIN ||
id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
valid_primitive = true;
else
valid_primitive = !id && validUnit(value, FNumber|FLength|FPercent, strict);
break;
// End of CSS3 properties
#if APPLE_CHANGES
// Apple specific properties. These will never be standardized and are purely to
// support custom WebKit-based Apple applications.
case CSS_PROP__APPLE_LINE_CLAMP:
valid_primitive = (!id && validUnit(value, FPercent, false));
break;
case CSS_PROP__APPLE_TEXT_SIZE_ADJUST:
if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE)
valid_primitive = true;
break;
#endif
/* shorthand properties */
case CSS_PROP_BACKGROUND:
// ['background-color' || 'background-image' ||'background-repeat' ||
// 'background-attachment' || 'background-position'] | inherit
return parseBackgroundShorthand(important);
case CSS_PROP_BORDER:
// [ 'border-width' || 'border-style' || <color> ] | inherit
{
const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
CSS_PROP_BORDER_COLOR };
return parseShortHand(properties, 3, important);
}
case CSS_PROP_BORDER_TOP:
// [ 'border-top-width' || 'border-style' || <color> ] | inherit
{
const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
CSS_PROP_BORDER_TOP_COLOR};
return parseShortHand(properties, 3, important);
}
case CSS_PROP_BORDER_RIGHT:
// [ 'border-right-width' || 'border-style' || <color> ] | inherit
{
const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
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} | 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;
}
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;
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: " << properties[propIndex] << endl;
#endif
if ( parseValue( properties[propIndex], important ) ) {
fnd[propIndex] = found = true;
#ifdef CSS_DEBUG
kdDebug(6080) << "FOUND: " << properties[propIndex] << 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -