📄 cssparser.cpp
字号:
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 ]+ | inherit
bool 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;
}
CSSValueImpl* CSSParser::parseBackgroundColor()
{
int id = valueList->current()->id;
if (id == CSS_VAL__KHTML_TEXT || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU ||
(id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && !strict))
return new CSSPrimitiveValueImpl(id);
return parseColor();
}
CSSValueImpl* CSSParser::parseBackgroundImage()
{
if (valueList->current()->id == CSS_VAL_NONE)
return new CSSImageValueImpl();
if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
DOMString uri = khtml::parseURL(domString(valueList->current()->string));
if (!uri.isEmpty())
return new CSSImageValueImpl(DOMString(KURL(styleElement->baseURL().string(), uri.string()).url()),
styleElement);
}
return 0;
}
CSSValueImpl* CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound)
{
int id = valueList->current()->id;
if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) {
int percent = 0;
if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) {
if (xFound)
return 0;
xFound = true;
if (id == CSS_VAL_RIGHT)
percent = 100;
}
else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) {
if (yFound)
return 0;
yFound = true;
if (id == CSS_VAL_BOTTOM)
percent = 100;
}
else if (id == CSS_VAL_CENTER)
// Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
percent = 50;
return new CSSPrimitiveValueImpl(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
}
if (validUnit(valueList->current(), FPercent|FLength, strict))
return new CSSPrimitiveValueImpl(valueList->current()->fValue,
(CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
return 0;
}
void CSSParser::parseBackgroundPosition(CSSValueImpl*& value1, CSSValueImpl*& value2)
{
value1 = value2 = 0;
Value* value = valueList->current();
// Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
bool value1IsX = false, value1IsY = false;
value1 = parseBackgroundPositionXY(value1IsX, value1IsY);
if (!value1)
return;
// It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
// can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
// value was explicitly specified for our property.
value = valueList->next();
// First check for the comma. If so, we are finished parsing this value or value pair.
if (value && value->unit == Value::Operator && value->iValue == ',')
value = 0;
bool value2IsX = false, value2IsY = false;
if (value) {
value2 = parseBackgroundPositionXY(value2IsX, value2IsY);
if (value2)
valueList->next();
else {
if (!inParseShortHand) {
delete value1;
value1 = 0;
return;
}
}
}
if (!value2)
// Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
// is simply 50%. This is our default.
// For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
// For left/right/center, the default of 50% in the y is still correct.
value2 = new CSSPrimitiveValueImpl(50, CSSPrimitiveValue::CSS_PERCENTAGE);
if (value1IsY || value2IsX) {
// Swap our two values.
CSSValueImpl* val = value2;
value2 = value1;
value1 = val;
}
}
bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2,
CSSValueImpl*& retValue1, CSSValueImpl*& retValue2)
{
CSSValueListImpl *values = 0, *values2 = 0;
Value* val;
CSSValueImpl *value = 0, *value2 = 0;
bool allowComma = false;
retValue1 = retValue2 = 0;
propId1 = propId;
propId2 = propId;
if (propId == CSS_PROP_BACKGROUND_POSITION) {
propId1 = CSS_PROP_BACKGROUND_POSITION_X;
propId2 = CSS_PROP_BACKGROUND_POSITION_Y;
}
while ((val = valueList->current())) {
CSSValueImpl *currValue = 0, *currValue2 = 0;
if (allowComma) {
if (val->unit != Value::Operator || val->iValue != ',')
goto failed;
valueList->next();
allowComma = false;
}
else {
switch (propId) {
case CSS_PROP_BACKGROUND_ATTACHMENT:
if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) {
currValue = new CSSPrimitiveValueImpl(val->id);
valueList->next();
}
break;
case CSS_PROP_BACKGROUND_COLOR:
currValue = parseBackgroundColor();
if (currValue)
valueList->next();
break;
case CSS_PROP_BACKGROUND_IMAGE:
currValue = parseBackgroundImage();
if (currValue)
valueList->next();
break;
case CSS_PROP_BACKGROUND_POSITION:
parseBackgroundPosition(currValue, currValue2);
// unlike the other functions, parseBackgroundPosition advances the valueList pointer
break;
case CSS_PROP_BACKGROUND_POSITION_X: {
bool xFound = false, yFound = true;
currValue = parseBackgroundPositionXY(xFound, yFound);
if (currValue)
valueList->next();
break;
}
case CSS_PROP_BACKGROUND_POSITION_Y: {
bool xFound = true, yFound = false;
currValue = parseBackgroundPositionXY(xFound, yFound);
if (currValue)
valueList->next();
break;
}
case CSS_PROP_BACKGROUND_REPEAT:
if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) {
currValue = new CSSPrimitiveValueImpl(val->id);
valueList->next();
}
break;
}
if (!currValue)
goto failed;
if (value && !values) {
values = new CSSValueListImpl();
values->append(value);
value = 0;
}
if (value2 && !values2) {
values2 = new CSSValueListImpl();
values2->append(value2);
value2 = 0;
}
if (values)
values->append(currValue);
else
value = currValue;
if (currValue2) {
if (values2)
values2->append(currValue2);
else
value2 = currValue2;
}
allowComma = true;
}
// When parsing the 'background' shorthand property, we let it handle building up the lists for all
// properties.
if (inParseShortHand)
break;
}
if (values && values->length()) {
retValue1 = values;
if (values2 && values2->length())
retValue2 = values2;
return true;
}
if (value) {
retValue1 = value;
retValue2 = value2;
return true;
}
failed:
delete values; delete values2;
delete value; delete value2;
return false;
}
#define DASHBOARD_REGION_NUM_PARAMETERS 6
#define DASHBOARD_REGION_SHORT_NUM_PARAMETERS 2
static Value *skipCommaInDashboardRegion (ValueList *args)
{
if ( args->numValues == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
args->numValues == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
Value *current = args->current();
if (current->unit == Value::Operator && current->iValue == ',' )
return args->next();
}
return args->current();
}
#if APPLE_CHANGES
bool CSSParser::parseDashboardRegions( int propId, bool important )
{
bool valid = true;
Value *value = valueList->current();
if (value->id == CSS_VAL_NONE) {
addProperty( propId, new CSSPrimitiveValueImpl( value->id ), important );
return valid;
}
DashboardRegionImpl *firstRegion = new DashboardRegionImpl(), *region = 0;
while (value) {
if (region == 0) {
region = firstRegion;
}
else {
DashboardRegionImpl *nextRegion = new DashboardRegionImpl();
region->setNext (nextRegion);
region = nextRegion;
}
if ( value->unit != Value::Function) {
valid = false;
break;
}
// Commas count as values, so allow:
// dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
// dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
// also allow
// dashboard-region(label, type) or dashboard-region(label type)
// dashboard-region(label, type) or dashboard-region(label type)
ValueList *args = value->function->args;
int numArgs = value->function->args->numValues;
if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
(numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))){
valid = false;
break;
}
QString fname = qString( value->function->name ).lower();
if (fname != "dashboard-region(" ) {
valid = false;
break;
}
// First arg is a label.
Value *arg = args->current();
if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
valid = false;
break;
}
region->m_label = qString(arg->string);
// Second arg is a type.
arg = args->next();
arg = skipCommaInDashboardRegion (args);
if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
valid = false;
break;
}
QString geometryType = qString(arg->string).lower();
if (geometryType == "circle")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -