khtml Library API Documentation

cssstyleselector.cpp

00001 00023 #include "css/cssstyleselector.h" 00024 #include "rendering/render_style.h" 00025 #include "css/css_stylesheetimpl.h" 00026 #include "css/css_ruleimpl.h" 00027 #include "css/css_valueimpl.h" 00028 #include "css/csshelper.h" 00029 #include "rendering/render_object.h" 00030 #include "html/html_documentimpl.h" 00031 #include "html/html_elementimpl.h" 00032 #include "xml/dom_elementimpl.h" 00033 #include "dom/css_rule.h" 00034 #include "dom/css_value.h" 00035 #include "khtml_factory.h" 00036 #include "khtmlpart_p.h" 00037 using namespace khtml; 00038 using namespace DOM; 00039 00040 #include "css/cssproperties.h" 00041 #include "css/cssvalues.h" 00042 00043 #include "misc/khtmllayout.h" 00044 #include "khtml_settings.h" 00045 #include "misc/htmlhashes.h" 00046 #include "misc/helper.h" 00047 #include "misc/loader.h" 00048 00049 #include "rendering/font.h" 00050 00051 #include "khtmlview.h" 00052 #include "khtml_part.h" 00053 00054 #include <kstandarddirs.h> 00055 #include <kcharsets.h> 00056 #include <kglobal.h> 00057 #include <kconfig.h> 00058 #include <qfile.h> 00059 #include <qvaluelist.h> 00060 #include <qstring.h> 00061 #include <qtooltip.h> 00062 #include <kdebug.h> 00063 #include <kurl.h> 00064 #include <assert.h> 00065 #include <qpaintdevicemetrics.h> 00066 #include <stdlib.h> 00067 00068 #define HANDLE_INHERIT(prop, Prop) \ 00069 if (isInherit) \ 00070 {\ 00071 style->set##Prop(parentStyle->prop());\ 00072 return;\ 00073 } 00074 00075 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ 00076 HANDLE_INHERIT(prop, Prop) \ 00077 else if (isInitial) \ 00078 style->set##Prop(RenderStyle::initial##Prop()); 00079 00080 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ 00081 HANDLE_INHERIT(prop, Prop) \ 00082 else if (isInitial) \ 00083 style->set##Prop(RenderStyle::initial##Value()); 00084 00085 #define HANDLE_INHERIT_COND(propID, prop, Prop) \ 00086 if (id == propID) \ 00087 {\ 00088 style->set##Prop(parentStyle->prop());\ 00089 return;\ 00090 } 00091 00092 #define HANDLE_INITIAL_COND(propID, Prop) \ 00093 if (id == propID) \ 00094 {\ 00095 style->set##Prop(RenderStyle::initial##Prop());\ 00096 return;\ 00097 } 00098 00099 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ 00100 if (id == propID) \ 00101 {\ 00102 style->set##Prop(RenderStyle::initial##Value());\ 00103 return;\ 00104 } 00105 00106 namespace khtml { 00107 00108 CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle; 00109 CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle; 00110 CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle; 00111 CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet; 00112 RenderStyle* CSSStyleSelector::styleNotYetAvailable; 00113 CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet; 00114 00115 enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited}; 00116 static PseudoState pseudoState; 00117 00118 00119 CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets, 00120 const KURL &url, bool _strictParsing ) 00121 { 00122 KHTMLView* view = doc->view(); 00123 00124 init(view ? view->part()->settings() : 0); 00125 00126 strictParsing = _strictParsing; 00127 m_medium = view ? view->mediaType() : QString("all"); 00128 00129 selectors = 0; 00130 selectorCache = 0; 00131 properties = 0; 00132 userStyle = 0; 00133 userSheet = 0; 00134 paintDeviceMetrics = doc->paintDeviceMetrics(); 00135 00136 if(paintDeviceMetrics) // this may be null, not everyone uses khtmlview (Niko) 00137 computeFontSizes(paintDeviceMetrics, view ? view->part()->zoomFactor() : 100); 00138 00139 if ( !userStyleSheet.isEmpty() ) { 00140 userSheet = new DOM::CSSStyleSheetImpl(doc); 00141 userSheet->parseString( DOMString( userStyleSheet ) ); 00142 00143 userStyle = new CSSStyleSelectorList(); 00144 userStyle->append( userSheet, m_medium ); 00145 } 00146 00147 // add stylesheets from document 00148 authorStyle = new CSSStyleSelectorList(); 00149 00150 00151 QPtrListIterator<StyleSheetImpl> it( styleSheets->styleSheets ); 00152 for ( ; it.current(); ++it ) { 00153 if ( it.current()->isCSSStyleSheet() ) { 00154 authorStyle->append( static_cast<CSSStyleSheetImpl*>( it.current() ), m_medium ); 00155 } 00156 } 00157 00158 buildLists(); 00159 00160 //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl; 00161 //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl; 00162 00163 KURL u = url; 00164 00165 u.setQuery( QString::null ); 00166 u.setRef( QString::null ); 00167 encodedurl.file = u.url(); 00168 int pos = encodedurl.file.findRev('/'); 00169 encodedurl.path = encodedurl.file; 00170 if ( pos > 0 ) { 00171 encodedurl.path.truncate( pos ); 00172 encodedurl.path += '/'; 00173 } 00174 u.setPath( QString::null ); 00175 encodedurl.host = u.url(); 00176 00177 //kdDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path << endl; 00178 } 00179 00180 CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet ) 00181 { 00182 init(0L); 00183 00184 KHTMLView *view = sheet->doc()->view(); 00185 m_medium = view ? view->mediaType() : "screen"; 00186 00187 authorStyle = new CSSStyleSelectorList(); 00188 authorStyle->append( sheet, m_medium ); 00189 } 00190 00191 void CSSStyleSelector::init(const KHTMLSettings* _settings) 00192 { 00193 element = 0; 00194 settings = _settings; 00195 paintDeviceMetrics = 0; 00196 propsToApply = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *)); 00197 pseudoProps = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *)); 00198 propsToApplySize = 128; 00199 pseudoPropsSize = 128; 00200 if(!s_defaultStyle) loadDefaultStyle(settings); 00201 00202 defaultStyle = s_defaultStyle; 00203 defaultPrintStyle = s_defaultPrintStyle; 00204 defaultQuirksStyle = s_defaultQuirksStyle; 00205 } 00206 00207 CSSStyleSelector::~CSSStyleSelector() 00208 { 00209 clearLists(); 00210 delete authorStyle; 00211 delete userStyle; 00212 delete userSheet; 00213 free(propsToApply); 00214 free(pseudoProps); 00215 } 00216 00217 void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet ) 00218 { 00219 KHTMLView *view = sheet->doc()->view(); 00220 m_medium = view ? view->mediaType() : "screen"; 00221 authorStyle->append( sheet, m_medium ); 00222 } 00223 00224 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s) 00225 { 00226 if(s_defaultStyle) return; 00227 00228 { 00229 QFile f(locate( "data", "khtml/css/html4.css" ) ); 00230 f.open(IO_ReadOnly); 00231 00232 QCString file( f.size()+1 ); 00233 int readbytes = f.readBlock( file.data(), f.size() ); 00234 f.close(); 00235 if ( readbytes >= 0 ) 00236 file[readbytes] = '\0'; 00237 00238 QString style = QString::fromLatin1( file.data() ); 00239 if(s) 00240 style += s->settingsToCSS(); 00241 DOMString str(style); 00242 00243 s_defaultSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0); 00244 s_defaultSheet->parseString( str ); 00245 00246 // Collect only strict-mode rules. 00247 s_defaultStyle = new CSSStyleSelectorList(); 00248 s_defaultStyle->append( s_defaultSheet, "screen" ); 00249 00250 s_defaultPrintStyle = new CSSStyleSelectorList(); 00251 s_defaultPrintStyle->append( s_defaultSheet, "print" ); 00252 } 00253 { 00254 QFile f(locate( "data", "khtml/css/quirks.css" ) ); 00255 f.open(IO_ReadOnly); 00256 00257 QCString file( f.size()+1 ); 00258 int readbytes = f.readBlock( file.data(), f.size() ); 00259 f.close(); 00260 if ( readbytes >= 0 ) 00261 file[readbytes] = '\0'; 00262 00263 QString style = QString::fromLatin1( file.data() ); 00264 DOMString str(style); 00265 00266 s_quirksSheet = new DOM::CSSStyleSheetImpl((DOM::CSSStyleSheetImpl * ) 0); 00267 s_quirksSheet->parseString( str ); 00268 00269 // Collect only quirks-mode rules. 00270 s_defaultQuirksStyle = new CSSStyleSelectorList(); 00271 s_defaultQuirksStyle->append( s_quirksSheet, "screen" ); 00272 } 00273 00274 //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl; 00275 } 00276 00277 void CSSStyleSelector::clear() 00278 { 00279 delete s_defaultStyle; 00280 delete s_defaultQuirksStyle; 00281 delete s_defaultPrintStyle; 00282 delete s_defaultSheet; 00283 delete styleNotYetAvailable; 00284 s_defaultStyle = 0; 00285 s_defaultQuirksStyle = 0; 00286 s_defaultPrintStyle = 0; 00287 s_defaultSheet = 0; 00288 styleNotYetAvailable = 0; 00289 } 00290 00291 void CSSStyleSelector::reparseConfiguration() 00292 { 00293 // nice leak, but best we can do right now. hopefully its only rare. 00294 s_defaultStyle = 0; 00295 s_defaultQuirksStyle = 0; 00296 s_defaultPrintStyle = 0; 00297 s_defaultSheet = 0; 00298 } 00299 00300 #define MAXFONTSIZES 15 00301 00302 void CSSStyleSelector::computeFontSizes(QPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor) 00303 { 00304 computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fontSizes, false); 00305 computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fixedFontSizes, true); 00306 } 00307 00308 void CSSStyleSelector::computeFontSizesFor(QPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor, QValueList<int>& fontSizes, bool isFixed) 00309 { 00310 #ifdef APPLE_CHANGES 00311 // We don't want to scale the settings by the dpi. 00312 const float toPix = 1; 00313 #else 00314 Q_UNUSED( isFixed ); 00315 00316 // ### get rid of float / double 00317 float toPix = paintDeviceMetrics->logicalDpiY()/72.; 00318 if (toPix < 96./72.) toPix = 96./72.; 00319 #endif // ######### fix isFixed code again. 00320 00321 fontSizes.clear(); 00322 const float factor = 1.2; 00323 float scale = 1.0 / (factor*factor*factor); 00324 float mediumFontSize; 00325 float minFontSize; 00326 if (!khtml::printpainter) { 00327 scale *= zoomFactor / 100.0; 00328 #ifdef APPLE_CHANGES 00329 if (isFixed) 00330 mediumFontSize = settings->mediumFixedFontSize() * toPix; 00331 else 00332 #endif 00333 mediumFontSize = settings->mediumFontSize() * toPix; 00334 minFontSize = settings->minFontSize() * toPix; 00335 } 00336 else { 00337 // ## depending on something / configurable ? 00338 mediumFontSize = 12; 00339 minFontSize = 6; 00340 } 00341 00342 for ( int i = 0; i < MAXFONTSIZES; i++ ) { 00343 fontSizes << int(KMAX( mediumFontSize * scale + 0.5f, minFontSize)); 00344 scale *= factor; 00345 } 00346 } 00347 00348 #undef MAXFONTSIZES 00349 00350 static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e ) 00351 { 00352 while( b < e ) { 00353 bool swapped = false; 00354 CSSOrderedProperty **y = e+1; 00355 CSSOrderedProperty **x = e; 00356 CSSOrderedProperty **swappedPos = 0; 00357 do { 00358 if ( !((**(--x)) < (**(--y))) ) { 00359 swapped = true; 00360 swappedPos = x; 00361 CSSOrderedProperty *tmp = *y; 00362 *y = *x; 00363 *x = tmp; 00364 } 00365 } while( x != b ); 00366 if ( !swapped ) break; 00367 b = swappedPos + 1; 00368 } 00369 } 00370 00371 RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e) 00372 { 00373 if (!e->getDocument()->haveStylesheetsLoaded() || !e->getDocument()->view()) { 00374 if (!styleNotYetAvailable) { 00375 styleNotYetAvailable = new RenderStyle(); 00376 styleNotYetAvailable->setDisplay(NONE); 00377 styleNotYetAvailable->ref(); 00378 } 00379 return styleNotYetAvailable; 00380 } 00381 00382 // set some variables we will need 00383 pseudoState = PseudoUnknown; 00384 00385 element = e; 00386 parentNode = e->parentNode(); 00387 parentStyle = ( parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0; 00388 view = element->getDocument()->view(); 00389 part = view->part(); 00390 settings = part->settings(); 00391 paintDeviceMetrics = element->getDocument()->paintDeviceMetrics(); 00392 00393 style = new RenderStyle(); 00394 if( parentStyle ) 00395 style->inheritFrom( parentStyle ); 00396 else 00397 parentStyle = style; 00398 00399 unsigned int numPropsToApply = 0; 00400 unsigned int numPseudoProps = 0; 00401 00402 // try to sort out most style rules as early as possible. 00403 int cssTagId = (e->id() & NodeImpl_IdLocalMask); 00404 int smatch = 0; 00405 int schecked = 0; 00406 00407 for ( unsigned int i = 0; i < selectors_size; i++ ) { 00408 int tag = selectors[i]->tag & NodeImpl_IdLocalMask; 00409 if ( cssTagId == tag || tag == 0xffff ) { 00410 ++schecked; 00411 00412 checkSelector( i, e ); 00413 00414 if ( selectorCache[i].state == Applies ) { 00415 ++smatch; 00416 00417 // qDebug("adding property" ); 00418 for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 ) 00419 for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j ) { 00420 if (numPropsToApply >= propsToApplySize ) { 00421 propsToApplySize *= 2; 00422 propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) ); 00423 } 00424 propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j]; 00425 } 00426 } else if ( selectorCache[i].state == AppliesPseudo ) { 00427 for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 ) 00428 for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) { 00429 if (numPseudoProps >= pseudoPropsSize ) { 00430 pseudoPropsSize *= 2; 00431 pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) ); 00432 } 00433 pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j]; 00434 properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId; 00435 } 00436 } 00437 } 00438 else 00439 selectorCache[i].state = Invalid; 00440 00441 } 00442 00443 // inline style declarations, after all others. non css hints 00444 // count as author rules, and come before all other style sheets, see hack in append() 00445 numPropsToApply = addInlineDeclarations( e, e->m_styleDecls, numPropsToApply ); 00446 00447 // qDebug( "styleForElement( %s )", e->tagName().string().latin1() ); 00448 // qDebug( "%d selectors, %d checked, %d match, %d properties ( of %d )", 00449 // selectors_size, schecked, smatch, numPropsToApply, properties_size ); 00450 00451 bubbleSort( propsToApply, propsToApply+numPropsToApply-1 ); 00452 bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 ); 00453 00454 // we can't apply style rules without a view() and a part. This 00455 // tends to happen on delayed destruction of widget Renderobjects 00456 if ( part ) { 00457 fontDirty = false; 00458 00459 if (numPropsToApply ) { 00460 CSSStyleSelector::style = style; 00461 for (unsigned int i = 0; i < numPropsToApply; ++i) { 00462 if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) { 00463 // we are past the font properties, time to update to the 00464 // correct font 00465 #ifdef APPLE_CHANGES 00466 checkForGenericFamilyChange(style, parentStyle); 00467 #endif 00468 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics ); 00469 fontDirty = false; 00470 } 00471 DOM::CSSProperty *prop = propsToApply[i]->prop; 00472 // if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) kdDebug(6080) << "El: "<<e->nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent() << endl; 00473 // if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) kdDebug(6080) << "El: "<<e->nodeName().string() << endl; 00474 applyRule( prop->m_id, prop->value() ); 00475 } 00476 if ( fontDirty ) { 00477 #ifdef APPLE_CHANGES 00478 checkForGenericFamilyChange(style, parentStyle); 00479 #endif 00480 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics ); 00481 } 00482 } 00483 00484 // Clean up our style object's display and text decorations (among other fixups). 00485 adjustRenderStyle(style, e); 00486 00487 if ( numPseudoProps ) { 00488 fontDirty = false; 00489 //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() ); 00490 for (unsigned int i = 0; i < numPseudoProps; ++i) { 00491 if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) { 00492 // we are past the font properties, time to update to the 00493 // correct font 00494 //We have to do this for all pseudo styles 00495 RenderStyle *pseudoStyle = style->pseudoStyle; 00496 while ( pseudoStyle ) { 00497 pseudoStyle->htmlFont().update( paintDeviceMetrics ); 00498 pseudoStyle = pseudoStyle->pseudoStyle; 00499 } 00500 fontDirty = false; 00501 } 00502 00503 RenderStyle *pseudoStyle; 00504 pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId); 00505 if (!pseudoStyle) 00506 { 00507 pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId); 00508 if (pseudoStyle) 00509 pseudoStyle->inheritFrom( style ); 00510 } 00511 00512 RenderStyle* oldStyle = style; 00513 RenderStyle* oldParentStyle = parentStyle; 00514 parentStyle = style; 00515 style = pseudoStyle; 00516 if ( pseudoStyle ) { 00517 DOM::CSSProperty *prop = pseudoProps[i]->prop; 00518 applyRule( prop->m_id, prop->value() ); 00519 } 00520 style = oldStyle; 00521 parentStyle = oldParentStyle; 00522 } 00523 00524 if ( fontDirty ) { 00525 RenderStyle *pseudoStyle = style->pseudoStyle; 00526 while ( pseudoStyle ) { 00527 pseudoStyle->htmlFont().update( paintDeviceMetrics ); 00528 pseudoStyle = pseudoStyle->pseudoStyle; 00529 } 00530 } 00531 } 00532 } 00533 00534 // Now adjust all our pseudo-styles. 00535 RenderStyle *pseudoStyle = style->pseudoStyle; 00536 while (pseudoStyle) { 00537 adjustRenderStyle(pseudoStyle, 0); 00538 pseudoStyle = pseudoStyle->pseudoStyle; 00539 } 00540 00541 // Now return the style. 00542 return style; 00543 } 00544 00545 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e) 00546 { 00547 #ifdef APPLE_CHANGES 00548 // Cache our original display. 00549 style->setOriginalDisplay(style->display()); 00550 #endif 00551 00552 if (style->display() != NONE) { 00553 // If we have a <td> that specifies a float property, in quirks mode we just drop the float 00554 // property. 00555 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force 00556 // these tags to retain their display types. 00557 if (!strictParsing && e) { 00558 if (e->id() == ID_TD) { 00559 style->setDisplay(TABLE_CELL); 00560 style->setFloating(FNONE); 00561 } 00562 // else if (e->id() == ID_TABLE) 00563 // style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); 00564 } 00565 00566 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to 00567 // position or float an inline, compact, or run-in. Cache the original display, since it 00568 // may be needed for positioned elements that have to compute their static normal flow 00569 // positions. We also force inline-level roots to be block-level. 00570 if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ && 00571 (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE || 00572 (e && e->getDocument()->documentElement() == e))) { 00573 if (style->display() == INLINE_TABLE) 00574 style->setDisplay(TABLE); 00575 // else if (style->display() == INLINE_BOX) 00576 // style->setDisplay(BOX); 00577 else if (style->display() == LIST_ITEM) { 00578 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, 00579 // but only in quirks mode. 00580 if (!strictParsing && style->floating() != FNONE) 00581 style->setDisplay(BLOCK); 00582 } 00583 else 00584 style->setDisplay(BLOCK); 00585 } 00586 00587 // After performing the display mutation, check table rows. We do not honor position:relative on 00588 // table rows. This has been established in CSS2.1 (and caused a crash in containingBlock() on 00589 // some sites). 00590 if (style->display() == TABLE_ROW && style->position() == RELATIVE) 00591 style->setPosition(STATIC); 00592 } 00593 00594 // Frames and framesets never honor position:relative or position:absolute. This is necessary to 00595 // fix a crash where a site tries to position these objects. 00596 if ( e ) { 00597 // ignore display: none for <frame> 00598 if ( e->id() == ID_FRAME ) { 00599 style->setPosition( STATIC ); 00600 style->setDisplay( BLOCK ); 00601 } 00602 else if ( e->id() == ID_FRAMESET ) { 00603 style->setPosition( STATIC ); 00604 } 00605 } 00606 00607 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through 00608 // tables, inline blocks, inline tables, or run-ins. 00609 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN 00610 || style->display() == INLINE_BLOCK /*|| style->display() == INLINE_BOX*/) 00611 style->setTextDecorationsInEffect(style->textDecoration()); 00612 else 00613 style->addToTextDecorationsInEffect(style->textDecoration()); 00614 } 00615 00616 unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e, 00617 DOM::CSSStyleDeclarationImpl *decl, 00618 unsigned int numProps) 00619 { 00620 CSSStyleDeclarationImpl* addDecls = 0; 00621 #ifdef APPLE_CHANGES 00622 if (e->id() == ID_TD || e->id() == ID_TH) // For now only TableCellElement implements the 00623 addDecls = e->getAdditionalStyleDecls(); // virtual function for shared cell rules. 00624 #else 00625 Q_UNUSED( e ); 00626 #endif 00627 00628 if (!decl && !addDecls) 00629 return numProps; 00630 00631 QPtrList<CSSProperty>* values = decl ? decl->values() : 0; 00632 QPtrList<CSSProperty>* addValues = addDecls ? addDecls->values() : 0; 00633 if (!values && !addValues) 00634 return numProps; 00635 00636 int firstLen = values ? values->count() : 0; 00637 int secondLen = addValues ? addValues->count() : 0; 00638 int totalLen = firstLen + secondLen; 00639 00640 if (inlineProps.size() < (uint)totalLen) 00641 inlineProps.resize(totalLen + 1); 00642 00643 if (numProps + totalLen >= propsToApplySize ) { 00644 propsToApplySize += propsToApplySize; 00645 propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) ); 00646 } 00647 00648 CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data(); 00649 for(int i = 0; i < totalLen; i++) 00650 { 00651 if (i == firstLen) 00652 values = addValues; 00653 00654 CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i); 00655 Source source = Inline; 00656 00657 if( prop->m_bImportant ) source = InlineImportant; 00658 if( prop->nonCSSHint ) source = NonCSSHint; 00659 00660 bool first; 00661 // give special priority to font-xxx, color properties 00662 switch(prop->m_id) 00663 { 00664 case CSS_PROP_FONT_STYLE: 00665 case CSS_PROP_FONT_SIZE: 00666 case CSS_PROP_FONT_WEIGHT: 00667 case CSS_PROP_FONT_FAMILY: 00668 case CSS_PROP_FONT: 00669 case CSS_PROP_COLOR: 00670 case CSS_PROP_BACKGROUND_IMAGE: 00671 case CSS_PROP_DISPLAY: 00672 // these have to be applied first, because other properties use the computed 00673 // values of these properties. 00674 first = true; 00675 break; 00676 default: 00677 first = false; 00678 break; 00679 } 00680 00681 array->prop = prop; 00682 array->pseudoId = RenderStyle::NOPSEUDO; 00683 array->selector = 0; 00684 array->position = i; 00685 array->priority = (!first << 30) | (source << 24); 00686 propsToApply[numProps++] = array++; 00687 } 00688 return numProps; 00689 } 00690 00691 static bool subject; 00692 00693 // modified version of the one in kurl.cpp 00694 static void cleanpath(QString &path) 00695 { 00696 int pos; 00697 while ( (pos = path.find( "/../" )) != -1 ) { 00698 int prev = 0; 00699 if ( pos > 0 ) 00700 prev = path.findRev( "/", pos -1 ); 00701 // don't remove the host, i.e. http://foo.org/../foo.html 00702 if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2)) 00703 path.remove( pos, 3); 00704 else 00705 // matching directory found ? 00706 path.remove( prev, pos- prev + 3 ); 00707 } 00708 pos = 0; 00709 00710 // Don't remove "//" from an anchor identifier. -rjw 00711 // Set refPos to -2 to mean "I haven't looked for the anchor yet". 00712 // We don't want to waste a function call on the search for the anchor 00713 // in the vast majority of cases where there is no "//" in the path. 00714 int refPos = -2; 00715 while ( (pos = path.find( "//", pos )) != -1) { 00716 if (refPos == -2) 00717 refPos = path.find("#", 0); 00718 if (refPos > 0 && pos >= refPos) 00719 break; 00720 00721 if ( pos == 0 || path[pos-1] != ':' ) 00722 path.remove( pos, 1 ); 00723 else 00724 pos += 2; 00725 } 00726 while ( (pos = path.find( "/./" )) != -1) 00727 path.remove( pos, 2 ); 00728 //kdDebug() << "checkPseudoState " << path << endl; 00729 } 00730 00731 static void checkPseudoState( const CSSStyleSelector::Encodedurl& encodedurl, DOM::ElementImpl *e ) 00732 { 00733 if( e->id() != ID_A ) { 00734 pseudoState = PseudoNone; 00735 return; 00736 } 00737 DOMString attr = e->getAttribute(ATTR_HREF); 00738 if( attr.isNull() ) { 00739 pseudoState = PseudoNone; 00740 return; 00741 } 00742 QConstString cu(attr.unicode(), attr.length()); 00743 QString u = cu.string(); 00744 if ( !u.contains("://") ) { 00745 if ( u[0] == '/' ) 00746 u = encodedurl.host + u; 00747 else if ( u[0] == '#' ) 00748 u = encodedurl.file + u; 00749 else 00750 u = encodedurl.path + u; 00751 cleanpath( u ); 00752 } 00753 //completeURL( attr.string() ); 00754 pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink; 00755 } 00756 00757 void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl *e) 00758 { 00759 dynamicPseudo = RenderStyle::NOPSEUDO; 00760 00761 NodeImpl *n = e; 00762 00763 selectorCache[ selIndex ].state = Invalid; 00764 CSSSelector *sel = selectors[ selIndex ]; 00765 00766 // we have the subject part of the selector 00767 subject = true; 00768 00769 // We track whether or not the rule contains only :hover and :active in a simple selector. If 00770 // so, we can't allow that to apply to every element on the page. We assume the author intended 00771 // to apply the rules only to links. 00772 bool onlyHoverActive = (((sel->tag & NodeImpl_IdLocalMask) == NodeImpl_IdLocalMask) && 00773 (sel->match == CSSSelector::Pseudo && 00774 (sel->pseudoType() == CSSSelector::PseudoHover || 00775 sel->pseudoType() == CSSSelector::PseudoActive))); 00776 bool affectedByHover = style->affectedByHoverRules(); 00777 bool affectedByActive = style->affectedByActiveRules(); 00778 00779 // first selector has to match 00780 if(!checkOneSelector(sel, e)) return; 00781 00782 // check the subselectors 00783 CSSSelector::Relation relation = sel->relation; 00784 while((sel = sel->tagHistory)) 00785 { 00786 if(!n->isElementNode()) return; 00787 switch(relation) 00788 { 00789 case CSSSelector::Descendant: 00790 { 00791 bool found = false; 00792 while(!found) 00793 { 00794 subject = false; 00795 n = n->parentNode(); 00796 if(!n || !n->isElementNode()) return; 00797 ElementImpl *elem = static_cast<ElementImpl *>(n); 00798 if(checkOneSelector(sel, elem)) found = true; 00799 } 00800 break; 00801 } 00802 case CSSSelector::Child: 00803 { 00804 subject = false; 00805 n = n->parentNode(); 00806 if (!strictParsing) 00807 while (n && n->implicitNode()) n = n->parentNode(); 00808 if(!n || !n->isElementNode()) return; 00809 ElementImpl *elem = static_cast<ElementImpl *>(n); 00810 if(!checkOneSelector(sel, elem)) return; 00811 break; 00812 } 00813 case CSSSelector::Sibling: 00814 { 00815 subject = false; 00816 n = n->previousSibling(); 00817 while( n && !n->isElementNode() ) 00818 n = n->previousSibling(); 00819 if( !n ) return; 00820 ElementImpl *elem = static_cast<ElementImpl *>(n); 00821 if(!checkOneSelector(sel, elem)) return; 00822 break; 00823 } 00824 case CSSSelector::SubSelector: 00825 { 00826 if (onlyHoverActive) 00827 onlyHoverActive = (sel->match == CSSSelector::Pseudo && 00828 (sel->pseudoType() == CSSSelector::PseudoHover || 00829 sel->pseudoType() == CSSSelector::PseudoActive)); 00830 00831 //kdDebug() << "CSSOrderedRule::checkSelector" << endl; 00832 ElementImpl *elem = static_cast<ElementImpl *>(n); 00833 // a selector is invalid if something follows :first-xxx 00834 if ( dynamicPseudo != RenderStyle::NOPSEUDO ) { 00835 return; 00836 } 00837 if(!checkOneSelector(sel, elem)) return; 00838 //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl; 00839 break; 00840 } 00841 } 00842 relation = sel->relation; 00843 } 00844 00845 // disallow *:hover, *:active, and *:hover:active except for links 00846 if (onlyHoverActive && subject) { 00847 if (pseudoState == PseudoUnknown) 00848 checkPseudoState( encodedurl, e ); 00849 00850 if (pseudoState == PseudoNone) { 00851 if (!affectedByHover && style->affectedByHoverRules()) 00852 style->setAffectedByHoverRules(false); 00853 if (!affectedByActive && style->affectedByActiveRules()) 00854 style->setAffectedByActiveRules(false); 00855 return; 00856 } 00857 } 00858 00859 if ( dynamicPseudo != RenderStyle::NOPSEUDO ) { 00860 selectorCache[selIndex].state = AppliesPseudo; 00861 selectors[ selIndex ]->pseudoId = dynamicPseudo; 00862 } else 00863 selectorCache[ selIndex ].state = Applies; 00864 //qDebug( "selector %d applies", selIndex ); 00865 //selectors[ selIndex ]->print(); 00866 return; 00867 } 00868 00869 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e) 00870 { 00871 if(!e) 00872 return false; 00873 00874 unsigned int element_id = e->id(); 00875 if ( (sel->tag & NodeImpl_IdNSMask) == NodeImpl_IdNSMask ) { 00876 // all namespaces would match 00877 unsigned int sel_id = sel->tag & NodeImpl_IdLocalMask; 00878 if ( (element_id & NodeImpl_IdLocalMask) != sel_id && 00879 sel_id != NodeImpl_IdLocalMask ) 00880 return false; 00881 } else { 00882 // specific namespace selected 00883 if( (element_id & NodeImpl_IdNSMask) != (sel->tag & NodeImpl_IdNSMask) ) 00884 return false; 00885 if ( element_id != sel->tag && 00886 (sel->tag & NodeImpl_IdLocalMask) != NodeImpl_IdLocalMask ) 00887 return false; 00888 } 00889 00890 if(sel->attr) 00891 { 00892 unsigned int attr_id = sel->attr; 00893 if ( (attr_id & NodeImpl_IdNSMask ) == NodeImpl_IdNSMask ) { 00894 // ### fixme: this should allow attributes from all 00895 // ### namespaces. I'm not 100% sure what the semantics 00896 // ### should be in this case. Do they all have to match? 00897 // ### Or should only one of them match. Anyways it might 00898 // ### be we have to iterate over all namespaces and check 00899 // ### all of them. For now we just set the namespace to 00900 // ### 0, so they at least match attributes in the default 00901 // ### namespace. 00902 attr_id &= NodeImpl_IdLocalMask; 00903 } 00904 DOMString value = e->getAttribute(attr_id); 00905 if(value.isNull()) return false; // attribute is not set 00906 00907 switch(sel->match) 00908 { 00909 case CSSSelector::Exact: 00910 case CSSSelector::Id: 00911 if( (strictParsing && strcmp(sel->value, value) ) || 00912 (!strictParsing && strcasecmp(sel->value, value))) 00913 return false; 00914 break; 00915 case CSSSelector::Set: 00916 break; 00917 case CSSSelector::List: 00918 { 00919 int spacePos = value.find(' ', 0); 00920 if (spacePos == -1) { 00921 // There is no list, just a single item. We can avoid 00922 // allocing QStrings and just treat this as an exact 00923 // match check. 00924 if( (strictParsing && strcmp(sel->value, value) ) || 00925 (!strictParsing && strcasecmp(sel->value, value))) 00926 return false; 00927 break; 00928 } 00929 00930 // The selector's value can't contain a space, or it's totally bogus. 00931 spacePos = sel->value.find(' '); 00932 if (spacePos != -1) 00933 return false; 00934 00935 QString str = value.string(); 00936 QString selStr = sel->value.string(); 00937 const int selStrlen = selStr.length(); 00938 int pos = 0; 00939 for ( ;; ) { 00940 pos = str.find(selStr, pos, strictParsing); 00941 if ( pos == -1 ) return false; 00942 if ( pos == 0 || str[pos-1] == ' ' ) { 00943 uint endpos = pos + selStrlen; 00944 if ( endpos >= str.length() || str[endpos] == ' ' ) 00945 break; // We have a match. 00946 } 00947 ++pos; 00948 } 00949 break; 00950 } 00951 case CSSSelector::Contain: 00952 { 00953 //kdDebug( 6080 ) << "checking for contains match" << endl; 00954 QString str = value.string(); 00955 QString selStr = sel->value.string(); 00956 int pos = str.find(selStr, 0, strictParsing); 00957 if(pos == -1) return false; 00958 break; 00959 } 00960 case CSSSelector::Begin: 00961 { 00962 //kdDebug( 6080 ) << "checking for beginswith match" << endl; 00963 QString str = value.string(); 00964 QString selStr = sel->value.string(); 00965 int pos = str.find(selStr, 0, strictParsing); 00966 if(pos != 0) return false; 00967 break; 00968 } 00969 case CSSSelector::End: 00970 { 00971 //kdDebug( 6080 ) << "checking for endswith match" << endl; 00972 QString str = value.string(); 00973 QString selStr = sel->value.string(); 00974 if (strictParsing && !str.endsWith(selStr)) return false; 00975 if (!strictParsing) { 00976 int pos = str.length() - selStr.length(); 00977 if (pos < 0 || pos != str.find(selStr, pos, false) ) 00978 return false; 00979 } 00980 break; 00981 } 00982 case CSSSelector::Hyphen: 00983 { 00984 //kdDebug( 6080 ) << "checking for hyphen match" << endl; 00985 QString str = value.string(); 00986 QString selStr = sel->value.string(); 00987 if(str.length() < selStr.length()) return false; 00988 // Check if str begins with selStr: 00989 if(str.find(selStr, 0, strictParsing) != 0) return false; 00990 // It does. Check for exact match or following '-': 00991 if(str.length() != selStr.length() 00992 && str[selStr.length()] != '-') return false; 00993 break; 00994 } 00995 case CSSSelector::Pseudo: 00996 case CSSSelector::None: 00997 break; 00998 } 00999 } 01000 if(sel->match == CSSSelector::Pseudo) 01001 { 01002 // Pseudo elements. We need to check first child here. No dynamic pseudo 01003 // elements for the moment 01004 // kdDebug() << "CSSOrderedRule::pseudo " << value << endl; 01005 switch (sel->pseudoType()) { 01006 case CSSSelector::PseudoEmpty: 01007 if (!e->firstChild()) 01008 return true; 01009 break; 01010 case CSSSelector::PseudoFirstChild: { 01011 // first-child matches the first child that is an element! 01012 if (e->parentNode() && e->parentNode()->isElementNode()) { 01013 DOM::NodeImpl* n = e->previousSibling(); 01014 while ( n && !n->isElementNode() ) 01015 n = n->previousSibling(); 01016 if ( !n ) 01017 return true; 01018 } 01019 break; 01020 } 01021 case CSSSelector::PseudoLastChild: { 01022 // last-child matches the last child that is an element! 01023 if (e->parentNode() && e->parentNode()->isElementNode()) { 01024 DOM::NodeImpl* n = e->nextSibling(); 01025 while ( n && !n->isElementNode() ) 01026 n = n->nextSibling(); 01027 if ( !n ) 01028 return true; 01029 } 01030 break; 01031 } 01032 case CSSSelector::PseudoOnlyChild: { 01033 // If both first-child and last-child apply, then only-child applies. 01034 if (e->parentNode() && e->parentNode()->isElementNode()) { 01035 DOM::NodeImpl* n = e->previousSibling(); 01036 while ( n && !n->isElementNode() ) 01037 n = n->previousSibling(); 01038 if ( !n ) { 01039 n = e->nextSibling(); 01040 while ( n && !n->isElementNode() ) 01041 n = n->nextSibling(); 01042 if ( !n ) 01043 return true; 01044 } 01045 } 01046 break; 01047 } 01048 case CSSSelector::PseudoFirstLine: 01049 if ( subject ) { 01050 dynamicPseudo=RenderStyle::FIRST_LINE; 01051 return true; 01052 } 01053 break; 01054 case CSSSelector::PseudoFirstLetter: 01055 if ( subject ) { 01056 dynamicPseudo=RenderStyle::FIRST_LETTER; 01057 return true; 01058 } 01059 break; 01060 case CSSSelector::PseudoTarget: 01061 #ifdef APPLE_CHANGES 01062 if (!e->getDocument()->getCSSTarget() && // :target matches the root when no CSS target exists 01063 e == e->getDocument()->documentElement()) 01064 return true; 01065 if (e == e->getDocument()->getCSSTarget()) 01066 return true; 01067 #endif 01068 break; 01069 case CSSSelector::PseudoLink: 01070 if ( pseudoState == PseudoUnknown ) 01071 checkPseudoState( encodedurl, e ); 01072 if ( pseudoState == PseudoLink ) 01073 return true; 01074 break; 01075 case CSSSelector::PseudoVisited: 01076 if ( pseudoState == PseudoUnknown ) 01077 checkPseudoState( encodedurl, e ); 01078 if ( pseudoState == PseudoVisited ) 01079 return true; 01080 break; 01081 case CSSSelector::PseudoHover: { 01082 // If we're in quirks mode, then hover should never match anchors with no 01083 // href. This is important for sites like wsj.com. 01084 if (strictParsing || e->id() != ID_A || e->hasAnchor()) { 01085 if (element == e) 01086 style->setAffectedByHoverRules(true); 01087 if (e->renderer()) { 01088 if (element != e) 01089 e->renderer()->style()->setAffectedByHoverRules(true); 01090 if (e->renderer()->mouseInside()) 01091 return true; 01092 } 01093 } 01094 break; 01095 } 01096 case CSSSelector::PseudoFocus: 01097 if (e && e->focused()) { 01098 return true; 01099 } 01100 break; 01101 case CSSSelector::PseudoActive: 01102 // If we're in quirks mode, then :active should never match anchors with no 01103 // href. 01104 if (strictParsing || e->id() != ID_A || e->hasAnchor()) { 01105 if (element == e) 01106 style->setAffectedByActiveRules(true); 01107 else if (e->renderer()) 01108 e->renderer()->style()->setAffectedByActiveRules(true); 01109 if (e->active()) 01110 return true; 01111 } 01112 break; 01113 case CSSSelector::PseudoRoot: 01114 if (e == e->getDocument()->documentElement()) 01115 return true; 01116 break; 01117 case CSSSelector::PseudoNot: { 01118 // check the simple selector 01119 for (CSSSelector* subSel = sel->simpleSelector; subSel; 01120 subSel = subSel->tagHistory) { 01121 // :not cannot nest. I don't really know why this is a restriction in CSS3, 01122 // but it is, so let's honor it. 01123 if (subSel->simpleSelector) 01124 break; 01125 if (!checkOneSelector(subSel, e)) 01126 return true; 01127 } 01128 break; 01129 } 01130 case CSSSelector::PseudoSelection: 01131 dynamicPseudo = RenderStyle::SELECTION; 01132 return true; 01133 case CSSSelector::PseudoBefore: 01134 dynamicPseudo = RenderStyle::BEFORE; 01135 return true; 01136 case CSSSelector::PseudoAfter: 01137 dynamicPseudo = RenderStyle::AFTER; 01138 return true; 01139 01140 case CSSSelector::PseudoNotParsed: 01141 assert(false); 01142 break; 01143 case CSSSelector::PseudoLang: 01144 /* not supported for now */ 01145 case CSSSelector::PseudoOther: 01146 break; 01147 } 01148 return false; 01149 } 01150 // ### add the rest of the checks... 01151 return true; 01152 } 01153 01154 void CSSStyleSelector::clearLists() 01155 { 01156 delete [] selectors; 01157 if ( selectorCache ) { 01158 for ( unsigned int i = 0; i < selectors_size; i++ ) 01159 delete [] selectorCache[i].props; 01160 01161 delete [] selectorCache; 01162 } 01163 if ( properties ) { 01164 CSSOrderedProperty **prop = properties; 01165 while ( *prop ) { 01166 delete (*prop); 01167 prop++; 01168 } 01169 delete [] properties; 01170 } 01171 selectors = 0; 01172 properties = 0; 01173 selectorCache = 0; 01174 } 01175 01176 01177 void CSSStyleSelector::buildLists() 01178 { 01179 clearLists(); 01180 // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup. 01181 01182 QPtrList<CSSSelector> selectorList; 01183 CSSOrderedPropertyList propertyList; 01184 01185 if(m_medium == "print" && defaultPrintStyle) 01186 defaultPrintStyle->collect( &selectorList, &propertyList, Default, 01187 Default ); 01188 else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList, 01189 Default, Default ); 01190 01191 if (!strictParsing && defaultQuirksStyle) 01192 defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default ); 01193 01194 if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant ); 01195 if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant ); 01196 01197 selectors_size = selectorList.count(); 01198 selectors = new CSSSelector *[selectors_size]; 01199 CSSSelector *s = selectorList.first(); 01200 CSSSelector **sel = selectors; 01201 while ( s ) { 01202 *sel = s; 01203 s = selectorList.next(); 01204 ++sel; 01205 } 01206 01207 selectorCache = new SelectorCache[selectors_size]; 01208 for ( unsigned int i = 0; i < selectors_size; i++ ) { 01209 selectorCache[i].state = Unknown; 01210 selectorCache[i].props_size = 0; 01211 selectorCache[i].props = 0; 01212 } 01213 01214 // presort properties. Should make the sort() calls in styleForElement faster. 01215 propertyList.sort(); 01216 properties_size = propertyList.count() + 1; 01217 properties = new CSSOrderedProperty *[ properties_size ]; 01218 CSSOrderedProperty *p = propertyList.first(); 01219 CSSOrderedProperty **prop = properties; 01220 while ( p ) { 01221 *prop = p; 01222 p = propertyList.next(); 01223 ++prop; 01224 } 01225 *prop = 0; 01226 01227 unsigned int* offsets = new unsigned int[selectors_size]; 01228 if(properties[0]) 01229 offsets[properties[0]->selector] = 0; 01230 for(unsigned int p = 1; p < properties_size; ++p) { 01231 01232 if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) { 01233 unsigned int sel = properties[p - 1]->selector; 01234 int* newprops = new int[selectorCache[sel].props_size+2]; 01235 for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ ) 01236 newprops[i] = selectorCache[sel].props[i]; 01237 01238 newprops[selectorCache[sel].props_size] = offsets[sel]; 01239 newprops[selectorCache[sel].props_size+1] = p - offsets[sel]; 01240 delete [] selectorCache[sel].props; 01241 selectorCache[sel].props = newprops; 01242 selectorCache[sel].props_size += 2; 01243 01244 if(properties[p]) { 01245 sel = properties[p]->selector; 01246 offsets[sel] = p; 01247 } 01248 } 01249 } 01250 delete [] offsets; 01251 01252 01253 #if 0 01254 // and now the same for the selector map 01255 for ( unsigned int sel = 0; sel < selectors_size; ++sel ) { 01256 kdDebug( 6080 ) << "trying for sel: " << sel << endl; 01257 int len = 0; 01258 int offset = 0; 01259 bool matches = false; 01260 for ( unsigned int i = 0; i < selectors_size; i++ ) { 01261 int tag = selectors[i]->tag; 01262 if ( sel != tag && tag != -1 ) 01263 selectorCache[i].state = Invalid; 01264 else 01265 selectorCache[i].state = Unknown; 01266 01267 if ( matches != ( selectorCache[i].state == Unknown ) ) { 01268 if ( matches ) { 01269 kdDebug( 6080 ) << "new: offs: " << offset << " len: " << len << endl; 01270 matches = false; 01271 } 01272 else { 01273 matches = true; 01274 // offset = p-selectors; 01275 len = 0; 01276 } 01277 } 01278 ++len; 01279 } 01280 } 01281 #endif 01282 } 01283 01284 01285 // ---------------------------------------------------------------------- 01286 01287 01288 CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index) 01289 { 01290 rule = r; 01291 if(rule) r->ref(); 01292 index = _index; 01293 selector = s; 01294 } 01295 01296 CSSOrderedRule::~CSSOrderedRule() 01297 { 01298 if(rule) rule->deref(); 01299 } 01300 01301 // ----------------------------------------------------------------- 01302 01303 CSSStyleSelectorList::CSSStyleSelectorList() 01304 : QPtrList<CSSOrderedRule>() 01305 { 01306 setAutoDelete(true); 01307 } 01308 CSSStyleSelectorList::~CSSStyleSelectorList() 01309 { 01310 } 01311 01312 void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet, 01313 const DOMString &medium ) 01314 { 01315 if(!sheet || !sheet->isCSSStyleSheet()) return; 01316 01317 // No media implies "all", but if a medialist exists it must 01318 // contain our current medium 01319 if( sheet->media() && !sheet->media()->contains( medium ) ) 01320 return; // style sheet not applicable for this medium 01321 01322 int len = sheet->length(); 01323 01324 for(int i = 0; i< len; i++) 01325 { 01326 StyleBaseImpl *item = sheet->item(i); 01327 if(item->isStyleRule()) 01328 { 01329 CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item); 01330 QPtrList<CSSSelector> *s = r->selector(); 01331 for(int j = 0; j < (int)s->count(); j++) 01332 { 01333 CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count()); 01334 QPtrList<CSSOrderedRule>::append(rule); 01335 //kdDebug( 6080 ) << "appending StyleRule!" << endl; 01336 } 01337 } 01338 else if(item->isImportRule()) 01339 { 01340 CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item); 01341 01342 //kdDebug( 6080 ) << "@import: Media: " 01343 // << import->media()->mediaText().string() << endl; 01344 01345 if( !import->media() || import->media()->contains( medium ) ) 01346 { 01347 CSSStyleSheetImpl *importedSheet = import->styleSheet(); 01348 append( importedSheet, medium ); 01349 } 01350 } 01351 else if( item->isMediaRule() ) 01352 { 01353 CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>( item ); 01354 CSSRuleListImpl *rules = r->cssRules(); 01355 01356 //DOMString mediaText = media->mediaText(); 01357 //kdDebug( 6080 ) << "@media: Media: " 01358 // << r->media()->mediaText().string() << endl; 01359 01360 if( ( !r->media() || r->media()->contains( medium ) ) && rules) 01361 { 01362 // Traverse child elements of the @import rule. Since 01363 // many elements are not allowed as child we do not use 01364 // a recursive call to append() here 01365 for( unsigned j = 0; j < rules->length(); j++ ) 01366 { 01367 //kdDebug( 6080 ) << "*** Rule #" << j << endl; 01368 01369 CSSRuleImpl *childItem = rules->item( j ); 01370 if( childItem->isStyleRule() ) 01371 { 01372 // It is a StyleRule, so append it to our list 01373 CSSStyleRuleImpl *styleRule = 01374 static_cast<CSSStyleRuleImpl *>( childItem ); 01375 01376 QPtrList<CSSSelector> *s = styleRule->selector(); 01377 for( int j = 0; j < ( int ) s->count(); j++ ) 01378 { 01379 CSSOrderedRule *orderedRule = new CSSOrderedRule( 01380 styleRule, s->at( j ), count() ); 01381 QPtrList<CSSOrderedRule>::append( orderedRule ); 01382 } 01383 } 01384 else 01385 { 01386 //kdDebug( 6080 ) << "Ignoring child rule of " 01387 // "ImportRule: rule is not a StyleRule!" << endl; 01388 } 01389 } // for rules 01390 } // if rules 01391 else 01392 { 01393 //kdDebug( 6080 ) << "CSSMediaRule not rendered: " 01394 // << "rule empty or wrong medium!" << endl; 01395 } 01396 } 01397 // ### include other rules 01398 } 01399 } 01400 01401 01402 void CSSStyleSelectorList::collect( QPtrList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList, 01403 Source regular, Source important ) 01404 { 01405 CSSOrderedRule *r = first(); 01406 while( r ) { 01407 CSSSelector *sel = selectorList->first(); 01408 int selectorNum = 0; 01409 while( sel ) { 01410 if ( *sel == *(r->selector) ) 01411 break; 01412 sel = selectorList->next(); 01413 selectorNum++; 01414 } 01415 if ( !sel ) 01416 selectorList->append( r->selector ); 01417 // else 01418 // qDebug("merged one selector"); 01419 propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important ); 01420 r = next(); 01421 } 01422 } 01423 01424 // ------------------------------------------------------------------------- 01425 01426 int CSSOrderedPropertyList::compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2) 01427 { 01428 int diff = static_cast<CSSOrderedProperty *>(i1)->priority 01429 - static_cast<CSSOrderedProperty *>(i2)->priority; 01430 return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position 01431 - static_cast<CSSOrderedProperty *>(i2)->position; 01432 } 01433 01434 void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity, 01435 Source regular, Source important ) 01436 { 01437 QPtrList<CSSProperty> *values = decl->values(); 01438 if(!values) return; 01439 int len = values->count(); 01440 for(int i = 0; i < len; i++) 01441 { 01442 CSSProperty *prop = values->at(i); 01443 Source source = regular; 01444 01445 if( prop->m_bImportant ) source = important; 01446 if( prop->nonCSSHint ) source = NonCSSHint; 01447 01448 bool first = false; 01449 // give special priority to font-xxx, color properties 01450 switch(prop->m_id) 01451 { 01452 case CSS_PROP_FONT_STYLE: 01453 case CSS_PROP_FONT_SIZE: 01454 case CSS_PROP_FONT_WEIGHT: 01455 case CSS_PROP_FONT_FAMILY: 01456 case CSS_PROP_FONT: 01457 case CSS_PROP_COLOR: 01458 case CSS_PROP_BACKGROUND_IMAGE: 01459 case CSS_PROP_DISPLAY: 01460 // these have to be applied first, because other properties use the computed 01461 // values of these porperties. 01462 first = true; 01463 break; 01464 default: 01465 break; 01466 } 01467 01468 QPtrList<CSSOrderedProperty>::append(new CSSOrderedProperty(prop, selector, 01469 first, source, specificity, 01470 count() )); 01471 } 01472 } 01473 01474 // ------------------------------------------------------------------------------------- 01475 // this is mostly boring stuff on how to apply a certain rule to the renderstyle... 01476 01477 static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, QPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 ) 01478 { 01479 Length l; 01480 if ( !primitiveValue ) { 01481 if ( ok ) 01482 *ok = false; 01483 } else { 01484 int type = primitiveValue->primitiveType(); 01485 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 01486 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed); 01487 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 01488 l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent); 01489 else if(type == CSSPrimitiveValue::CSS_NUMBER) 01490 l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent); 01491 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) 01492 l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative); 01493 else if ( ok ) 01494 *ok = false; 01495 } 01496 return l; 01497 } 01498 01499 01500 // color mapping code 01501 struct colorMap { 01502 int css_value; 01503 QRgb color; 01504 }; 01505 01506 static const colorMap cmap[] = { 01507 { CSS_VAL_AQUA, 0xFF00FFFF }, 01508 { CSS_VAL_BLACK, 0xFF000000 }, 01509 { CSS_VAL_BLUE, 0xFF0000FF }, 01510 { CSS_VAL_CRIMSON, 0xFFDC143C }, 01511 { CSS_VAL_FUCHSIA, 0xFFFF00FF }, 01512 { CSS_VAL_GRAY, 0xFF808080 }, 01513 { CSS_VAL_GREEN, 0xFF008000 }, 01514 { CSS_VAL_INDIGO, 0xFF4B0082 }, 01515 { CSS_VAL_LIME, 0xFF00FF00 }, 01516 { CSS_VAL_MAROON, 0xFF800000 }, 01517 { CSS_VAL_NAVY, 0xFF000080 }, 01518 { CSS_VAL_OLIVE, 0xFF808000 }, 01519 { CSS_VAL_ORANGE, 0xFFFFA500 }, 01520 { CSS_VAL_PURPLE, 0xFF800080 }, 01521 { CSS_VAL_RED, 0xFFFF0000 }, 01522 { CSS_VAL_SILVER, 0xFFC0C0C0 }, 01523 { CSS_VAL_TEAL, 0xFF008080 }, 01524 { CSS_VAL_WHITE, 0xFFFFFFFF }, 01525 { CSS_VAL_YELLOW, 0xFFFFFF00 }, 01526 { CSS_VAL_INVERT, invertedColor }, 01527 { CSS_VAL_TRANSPARENT, transparentColor }, 01528 { CSS_VAL_GREY, 0xff808080 }, 01529 { 0, 0 } 01530 }; 01531 01532 struct uiColors { 01533 int css_value; 01534 const char * configGroup; 01535 const char * configEntry; 01536 QPalette::ColorGroup group; 01537 QColorGroup::ColorRole role; 01538 }; 01539 01540 const char * const wmgroup = "WM"; 01541 const char * const generalgroup = "General"; 01542 01543 /* Mapping system settings to CSS 2 01544 * Tried hard to get an appropriate mapping - schlpbch 01545 */ 01546 static const uiColors uimap[] = { 01547 // Active window border. 01548 { CSS_VAL_ACTIVEBORDER, wmgroup, "background", QPalette::Active, QColorGroup::Light }, 01549 // Active window caption. 01550 { CSS_VAL_ACTIVECAPTION, wmgroup, "background", QPalette::Active, QColorGroup::Text }, 01551 // Text in caption, size box, and scrollbar arrow box. 01552 { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", QPalette::Active, QColorGroup::Text }, 01553 // Face color for three-dimensional display elements. 01554 { CSS_VAL_BUTTONFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button }, 01555 // Dark shadow for three-dimensional display elements (for edges facing away from the light source). 01556 { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light }, 01557 // Shadow color for three-dimensional display elements. 01558 { CSS_VAL_BUTTONSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow }, 01559 // Text on push buttons. 01560 { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", QPalette::Inactive, QColorGroup::ButtonText }, 01561 // Dark shadow for three-dimensional display elements. 01562 { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Dark }, 01563 // Face color for three-dimensional display elements. 01564 { CSS_VAL_THREEDFACE, wmgroup, 0, QPalette::Inactive, QColorGroup::Button }, 01565 // Highlight color for three-dimensional display elements. 01566 { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, QPalette::Inactive, QColorGroup::Light }, 01567 // Light color for three-dimensional display elements (for edges facing the light source). 01568 { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Midlight }, 01569 // Dark shadow for three-dimensional display elements. 01570 { CSS_VAL_THREEDSHADOW, wmgroup, 0, QPalette::Inactive, QColorGroup::Shadow }, 01571 01572 // Inactive window border. 01573 { CSS_VAL_INACTIVEBORDER, wmgroup, "background", QPalette::Disabled, QColorGroup::Background }, 01574 // Inactive window caption. 01575 { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", QPalette::Disabled, QColorGroup::Background }, 01576 // Color of text in an inactive caption. 01577 { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", QPalette::Disabled, QColorGroup::Text }, 01578 { CSS_VAL_GRAYTEXT, wmgroup, 0, QPalette::Disabled, QColorGroup::Text }, 01579 01580 // Menu background 01581 { CSS_VAL_MENU, generalgroup, "background", QPalette::Inactive, QColorGroup::Background }, 01582 // Text in menus 01583 { CSS_VAL_MENUTEXT, generalgroup, "foreground", QPalette::Inactive, QColorGroup::Background }, 01584 01585 // Text of item(s) selected in a control. 01586 { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", QPalette::Inactive, QColorGroup::Background }, 01587 01588 // Text of item(s) selected in a control. 01589 { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", QPalette::Inactive, QColorGroup::Background }, 01590 01591 // Background color of multiple document interface. 01592 { CSS_VAL_APPWORKSPACE, generalgroup, "background", QPalette::Inactive, QColorGroup::Text }, 01593 01594 // Scroll bar gray area. 01595 { CSS_VAL_SCROLLBAR, generalgroup, "background", QPalette::Inactive, QColorGroup::Background }, 01596 01597 // Window background. 01598 { CSS_VAL_WINDOW, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background }, 01599 // Window frame. 01600 { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", QPalette::Inactive, QColorGroup::Background }, 01601 // WindowText 01602 { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", QPalette::Inactive, QColorGroup::Text }, 01603 { CSS_VAL_TEXT, generalgroup, 0, QPalette::Inactive, QColorGroup::Text }, 01604 { 0, 0, 0, QPalette::NColorGroups, QColorGroup::NColorRoles } 01605 }; 01606 01607 static QColor colorForCSSValue( int css_value ) 01608 { 01609 // try the regular ones first 01610 const colorMap *col = cmap; 01611 while ( col->css_value && col->css_value != css_value ) 01612 ++col; 01613 if ( col->css_value ) 01614 return col->color; 01615 01616 const uiColors *uicol = uimap; 01617 while ( uicol->css_value && uicol->css_value != css_value ) 01618 ++uicol; 01619 #ifndef APPLE_CHANGES 01620 if ( !uicol->css_value ) { 01621 if ( css_value == CSS_VAL_INFOBACKGROUND ) 01622 return QToolTip::palette().inactive().background(); 01623 else if ( css_value == CSS_VAL_INFOTEXT ) 01624 return QToolTip::palette().inactive().foreground(); 01625 else if ( css_value == CSS_VAL_BACKGROUND ) { 01626 KConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support 01627 bckgrConfig.setGroup("Desktop0"); 01628 // Desktop background. 01629 return bckgrConfig.readColorEntry("Color1", &qApp->palette().disabled().background()); 01630 } 01631 return QColor(); 01632 } 01633 #endif 01634 01635 const QPalette &pal = qApp->palette(); 01636 QColor c = pal.color( uicol->group, uicol->role ); 01637 #ifndef APPLE_CHANGES 01638 if ( uicol->configEntry ) { 01639 KConfig *globalConfig = KGlobal::config(); 01640 globalConfig->setGroup( uicol->configGroup ); 01641 c = globalConfig->readColorEntry( uicol->configEntry, &c ); 01642 } 01643 #endif 01644 01645 return c; 01646 } 01647 01648 01649 void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value ) 01650 { 01651 // kdDebug( 6080 ) << "applying property " << id << endl; 01652 01653 CSSPrimitiveValueImpl *primitiveValue = 0; 01654 if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value); 01655 01656 Length l; 01657 bool apply = false; 01658 01659 bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT); 01660 bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) || 01661 (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT); 01662 01663 // What follows is a list that maps the CSS properties into their corresponding front-end 01664 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and 01665 // are only hit when mapping "inherit" or "initial" into front-end values. 01666 switch(id) 01667 { 01668 // ident only properties 01669 case CSS_PROP_BACKGROUND_ATTACHMENT: 01670 HANDLE_INHERIT_AND_INITIAL(backgroundAttachment, BackgroundAttachment) 01671 if(!primitiveValue) break; 01672 switch(primitiveValue->getIdent()) 01673 { 01674 case CSS_VAL_FIXED: 01675 { 01676 style->setBackgroundAttachment(false); 01677 // only use slow repaints if we actually have a background pixmap 01678 if( style->backgroundImage() ) 01679 view->useSlowRepaints(); 01680 break; 01681 } 01682 case CSS_VAL_SCROLL: 01683 style->setBackgroundAttachment(true); 01684 break; 01685 default: 01686 return; 01687 } 01688 case CSS_PROP_BACKGROUND_REPEAT: 01689 { 01690 HANDLE_INHERIT_AND_INITIAL(backgroundRepeat, BackgroundRepeat) 01691 if(!primitiveValue) return; 01692 switch(primitiveValue->getIdent()) 01693 { 01694 case CSS_VAL_REPEAT: 01695 style->setBackgroundRepeat( REPEAT ); 01696 break; 01697 case CSS_VAL_REPEAT_X: 01698 style->setBackgroundRepeat( REPEAT_X ); 01699 break; 01700 case CSS_VAL_REPEAT_Y: 01701 style->setBackgroundRepeat( REPEAT_Y ); 01702 break; 01703 case CSS_VAL_NO_REPEAT: 01704 style->setBackgroundRepeat( NO_REPEAT ); 01705 break; 01706 default: 01707 return; 01708 } 01709 } 01710 case CSS_PROP_BORDER_COLLAPSE: 01711 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) 01712 if(!primitiveValue) break; 01713 switch(primitiveValue->getIdent()) 01714 { 01715 case CSS_VAL_COLLAPSE: 01716 style->setBorderCollapse(true); 01717 break; 01718 case CSS_VAL_SEPARATE: 01719 style->setBorderCollapse(false); 01720 break; 01721 default: 01722 return; 01723 } 01724 break; 01725 01726 case CSS_PROP_BORDER_TOP_STYLE: 01727 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) 01728 if (!primitiveValue) return; 01729 style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); 01730 break; 01731 case CSS_PROP_BORDER_RIGHT_STYLE: 01732 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) 01733 if (!primitiveValue) return; 01734 style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); 01735 break; 01736 case CSS_PROP_BORDER_BOTTOM_STYLE: 01737 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) 01738 if (!primitiveValue) return; 01739 style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); 01740 break; 01741 case CSS_PROP_BORDER_LEFT_STYLE: 01742 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) 01743 if (!primitiveValue) return; 01744 style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); 01745 break; 01746 case CSS_PROP_OUTLINE_STYLE: 01747 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) 01748 if (!primitiveValue) return; 01749 style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL_NONE)); 01750 break; 01751 case CSS_PROP_CAPTION_SIDE: 01752 { 01753 HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide) 01754 if(!primitiveValue) break; 01755 ECaptionSide c = RenderStyle::initialCaptionSide(); 01756 switch(primitiveValue->getIdent()) 01757 { 01758 case CSS_VAL_TOP: 01759 c = CAPTOP; break; 01760 case CSS_VAL_BOTTOM: 01761 c = CAPBOTTOM; break; 01762 default: 01763 return; 01764 } 01765 style->setCaptionSide(c); 01766 return; 01767 } 01768 case CSS_PROP_CLEAR: 01769 { 01770 HANDLE_INHERIT_AND_INITIAL(clear, Clear) 01771 if(!primitiveValue) break; 01772 EClear c = CNONE; 01773 switch(primitiveValue->getIdent()) 01774 { 01775 case CSS_VAL_LEFT: 01776 c = CLEFT; break; 01777 case CSS_VAL_RIGHT: 01778 c = CRIGHT; break; 01779 case CSS_VAL_BOTH: 01780 c = CBOTH; break; 01781 case CSS_VAL_NONE: 01782 c = CNONE; break; 01783 default: 01784 return; 01785 } 01786 style->setClear(c); 01787 return; 01788 } 01789 case CSS_PROP_DIRECTION: 01790 { 01791 HANDLE_INHERIT_AND_INITIAL(direction, Direction) 01792 if(!primitiveValue) break; 01793 style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) ); 01794 return; 01795 } 01796 case CSS_PROP_DISPLAY: 01797 { 01798 HANDLE_INHERIT_AND_INITIAL(display, Display) 01799 if(!primitiveValue) break; 01800 int id = primitiveValue->getIdent(); 01801 style->setDisplay( id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE) ); 01802 break; 01803 } 01804 01805 case CSS_PROP_EMPTY_CELLS: 01806 { 01807 HANDLE_INHERIT(emptyCells, EmptyCells); 01808 if (!primitiveValue) break; 01809 int id = primitiveValue->getIdent(); 01810 if (id == CSS_VAL_SHOW) 01811 style->setEmptyCells(SHOW); 01812 else if (id == CSS_VAL_HIDE) 01813 style->setEmptyCells(HIDE); 01814 break; 01815 } 01816 case CSS_PROP_FLOAT: 01817 { 01818 HANDLE_INHERIT_AND_INITIAL(floating, Floating) 01819 if(!primitiveValue) return; 01820 EFloat f; 01821 switch(primitiveValue->getIdent()) 01822 { 01823 case CSS_VAL_LEFT: 01824 f = FLEFT; break; 01825 case CSS_VAL_RIGHT: 01826 f = FRIGHT; break; 01827 case CSS_VAL_NONE: 01828 case CSS_VAL_CENTER: //Non standart CSS-Value 01829 f = FNONE; break; 01830 default: 01831 return; 01832 } 01833 if (f!=FNONE && style->display()==LIST_ITEM) 01834 style->setDisplay(BLOCK); 01835 01836 style->setFloating(f); 01837 break; 01838 } 01839 01840 case CSS_PROP_FONT_STYLE: 01841 { 01842 FontDef fontDef = style->htmlFont().fontDef; 01843 if (isInherit) 01844 fontDef.italic = parentStyle->htmlFont().fontDef.italic; 01845 else if (isInitial) 01846 fontDef.italic = false; 01847 else { 01848 if(!primitiveValue) return; 01849 switch(primitiveValue->getIdent()) { 01850 case CSS_VAL_OBLIQUE: 01851 // ### oblique is the same as italic for the moment... 01852 case CSS_VAL_ITALIC: 01853 fontDef.italic = true; 01854 break; 01855 case CSS_VAL_NORMAL: 01856 fontDef.italic = false; 01857 break; 01858 default: 01859 return; 01860 } 01861 } 01862 fontDirty |= style->setFontDef( fontDef ); 01863 break; 01864 } 01865 01866 01867 case CSS_PROP_FONT_VARIANT: 01868 { 01869 FontDef fontDef = style->htmlFont().fontDef; 01870 if (isInherit) 01871 fontDef.smallCaps = parentStyle->htmlFont().fontDef.weight; 01872 else if (isInitial) 01873 fontDef.smallCaps = false; 01874 else { 01875 if(!primitiveValue) return; 01876 int id = primitiveValue->getIdent(); 01877 if ( id == CSS_VAL_NORMAL ) 01878 fontDef.smallCaps = false; 01879 else if ( id == CSS_VAL_SMALL_CAPS ) 01880 fontDef.smallCaps = true; 01881 else 01882 return; 01883 } 01884 fontDirty |= style->setFontDef( fontDef ); 01885 break; 01886 } 01887 01888 case CSS_PROP_FONT_WEIGHT: 01889 { 01890 FontDef fontDef = style->htmlFont().fontDef; 01891 if (isInherit) 01892 fontDef.weight = parentStyle->htmlFont().fontDef.weight; 01893 else if (isInitial) 01894 fontDef.weight = QFont::Normal; 01895 else { 01896 if(!primitiveValue) return; 01897 if(primitiveValue->getIdent()) 01898 { 01899 switch(primitiveValue->getIdent()) { 01900 // ### we just support normal and bold fonts at the moment... 01901 // setWeight can actually accept values between 0 and 99... 01902 case CSS_VAL_BOLD: 01903 case CSS_VAL_BOLDER: 01904 case CSS_VAL_600: 01905 case CSS_VAL_700: 01906 case CSS_VAL_800: 01907 case CSS_VAL_900: 01908 fontDef.weight = QFont::Bold; 01909 break; 01910 case CSS_VAL_NORMAL: 01911 case CSS_VAL_LIGHTER: 01912 case CSS_VAL_100: 01913 case CSS_VAL_200: 01914 case CSS_VAL_300: 01915 case CSS_VAL_400: 01916 case CSS_VAL_500: 01917 fontDef.weight = QFont::Normal; 01918 break; 01919 default: 01920 return; 01921 } 01922 } 01923 else 01924 { 01925 // ### fix parsing of 100-900 values in parser, apply them here 01926 } 01927 } 01928 fontDirty |= style->setFontDef( fontDef ); 01929 break; 01930 } 01931 01932 case CSS_PROP_LIST_STYLE_POSITION: 01933 { 01934 HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition) 01935 if (!primitiveValue) return; 01936 if (primitiveValue->getIdent()) 01937 style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) ); 01938 return; 01939 } 01940 01941 case CSS_PROP_LIST_STYLE_TYPE: 01942 { 01943 HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType) 01944 if (!primitiveValue) return; 01945 if (primitiveValue->getIdent()) 01946 { 01947 EListStyleType t; 01948 int id = primitiveValue->getIdent(); 01949 if ( id == CSS_VAL_NONE) { // important!! 01950 t = LNONE; 01951 } else { 01952 t = EListStyleType(id - CSS_VAL_DISC); 01953 } 01954 style->setListStyleType(t); 01955 } 01956 return; 01957 } 01958 01959 case CSS_PROP_OVERFLOW: 01960 { 01961 HANDLE_INHERIT_AND_INITIAL(overflow, Overflow) 01962 if (!primitiveValue) return; 01963 EOverflow o; 01964 switch(primitiveValue->getIdent()) 01965 { 01966 case CSS_VAL_VISIBLE: 01967 o = OVISIBLE; break; 01968 case CSS_VAL_HIDDEN: 01969 o = OHIDDEN; break; 01970 case CSS_VAL_SCROLL: 01971 o = OSCROLL; break; 01972 case CSS_VAL_AUTO: 01973 o = OAUTO; break; 01974 case CSS_VAL_MARQUEE: 01975 o = OMARQUEE; break; 01976 default: 01977 return; 01978 } 01979 style->setOverflow(o); 01980 return; 01981 } 01982 break; 01983 case CSS_PROP_PAGE_BREAK_AFTER: 01984 case CSS_PROP_PAGE_BREAK_BEFORE: 01985 case CSS_PROP_PAGE_BREAK_INSIDE: 01986 // case CSS_PROP_PAUSE_AFTER: 01987 // case CSS_PROP_PAUSE_BEFORE: 01988 break; 01989 01990 case CSS_PROP_POSITION: 01991 { 01992 HANDLE_INHERIT_AND_INITIAL(position, Position) 01993 if (!primitiveValue) return; 01994 EPosition p; 01995 switch(primitiveValue->getIdent()) 01996 { 01997 case CSS_VAL_STATIC: 01998 p = STATIC; break; 01999 case CSS_VAL_RELATIVE: 02000 p = RELATIVE; break; 02001 case CSS_VAL_ABSOLUTE: 02002 p = ABSOLUTE; break; 02003 case CSS_VAL_FIXED: 02004 { 02005 view->useSlowRepaints(); 02006 p = FIXED; 02007 break; 02008 } 02009 default: 02010 return; 02011 } 02012 style->setPosition(p); 02013 return; 02014 } 02015 02016 case CSS_PROP_TABLE_LAYOUT: { 02017 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout) 02018 02019 if ( !primitiveValue ) 02020 return; 02021 02022 ETableLayout l = RenderStyle::initialTableLayout(); 02023 switch( primitiveValue->getIdent() ) { 02024 case CSS_VAL_FIXED: 02025 l = TFIXED; 02026 // fall through 02027 case CSS_VAL_AUTO: 02028 style->setTableLayout( l ); 02029 default: 02030 break; 02031 } 02032 break; 02033 } 02034 02035 case CSS_PROP_UNICODE_BIDI: { 02036 HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi) 02037 if(!primitiveValue) break; 02038 switch (primitiveValue->getIdent()) { 02039 case CSS_VAL_NORMAL: 02040 style->setUnicodeBidi(UBNormal); 02041 break; 02042 case CSS_VAL_EMBED: 02043 style->setUnicodeBidi(Embed); 02044 break; 02045 case CSS_VAL_BIDI_OVERRIDE: 02046 style->setUnicodeBidi(Override); 02047 break; 02048 default: 02049 return; 02050 } 02051 break; 02052 } 02053 case CSS_PROP_TEXT_TRANSFORM: { 02054 HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform) 02055 02056 if(!primitiveValue) break; 02057 if(!primitiveValue->getIdent()) return; 02058 02059 ETextTransform tt; 02060 switch(primitiveValue->getIdent()) { 02061 case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break; 02062 case CSS_VAL_UPPERCASE: tt = UPPERCASE; break; 02063 case CSS_VAL_LOWERCASE: tt = LOWERCASE; break; 02064 case CSS_VAL_NONE: 02065 default: tt = TTNONE; break; 02066 } 02067 style->setTextTransform(tt); 02068 break; 02069 } 02070 02071 case CSS_PROP_VISIBILITY: 02072 { 02073 HANDLE_INHERIT_AND_INITIAL(visibility, Visibility) 02074 02075 if(!primitiveValue) break; 02076 switch( primitiveValue->getIdent() ) { 02077 case CSS_VAL_HIDDEN: 02078 style->setVisibility( HIDDEN ); 02079 break; 02080 case CSS_VAL_VISIBLE: 02081 style->setVisibility( VISIBLE ); 02082 break; 02083 case CSS_VAL_COLLAPSE: 02084 style->setVisibility( COLLAPSE ); 02085 default: 02086 break; 02087 } 02088 break; 02089 } 02090 case CSS_PROP_WHITE_SPACE: 02091 HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace) 02092 02093 if(!primitiveValue) break; 02094 if(!primitiveValue->getIdent()) return; 02095 02096 EWhiteSpace s; 02097 switch(primitiveValue->getIdent()) { 02098 case CSS_VAL__KHTML_NOWRAP: 02099 s = KHTML_NOWRAP; 02100 break; 02101 case CSS_VAL_NOWRAP: 02102 s = NOWRAP; 02103 break; 02104 case CSS_VAL_PRE: 02105 s = PRE; 02106 break; 02107 case CSS_VAL_NORMAL: 02108 default: 02109 s = NORMAL; 02110 break; 02111 } 02112 style->setWhiteSpace(s); 02113 break; 02114 02115 case CSS_PROP_BACKGROUND_POSITION: 02116 if (isInherit) { 02117 style->setBackgroundXPosition(parentStyle->backgroundXPosition()); 02118 style->setBackgroundYPosition(parentStyle->backgroundYPosition()); 02119 } 02120 else if (isInitial) { 02121 style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition()); 02122 style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition()); 02123 } 02124 break; 02125 case CSS_PROP_BACKGROUND_POSITION_X: { 02126 HANDLE_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition) 02127 if(!primitiveValue) break; 02128 Length l; 02129 int type = primitiveValue->primitiveType(); 02130 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 02131 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed); 02132 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02133 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 02134 else 02135 return; 02136 style->setBackgroundXPosition(l); 02137 break; 02138 } 02139 case CSS_PROP_BACKGROUND_POSITION_Y: { 02140 HANDLE_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition) 02141 if(!primitiveValue) break; 02142 Length l; 02143 int type = primitiveValue->primitiveType(); 02144 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 02145 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed); 02146 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02147 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 02148 else 02149 return; 02150 style->setBackgroundYPosition(l); 02151 break; 02152 } 02153 case CSS_PROP_BORDER_SPACING: 02154 assert( false ); 02155 02156 case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: { 02157 HANDLE_INHERIT_AND_INITIAL(borderHorizontalSpacing, BorderHorizontalSpacing) 02158 if (!primitiveValue) break; 02159 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics); 02160 style->setBorderHorizontalSpacing(spacing); 02161 break; 02162 } 02163 case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: { 02164 HANDLE_INHERIT_AND_INITIAL(borderVerticalSpacing, BorderVerticalSpacing) 02165 if (!primitiveValue) break; 02166 short spacing = primitiveValue->computeLength(style, paintDeviceMetrics); 02167 style->setBorderVerticalSpacing(spacing); 02168 break; 02169 } 02170 02171 case CSS_PROP_CURSOR: 02172 HANDLE_INHERIT_AND_INITIAL(cursor, Cursor) 02173 if(primitiveValue) 02174 style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) ); 02175 break; 02176 // colors || inherit 02177 case CSS_PROP_BACKGROUND_COLOR: 02178 case CSS_PROP_BORDER_TOP_COLOR: 02179 case CSS_PROP_BORDER_RIGHT_COLOR: 02180 case CSS_PROP_BORDER_BOTTOM_COLOR: 02181 case CSS_PROP_BORDER_LEFT_COLOR: 02182 case CSS_PROP_COLOR: 02183 case CSS_PROP_OUTLINE_COLOR: 02184 // this property is an extension used to get HTML4 <font> right. 02185 case CSS_PROP_SCROLLBAR_FACE_COLOR: 02186 case CSS_PROP_SCROLLBAR_SHADOW_COLOR: 02187 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: 02188 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: 02189 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: 02190 case CSS_PROP_SCROLLBAR_TRACK_COLOR: 02191 case CSS_PROP_SCROLLBAR_ARROW_COLOR: 02192 { 02193 QColor col; 02194 if (isInherit) { 02195 HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor) 02196 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor) 02197 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor) 02198 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor) 02199 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor) 02200 HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color) 02201 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor) 02202 return; 02203 } else if (isInitial) { 02204 // The border/outline colors will just map to the invalid color |col| above. This will have the 02205 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of 02206 // not painting the background since the color won't be valid). 02207 if (id == CSS_PROP_COLOR) 02208 col = RenderStyle::initialColor(); 02209 } else { 02210 if(!primitiveValue ) 02211 return; 02212 int ident = primitiveValue->getIdent(); 02213 if ( ident ) { 02214 if ( ident == CSS_VAL__KHTML_TEXT ) 02215 col = element->getDocument()->textColor(); 02216 // ### should be eliminated 02217 else if ( ident == CSS_VAL_TRANSPARENT 02218 && id != CSS_PROP_BORDER_TOP_COLOR 02219 && id != CSS_PROP_BORDER_RIGHT_COLOR 02220 && id != CSS_PROP_BORDER_BOTTOM_COLOR 02221 && id != CSS_PROP_BORDER_LEFT_COLOR ) 02222 col = QColor(); 02223 else 02224 col = colorForCSSValue( ident ); 02225 } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) { 02226 #ifndef APPLE_CHANGES 02227 if(qAlpha(primitiveValue->getRGBColorValue())) 02228 #endif 02229 col.setRgb(primitiveValue->getRGBColorValue()); 02230 } else { 02231 return; 02232 } 02233 } 02234 //kdDebug( 6080 ) << "applying color " << col.isValid() << endl; 02235 switch(id) 02236 { 02237 case CSS_PROP_BACKGROUND_COLOR: 02238 style->setBackgroundColor(col); break; 02239 case CSS_PROP_BORDER_TOP_COLOR: 02240 style->setBorderTopColor(col); break; 02241 case CSS_PROP_BORDER_RIGHT_COLOR: 02242 style->setBorderRightColor(col); break; 02243 case CSS_PROP_BORDER_BOTTOM_COLOR: 02244 style->setBorderBottomColor(col); break; 02245 case CSS_PROP_BORDER_LEFT_COLOR: 02246 style->setBorderLeftColor(col); break; 02247 case CSS_PROP_COLOR: 02248 style->setColor(col); break; 02249 case CSS_PROP__KHTML_TEXT_DECORATION_COLOR: 02250 style->setTextDecorationColor(col); break; 02251 case CSS_PROP_OUTLINE_COLOR: 02252 style->setOutlineColor(col); break; 02253 #ifndef APPLE_CHANGES 02254 case CSS_PROP_SCROLLBAR_FACE_COLOR: 02255 style->setPaletteColor(QPalette::Active, QColorGroup::Button, col); 02256 style->setPaletteColor(QPalette::Inactive, QColorGroup::Button, col); 02257 break; 02258 case CSS_PROP_SCROLLBAR_SHADOW_COLOR: 02259 style->setPaletteColor(QPalette::Active, QColorGroup::Shadow, col); 02260 style->setPaletteColor(QPalette::Inactive, QColorGroup::Shadow, col); 02261 break; 02262 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: 02263 style->setPaletteColor(QPalette::Active, QColorGroup::Light, col); 02264 style->setPaletteColor(QPalette::Inactive, QColorGroup::Light, col); 02265 break; 02266 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: 02267 break; 02268 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: 02269 style->setPaletteColor(QPalette::Active, QColorGroup::Dark, col); 02270 style->setPaletteColor(QPalette::Inactive, QColorGroup::Dark, col); 02271 break; 02272 case CSS_PROP_SCROLLBAR_TRACK_COLOR: 02273 style->setPaletteColor(QPalette::Active, QColorGroup::Mid, col); 02274 style->setPaletteColor(QPalette::Inactive, QColorGroup::Mid, col); 02275 style->setPaletteColor(QPalette::Active, QColorGroup::Background, col); 02276 style->setPaletteColor(QPalette::Inactive, QColorGroup::Background, col); 02277 // fall through 02278 case CSS_PROP_SCROLLBAR_BASE_COLOR: 02279 style->setPaletteColor(QPalette::Active, QColorGroup::Base, col); 02280 style->setPaletteColor(QPalette::Inactive, QColorGroup::Base, col); 02281 break; 02282 case CSS_PROP_SCROLLBAR_ARROW_COLOR: 02283 style->setPaletteColor(QPalette::Active, QColorGroup::ButtonText, col); 02284 style->setPaletteColor(QPalette::Inactive, QColorGroup::ButtonText, col); 02285 break; 02286 #endif 02287 default: 02288 return; 02289 } 02290 return; 02291 } 02292 break; 02293 // uri || inherit 02294 case CSS_PROP_BACKGROUND_IMAGE: 02295 { 02296 HANDLE_INHERIT_AND_INITIAL(backgroundImage, BackgroundImage) 02297 if (!primitiveValue) return; 02298 style->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image()); 02299 //kdDebug( 6080 ) << "setting image in style to " << image << endl; 02300 break; 02301 } 02302 case CSS_PROP_LIST_STYLE_IMAGE: 02303 { 02304 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) 02305 if (!primitiveValue) return; 02306 style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image()); 02307 //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl; 02308 break; 02309 } 02310 02311 // length 02312 case CSS_PROP_BORDER_TOP_WIDTH: 02313 case CSS_PROP_BORDER_RIGHT_WIDTH: 02314 case CSS_PROP_BORDER_BOTTOM_WIDTH: 02315 case CSS_PROP_BORDER_LEFT_WIDTH: 02316 case CSS_PROP_OUTLINE_WIDTH: 02317 { 02318 if (isInherit) { 02319 HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth) 02320 HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth) 02321 HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth) 02322 HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth) 02323 HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth) 02324 return; 02325 } 02326 else if (isInitial) { 02327 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth) 02328 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth) 02329 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth) 02330 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth) 02331 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth) 02332 return; 02333 } 02334 02335 if(!primitiveValue) break; 02336 short width = 3; 02337 switch(primitiveValue->getIdent()) 02338 { 02339 case CSS_VAL_THIN: 02340 width = 1; 02341 break; 02342 case CSS_VAL_MEDIUM: 02343 width = 3; 02344 break; 02345 case CSS_VAL_THICK: 02346 width = 5; 02347 break; 02348 case CSS_VAL_INVALID: 02349 { 02350 double widthd = primitiveValue->computeLengthFloat(style, paintDeviceMetrics); 02351 width = (int)widthd; 02352 // somewhat resemble Mozilla's granularity 02353 // this makes border-width: 0.5pt borders visible 02354 if (width == 0 && widthd >= 0.025) width++; 02355 break; 02356 } 02357 default: 02358 return; 02359 } 02360 02361 if(width < 0) return; 02362 switch(id) 02363 { 02364 case CSS_PROP_BORDER_TOP_WIDTH: 02365 style->setBorderTopWidth(width); 02366 break; 02367 case CSS_PROP_BORDER_RIGHT_WIDTH: 02368 style->setBorderRightWidth(width); 02369 break; 02370 case CSS_PROP_BORDER_BOTTOM_WIDTH: 02371 style->setBorderBottomWidth(width); 02372 break; 02373 case CSS_PROP_BORDER_LEFT_WIDTH: 02374 style->setBorderLeftWidth(width); 02375 break; 02376 case CSS_PROP_OUTLINE_WIDTH: 02377 style->setOutlineWidth(width); 02378 break; 02379 default: 02380 return; 02381 } 02382 return; 02383 } 02384 02385 case CSS_PROP_LETTER_SPACING: 02386 case CSS_PROP_WORD_SPACING: 02387 { 02388 if (isInherit) { 02389 HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing) 02390 HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing) 02391 return; 02392 } else if (isInitial) { 02393 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing) 02394 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing) 02395 return; 02396 } 02397 if(!primitiveValue) return; 02398 02399 int width = 0; 02400 if (primitiveValue->getIdent() != CSS_VAL_NORMAL) 02401 width = primitiveValue->computeLength(style, paintDeviceMetrics); 02402 02403 switch(id) 02404 { 02405 case CSS_PROP_LETTER_SPACING: 02406 style->setLetterSpacing(width); 02407 break; 02408 case CSS_PROP_WORD_SPACING: 02409 style->setWordSpacing(width); 02410 break; 02411 // ### needs the definitions in renderstyle 02412 default: break; 02413 } 02414 return; 02415 } 02416 02417 // length, percent 02418 case CSS_PROP_MAX_WIDTH: 02419 // +none +inherit 02420 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) 02421 apply = true; 02422 case CSS_PROP_TOP: 02423 case CSS_PROP_LEFT: 02424 case CSS_PROP_RIGHT: 02425 case CSS_PROP_BOTTOM: 02426 case CSS_PROP_WIDTH: 02427 case CSS_PROP_MIN_WIDTH: 02428 case CSS_PROP_MARGIN_TOP: 02429 case CSS_PROP_MARGIN_RIGHT: 02430 case CSS_PROP_MARGIN_BOTTOM: 02431 case CSS_PROP_MARGIN_LEFT: 02432 // +inherit +auto 02433 if(id != CSS_PROP_MAX_WIDTH && primitiveValue && 02434 primitiveValue->getIdent() == CSS_VAL_AUTO) 02435 { 02436 //kdDebug( 6080 ) << "found value=auto" << endl; 02437 apply = true; 02438 } 02439 case CSS_PROP_PADDING_TOP: 02440 case CSS_PROP_PADDING_RIGHT: 02441 case CSS_PROP_PADDING_BOTTOM: 02442 case CSS_PROP_PADDING_LEFT: 02443 case CSS_PROP_TEXT_INDENT: 02444 // +inherit 02445 { 02446 if (isInherit) { 02447 HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth) 02448 HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom) 02449 HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top) 02450 HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left) 02451 HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right) 02452 HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width) 02453 HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth) 02454 HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop) 02455 HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight) 02456 HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom) 02457 HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft) 02458 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop) 02459 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight) 02460 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom) 02461 HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft) 02462 HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent) 02463 return; 02464 } else if (isInitial) { 02465 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize) 02466 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset) 02467 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset) 02468 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset) 02469 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset) 02470 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size) 02471 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize) 02472 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding) 02473 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding) 02474 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding) 02475 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding) 02476 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin) 02477 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin) 02478 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin) 02479 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin) 02480 HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent) 02481 return; 02482 } 02483 02484 if (primitiveValue && !apply) { 02485 int type = primitiveValue->primitiveType(); 02486 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 02487 // Handle our quirky margin units if we have them. 02488 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed, 02489 primitiveValue->isQuirkValue()); 02490 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02491 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 02492 else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) 02493 l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative); 02494 else 02495 return; 02496 apply = true; 02497 } 02498 if(!apply) return; 02499 switch(id) 02500 { 02501 case CSS_PROP_MAX_WIDTH: 02502 style->setMaxWidth(l); break; 02503 case CSS_PROP_BOTTOM: 02504 style->setBottom(l); break; 02505 case CSS_PROP_TOP: 02506 style->setTop(l); break; 02507 case CSS_PROP_LEFT: 02508 style->setLeft(l); break; 02509 case CSS_PROP_RIGHT: 02510 style->setRight(l); break; 02511 case CSS_PROP_WIDTH: 02512 style->setWidth(l); break; 02513 case CSS_PROP_MIN_WIDTH: 02514 style->setMinWidth(l); break; 02515 case CSS_PROP_PADDING_TOP: 02516 style->setPaddingTop(l); break; 02517 case CSS_PROP_PADDING_RIGHT: 02518 style->setPaddingRight(l); break; 02519 case CSS_PROP_PADDING_BOTTOM: 02520 style->setPaddingBottom(l); break; 02521 case CSS_PROP_PADDING_LEFT: 02522 style->setPaddingLeft(l); break; 02523 case CSS_PROP_MARGIN_TOP: 02524 style->setMarginTop(l); break; 02525 case CSS_PROP_MARGIN_RIGHT: 02526 style->setMarginRight(l); break; 02527 case CSS_PROP_MARGIN_BOTTOM: 02528 style->setMarginBottom(l); break; 02529 case CSS_PROP_MARGIN_LEFT: 02530 style->setMarginLeft(l); break; 02531 case CSS_PROP_TEXT_INDENT: 02532 style->setTextIndent(l); break; 02533 default: break; 02534 } 02535 return; 02536 } 02537 02538 case CSS_PROP_MAX_HEIGHT: 02539 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) 02540 apply = true; 02541 case CSS_PROP_HEIGHT: 02542 case CSS_PROP_MIN_HEIGHT: 02543 if(id != CSS_PROP_MAX_HEIGHT && primitiveValue && 02544 primitiveValue->getIdent() == CSS_VAL_AUTO) 02545 apply = true; 02546 if (isInherit) { 02547 HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight) 02548 HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height) 02549 HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight) 02550 return; 02551 } 02552 else if (isInitial) { 02553 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize) 02554 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size) 02555 HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize) 02556 return; 02557 } 02558 02559 if (primitiveValue && !apply) 02560 { 02561 int type = primitiveValue->primitiveType(); 02562 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 02563 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed); 02564 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02565 l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 02566 else 02567 return; 02568 apply = true; 02569 } 02570 if(!apply) return; 02571 switch(id) 02572 { 02573 case CSS_PROP_MAX_HEIGHT: 02574 style->setMaxHeight(l); break; 02575 case CSS_PROP_HEIGHT: 02576 style->setHeight(l); break; 02577 case CSS_PROP_MIN_HEIGHT: 02578 style->setMinHeight(l); break; 02579 default: 02580 return; 02581 } 02582 return; 02583 02584 break; 02585 02586 case CSS_PROP_VERTICAL_ALIGN: 02587 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign) 02588 if (!primitiveValue) return; 02589 if (primitiveValue->getIdent()) { 02590 khtml::EVerticalAlign align; 02591 02592 switch(primitiveValue->getIdent()) 02593 { 02594 case CSS_VAL_TOP: 02595 align = TOP; break; 02596 case CSS_VAL_BOTTOM: 02597 align = BOTTOM; break; 02598 case CSS_VAL_MIDDLE: 02599 align = MIDDLE; break; 02600 case CSS_VAL_BASELINE: 02601 align = BASELINE; break; 02602 case CSS_VAL_TEXT_BOTTOM: 02603 align = TEXT_BOTTOM; break; 02604 case CSS_VAL_TEXT_TOP: 02605 align = TEXT_TOP; break; 02606 case CSS_VAL_SUB: 02607 align = SUB; break; 02608 case CSS_VAL_SUPER: 02609 align = SUPER; break; 02610 case CSS_VAL__KHTML_BASELINE_MIDDLE: 02611 align = BASELINE_MIDDLE; break; 02612 default: 02613 return; 02614 } 02615 style->setVerticalAlign(align); 02616 return; 02617 } else { 02618 int type = primitiveValue->primitiveType(); 02619 Length l; 02620 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) 02621 l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed ); 02622 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02623 l = Length( int( primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent ); 02624 02625 style->setVerticalAlign( LENGTH ); 02626 style->setVerticalAlignLength( l ); 02627 } 02628 break; 02629 02630 case CSS_PROP_FONT_SIZE: 02631 { 02632 FontDef fontDef = style->htmlFont().fontDef; 02633 int oldSize; 02634 int size = 0; 02635 02636 float toPix = paintDeviceMetrics->logicalDpiY()/72.; 02637 if (toPix < 96./72.) toPix = 96./72.; 02638 02639 int minFontSize = int(settings->minFontSize() * toPix); 02640 02641 if(parentNode) { 02642 oldSize = parentStyle->font().pixelSize(); 02643 } else 02644 oldSize = m_fontSizes[3]; 02645 02646 if (isInherit ) 02647 size = oldSize; 02648 else if (isInitial) 02649 size = m_fontSizes[3]; 02650 else if(primitiveValue->getIdent()) { 02651 // keywords are being used. Pick the correct default 02652 // based off the font family. 02653 #ifdef APPLE_CHANGES 02654 QValueList<int>& fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ? 02655 m_fixedFontSizes : m_fontSizes; 02656 #else 02657 QValueList<int>& fontSizes = m_fontSizes; 02658 #endif 02659 switch(primitiveValue->getIdent()) 02660 { 02661 case CSS_VAL_XX_SMALL: size = int( fontSizes[0] ); break; 02662 case CSS_VAL_X_SMALL: size = int( fontSizes[1] ); break; 02663 case CSS_VAL_SMALL: size = int( fontSizes[2] ); break; 02664 case CSS_VAL_MEDIUM: size = int( fontSizes[3] ); break; 02665 case CSS_VAL_LARGE: size = int( fontSizes[4] ); break; 02666 case CSS_VAL_X_LARGE: size = int( fontSizes[5] ); break; 02667 case CSS_VAL_XX_LARGE: size = int( fontSizes[6] ); break; 02668 case CSS_VAL__KHTML_XXX_LARGE: size = ( fontSizes[6]*5 )/3; break; 02669 case CSS_VAL_LARGER: 02670 // ### use the next bigger standardSize!!! 02671 size = ( oldSize * 5 ) / 4; 02672 break; 02673 case CSS_VAL_SMALLER: 02674 size = ( oldSize * 4 ) / 5; 02675 break; 02676 default: 02677 return; 02678 } 02679 02680 } else { 02681 int type = primitiveValue->primitiveType(); 02682 if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { 02683 if (!khtml::printpainter && element && element->getDocument()->view()) 02684 size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) * 02685 element->getDocument()->view()->part()->zoomFactor() ) / 100; 02686 else 02687 size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) ); 02688 } 02689 else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) 02690 size = int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) 02691 * parentStyle->font().pixelSize()) / 100; 02692 else 02693 return; 02694 } 02695 02696 if(size < 1) return; 02697 02698 // we never want to get smaller than the minimum font size to keep fonts readable 02699 if(size < minFontSize ) size = minFontSize; 02700 02701 //kdDebug( 6080 ) << "computed raw font size: " << size << endl; 02702 02703 fontDef.size = size; 02704 fontDirty |= style->setFontDef( fontDef ); 02705 return; 02706 } 02707 02708 case CSS_PROP_Z_INDEX: 02709 { 02710 HANDLE_INHERIT(zIndex, ZIndex) 02711 else if (isInitial) { 02712 style->setHasAutoZIndex(); 02713 return; 02714 } 02715 02716 if (!primitiveValue) 02717 return; 02718 02719 if (primitiveValue->getIdent() == CSS_VAL_AUTO) { 02720 style->setHasAutoZIndex(); 02721 return; 02722 } 02723 02724 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 02725 return; // Error case. 02726 02727 style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); 02728 return; 02729 } 02730 02731 /* 02732 case CSS_PROP_WIDOWS: 02733 { 02734 HANDLE_INHERIT_AND_INITIAL(widows, Widows) 02735 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 02736 return; 02737 style->setWidows((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); 02738 break; 02739 } 02740 02741 case CSS_PROP_ORPHANS: 02742 { 02743 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans) 02744 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) 02745 return; 02746 style->setOrphans((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); 02747 break; 02748 } 02749 */ 02750 02751 // length, percent, number 02752 case CSS_PROP_LINE_HEIGHT: 02753 { 02754 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight) 02755 if(!primitiveValue) return; 02756 Length lineHeight; 02757 int type = primitiveValue->primitiveType(); 02758 if (primitiveValue->getIdent() == CSS_VAL_NORMAL) 02759 lineHeight = Length( -100, Percent ); 02760 else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { 02761 #ifdef APPLE_CHANGES 02762 double multiplier = 1.0; 02763 // Scale for the font zoom factor only for types other than "em" and "ex", since those are 02764 // already based on the font size. 02765 if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) { 02766 multiplier = view->part()->zoomFactor() / 100.0; 02767 } 02768 lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics, multiplier), Fixed); 02769 #else 02770 lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed); 02771 #endif 02772 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) 02773 lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed ); 02774 else if (type == CSSPrimitiveValue::CSS_NUMBER) 02775 lineHeight = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent); 02776 else 02777 return; 02778 style->setLineHeight(lineHeight); 02779 return; 02780 } 02781 02782 // string 02783 case CSS_PROP_TEXT_ALIGN: 02784 { 02785 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) 02786 if (!primitiveValue) return; 02787 if (primitiveValue->getIdent()) 02788 style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) ); 02789 return; 02790 } 02791 02792 // rect 02793 case CSS_PROP_CLIP: 02794 { 02795 Length top; 02796 Length right; 02797 Length bottom; 02798 Length left; 02799 bool hasClip = true; 02800 if (isInherit) { 02801 if (parentStyle->hasClip()) { 02802 top = parentStyle->clipTop(); 02803 right = parentStyle->clipRight(); 02804 bottom = parentStyle->clipBottom(); 02805 left = parentStyle->clipLeft(); 02806 } 02807 else { 02808 hasClip = false; 02809 top = right = bottom = left = Length(); 02810 } 02811 } else if (isInitial) { 02812 hasClip = false; 02813 top = right = bottom = left = Length(); 02814 } else if ( !primitiveValue ) { 02815 break; 02816 } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT ) { 02817 RectImpl *rect = primitiveValue->getRectValue(); 02818 if ( !rect ) 02819 break; 02820 top = convertToLength( rect->top(), style, paintDeviceMetrics ); 02821 right = convertToLength( rect->right(), style, paintDeviceMetrics ); 02822 bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics ); 02823 left = convertToLength( rect->left(), style, paintDeviceMetrics ); 02824 02825 } else if ( primitiveValue->getIdent() != CSS_VAL_AUTO ) { 02826 break; 02827 } 02828 // qDebug("setting clip top to %d", top.value ); 02829 // qDebug("setting clip right to %d", right.value ); 02830 // qDebug("setting clip bottom to %d", bottom.value ); 02831 // qDebug("setting clip left to %d", left.value ); 02832 style->setClip(top, right, bottom, left ); 02833 style->setHasClip(hasClip); 02834 // rect, ident 02835 break; 02836 } 02837 02838 // lists 02839 case CSS_PROP_CONTENT: 02840 // list of string, uri, counter, attr, i 02841 { 02842 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This 02843 // note is a reminder that eventually "inherit" needs to be supported. 02844 if (!(style->styleType()==RenderStyle::BEFORE || 02845 style->styleType()==RenderStyle::AFTER)) 02846 break; 02847 02848 if (isInitial) { 02849 if (style->contentData()) 02850 style->contentData()->clearContent(); 02851 return; 02852 } 02853 02854 if(!value->isValueList()) return; 02855 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value); 02856 int len = list->length(); 02857 02858 for(int i = 0; i < len; i++) { 02859 CSSValueImpl *item = list->item(i); 02860 if(!item->isPrimitiveValue()) continue; 02861 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item); 02862 if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING) 02863 { 02864 style->setContent(val->getStringValue(), i != 0); 02865 } 02866 else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) 02867 { 02868 #ifdef APPLE_CHANGES 02869 int attrID = element->getDocument()->attrId(0, val->getStringValue(), false); 02870 if (attrID) 02871 style->setContent(element->getAttribute(attrID).implementation(), i != 0); 02872 #else 02873 int attrID = element->getDocument()->getId(NodeImpl::AttributeId, val->getStringValue(), false, true); 02874 if (attrID) 02875 style->setContent(element->getAttribute(attrID).implementation(), i != 0); 02876 #endif 02877 } 02878 else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) 02879 { 02880 CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val); 02881 style->setContent(image->image(), i != 0); 02882 } 02883 02884 } 02885 break; 02886 } 02887 02888 case CSS_PROP_COUNTER_INCREMENT: 02889 // list of CSS2CounterIncrement 02890 case CSS_PROP_COUNTER_RESET: 02891 // list of CSS2CounterReset 02892 break; 02893 case CSS_PROP_FONT_FAMILY: 02894 // list of strings and ids 02895 { 02896 if (isInherit) { 02897 FontDef parentFontDef = parentStyle->htmlFont().fontDef; 02898 FontDef fontDef = style->htmlFont().fontDef; 02899 fontDef.family = parentFontDef.family; 02900 if (style->setFontDef(fontDef)) 02901 fontDirty = true; 02902 return; 02903 } 02904 else if (isInitial) { 02905 FontDef fontDef = style->htmlFont().fontDef; 02906 FontDef initialDef = FontDef(); 02907 #ifdef APPLE_CHANGES 02908 fontDef.family = initialDef.firstFamily(); 02909 #else 02910 fontDef.family = QString::null; 02911 #endif 02912 if (style->setFontDef(fontDef)) 02913 fontDirty = true; 02914 return; 02915 } 02916 if(!value->isValueList()) return; 02917 FontDef fontDef = style->htmlFont().fontDef; 02918 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value); 02919 int len = list->length(); 02920 for(int i = 0; i < len; i++) { 02921 CSSValueImpl *item = list->item(i); 02922 if(!item->isPrimitiveValue()) continue; 02923 CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item); 02924 QString face; 02925 if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING ) 02926 face = static_cast<FontFamilyValueImpl *>(val)->fontName(); 02927 else if ( val->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) { 02928 switch( val->getIdent() ) { 02929 case CSS_VAL_SERIF: 02930 face = settings->serifFontName(); 02931 break; 02932 case CSS_VAL_SANS_SERIF: 02933 face = settings->sansSerifFontName(); 02934 break; 02935 case CSS_VAL_CURSIVE: 02936 face = settings->cursiveFontName(); 02937 break; 02938 case CSS_VAL_FANTASY: 02939 face = settings->fantasyFontName(); 02940 break; 02941 case CSS_VAL_MONOSPACE: 02942 face = settings->fixedFontName(); 02943 break; 02944 default: 02945 return; 02946 } 02947 } else { 02948 return; 02949 } 02950 if ( !face.isEmpty() ) { 02951 fontDef.family = face; 02952 fontDirty |= style->setFontDef( fontDef ); 02953 return; 02954 } 02955 } 02956 break; 02957 } 02958 case CSS_PROP_QUOTES: 02959 // list of strings or i 02960 case CSS_PROP_SIZE: 02961 // ### look up 02962 break; 02963 case CSS_PROP_TEXT_DECORATION: { 02964 // list of ident 02965 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration) 02966 int t = RenderStyle::initialTextDecoration(); 02967 if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { 02968 // do nothing 02969 } else { 02970 if(!value->isValueList()) return; 02971 CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value); 02972 int len = list->length(); 02973 for(int i = 0; i < len; i++) 02974 { 02975 CSSValueImpl *item = list->item(i); 02976 if(!item->isPrimitiveValue()) continue; 02977 primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item); 02978 switch(primitiveValue->getIdent()) 02979 { 02980 case CSS_VAL_NONE: 02981 t = TDNONE; break; 02982 case CSS_VAL_UNDERLINE: 02983 t |= UNDERLINE; break; 02984 case CSS_VAL_OVERLINE: 02985 t |= OVERLINE; break; 02986 case CSS_VAL_LINE_THROUGH: 02987 t |= LINE_THROUGH; break; 02988 case CSS_VAL_BLINK: 02989 t |= BLINK; break; 02990 default: 02991 return; 02992 } 02993 } 02994 } 02995 style->setTextDecoration(t); 02996 break; 02997 } 02998 case CSS_PROP__KHTML_FLOW_MODE: 02999 HANDLE_INHERIT_AND_INITIAL(flowAroundFloats, FlowAroundFloats) 03000 if (!primitiveValue) return; 03001 if (primitiveValue->getIdent()) { 03002 style->setFlowAroundFloats( primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS ); 03003 return; 03004 } 03005 break; 03006 case CSS_PROP__KHTML_USER_INPUT: { 03007 if(value->cssValueType() == CSSValue::CSS_INHERIT) 03008 { 03009 if(!parentNode) return; 03010 style->setUserInput(parentStyle->userInput()); 03011 // kdDebug() << "UI erm" << endl; 03012 return; 03013 } 03014 if(!primitiveValue) return; 03015 int id = primitiveValue->getIdent(); 03016 if (id == CSS_VAL_NONE) 03017 style->setUserInput(UI_NONE); 03018 else 03019 style->setUserInput(EUserInput(id - CSS_VAL_ENABLED)); 03020 // kdDebug(6080) << "userInput: " << style->userEdit() << endl; 03021 return; 03022 } 03023 03024 // shorthand properties 03025 case CSS_PROP_BACKGROUND: 03026 if (isInherit) { 03027 style->setBackgroundColor(parentStyle->backgroundColor()); 03028 style->setBackgroundImage(parentStyle->backgroundImage()); 03029 style->setBackgroundRepeat(parentStyle->backgroundRepeat()); 03030 style->setBackgroundAttachment(parentStyle->backgroundAttachment()); 03031 style->setBackgroundXPosition(parentStyle->backgroundXPosition()); 03032 style->setBackgroundYPosition(parentStyle->backgroundYPosition()); 03033 } 03034 else if (isInitial) { 03035 style->setBackgroundColor(QColor()); 03036 style->setBackgroundImage(RenderStyle::initialBackgroundImage()); 03037 style->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat()); 03038 style->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment()); 03039 style->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition()); 03040 style->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition()); 03041 } 03042 break; 03043 case CSS_PROP_BORDER: 03044 case CSS_PROP_BORDER_STYLE: 03045 case CSS_PROP_BORDER_WIDTH: 03046 case CSS_PROP_BORDER_COLOR: 03047 if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR) 03048 { 03049 if (isInherit) { 03050 style->setBorderTopColor(parentStyle->borderTopColor()); 03051 style->setBorderBottomColor(parentStyle->borderBottomColor()); 03052 style->setBorderLeftColor(parentStyle->borderLeftColor()); 03053 style->setBorderRightColor(parentStyle->borderRightColor()); 03054 } 03055 else if (isInitial) { 03056 style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead. 03057 style->setBorderBottomColor(QColor()); 03058 style->setBorderLeftColor(QColor()); 03059 style->setBorderRightColor(QColor()); 03060 } 03061 } 03062 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE) 03063 { 03064 if (isInherit) { 03065 style->setBorderTopStyle(parentStyle->borderTopStyle()); 03066 style->setBorderBottomStyle(parentStyle->borderBottomStyle()); 03067 style->setBorderLeftStyle(parentStyle->borderLeftStyle()); 03068 style->setBorderRightStyle(parentStyle->borderRightStyle()); 03069 } 03070 else if (isInitial) { 03071 style->setBorderTopStyle(RenderStyle::initialBorderStyle()); 03072 style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); 03073 style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); 03074 style->setBorderRightStyle(RenderStyle::initialBorderStyle()); 03075 } 03076 } 03077 if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH) 03078 { 03079 if (isInherit) { 03080 style->setBorderTopWidth(parentStyle->borderTopWidth()); 03081 style->setBorderBottomWidth(parentStyle->borderBottomWidth()); 03082 style->setBorderLeftWidth(parentStyle->borderLeftWidth()); 03083 style->setBorderRightWidth(parentStyle->borderRightWidth()); 03084 } 03085 else if (isInitial) { 03086 style->setBorderTopWidth(RenderStyle::initialBorderWidth()); 03087 style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); 03088 style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); 03089 style->setBorderRightWidth(RenderStyle::initialBorderWidth()); 03090 } 03091 } 03092 return; 03093 case CSS_PROP_BORDER_TOP: 03094 if ( isInherit ) { 03095 style->setBorderTopColor(parentStyle->borderTopColor()); 03096 style->setBorderTopStyle(parentStyle->borderTopStyle()); 03097 style->setBorderTopWidth(parentStyle->borderTopWidth()); 03098 } else if (isInitial) 03099 style->resetBorderTop(); 03100 return; 03101 case CSS_PROP_BORDER_RIGHT: 03102 if (isInherit) { 03103 style->setBorderRightColor(parentStyle->borderRightColor()); 03104 style->setBorderRightStyle(parentStyle->borderRightStyle()); 03105 style->setBorderRightWidth(parentStyle->borderRightWidth()); 03106 } 03107 else if (isInitial) 03108 style->resetBorderRight(); 03109 return; 03110 case CSS_PROP_BORDER_BOTTOM: 03111 if (isInherit) { 03112 style->setBorderBottomColor(parentStyle->borderBottomColor()); 03113 style->setBorderBottomStyle(parentStyle->borderBottomStyle()); 03114 style->setBorderBottomWidth(parentStyle->borderBottomWidth()); 03115 } 03116 else if (isInitial) 03117 style->resetBorderBottom(); 03118 return; 03119 case CSS_PROP_BORDER_LEFT: 03120 if (isInherit) { 03121 style->setBorderLeftColor(parentStyle->borderLeftColor()); 03122 style->setBorderLeftStyle(parentStyle->borderLeftStyle()); 03123 style->setBorderLeftWidth(parentStyle->borderLeftWidth()); 03124 } 03125 else if (isInitial) 03126 style->resetBorderLeft(); 03127 return; 03128 case CSS_PROP_MARGIN: 03129 if (isInherit) { 03130 style->setMarginTop(parentStyle->marginTop()); 03131 style->setMarginBottom(parentStyle->marginBottom()); 03132 style->setMarginLeft(parentStyle->marginLeft()); 03133 style->setMarginRight(parentStyle->marginRight()); 03134 } 03135 else if (isInitial) 03136 style->resetMargin(); 03137 return; 03138 case CSS_PROP_PADDING: 03139 if (isInherit) { 03140 style->setPaddingTop(parentStyle->paddingTop()); 03141 style->setPaddingBottom(parentStyle->paddingBottom()); 03142 style->setPaddingLeft(parentStyle->paddingLeft()); 03143 style->setPaddingRight(parentStyle->paddingRight()); 03144 } 03145 else if (isInitial) 03146 style->resetPadding(); 03147 return; 03148 case CSS_PROP_FONT: 03149 if ( isInherit ) { 03150 FontDef fontDef = parentStyle->htmlFont().fontDef; 03151 style->setLineHeight( parentStyle->lineHeight() ); 03152 fontDirty |= style->setFontDef( fontDef ); 03153 } else if (isInitial) { 03154 FontDef fontDef; 03155 style->setLineHeight(RenderStyle::initialLineHeight()); 03156 if (style->setFontDef( fontDef )) 03157 fontDirty = true; 03158 } else if ( value->isFontValue() ) { 03159 FontValueImpl *font = static_cast<FontValueImpl *>(value); 03160 if ( !font->style || !font->variant || !font->weight || 03161 !font->size || !font->lineHeight || !font->family ) 03162 return; 03163 applyRule( CSS_PROP_FONT_STYLE, font->style ); 03164 applyRule( CSS_PROP_FONT_VARIANT, font->variant ); 03165 applyRule( CSS_PROP_FONT_WEIGHT, font->weight ); 03166 applyRule( CSS_PROP_FONT_SIZE, font->size ); 03167 03168 // Line-height can depend on font().pixelSize(), so we have to update the font 03169 // before we evaluate line-height, e.g., font: 1em/1em. FIXME: Still not 03170 // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px. 03171 if (fontDirty) 03172 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics ); 03173 03174 applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight ); 03175 applyRule( CSS_PROP_FONT_FAMILY, font->family ); 03176 } 03177 return; 03178 03179 case CSS_PROP_LIST_STYLE: 03180 if (isInherit) { 03181 style->setListStyleType(parentStyle->listStyleType()); 03182 style->setListStyleImage(parentStyle->listStyleImage()); 03183 style->setListStylePosition(parentStyle->listStylePosition()); 03184 } 03185 else if (isInitial) { 03186 style->setListStyleType(RenderStyle::initialListStyleType()); 03187 style->setListStyleImage(RenderStyle::initialListStyleImage()); 03188 style->setListStylePosition(RenderStyle::initialListStylePosition()); 03189 } 03190 break; 03191 case CSS_PROP_OUTLINE: 03192 if (isInherit) { 03193 style->setOutlineWidth(parentStyle->outlineWidth()); 03194 style->setOutlineColor(parentStyle->outlineColor()); 03195 style->setOutlineStyle(parentStyle->outlineStyle()); 03196 } 03197 else if (isInitial) 03198 style->resetOutline(); 03199 break; 03200 case CSS_PROP__KHTML_MARQUEE: 03201 if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return; 03202 style->setMarqueeDirection(parentStyle->marqueeDirection()); 03203 style->setMarqueeIncrement(parentStyle->marqueeIncrement()); 03204 style->setMarqueeSpeed(parentStyle->marqueeSpeed()); 03205 style->setMarqueeLoopCount(parentStyle->marqueeLoopCount()); 03206 style->setMarqueeBehavior(parentStyle->marqueeBehavior()); 03207 break; 03208 case CSS_PROP__KHTML_MARQUEE_REPETITION: { 03209 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) 03210 if (!primitiveValue) return; 03211 if (primitiveValue->getIdent() == CSS_VAL_INFINITE) 03212 style->setMarqueeLoopCount(-1); // -1 means repeat forever. 03213 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) 03214 style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))); 03215 break; 03216 } 03217 case CSS_PROP__KHTML_MARQUEE_SPEED: { 03218 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) 03219 if (!primitiveValue) return; 03220 if (primitiveValue->getIdent()) { 03221 switch (primitiveValue->getIdent()) 03222 { 03223 case CSS_VAL_SLOW: 03224 style->setMarqueeSpeed(500); // 500 msec. 03225 break; 03226 case CSS_VAL_NORMAL: 03227 style->setMarqueeSpeed(85); // 85msec. The WinIE default. 03228 break; 03229 case CSS_VAL_FAST: 03230 style->setMarqueeSpeed(10); // 10msec. Super fast. 03231 break; 03232 } 03233 } 03234 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 03235 style->setMarqueeSpeed(int(1000*primitiveValue->floatValue(CSSPrimitiveValue::CSS_S))); 03236 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) 03237 style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS))); 03238 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. 03239 style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))); 03240 break; 03241 } 03242 case CSS_PROP__KHTML_MARQUEE_INCREMENT: { 03243 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement) 03244 if (!primitiveValue) return; 03245 if (primitiveValue->getIdent()) { 03246 switch (primitiveValue->getIdent()) 03247 { 03248 case CSS_VAL_SMALL: 03249 style->setMarqueeIncrement(Length(1, Fixed)); // 1px. 03250 break; 03251 case CSS_VAL_NORMAL: 03252 style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. 03253 break; 03254 case CSS_VAL_LARGE: 03255 style->setMarqueeIncrement(Length(36, Fixed)); // 36px. 03256 break; 03257 } 03258 } 03259 else { 03260 bool ok = true; 03261 Length l = convertToLength(primitiveValue, style, paintDeviceMetrics, &ok); 03262 if (ok) 03263 style->setMarqueeIncrement(l); 03264 } 03265 break; 03266 } 03267 case CSS_PROP__KHTML_MARQUEE_STYLE: { 03268 HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior) 03269 if (!primitiveValue || !primitiveValue->getIdent()) return; 03270 switch (primitiveValue->getIdent()) 03271 { 03272 case CSS_VAL_NONE: 03273 style->setMarqueeBehavior(MNONE); 03274 break; 03275 case CSS_VAL_SCROLL: 03276 style->setMarqueeBehavior(MSCROLL); 03277 break; 03278 case CSS_VAL_SLIDE: 03279 style->setMarqueeBehavior(MSLIDE); 03280 break; 03281 case CSS_VAL_ALTERNATE: 03282 style->setMarqueeBehavior(MALTERNATE); 03283 break; 03284 case CSS_VAL_UNFURL: 03285 style->setMarqueeBehavior(MUNFURL); 03286 break; 03287 } 03288 break; 03289 } 03290 case CSS_PROP__KHTML_MARQUEE_DIRECTION: { 03291 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) 03292 if (!primitiveValue || !primitiveValue->getIdent()) return; 03293 switch (primitiveValue->getIdent()) 03294 { 03295 case CSS_VAL_FORWARDS: 03296 style->setMarqueeDirection(MFORWARD); 03297 break; 03298 case CSS_VAL_BACKWARDS: 03299 style->setMarqueeDirection(MBACKWARD); 03300 break; 03301 case CSS_VAL_AUTO: 03302 style->setMarqueeDirection(MAUTO); 03303 break; 03304 case CSS_VAL_AHEAD: 03305 case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP. 03306 style->setMarqueeDirection(MUP); 03307 break; 03308 case CSS_VAL_REVERSE: 03309 case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text. 03310 style->setMarqueeDirection(MDOWN); 03311 break; 03312 case CSS_VAL_LEFT: 03313 style->setMarqueeDirection(MLEFT); 03314 break; 03315 case CSS_VAL_RIGHT: 03316 style->setMarqueeDirection(MRIGHT); 03317 break; 03318 } 03319 break; 03320 } 03321 default: 03322 return; 03323 } 03324 } 03325 03326 #ifdef APPLE_CHANGES 03327 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle) 03328 { 03329 const FontDef& childFont = aStyle->htmlFont().fontDef; 03330 03331 if (childFont.sizeSpecified || !aParentStyle) 03332 return; 03333 03334 const FontDef& parentFont = aParentStyle->htmlFont().fontDef; 03335 03336 if (childFont.genericFamily == parentFont.genericFamily) 03337 return; 03338 03339 // For now, lump all families but monospace together. 03340 if (childFont.genericFamily != FontDef::eMonospace && 03341 parentFont.genericFamily != FontDef::eMonospace) 03342 return; 03343 03344 // We know the parent is monospace or the child is monospace, and that font 03345 // size was unspecified. We want to alter our font size to use the correct 03346 // "medium" font for our family. 03347 float size = 0; 03348 int minFontSize = settings->minFontSize(); 03349 size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3]; 03350 int isize = (int)size; 03351 if (isize < minFontSize) 03352 isize = minFontSize; 03353 03354 FontDef newFontDef(childFont); 03355 newFontDef.size = isize; 03356 aStyle->setFontDef(newFontDef); 03357 } 03358 #endif 03359 03360 } // namespace khtml
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:33:50 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003