⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cssparser.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        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 + -