khtml Library API Documentation

css_valueimpl.cpp

00001 00024 #include "dom/css_value.h" 00025 #include "dom/dom_exception.h" 00026 #include "dom/dom_string.h" 00027 00028 #include "css/css_valueimpl.h" 00029 #include "css/css_ruleimpl.h" 00030 #include "css/css_stylesheetimpl.h" 00031 #include "css/cssparser.h" 00032 #include "css/cssproperties.h" 00033 #include "css/cssvalues.h" 00034 00035 #include "xml/dom_stringimpl.h" 00036 #include "xml/dom_docimpl.h" 00037 00038 #include "misc/loader.h" 00039 00040 #include "rendering/font.h" 00041 #include "rendering/render_style.h" 00042 00043 #include <kdebug.h> 00044 #include <qregexp.h> 00045 #include <qpaintdevice.h> 00046 #include <qpaintdevicemetrics.h> 00047 00048 // Hack for debugging purposes 00049 extern DOM::DOMString getPropertyName(unsigned short id); 00050 00051 using khtml::FontDef; 00052 00053 using namespace DOM; 00054 00055 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent) 00056 : StyleBaseImpl(parent) 00057 { 00058 m_lstValues = 0; 00059 m_node = 0; 00060 } 00061 00062 CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent, QPtrList<CSSProperty> *lstValues) 00063 : StyleBaseImpl(parent) 00064 { 00065 m_lstValues = lstValues; 00066 m_node = 0; 00067 } 00068 00069 CSSStyleDeclarationImpl& CSSStyleDeclarationImpl::operator= (const CSSStyleDeclarationImpl& o) 00070 { 00071 // don't attach it to the same node, just leave the current m_node value 00072 delete m_lstValues; 00073 m_lstValues = 0; 00074 if (o.m_lstValues) { 00075 m_lstValues = new QPtrList<CSSProperty>; 00076 m_lstValues->setAutoDelete( true ); 00077 00078 QPtrListIterator<CSSProperty> lstValuesIt(*o.m_lstValues); 00079 for (lstValuesIt.toFirst(); lstValuesIt.current(); ++lstValuesIt) 00080 m_lstValues->append(new CSSProperty(*lstValuesIt.current())); 00081 } 00082 00083 return *this; 00084 } 00085 00086 CSSStyleDeclarationImpl::~CSSStyleDeclarationImpl() 00087 { 00088 delete m_lstValues; 00089 // we don't use refcounting for m_node, to avoid cyclic references (see ElementImpl) 00090 } 00091 00092 DOMString CSSStyleDeclarationImpl::getPropertyValue( int propertyID ) const 00093 { 00094 if(!m_lstValues) return DOMString(); 00095 CSSValueImpl* value = getPropertyCSSValue( propertyID ); 00096 if ( value ) 00097 return value->cssText(); 00098 00099 // Shorthand and 4-values properties 00100 switch ( propertyID ) { 00101 case CSS_PROP_BACKGROUND_POSITION: 00102 { 00103 // ## Is this correct? The code in cssparser.cpp is confusing 00104 const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X, 00105 CSS_PROP_BACKGROUND_POSITION_Y }; 00106 return getShortHandValue( properties, 2 ); 00107 } 00108 case CSS_PROP_BACKGROUND: 00109 { 00110 const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, 00111 CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, 00112 CSS_PROP_BACKGROUND_COLOR }; 00113 return getShortHandValue( properties, 5 ); 00114 } 00115 case CSS_PROP_BORDER: 00116 { 00117 const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE, 00118 CSS_PROP_BORDER_COLOR }; 00119 return getShortHandValue( properties, 3 ); 00120 } 00121 case CSS_PROP_BORDER_TOP: 00122 { 00123 const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE, 00124 CSS_PROP_BORDER_TOP_COLOR}; 00125 return getShortHandValue( properties, 3 ); 00126 } 00127 case CSS_PROP_BORDER_RIGHT: 00128 { 00129 const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE, 00130 CSS_PROP_BORDER_RIGHT_COLOR}; 00131 return getShortHandValue( properties, 3 ); 00132 } 00133 case CSS_PROP_BORDER_BOTTOM: 00134 { 00135 const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, 00136 CSS_PROP_BORDER_BOTTOM_COLOR}; 00137 return getShortHandValue( properties, 3 ); 00138 } 00139 case CSS_PROP_BORDER_LEFT: 00140 { 00141 const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, 00142 CSS_PROP_BORDER_LEFT_COLOR}; 00143 return getShortHandValue( properties, 3 ); 00144 } 00145 case CSS_PROP_OUTLINE: 00146 { 00147 const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE, 00148 CSS_PROP_OUTLINE_COLOR }; 00149 return getShortHandValue( properties, 3 ); 00150 } 00151 case CSS_PROP_BORDER_COLOR: 00152 { 00153 const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR, 00154 CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR }; 00155 return get4Values( properties ); 00156 } 00157 case CSS_PROP_BORDER_WIDTH: 00158 { 00159 const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH, 00160 CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH }; 00161 return get4Values( properties ); 00162 } 00163 case CSS_PROP_BORDER_STYLE: 00164 { 00165 const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE, 00166 CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE }; 00167 return get4Values( properties ); 00168 } 00169 case CSS_PROP_MARGIN: 00170 { 00171 const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, 00172 CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; 00173 return get4Values( properties ); 00174 } 00175 case CSS_PROP_PADDING: 00176 { 00177 const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, 00178 CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; 00179 return get4Values( properties ); 00180 } 00181 case CSS_PROP_LIST_STYLE: 00182 { 00183 const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION, 00184 CSS_PROP_LIST_STYLE_IMAGE }; 00185 return getShortHandValue( properties, 3 ); 00186 } 00187 } 00188 //kdDebug() << k_funcinfo << "property not found:" << propertyID << endl; 00189 return DOMString(); 00190 } 00191 00192 DOMString CSSStyleDeclarationImpl::get4Values( const int* properties ) const 00193 { 00194 DOMString res; 00195 for ( int i = 0 ; i < 4 ; ++i ) { 00196 CSSValueImpl* value = getPropertyCSSValue( properties[i] ); 00197 if ( !value ) { // apparently all 4 properties must be specified. 00198 return DOMString(); 00199 } 00200 if ( i > 0 ) 00201 res += " "; 00202 res += value->cssText(); 00203 } 00204 return res; 00205 } 00206 00207 DOMString CSSStyleDeclarationImpl::getShortHandValue( const int* properties, int number ) const 00208 { 00209 DOMString res; 00210 for ( int i = 0 ; i < number ; ++i ) { 00211 CSSValueImpl* value = getPropertyCSSValue( properties[i] ); 00212 if ( value ) { // TODO provide default value if !value 00213 if ( !res.isNull() ) 00214 res += " "; 00215 res += value->cssText(); 00216 } 00217 } 00218 return res; 00219 } 00220 00221 CSSValueImpl *CSSStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const 00222 { 00223 if(!m_lstValues) return 0; 00224 00225 QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); 00226 CSSProperty *current; 00227 for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt ) 00228 if (current->m_id == propertyID && !current->nonCSSHint) 00229 return current->value(); 00230 return 0; 00231 } 00232 00233 DOMString CSSStyleDeclarationImpl::removeProperty( int propertyID, bool NonCSSHint ) 00234 { 00235 if(!m_lstValues) return DOMString(); 00236 DOMString value; 00237 00238 QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); 00239 CSSProperty *current; 00240 for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt ) { 00241 if (current->m_id == propertyID && NonCSSHint == current->nonCSSHint) { 00242 value = current->value()->cssText(); 00243 m_lstValues->removeRef(current); 00244 setChanged(); 00245 break; 00246 } 00247 } 00248 00249 return value; 00250 } 00251 00252 void CSSStyleDeclarationImpl::setChanged() 00253 { 00254 if (m_node) { 00255 m_node->setChanged(); 00256 return; 00257 } 00258 00259 // ### quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk) 00260 for (StyleBaseImpl* stylesheet = this; stylesheet; stylesheet = stylesheet->parent()) 00261 if (stylesheet->isCSSStyleSheet()) { 00262 static_cast<CSSStyleSheetImpl*>(stylesheet)->doc()->updateStyleSelector(); 00263 break; 00264 } 00265 } 00266 00267 void CSSStyleDeclarationImpl::removeCSSHints() 00268 { 00269 if (!m_lstValues) 00270 return; 00271 00272 for (int i = (int)m_lstValues->count()-1; i >= 0; i--) { 00273 if (!m_lstValues->at(i)->nonCSSHint) 00274 m_lstValues->remove(i); 00275 } 00276 } 00277 00278 bool CSSStyleDeclarationImpl::getPropertyPriority( int propertyID ) const 00279 { 00280 if ( m_lstValues) { 00281 QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); 00282 CSSProperty *current; 00283 for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) { 00284 if( propertyID == current->m_id ) 00285 return current->m_bImportant; 00286 } 00287 } 00288 return false; 00289 } 00290 00291 bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool nonCSSHint) 00292 { 00293 if(!m_lstValues) { 00294 m_lstValues = new QPtrList<CSSProperty>; 00295 m_lstValues->setAutoDelete(true); 00296 } 00297 00298 CSSParser parser( strictParsing ); 00299 bool success = parser.parseValue( this, id, value, important, nonCSSHint ); 00300 if(!success) 00301 kdDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string() 00302 << "] value: [" << value.string() << "]"<< endl; 00303 else 00304 setChanged(); 00305 return success; 00306 } 00307 00308 void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool nonCSSHint) 00309 { 00310 if(!m_lstValues) { 00311 m_lstValues = new QPtrList<CSSProperty>; 00312 m_lstValues->setAutoDelete(true); 00313 } 00314 removeProperty(id, nonCSSHint ); 00315 00316 CSSValueImpl * cssValue = new CSSPrimitiveValueImpl(value); 00317 setParsedValue(id, cssValue, important, nonCSSHint, m_lstValues); 00318 setChanged(); 00319 } 00320 00321 void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint, bool _multiLength ) 00322 { 00323 bool parseMode = strictParsing; 00324 strictParsing = false; 00325 multiLength = _multiLength; 00326 setProperty( id, value, important, nonCSSHint); 00327 strictParsing = parseMode; 00328 multiLength = false; 00329 } 00330 00331 void CSSStyleDeclarationImpl::setProperty ( const DOMString &propertyString) 00332 { 00333 if(!m_lstValues) { 00334 m_lstValues = new QPtrList<CSSProperty>; 00335 m_lstValues->setAutoDelete( true ); 00336 } 00337 00338 CSSParser parser( strictParsing ); 00339 parser.parseDeclaration( this, propertyString, false ); 00340 setChanged(); 00341 } 00342 00343 unsigned long CSSStyleDeclarationImpl::length() const 00344 { 00345 return m_lstValues ? m_lstValues->count() : 0; 00346 } 00347 00348 DOMString CSSStyleDeclarationImpl::item( unsigned long index ) const 00349 { 00350 if(m_lstValues && index < m_lstValues->count() && m_lstValues->at(index)) 00351 return getPropertyName(m_lstValues->at(index)->m_id); 00352 return DOMString(); 00353 } 00354 00355 CSSRuleImpl *CSSStyleDeclarationImpl::parentRule() const 00356 { 00357 return (m_parent && m_parent->isRule() ) ? 00358 static_cast<CSSRuleImpl *>(m_parent) : 0; 00359 } 00360 00361 DOM::DOMString CSSStyleDeclarationImpl::cssText() const 00362 { 00363 DOMString result; 00364 00365 if ( m_lstValues) { 00366 QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); 00367 CSSProperty *current; 00368 for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) { 00369 result += current->cssText(); 00370 } 00371 } 00372 00373 return result; 00374 } 00375 00376 void CSSStyleDeclarationImpl::setCssText(DOM::DOMString text) 00377 { 00378 if (m_lstValues) { 00379 m_lstValues->clear(); 00380 } else { 00381 m_lstValues = new QPtrList<CSSProperty>; 00382 m_lstValues->setAutoDelete( true ); 00383 } 00384 00385 CSSParser parser( strictParsing ); 00386 parser.parseDeclaration( this, text, false ); 00387 setChanged(); 00388 } 00389 00390 bool CSSStyleDeclarationImpl::parseString( const DOMString &/*string*/, bool ) 00391 { 00392 kdDebug() << "WARNING: CSSStyleDeclarationImpl::parseString, unimplemented, was called" << endl; 00393 return false; 00394 // ### 00395 } 00396 00397 00398 // -------------------------------------------------------------------------------------- 00399 00400 unsigned short CSSInheritedValueImpl::cssValueType() const 00401 { 00402 return CSSValue::CSS_INHERIT; 00403 } 00404 00405 DOM::DOMString CSSInheritedValueImpl::cssText() const 00406 { 00407 return DOMString("inherited"); 00408 } 00409 00410 unsigned short CSSInitialValueImpl::cssValueType() const 00411 { 00412 return CSSValue::CSS_INITIAL; 00413 } 00414 00415 DOM::DOMString CSSInitialValueImpl::cssText() const 00416 { 00417 return DOMString("initial"); 00418 } 00419 00420 // ---------------------------------------------------------------------------------------- 00421 00422 CSSValueListImpl::~CSSValueListImpl() 00423 { 00424 CSSValueImpl *val = m_values.first(); 00425 while( val ) { 00426 val->deref(); 00427 val = m_values.next(); 00428 } 00429 } 00430 00431 unsigned short CSSValueListImpl::cssValueType() const 00432 { 00433 return CSSValue::CSS_VALUE_LIST; 00434 } 00435 00436 void CSSValueListImpl::append(CSSValueImpl *val) 00437 { 00438 m_values.append(val); 00439 val->ref(); 00440 } 00441 00442 DOM::DOMString CSSValueListImpl::cssText() const 00443 { 00444 DOMString result = ""; 00445 00446 for (QPtrListIterator<CSSValueImpl> iterator(m_values); iterator.current(); ++iterator) { 00447 result += iterator.current()->cssText(); 00448 } 00449 00450 return result; 00451 } 00452 00453 // ------------------------------------------------------------------------------------- 00454 00455 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl() 00456 : CSSValueImpl() 00457 { 00458 m_type = 0; 00459 } 00460 00461 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(int ident) 00462 : CSSValueImpl() 00463 { 00464 m_value.ident = ident; 00465 m_type = CSSPrimitiveValue::CSS_IDENT; 00466 } 00467 00468 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type) 00469 { 00470 m_value.num = num; 00471 m_type = type; 00472 } 00473 00474 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type) 00475 { 00476 m_value.string = str.implementation(); 00477 if(m_value.string) m_value.string->ref(); 00478 m_type = type; 00479 } 00480 00481 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(CounterImpl *c) 00482 { 00483 m_value.counter = c; 00484 if (m_value.counter) 00485 m_value.counter->ref(); 00486 m_type = CSSPrimitiveValue::CSS_COUNTER; 00487 } 00488 00489 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl( RectImpl *r) 00490 { 00491 m_value.rect = r; 00492 if (m_value.rect) 00493 m_value.rect->ref(); 00494 m_type = CSSPrimitiveValue::CSS_RECT; 00495 } 00496 00497 CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color) 00498 { 00499 m_value.rgbcolor = color; 00500 m_type = CSSPrimitiveValue::CSS_RGBCOLOR; 00501 } 00502 00503 CSSPrimitiveValueImpl::~CSSPrimitiveValueImpl() 00504 { 00505 cleanup(); 00506 } 00507 00508 void CSSPrimitiveValueImpl::cleanup() 00509 { 00510 switch(m_type) { 00511 case CSSPrimitiveValue::CSS_STRING: 00512 case CSSPrimitiveValue::CSS_URI: 00513 case CSSPrimitiveValue::CSS_ATTR: 00514 if(m_value.string) m_value.string->deref(); 00515 break; 00516 case CSSPrimitiveValue::CSS_COUNTER: 00517 m_value.counter->deref(); 00518 break; 00519 case CSSPrimitiveValue::CSS_RECT: 00520 m_value.rect->deref(); 00521 default: 00522 break; 00523 } 00524 00525 m_type = 0; 00526 } 00527 00528 int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics ) 00529 { 00530 double result = computeLengthFloat( style, devMetrics ); 00531 int intResult = (int)result; 00532 #ifdef APPLE_CHANGES 00533 // This conversion is imprecise, often resulting in values of e.g., 44.99998. We 00534 // need to go ahead and round if we're really close to the next integer value. 00535 double newResult = (intResult < 0) ? result-0.01 : result+0.01; 00536 int secondIntResult = (int)newResult; 00537 if (secondIntResult != intResult) 00538 return secondIntResult; 00539 #endif 00540 return intResult; 00541 } 00542 00543 double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics ) 00544 { 00545 unsigned short type = primitiveType(); 00546 00547 double dpiY = 72.; // fallback 00548 if ( devMetrics ) 00549 dpiY = devMetrics->logicalDpiY(); 00550 if ( !khtml::printpainter && dpiY < 96 ) 00551 dpiY = 96.; 00552 00553 double factor = 1.; 00554 switch(type) 00555 { 00556 case CSSPrimitiveValue::CSS_EMS: 00557 factor = style->font().pixelSize(); 00558 break; 00559 case CSSPrimitiveValue::CSS_EXS: 00560 { 00561 QFontMetrics fm = style->fontMetrics(); 00562 #ifdef APPLE_CHANGES 00563 factor = fm.xHeight(); 00564 #else 00565 QRect b = fm.boundingRect('x'); 00566 factor = b.height(); 00567 #endif 00568 break; 00569 } 00570 case CSSPrimitiveValue::CSS_PX: 00571 break; 00572 case CSSPrimitiveValue::CSS_CM: 00573 factor = dpiY/2.54; //72dpi/(2.54 cm/in) 00574 break; 00575 case CSSPrimitiveValue::CSS_MM: 00576 factor = dpiY/25.4; 00577 break; 00578 case CSSPrimitiveValue::CSS_IN: 00579 factor = dpiY; 00580 break; 00581 case CSSPrimitiveValue::CSS_PT: 00582 factor = dpiY/72.; 00583 break; 00584 case CSSPrimitiveValue::CSS_PC: 00585 // 1 pc == 12 pt 00586 factor = dpiY*12./72.; 00587 break; 00588 default: 00589 return -1; 00590 } 00591 00592 return floatValue(type)*factor; 00593 } 00594 00595 void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode ) 00596 { 00597 exceptioncode = 0; 00598 cleanup(); 00599 // ### check if property supports this type 00600 if(m_type > CSSPrimitiveValue::CSS_DIMENSION) { 00601 exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET; 00602 return; 00603 } 00604 //if(m_type > CSSPrimitiveValue::CSS_DIMENSION) throw DOMException(DOMException::INVALID_ACCESS_ERR); 00605 m_value.num = floatValue; 00606 m_type = unitType; 00607 } 00608 00609 void CSSPrimitiveValueImpl::setStringValue( unsigned short stringType, const DOMString &stringValue, int &exceptioncode ) 00610 { 00611 exceptioncode = 0; 00612 cleanup(); 00613 //if(m_type < CSSPrimitiveValue::CSS_STRING) throw DOMException(DOMException::INVALID_ACCESS_ERR); 00614 //if(m_type > CSSPrimitiveValue::CSS_ATTR) throw DOMException(DOMException::INVALID_ACCESS_ERR); 00615 if(m_type < CSSPrimitiveValue::CSS_STRING || m_type > CSSPrimitiveValue::CSS_ATTR) { 00616 exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET; 00617 return; 00618 } 00619 if(stringType != CSSPrimitiveValue::CSS_IDENT) 00620 { 00621 m_value.string = stringValue.implementation(); 00622 m_value.string->ref(); 00623 m_type = stringType; 00624 } 00625 // ### parse ident 00626 } 00627 00628 unsigned short CSSPrimitiveValueImpl::cssValueType() const 00629 { 00630 return CSSValue::CSS_PRIMITIVE_VALUE; 00631 } 00632 00633 bool CSSPrimitiveValueImpl::parseString( const DOMString &/*string*/, bool ) 00634 { 00635 // ### 00636 kdDebug() << "WARNING: CSSPrimitiveValueImpl::parseString, unimplemented, was called" << endl; 00637 return false; 00638 } 00639 00640 int CSSPrimitiveValueImpl::getIdent() 00641 { 00642 if(m_type != CSSPrimitiveValue::CSS_IDENT) return 0; 00643 return m_value.ident; 00644 } 00645 00646 DOM::DOMString CSSPrimitiveValueImpl::cssText() const 00647 { 00648 // ### return the original value instead of a generated one (e.g. color 00649 // name if it was specified) - check what spec says about this 00650 DOMString text; 00651 switch ( m_type ) { 00652 case CSSPrimitiveValue::CSS_UNKNOWN: 00653 // ### 00654 break; 00655 case CSSPrimitiveValue::CSS_NUMBER: 00656 text = DOMString(QString::number( (int)m_value.num )); 00657 break; 00658 case CSSPrimitiveValue::CSS_PERCENTAGE: 00659 text = DOMString(QString::number( m_value.num ) + "%"); 00660 break; 00661 case CSSPrimitiveValue::CSS_EMS: 00662 text = DOMString(QString::number( m_value.num ) + "em"); 00663 break; 00664 case CSSPrimitiveValue::CSS_EXS: 00665 text = DOMString(QString::number( m_value.num ) + "ex"); 00666 break; 00667 case CSSPrimitiveValue::CSS_PX: 00668 text = DOMString(QString::number( m_value.num ) + "px"); 00669 break; 00670 case CSSPrimitiveValue::CSS_CM: 00671 text = DOMString(QString::number( m_value.num ) + "cm"); 00672 break; 00673 case CSSPrimitiveValue::CSS_MM: 00674 text = DOMString(QString::number( m_value.num ) + "mm"); 00675 break; 00676 case CSSPrimitiveValue::CSS_IN: 00677 text = DOMString(QString::number( m_value.num ) + "in"); 00678 break; 00679 case CSSPrimitiveValue::CSS_PT: 00680 text = DOMString(QString::number( m_value.num ) + "pt"); 00681 break; 00682 case CSSPrimitiveValue::CSS_PC: 00683 text = DOMString(QString::number( m_value.num ) + "pc"); 00684 break; 00685 case CSSPrimitiveValue::CSS_DEG: 00686 text = DOMString(QString::number( m_value.num ) + "deg"); 00687 break; 00688 case CSSPrimitiveValue::CSS_RAD: 00689 text = DOMString(QString::number( m_value.num ) + "rad"); 00690 break; 00691 case CSSPrimitiveValue::CSS_GRAD: 00692 text = DOMString(QString::number( m_value.num ) + "grad"); 00693 break; 00694 case CSSPrimitiveValue::CSS_MS: 00695 text = DOMString(QString::number( m_value.num ) + "ms"); 00696 break; 00697 case CSSPrimitiveValue::CSS_S: 00698 text = DOMString(QString::number( m_value.num ) + "s"); 00699 break; 00700 case CSSPrimitiveValue::CSS_HZ: 00701 text = DOMString(QString::number( m_value.num ) + "hz"); 00702 break; 00703 case CSSPrimitiveValue::CSS_KHZ: 00704 text = DOMString(QString::number( m_value.num ) + "khz"); 00705 break; 00706 case CSSPrimitiveValue::CSS_DIMENSION: 00707 // ### 00708 break; 00709 case CSSPrimitiveValue::CSS_STRING: 00710 // ### 00711 break; 00712 case CSSPrimitiveValue::CSS_URI: 00713 text = "url("; 00714 text += DOMString( m_value.string ); 00715 text += ")"; 00716 break; 00717 case CSSPrimitiveValue::CSS_IDENT: 00718 text = getValueName(m_value.ident); 00719 break; 00720 case CSSPrimitiveValue::CSS_ATTR: 00721 // ### 00722 break; 00723 case CSSPrimitiveValue::CSS_COUNTER: 00724 text = "counter("; 00725 text += m_value.counter->m_identifier; 00726 text += ")"; 00727 // ### add list-style and separator 00728 break; 00729 case CSSPrimitiveValue::CSS_RECT: 00730 { 00731 RectImpl* rectVal = getRectValue(); 00732 text = "rect("; 00733 text += rectVal->top()->cssText() + " "; 00734 text += rectVal->right()->cssText() + " "; 00735 text += rectVal->bottom()->cssText() + " "; 00736 text += rectVal->left()->cssText() + ")"; 00737 } 00738 break; 00739 case CSSPrimitiveValue::CSS_RGBCOLOR: 00740 text = QColor(m_value.rgbcolor).name(); 00741 break; 00742 default: 00743 break; 00744 } 00745 return text; 00746 } 00747 00748 // ----------------------------------------------------------------- 00749 00750 RectImpl::RectImpl() 00751 { 00752 m_top = 0; 00753 m_right = 0; 00754 m_bottom = 0; 00755 m_left = 0; 00756 } 00757 00758 RectImpl::~RectImpl() 00759 { 00760 if (m_top) m_top->deref(); 00761 if (m_right) m_right->deref(); 00762 if (m_bottom) m_bottom->deref(); 00763 if (m_left) m_left->deref(); 00764 } 00765 00766 void RectImpl::setTop( CSSPrimitiveValueImpl *top ) 00767 { 00768 if( top ) top->ref(); 00769 if ( m_top ) m_top->deref(); 00770 m_top = top; 00771 } 00772 00773 void RectImpl::setRight( CSSPrimitiveValueImpl *right ) 00774 { 00775 if( right ) right->ref(); 00776 if ( m_right ) m_right->deref(); 00777 m_right = right; 00778 } 00779 00780 void RectImpl::setBottom( CSSPrimitiveValueImpl *bottom ) 00781 { 00782 if( bottom ) bottom->ref(); 00783 if ( m_bottom ) m_bottom->deref(); 00784 m_bottom = bottom; 00785 } 00786 00787 void RectImpl::setLeft( CSSPrimitiveValueImpl *left ) 00788 { 00789 if( left ) left->ref(); 00790 if ( m_left ) m_left->deref(); 00791 m_left = left; 00792 } 00793 00794 // ----------------------------------------------------------------- 00795 00796 CSSImageValueImpl::CSSImageValueImpl(const DOMString &url, const StyleBaseImpl* style) 00797 : CSSPrimitiveValueImpl(url, CSSPrimitiveValue::CSS_URI) 00798 { 00799 khtml::DocLoader *docLoader = 0; 00800 const StyleBaseImpl *root = style; 00801 while (root->parent()) 00802 root = root->parent(); 00803 if (root->isCSSStyleSheet()) 00804 docLoader = static_cast<const CSSStyleSheetImpl*>(root)->docLoader(); 00805 00806 m_image = docLoader->requestImage(url); 00807 if(m_image) m_image->ref(this); 00808 } 00809 00810 CSSImageValueImpl::CSSImageValueImpl() 00811 : CSSPrimitiveValueImpl(CSS_VAL_NONE) 00812 { 00813 m_image = 0; 00814 } 00815 00816 CSSImageValueImpl::~CSSImageValueImpl() 00817 { 00818 if(m_image) m_image->deref(this); 00819 } 00820 00821 // ------------------------------------------------------------------------ 00822 00823 FontFamilyValueImpl::FontFamilyValueImpl( const QString &string) 00824 : CSSPrimitiveValueImpl( DOMString(string), CSSPrimitiveValue::CSS_STRING) 00825 { 00826 static const QRegExp parenReg(" \\(.*\\)$"); 00827 static const QRegExp braceReg(" \\[.*\\]$"); 00828 00829 parsedFontName = string; 00830 // a language tag is often added in braces at the end. Remove it. 00831 parsedFontName.replace(parenReg, QString::null); 00832 // remove [Xft] qualifiers 00833 parsedFontName.replace(braceReg, QString::null); 00834 00835 #ifndef APPLE_CHANGES 00836 const QString &available = KHTMLSettings::availableFamilies(); 00837 00838 parsedFontName = parsedFontName.lower(); 00839 // kdDebug(0) << "searching for face '" << parsedFontName << "'" << endl; 00840 00841 int pos = available.find( ',' + parsedFontName + ',', 0, false ); 00842 if ( pos == -1 ) { 00843 // many pages add extra MSs to make sure it's windows only ;( 00844 if ( parsedFontName.startsWith( "ms " ) ) 00845 parsedFontName = parsedFontName.mid( 3 ); 00846 if ( parsedFontName.endsWith( " ms" ) ) 00847 parsedFontName.truncate( parsedFontName.length() - 3 ); 00848 pos = available.find( ",ms " + parsedFontName + ',', 0, false ); 00849 if ( pos == -1 ) 00850 pos = available.find( ',' + parsedFontName + " ms,", 0, false ); 00851 } 00852 00853 if ( pos != -1 ) { 00854 ++pos; 00855 int p = available.find(',', pos); 00856 assert( p != -1 ); // available is supposed to start and end with , 00857 parsedFontName = available.mid( pos, p - pos); 00858 // kdDebug(0) << "going for '" << parsedFontName << "'" << endl; 00859 } else 00860 parsedFontName = QString::null; 00861 00862 #endif // !APPLE_CHANGES 00863 } 00864 00865 FontValueImpl::FontValueImpl() 00866 : style(0), variant(0), weight(0), size(0), lineHeight(0), family(0) 00867 { 00868 } 00869 00870 FontValueImpl::~FontValueImpl() 00871 { 00872 delete style; 00873 delete variant; 00874 delete weight; 00875 delete size; 00876 delete lineHeight; 00877 delete family; 00878 } 00879 00880 DOMString FontValueImpl::cssText() const 00881 { 00882 // font variant weight size / line-height family 00883 00884 DOMString result(""); 00885 00886 if (style) { 00887 result += style->cssText(); 00888 } 00889 if (variant) { 00890 if (result.length() > 0) { 00891 result += " "; 00892 } 00893 result += variant->cssText(); 00894 } 00895 if (weight) { 00896 if (result.length() > 0) { 00897 result += " "; 00898 } 00899 result += weight->cssText(); 00900 } 00901 if (size) { 00902 if (result.length() > 0) { 00903 result += " "; 00904 } 00905 result += size->cssText(); 00906 } 00907 if (lineHeight) { 00908 if (!size) { 00909 result += " "; 00910 } 00911 result += "/"; 00912 result += lineHeight->cssText(); 00913 } 00914 if (family) { 00915 if (result.length() > 0) { 00916 result += " "; 00917 } 00918 result += family->cssText(); 00919 } 00920 00921 return result; 00922 } 00923 00924 QuotesValueImpl::QuotesValueImpl() 00925 : levels(0) 00926 { 00927 } 00928 00929 DOMString QuotesValueImpl::cssText() const 00930 { 00931 return "\"" + data.join("\" \"") + "\""; 00932 } 00933 00934 void QuotesValueImpl::addLevel(const QString& open, const QString& close) 00935 { 00936 data.append(open); 00937 data.append(close); 00938 levels++; 00939 } 00940 00941 QString QuotesValueImpl::openQuote(int level) const 00942 { 00943 if (levels == 0) return ""; 00944 level--; // increments are calculated before openQuote is called 00945 // kdDebug( 6080 ) << "Open quote level:" << level << endl; 00946 if (level < 0) level = 0; 00947 else 00948 if (level >= levels) level = levels-1; 00949 return data[level*2]; 00950 } 00951 00952 QString QuotesValueImpl::closeQuote(int level) const 00953 { 00954 if (levels == 0) return ""; 00955 // kdDebug( 6080 ) << "Close quote level:" << level << endl; 00956 if (level < 0) level = 0; 00957 else 00958 if (level >= levels) level = levels-1; 00959 return data[level*2+1]; 00960 } 00961 00962 // Used for text-shadow and box-shadow 00963 ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y, 00964 CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color) 00965 :x(_x), y(_y), blur(_blur), color(_color) 00966 {} 00967 00968 ShadowValueImpl::~ShadowValueImpl() 00969 { 00970 delete x; 00971 delete y; 00972 delete blur; 00973 delete color; 00974 } 00975 00976 DOMString ShadowValueImpl::cssText() const 00977 { 00978 DOMString text(""); 00979 if (color) { 00980 text += color->cssText(); 00981 } 00982 if (x) { 00983 if (text.length() > 0) { 00984 text += " "; 00985 } 00986 text += x->cssText(); 00987 } 00988 if (y) { 00989 if (text.length() > 0) { 00990 text += " "; 00991 } 00992 text += y->cssText(); 00993 } 00994 if (blur) { 00995 if (text.length() > 0) { 00996 text += " "; 00997 } 00998 text += blur->cssText(); 00999 } 01000 01001 return text; 01002 } 01003 01004 DOMString CounterActImpl::cssText() const 01005 { 01006 DOMString text(m_counter); 01007 text += DOMString(QString::number(m_value)); 01008 01009 return text; 01010 } 01011 01012 DOMString CSSProperty::cssText() const 01013 { 01014 return getPropertyName(m_id) + DOMString(": ") + m_value->cssText() + (m_bImportant ? DOMString(" !important") : DOMString()) + DOMString("; "); 01015 }
KDE Logo
This file is part of the documentation for khtml Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:31:21 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003