khtml Library API Documentation

cssstyleselector.cpp

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