📄 cssparser.cpp
字号:
if(face[0] == '\"') face.remove(0, 1); if(face[face.length()-1] == '\"') face = face.left(face.length()-1); //kdDebug( 6080 ) << "found face '" << face << "'" << endl; list->append(new CSSPrimitiveValueImpl(DOMString(face), CSSPrimitiveValue::CSS_STRING)); pos = pos2 + 1; if(pos2 == -1) break; } //kdDebug( 6080 ) << "got " << list->length() << " faces" << endl; if(list->length()) parsedValue = list; else delete list; break; } case CSS_PROP_QUOTES: // list of strings or i case CSS_PROP_SIZE: // ### look up break; case CSS_PROP_TEXT_DECORATION: // list of ident { CSSValueListImpl *list = new CSSValueListImpl; QString str(curP, endP-curP); str.simplifyWhiteSpace(); //kdDebug( 6080 ) << "text-decoration: '" << str << "'" << endl; int pos=0, pos2; while( 1 ) { pos2 = str.find(' ', pos); QString decoration = str.mid(pos, pos2-pos); decoration = decoration.stripWhiteSpace(); //kdDebug( 6080 ) << "found decoration '" << decoration << "'" << endl; const struct css_value *cssval = findValue(decoration.lower().ascii(), decoration.length()); if (cssval) list->append(new CSSPrimitiveValueImpl(cssval->id)); pos = pos2 + 1; if(pos2 == -1) break; } //kdDebug( 6080 ) << "got " << list->length() << "d decorations" << endl; if(list->length()) parsedValue = list; else delete list; break; } case CSS_PROP_VOICE_FAMILY: // list of strings and i break;// shorthand properties case CSS_PROP_BACKGROUND: return parseBackground(curP, endP, important, propList);// add all shorthand properties to the list... case CSS_PROP_BORDER: case CSS_PROP_BORDER_TOP: case CSS_PROP_BORDER_RIGHT: case CSS_PROP_BORDER_BOTTOM: case CSS_PROP_BORDER_LEFT: {#ifdef CSS_DEBUG// kdDebug(6080) << "parsing border property" << endl;#endif const int *properties; const int properties_border[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE, CSS_PROP_BORDER_COLOR }; const int properties_border_top[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_TOP_COLOR }; const int properties_border_bottom[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_BOTTOM_COLOR }; const int properties_border_left[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_LEFT_COLOR }; const int properties_border_right[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_RIGHT_COLOR }; if(propId == CSS_PROP_BORDER) properties = properties_border; else if(propId == CSS_PROP_BORDER_TOP) properties = properties_border_top; else if(propId == CSS_PROP_BORDER_BOTTOM) properties = properties_border_bottom; else if(propId == CSS_PROP_BORDER_LEFT) properties = properties_border_left; else if(propId == CSS_PROP_BORDER_RIGHT) properties = properties_border_right; else return false; return parseShortHand(curP, endP, properties, 3, important, propList); } case CSS_PROP_BORDER_COLOR: { const struct css_value *cssval = findValue(val, value.length()); if (cssval && cssval->id == CSS_VAL_TRANSPARENT) { // set border colors to invalid parsedValue = new CSSPrimitiveValueImpl(CSS_VAL_TRANSPARENT); break; } 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(curP, endP, properties, important, propList); } case CSS_PROP_BORDER_WIDTH: { 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(curP, endP, properties, important, propList); } case CSS_PROP_BORDER_STYLE: { 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(curP, endP, properties, important, propList); } case CSS_PROP_MARGIN: { const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; return parse4Values(curP, endP, properties, important, propList); } case CSS_PROP_PADDING: { const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; return parse4Values(curP, endP, properties, important, propList); } case CSS_PROP_CUE: break; case CSS_PROP_FONT: { QString fontStr = QString( curP, endP - curP ); return parseFont( curP, endP, important, propList ); } 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(curP, endP, properties, 3, important, propList); } case CSS_PROP_OUTLINE: case CSS_PROP_PAUSE: break;#ifdef CSS_DEBUG default:// kdDebug( 6080 ) << "illegal property!" << endl;#endif } end: if(!parsedValue) return false; QListIterator<CSSProperty> propIt(*propList); propIt.toLast(); // just remove the top one - not sure what should happen if we have multiple instances of the property while (propIt.current() && propIt.current()->m_id != propId) --propIt; if (propIt.current()) propList->removeRef(propIt.current()); CSSProperty *prop = new CSSProperty(); prop->m_id = propId; prop->setValue(parsedValue); prop->m_bImportant = important; propList->append(prop); //kdDebug( 6080 ) << "added property " << propId << endl; return true;}static const QChar *getNext( const QChar *curP, const QChar *endP, bool &last ){ last = false; const QChar *nextP = curP; bool ignoreSpace = false; while(nextP <= endP) { if ( *nextP == '(' ) ignoreSpace = true; if ( *nextP == ')' ) ignoreSpace = false; if ( *nextP == ' ' && !ignoreSpace ) break; if ( *nextP == ';' || nextP == endP ) { last = true; break; } nextP++; } return nextP;}bool StyleBaseImpl::parseShortHand(const QChar *curP, const QChar *endP, const int *properties, int num, bool important, QList<CSSProperty> *propList, bool multiple){ bool last = false; bool fnd[10]; // 10 should be big enough... for( int i = 0; i < num; i++ ) fnd[i] = false; while(!last) { const QChar *nextP = getNext( curP, endP, last );; bool found = false;#ifdef CSS_DEBUG// kdDebug(6080) << "parsing \"" << QString(curP, nextP - curP) << "\"" << endl;#endif int i = 0; while ( !found && i < num ) { if( multiple || !fnd[i] ) found = parseValue(curP, nextP, properties[i], important, propList); if( found ) { //kdDebug() << "found " << i << endl; fnd[i] = true; } i++; } if(!found) {#ifdef CSS_DEBUG// kdDebug(6080) << "invalid property" << endl;#endif return false; } curP = nextP+1; if(curP >= endP) break; } return true;}bool StyleBaseImpl::parseBackground(const QChar *curP, const QChar *endP, bool important, QList<CSSProperty> *propList){ // ### implement background position bool last = false; bool fnd[5]; for( int i = 0; i < 5; i++ ) fnd[i] = false; while(!last) { bool found = false; const QChar *nextP = getNext( curP, endP, last ); if(!last && !fnd[0]) { bool l; const QChar *second = getNext( nextP+1, endP, l ); if(!fnd[0]) { found = parseValue(curP, second, CSS_PROP_BACKGROUND_POSITION, important, propList); if( found ) { fnd[0] = true; nextP = second; } } } //#ifdef CSS_DEBUG// kdDebug(6080) << "parsing \"" << QString(curP, nextP - curP) << "\"" << endl; //#endif if(!found && !fnd[2]) { found = parseValue(curP, nextP, CSS_PROP_BACKGROUND_COLOR, important, propList); if( found ) {// kdDebug(6080) << "color!!!" << endl; fnd[2] = true; } } if( !found ) { int id = -1; QString value(curP, nextP - curP); const struct css_value *cssval = findValue(value.latin1(), value.length()); if (cssval) id = cssval->id; int prop = -1; switch(id) { case CSS_VAL_REPEAT: case CSS_VAL_REPEAT_X: case CSS_VAL_REPEAT_Y: case CSS_VAL_NO_REPEAT: prop = CSS_PROP_BACKGROUND_REPEAT; fnd[3] = true; found = true; break; case CSS_VAL_SCROLL: case CSS_VAL_FIXED: prop = CSS_PROP_BACKGROUND_ATTACHMENT; fnd[4] = true; found = true; case CSS_VAL_CENTER: case CSS_VAL_TOP: case CSS_VAL_BOTTOM: case CSS_VAL_LEFT: case CSS_VAL_RIGHT: // #### remove this, do background position correctly found = true; break; default: break; } if( id != -1 ) found = parseValue(curP, nextP, prop, important, propList); } if(!found && !fnd[1]) { found = parseValue(curP, nextP, CSS_PROP_BACKGROUND_IMAGE, important, propList); if( found ) {// kdDebug(0) << "image!!!" << endl; fnd[1] = true; } } if(!found && !fnd[0]) { found = parseValue(curP, nextP, CSS_PROP_BACKGROUND_POSITION, important, propList); if( found ) fnd[0] = true; } if(!found) { //#ifdef CSS_DEBUG// kdDebug(6080) << "invalid property" << endl; //#endif // ##### //return false; } curP = nextP+1; if(curP >= endP) break; } return true;}// used for shorthand properties xxx{1,4}bool StyleBaseImpl::parse4Values(const QChar *curP, const QChar *endP, const int *properties, bool important, QList<CSSProperty> *propList){ bool last = false; QList<QChar> list; while(!last) { const QChar *nextP = curP; while(*nextP != ' ' && *nextP != ';') { nextP++; if(nextP >= endP) { last = true; break; } } list.append(curP); list.append(nextP); curP = nextP+1; if(curP >= endP) break; } switch(list.count()) { case 2: // this is needed to get a correct reply for the border shorthand // property if(!parseValue(list.at(0), list.at(1), properties[0], important, propList)) return false; parseValue(list.at(0), list.at(1), properties[1], important, propList); parseValue(list.at(0), list.at(1), properties[2], important, propList); parseValue(list.at(0), list.at(1), properties[3], important, propList); return true; case 4: if(!parseValue(list.at(0), list.at(1), properties[0], important, propList)) return false; if(!parseValue(list.at(2), list.at(3), properties[1], important, propList)) return false; parseValue(list.at(0), list.at(1), properties[2], important, propList); parseValue(list.at(2), list.at(3), properties[3], important, propList); return true; case 6: if(!parseValue(list.at(0), list.at(1), properties[0], important, propList)) return false; if(!parseValue(list.at(2), list.at(3), properties[1], important, propList)) return false; if(!parseValue(list.at(4), list.at(5), properties[2], important, propList)) return false; parseValue(list.at(2), list.at(3), properties[3], important, propList); return true; case 8: if(!parseValue(list.at(0), list.at(1), properties[0], important, propList)) return false; if(!parseValue(list.at(2), list.at(3), properties[1], important, propList)) return false; if(!parseValue(list.at(4), list.at(5), properties[2], important, propList)) return false; if(!parseValue(list.at(6), list.at(7), properties[3], important, propList)) return false; return true; default: return false; }}CSSValueImpl *StyleBaseImpl::parseUnit(const QChar * curP, const QChar *endP, int allowedUnits){ endP--; while(*endP == ' ' && endP > curP) endP--; const QChar *split = endP; // splt up number and unit while( (*split < '0' || *split > '9') && *split != '.' && split > curP) split--; split++; QString s(curP, split-curP); bool isInt = false; if(s.find('.') == -1) isInt = true; bool ok; float value = s.toFloat(&ok); if(!ok) return 0; if(split > endP) // no unit { if(allowedUnits & NUMBER) return new CSSPrimitiveValueImpl(value, CSSPrimitiveValue::CSS_NUMBER); if(allowedUnits & INTEGER && isInt) // ### DOM CSS doesn't seem to define something for integer return new CSSPrimitiveValueImpl(value, CSSPrimitiveValue::CSS_NUMBER); // ### according to the css specs only 0 is allowed without unit. // there are however too many web pages out there using CSS without units // cause ie and ns allow them. Better get a buggy in the CSS test suite than // messing up lots of bages. // CHECK_STRICT if(allowedUnits & LENGTH ) // && value == 0) return new CSSPrimitiveValueImpl(value, CSSPrimitiveValue::CSS_PX); return 0; } CSSPrimitiveValue::UnitTypes type = CSSPrimitiveValue::CSS_UNKNOWN; int unit = 0; switch(split->lower().latin1()) { case '%': type = CSSPrimitiveValue::CSS_PERCENTAGE; unit = PERCENT; break; case 'e': split++; if(split > endP) break; if(split->latin1() == 'm' || split->latin1() == 'M') { type = CSSPrimitiveValue::CSS_EMS; unit = LENGTH; } else if(split->latin1() == 'x' || split->latin1() == 'X') { type = CSSPrimitiveValue::CSS_EXS; unit = LENGTH; } break; case 'p': split++; if(split > endP) break; if(split->latin1() == 'x' || split->latin1() == 'X') { type = CSSPrimitiveValue::CSS_PX; unit = LENGTH; } else if(split->latin1() == 't' || split->latin1() == 'T') { type = CSSPrimitiveValue::CSS_PT; unit = LENGTH; } else if(split->latin1() == 'c' || split->latin1() == 'C') { type = CSSPrimitiveValue::CSS_PC; unit = LENGTH; } break; case 'c': split++; if(split > endP) break; if(split->latin1() == 'm' || split->latin1() == 'M') { type = CSSPrimitiveValue::CSS_CM; unit = LENGTH; } break; case 'm': split++; if(split > endP) break; if(split->latin1() == 'm' || split->latin1() == 'M') { type = CSSPrimitiveValue::CSS_MM; unit = LENGTH; } else if(split->latin1() == 's' || split->latin1() == 'S') { type = CSSPrimitiveValue::CSS_MS; unit = TIME; } break; case 'i': split++; if(split > endP) break; if(split->latin1() == 'n' || split->latin1() == 'N') { type = CSSPrimitiveValue::CSS_IN; unit = LENGTH; } break; case 'd': type = CSSPrimitiveValue::CSS_DEG; unit = ANGLE; break; case 'r': type = CSSPrimitiveValue::CSS_RAD; unit = ANGLE; break; case 'g': type = CSSPrimitiveValue::CSS_GRAD; unit = ANGLE; break; case 's': type = CSSPrimitiveValue::CSS_S; unit = TIME;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -