khtml Library API Documentation

render_style.cpp

00001 /*
00002  * This file is part of the DOM implementation for KDE.
00003  *
00004  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA 02111-1307, USA.
00020  *
00021  * $Id: render_style.cpp,v 1.53.2.1 2003/02/04 21:35:54 mueller Exp $
00022  */
00023 
00024 #include "xml/dom_stringimpl.h"
00025 
00026 #include "render_style.h"
00027 
00028 #include "kdebug.h"
00029 
00030 using namespace khtml;
00031 
00032 /* CSS says Fixde for the default padding value, but we treat variable as 0 padding anyways, and like
00033  * this is works fine for table paddings aswell
00034  */
00035 StyleSurroundData::StyleSurroundData()
00036     : margin( Fixed ), padding( Variable )
00037 {
00038 }
00039 
00040 StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
00041     : Shared<StyleSurroundData>(),
00042       offset( o.offset ), margin( o.margin ), padding( o.padding ),
00043       border( o.border )
00044 {
00045 }
00046 
00047 bool StyleSurroundData::operator==(const StyleSurroundData& o) const
00048 {
00049     return offset==o.offset && margin==o.margin &&
00050     padding==o.padding && border==o.border;
00051 }
00052 
00053 StyleBoxData::StyleBoxData()
00054     : z_index( ZAUTO )
00055 {
00056 }
00057 
00058 StyleBoxData::StyleBoxData(const StyleBoxData& o )
00059     : Shared<StyleBoxData>(),
00060       width( o.width ), height( o.height ),
00061       min_width( o.min_width ), max_width( o.max_width ),
00062       min_height ( o.min_height ), max_height( o.max_height ),
00063       z_index( o.z_index )
00064 {
00065 }
00066 
00067 bool StyleBoxData::operator==(const StyleBoxData& o) const
00068 {
00069     return
00070         width == o.width &&
00071         height == o.height &&
00072         min_width == o.min_width &&
00073         max_width == o.max_width &&
00074         min_height == o.min_height &&
00075         max_height == o.max_height &&
00076         z_index == o.z_index;
00077 }
00078 
00079 StyleVisualData::StyleVisualData()
00080     : colspan( 1 ), counter_increment( 0 ), counter_reset( 0 ),
00081       palette( QApplication::palette() )
00082 {
00083 }
00084 
00085 StyleVisualData::~StyleVisualData() {
00086 }
00087 
00088 StyleVisualData::StyleVisualData(const StyleVisualData& o )
00089     : Shared<StyleVisualData>(),
00090       clip( o.clip ), colspan( o.colspan ),
00091       counter_increment( o.counter_increment ), counter_reset( o.counter_reset ),
00092       palette( o.palette )
00093 {
00094 }
00095 
00096 
00097 
00098 StyleBackgroundData::StyleBackgroundData()
00099     : image( 0 )
00100 {
00101 }
00102 
00103 StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o )
00104     : Shared<StyleBackgroundData>(),
00105       color( o.color ), image( o.image ),
00106       x_position( o.x_position ), y_position( o.y_position ),
00107       outline( o.outline )
00108 {
00109 }
00110 
00111 bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
00112 {
00113     return
00114     color == o.color &&
00115     image == o.image &&
00116     x_position == o.x_position &&
00117     y_position == o.y_position &&
00118     outline == o.outline;
00119 }
00120 
00121 
00122 
00123 StyleInheritedData::StyleInheritedData()
00124     : indent( Fixed ), line_height( -100, Percent ), style_image( 0 ),
00125       font(), color( Qt::black ), decoration_color( Qt::black ), border_spacing( 0 )
00126 {
00127 }
00128 
00129 StyleInheritedData::~StyleInheritedData()
00130 {
00131 }
00132 
00133 StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
00134     : Shared<StyleInheritedData>(),
00135       indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
00136       font( o.font ), color( o.color ), decoration_color( o.decoration_color ),
00137       border_spacing( o.border_spacing )
00138 {
00139 }
00140 
00141 bool StyleInheritedData::operator==(const StyleInheritedData& o) const
00142 {
00143     return
00144     indent == o.indent &&
00145     line_height == o.line_height &&
00146     border_spacing == o.border_spacing &&
00147     style_image == o.style_image &&
00148     font == o.font &&
00149     color == o.color &&
00150     decoration_color == o.decoration_color;
00151 
00152     // doesn't work because structs are not packed
00153     //return memcmp(this, &o, sizeof(*this))==0;
00154 }
00155 
00156 RenderStyle::RenderStyle()
00157 {
00158 //    counter++;
00159     if (!_default)
00160     _default = new RenderStyle(true);
00161 
00162     box = _default->box;
00163     visual = _default->visual;
00164     background = _default->background;
00165     surround = _default->surround;
00166 
00167     inherited = _default->inherited;
00168 
00169     setBitDefaults();
00170 
00171     pseudoStyle = 0;
00172     content = 0;
00173 }
00174 
00175 RenderStyle::RenderStyle(bool)
00176 {
00177     setBitDefaults();
00178 
00179     box.init();
00180     visual.init();
00181     background.init();
00182     surround.init();
00183 
00184     inherited.init();
00185 
00186     pseudoStyle = 0;
00187     content = 0;
00188 }
00189 
00190 RenderStyle::RenderStyle(const RenderStyle& o)
00191     : Shared<RenderStyle>(),
00192       inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
00193       box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ),
00194       inherited( o.inherited ), pseudoStyle( 0 ), content( o.content )
00195 {
00196 }
00197 
00198 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
00199 {
00200     inherited = inheritParent->inherited;
00201     inherited_flags = inheritParent->inherited_flags;
00202 }
00203 
00204 RenderStyle::~RenderStyle()
00205 {
00206     RenderStyle *ps = pseudoStyle;
00207     RenderStyle *prev = 0;
00208 
00209     while (ps) {
00210         prev = ps;
00211         ps = ps->pseudoStyle;
00212     // to prevent a double deletion.
00213     // this works only because the styles below aren't really shared
00214     // Dirk said we need another construct as soon as these are shared
00215         prev->pseudoStyle = 0;
00216         prev->deref();
00217     }
00218     delete content;
00219 }
00220 
00221 bool RenderStyle::operator==(const RenderStyle& o) const
00222 {
00223 // compare everything except the pseudoStyle pointer
00224     return (inherited_flags == o.inherited_flags &&
00225             noninherited_flags == o.noninherited_flags &&
00226         box == o.box &&
00227             visual == o.visual &&
00228             background == o.background &&
00229             surround == o.surround &&
00230             inherited == o.inherited);
00231 }
00232 
00233 RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid)
00234 {
00235     RenderStyle *ps = 0;
00236     if (noninherited_flags.f._styleType==NOPSEUDO)
00237         for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
00238             if (ps->noninherited_flags.f._styleType==pid)
00239         break;
00240     return ps;
00241 }
00242 
00243 RenderStyle* RenderStyle::addPseudoStyle(PseudoId pid)
00244 {
00245     RenderStyle *ps = getPseudoStyle(pid);
00246 
00247     if (!ps)
00248     {
00249             ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
00250         ps->ref();
00251         ps->noninherited_flags.f._styleType = pid;
00252         ps->pseudoStyle = pseudoStyle;
00253 
00254         pseudoStyle = ps;
00255     }
00256 
00257     return ps;
00258 }
00259 
00260 void RenderStyle::removePseudoStyle(PseudoId pid)
00261 {
00262     RenderStyle *ps = pseudoStyle;
00263     RenderStyle *prev = this;
00264 
00265     while (ps) {
00266         if (ps->noninherited_flags.f._styleType==pid) {
00267             prev->pseudoStyle = ps->pseudoStyle;
00268             ps->deref();
00269             return;
00270         }
00271         prev = ps;
00272         ps = ps->pseudoStyle;
00273     }
00274 }
00275 
00276 
00277 bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
00278 {
00279     return
00280     (
00281         inherited_flags != other->inherited_flags ||
00282         inherited != other->inherited
00283         );
00284 }
00285 
00286 /*
00287   compares two styles. The result gives an idea of the action that
00288   needs to be taken when replacing the old style with a new one.
00289 
00290   CbLayout: The containing block of the object needs a relayout.
00291   Layout: the RenderObject needs a relayout after the style change
00292   Visible: The change is visible, but no relayout is needed
00293   NonVisible: The object does need neither repaint nor relayout after
00294        the change.
00295 
00296   ### TODO:
00297   A lot can be optimised here based on the display type, lots of
00298   optimisations are unimplemented, and currently result in the
00299   worst case result causing a relayout of the containing block.
00300 */
00301 RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
00302 {
00303     Diff d = Equal;
00304 
00305     // we anyway assume they are the same
00306 //  EDisplay _display : 5;
00307 
00308     // NonVisible:
00309 //  ECursor _cursor_style : 4;
00310 
00311 // ### this needs work to know more exactly if we need a relayout
00312 //     or just a repaint
00313 
00314 // non-inherited attributes
00315 //     DataRef<StyleBoxData> box;
00316 //     DataRef<StyleVisualData> visual;
00317 //     DataRef<StyleSurroundData> surround;
00318 
00319 // inherited attributes
00320 //     DataRef<StyleInheritedData> inherited;
00321 
00322     if ( *box.get() != *other->box.get() ||
00323      *visual.get() != *other->visual.get() ||
00324      *surround.get() != *other->surround.get() ||
00325      *inherited.get() != *other->inherited.get()
00326     )
00327     d = CbLayout;
00328 
00329     if ( d == CbLayout )
00330     return d;
00331 
00332     // changes causing Layout changes:
00333 
00334 // only for tables:
00335 //  _border_collapse
00336 //  EEmptyCell _empty_cells : 2 ;
00337 //  ECaptionSide _caption_side : 2;
00338 //     ETableLayout _table_layout : 1;
00339 //     EPosition _position : 2;
00340 //     EFloat _floating : 2;
00341     if ( ((int)noninherited_flags.f._display) >= TABLE ) {
00342     // Stupid gcc gives a compile error on
00343     // a != other->b if a and b are bitflags. Using
00344     // !(a== other->b) instead.
00345     if ( !(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
00346          !(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
00347          !(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
00348          !(noninherited_flags.f._table_layout == other->noninherited_flags.f._table_layout) ||
00349          !(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
00350          !(noninherited_flags.f._floating == other->noninherited_flags.f._floating) )
00351 
00352         d = CbLayout;
00353     }
00354 
00355 // only for lists:
00356 //  EListStyleType _list_style_type : 5 ;
00357 //  EListStylePosition _list_style_position :1;
00358     if (noninherited_flags.f._display == LIST_ITEM ) {
00359     if ( !(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
00360          !(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position) )
00361         d = Layout;
00362     }
00363 
00364     if ( d == Layout )
00365     return d;
00366 
00367 // ### These could be better optimised
00368 //  ETextAlign _text_align : 3;
00369 //  ETextTransform _text_transform : 4;
00370 //  EDirection _direction : 1;
00371 //  EWhiteSpace _white_space : 2;
00372 //  EFontVariant _font_variant : 1;
00373 //     EClear _clear : 2;
00374     if ( !(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
00375      !(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
00376      !(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
00377      !(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
00378      !(inherited_flags.f._font_variant == other->inherited_flags.f._font_variant) ||
00379      !(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
00380     )
00381     d = Layout;
00382 
00383 // only for inline:
00384 //     EVerticalAlign _vertical_align : 4;
00385 
00386     if ( !(noninherited_flags.f._display == INLINE) ) {
00387     if ( !(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align))
00388         d = Layout;
00389     }
00390 
00391     if ( d == Layout )
00392     return d;
00393 
00394 
00395     // Visible:
00396 //  EVisibility _visibility : 2;
00397 //     EOverflow _overflow : 4 ;
00398 //     EBackgroundRepeat _bg_repeat : 2;
00399 //     bool _bg_attachment : 1;
00400 //  int _text_decoration : 4;
00401 //     DataRef<StyleBackgroundData> background;
00402     if ( !(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
00403      !(noninherited_flags.f._overflow == other->noninherited_flags.f._overflow) ||
00404      !(noninherited_flags.f._bg_repeat == other->noninherited_flags.f._bg_repeat) ||
00405      !(noninherited_flags.f._bg_attachment == other->noninherited_flags.f._bg_attachment) ||
00406      !(noninherited_flags.f._clipSpecified == other->noninherited_flags.f._clipSpecified) ||
00407      !(inherited_flags.f._text_decoration == other->inherited_flags.f._text_decoration) ||
00408      *background.get() != *other->background.get()
00409     )
00410     d = Visible;
00411 
00412     // Position:
00413 
00414     return d;
00415 }
00416 
00417 
00418 RenderStyle* RenderStyle::_default = 0;
00419 //int RenderStyle::counter = 0;
00420 //int SharedData::counter = 0;
00421 
00422 void RenderStyle::cleanup()
00423 {
00424     delete _default;
00425     _default = 0;
00426 //    counter = 0;
00427 //    SharedData::counter = 0;
00428 }
00429 
00430 void RenderStyle::setContent(CachedObject* o)
00431 {
00432     if ( !content )
00433     content = new ContentData;
00434     else
00435     content->clearContent();
00436 
00437     content->_content.object = o;
00438     content->_contentType = o ? CONTENT_OBJECT : CONTENT_NONE;
00439 }
00440 
00441 
00442 void RenderStyle::setPaletteColor(QPalette::ColorGroup g, QColorGroup::ColorRole r, const QColor& c)
00443 {
00444     visual.access()->palette.setColor(g,r,c);
00445 }
00446 
00447 void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
00448 {
00449     StyleVisualData *data = visual.access();
00450     data->clip.top = top;
00451     data->clip.right = right;
00452     data->clip.bottom = bottom;
00453     data->clip.left = left;
00454 }
00455 
00456 void RenderStyle::setContent(DOM::DOMStringImpl* s)
00457 {
00458     if ( !content )
00459     content = new ContentData;
00460     else
00461     content->clearContent();
00462 
00463     content->_content.text = s;
00464 
00465     if (s) {
00466         content->_content.text->ref();
00467         content->_contentType = CONTENT_TEXT;
00468     }
00469     else
00470         content->_contentType = CONTENT_NONE;
00471 }
00472 
00473 ContentData::~ContentData()
00474 {
00475     clearContent();
00476 }
00477 
00478 void ContentData::clearContent()
00479 {
00480     switch (_contentType)
00481     {
00482         case CONTENT_OBJECT:
00483 //            _content.object->deref();
00484             _content.object = 0;
00485             break;
00486         case CONTENT_TEXT:
00487             _content.text->deref();
00488             _content.text = 0;
00489         default:
00490             ;
00491     }
00492 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:40 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001