| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# render_box.cpp

    00001
    00024 // -------------------------------------------------------------------------
    00025 //#define DEBUG_LAYOUT
    00026 //#define CLIP_DEBUG
    00027
    00028
    00029 #include <qpainter.h>
    00030
    00031 #include "rendering/render_box.h"
    00032 #include "rendering/render_replaced.h"
    00033 #include "rendering/render_root.h"
    00034 #include "misc/htmlhashes.h"
    00035 #include "xml/dom_nodeimpl.h"
    00036
    00037 #include <khtmlview.h>
    00038 #include <kdebug.h>
    00039 #include <kglobal.h>
    00040 #include <assert.h>
    00041
    00042
    00043 using namespace DOM;
    00044 using namespace khtml;
    00045
    00046 #define TABLECELLMARGIN -0x4000
    00047
    00048 RenderBox::RenderBox(DOM::NodeImpl* node)
    00049     : RenderContainer(node)
    00050 {
    00051     m_minWidth = -1;
    00052     m_maxWidth = -1;
    00053     m_width = m_height = 0;
    00054     m_x = 0;
    00055     m_y = 0;
    00056     m_marginTop = 0;
    00057     m_marginBottom = 0;
    00058     m_marginLeft = 0;
    00059     m_marginRight = 0;
    00060 }
    00061
    00062 void RenderBox::setStyle(RenderStyle *_style)
    00063 {
    00064     bool oldpos = isPositioned();
    00065
    00066     RenderObject::setStyle(_style);
    00067
    00068     switch(_style->position())
    00069     {
    00070     case ABSOLUTE:
    00071     case FIXED:
    00072         setPositioned(true);
    00073         break;
    00074     default:
    00075         if (oldpos)
    00076             {
    00077             setPositioned(true);
    00078             removeFromSpecialObjects();
    00079             }
    00080         setPositioned(false);
    00081         if(!isTableCell() && _style->isFloating()) {
    00082             setFloating(true);
    00083         } else {
    00084             if(_style->position() == RELATIVE)
    00085                 setRelPositioned(true);
    00086         }
    00087     }
    00088 }
    00089
    00090 RenderBox::~RenderBox()
    00091 {
    00092     //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
    00093 }
    00094
    00095 short RenderBox::contentWidth() const
    00096 {
    00097     short w = m_width - style()->borderLeftWidth() - style()->borderRightWidth();
    00098     w -= paddingLeft() + paddingRight();
    00099
    00100     //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl;
    00101     return w;
    00102 }
    00103
    00104 int RenderBox::contentHeight() const
    00105 {
    00106     int h = m_height - style()->borderTopWidth() - style()->borderBottomWidth();
    00107     h -= paddingTop() + paddingBottom();
    00108
    00109     return h;
    00110 }
    00111
    00112 void RenderBox::setPos( int xPos, int yPos )
    00113 {
    00114     m_x = xPos; m_y = yPos;
    00115 }
    00116
    00117 short RenderBox::width() const
    00118 {
    00119     return m_width;
    00120 }
    00121
    00122 int RenderBox::height() const
    00123 {
    00124     return m_height;
    00125 }
    00126
    00127
    00128 // --------------------- painting stuff -------------------------------
    00129
    00130 void RenderBox::paint(QPainter *p, int _x, int _y, int _w, int _h,
    00131                                   int _tx, int _ty)
    00132 {
    00133     _tx += m_x;
    00134     _ty += m_y;
    00135
    00136     // default implementation. Just pass things through to the children
    00137     RenderObject *child = firstChild();
    00138     while(child != 0)
    00139     {
    00140         child->paint(p, _x, _y, _w, _h, _tx, _ty);
    00141         child = child->nextSibling();
    00142     }
    00143 }
    00144
    00145 void RenderBox::setPixmap(const QPixmap &, const QRect&, CachedImage *image)
    00146 {
    00147     if(image && image->pixmap_size() == image->valid_rect().size() && parent())
    00148         repaint();      //repaint bg when it finished loading
    00149 }
    00150
    00151
    00152 void RenderBox::paintBoxDecorations(QPainter *p,int, int _y,
    00153                                        int, int _h, int _tx, int _ty)
    00154 {
    00155     //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
    00156
    00157     int w = width();
    00158     int h = height() + borderTopExtra() + borderBottomExtra();
    00159     _ty -= borderTopExtra();
    00160
    00161     int my = QMAX(_ty,_y);
    00162     int end = QMIN( _y + _h,  _ty + h );
    00163     int mh = end - my;
    00164
    00165     paintBackground(p, style()->backgroundColor(), style()->backgroundImage(), my, mh, _tx, _ty, w, h);
    00166
    00167     if(style()->hasBorder())
    00168         paintBorder(p, _tx, _ty, w, h, style());
    00169 }
    00170
    00171 void RenderBox::paintBackground(QPainter *p, const QColor &c, CachedImage *bg, int clipy, int cliph, int _tx, int _ty, int w, int h)
    00172 {
    00173     if ( cliph < 0 )
    00174         return;
    00175
    00176     if(c.isValid())
    00177         p->fillRect(_tx, clipy, w, cliph, c);
    00178     // no progressive loading of the background image
    00179     if(bg && bg->pixmap_size() == bg->valid_rect().size() && !bg->isTransparent() && !bg->isErrorImage()) {
    00180         //kdDebug( 6040 ) << "painting bgimage at " << _tx << "/" << _ty << endl;
    00181         // ### might need to add some correct offsets
    00182         // ### use paddingX/Y
    00183
    00184         //hacky stuff
    00185         RenderStyle* sptr = style();
    00186         if ( isHtml() && firstChild() && !style()->backgroundImage() )
    00187             sptr = firstChild()->style();
    00188
    00189         int sx = 0;
    00190         int sy = 0;
    00191             int cw,ch;
    00192         int cx,cy;
    00193         int vpab = borderRight() + borderLeft();
    00194         int hpab = borderTop() + borderBottom();
    00195
    00196         // CSS2 chapter 14.2.1
    00197
    00198         int pixw = bg->pixmap_size().width();
    00199         int pixh = bg->pixmap_size().height();
    00200         if (sptr->backgroundAttachment())
    00201         {
    00202             //scroll
    00203             int pw = m_width - vpab;
    00204             int ph = m_height - hpab;
    00205             EBackgroundRepeat bgr = sptr->backgroundRepeat();
    00206             if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && w > pixw ) {
    00207                 cw = pixw;
    00208                 cx = _tx + sptr->backgroundXPosition().minWidth(pw-pixw);
    00209             } else {
    00210                 cw = w-vpab;
    00211                 cx = _tx;
    00212                 sx =  pixw - ((sptr->backgroundXPosition().minWidth(pw-pixw)) % pixw );
    00213             }
    00214
    00215             cx += borderLeft();
    00216
    00217             if( (bgr == NO_REPEAT || bgr == REPEAT_X) && h > pixh ) {
    00218                 ch = pixh;
    00219                 cy = _ty + sptr->backgroundYPosition().minWidth(ph-pixh);
    00220             } else {
    00221                 ch = h-hpab;
    00222                 cy = _ty;
    00223                 sy = pixh - ((sptr->backgroundYPosition().minWidth(ph-pixh)) % pixh );
    00224             }
    00225
    00226             cy += borderTop();
    00227         }
    00228         else
    00229         {
    00230             //fixed
    00231             QRect vr = viewRect();
    00232             int pw = vr.width();
    00233             int ph = vr.height();
    00234
    00235             EBackgroundRepeat bgr = sptr->backgroundRepeat();
    00236             if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && w > pixw ) {
    00237                 cw = pixw;
    00238                 cx = vr.x() + sptr->backgroundXPosition().minWidth(pw-pixw);
    00239             } else {
    00240                 cw = pw;
    00241                 cx = vr.x();
    00242                 sx =  pixw - ((sptr->backgroundXPosition().minWidth(pw-pixw)) % pixw );
    00243             }
    00244
    00245             if( (bgr == NO_REPEAT || bgr == REPEAT_X) && h > pixh ) {
    00246                 ch = pixh;
    00247                 cy = vr.y() + sptr->backgroundYPosition().minWidth(ph-pixh);
    00248             } else {
    00249                 ch = ph;
    00250                 cy = vr.y();
    00251                 sy = pixh - ((sptr->backgroundYPosition().minWidth(ph-pixh)) % pixh );
    00252             }
    00253
    00254             QRect fix(cx,cy,cw,ch);
    00255             QRect ele(_tx+borderLeft(),_ty+borderTop(),w-vpab,h-hpab);
    00256             QRect b = fix.intersect(ele);
    00257             sx+=b.x()-cx;
    00258             sy+=b.y()-cy;
    00259             cx=b.x();cy=b.y();cw=b.width();ch=b.height();
    00260         }
    00261
    00262
    00263         //kdDebug() << "cy="<<cy<< " ch="<<ch << " clipy=" << clipy << " cliph=" << cliph << " sx="<<sx << " sy="<<sy << endl;
    00264         int diff = clipy - cy;
    00265         if ( diff > 0 ) {
    00266             cy += diff;
    00267             sy += diff;
    00268             sy %= pixh;
    00269             ch -= diff;
    00270         }
    00271         ch = QMIN( ch, clipy + cliph - cy );
    00272         //kdDebug() << "clip="<<cx << " cy="<<cy<< " cw="<<cw << " ch="<<ch << " sx="<<sx << " sy="<<sy << endl;
    00273
    00274         if (cw>0 && ch>0)
    00275             p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c), sx, sy);
    00276 //            p->drawTiledPixmap(cx, cy, cw, ch, bg->pixmap(), sx, sy);
    00277
    00278     }
    00279 }
    00280
    00281 void RenderBox::outlineBox(QPainter *p, int _tx, int _ty, const char *color)
    00282 {
    00283     p->setPen(QPen(QColor(color), 1, Qt::DotLine));
    00284     p->setBrush( Qt::NoBrush );
    00285     p->drawRect(_tx, _ty, m_width, m_height);
    00286 }
    00287
    00288
    00289 void RenderBox::calcClip(QPainter* p, int tx, int ty)
    00290 {
    00291     int clipw = m_width;
    00292     int cliph = m_height;
    00293
    00294     bool rtl = (style()->direction() == RTL);
    00295
    00296     int clipleft = 0;
    00297     int clipright = clipw;
    00298     int cliptop = 0;
    00299     int clipbottom = cliph;
    00300
    00301     if ( style()->clipSpecified() && style()->position() == ABSOLUTE ) {
    00302         // the only case we use the clip property according to CSS 2.1
    00303         if (!style()->clipLeft().isVariable()) {
    00304             int c = style()->clipLeft().width(clipw);
    00305             if ( rtl )
    00306                 clipleft = clipw - c;
    00307             else
    00308                 clipleft = c;
    00309         }
    00310         if (!style()->clipRight().isVariable()) {
    00311             int w = style()->clipRight().width(clipw);
    00312             if ( rtl ) {
    00313                 clipright = clipw - w;
    00314             } else {
    00315                 clipright = w;
    00316             }
    00317         }
    00318         if (!style()->clipTop().isVariable())
    00319             cliptop = style()->clipTop().width(cliph);
    00320         if (!style()->clipBottom().isVariable())
    00321             clipbottom = style()->clipBottom().width(cliph);
    00322     }
    00323     int clipx = tx + clipleft;
    00324     int clipy = ty + cliptop;
    00325     clipw = clipright-clipleft;
    00326     cliph = clipbottom-cliptop;
    00327
    00328
    00329     QRect cr(clipx,clipy,clipw,cliph);
    00330     cr = p->xForm(cr);
    00331     QRegion creg(cr);
    00332     QRegion old = p->clipRegion();
    00333     if (!old.isNull())
    00334         creg = old.intersect(creg);
    00335
    00336 #ifdef CLIP_DEBUG
    00337     kdDebug( 6040 ) << renderName() << ":" << this << ": setting clip("<<clipx<<","<<clipy<<","<<clipw<<","<<cliph<<") tx="<<tx<<" ty="<<ty<<endl;
    00338     p->setPen(QPen(Qt::red, 1, Qt::DotLine));
    00339     p->setBrush( Qt::NoBrush );
    00340     p->drawRect(clipx, clipy, clipw, cliph);
    00341 #endif
    00342
    00343     p->save();
    00344     p->setClipRegion(creg);
    00345 }
    00346
    00347 void RenderBox::close()
    00348 {
    00349     setMinMaxKnown(false);
    00350     setLayouted( false );
    00351 }
    00352
    00353 short RenderBox::containingBlockWidth() const
    00354 {
    00355     if ( ( style()->htmlHacks() || isTable() ) && style()->flowAroundFloats() && containingBlock()->isFlow()
    00356             && style()->width().isVariable())
    00357         return static_cast<RenderFlow*>(containingBlock())->lineWidth(m_y);
    00358     else
    00359         return containingBlock()->contentWidth();
    00360 }
    00361
    00362 bool RenderBox::absolutePosition(int &xPos, int &yPos, bool f)
    00363 {
    00364     if ( style()->position() == FIXED )
    00365         f = true;
    00366     RenderObject *o = container();
    00367     if( o && o->absolutePosition(xPos, yPos, f))
    00368     {
    00369         if(!isInline() || isReplaced())
    00370             xPos += m_x, yPos += m_y;
    00371
    00372         if(isRelPositioned())
    00373             relativePositionOffset(xPos, yPos);
    00374         return true;
    00375     }
    00376     else
    00377     {
    00378         xPos = yPos = 0;
    00379         return false;
    00380     }
    00381 }
    00382
    00383 void RenderBox::position(int x, int y, int, int, int, bool, bool, int)
    00384 {
    00385     m_x = x + marginLeft();
    00386     m_y = y;
    00387     // ### paddings
    00388     //m_width = width;
    00389 }
    00390
    00391 void RenderBox::repaint()
    00392 {
    00393     //kdDebug( 6040 ) << "repaint!" << endl;
    00394     int ow = style() ? style()->outlineWidth() : 0;
    00395     repaintRectangle(-ow, -ow, m_width+ow*2, m_height+ow*2);
    00396 }
    00397
    00398 void RenderBox::repaintRectangle(int x, int y, int w, int h, bool f)
    00399 {
    00400     x += m_x;
    00401     y += m_y;
    00402
    00403     if (style()->position()==FIXED) f=true;
    00404
    00405     // kdDebug( 6040 ) << "RenderBox(" << renderName() << ")::repaintRectangle (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl;
    00406     RenderObject *o = container();
    00407     if( o ) o->repaintRectangle(x, y, w, h, f);
    00408 }
    00409
    00410 void RenderBox::relativePositionOffset(int &tx, int &ty)
    00411 {
    00412     if(!style()->left().isVariable())
    00413         tx += style()->left().width(containingBlockWidth());
    00414     else if(!style()->right().isVariable())
    00415         tx -= style()->right().width(containingBlockWidth());
    00416     if(!style()->top().isVariable())
    00417     {
    00418         if (!style()->top().isPercent()
    00419                 || containingBlock()->style()->height().isFixed())
    00420             ty += style()->top().width(containingBlockHeight());
    00421     }
    00422     else if(!style()->bottom().isVariable())
    00423     {
    00424         if (!style()->bottom().isPercent()
    00425                 || containingBlock()->style()->height().isFixed())
    00426             ty -= style()->bottom().width(containingBlockHeight());
    00427     }
    00428 }
    00429
    00430 void RenderBox::calcWidth()
    00431 {
    00432 #ifdef DEBUG_LAYOUT
    00433     kdDebug( 6040 ) << "RenderBox("<<renderName()<<")::calcWidth()" << endl;
    00434 #endif
    00435     if (isPositioned())
    00436     {
    00437         calcAbsoluteHorizontal();
    00438     }
    00439     else
    00440     {
    00441         Length w;
    00442         if ( isReplaced () )
    00443             w = Length( calcReplacedWidth(), Fixed );
    00444         else
    00445             w = style()->width();
    00446
    00447         Length ml = style()->marginLeft();
    00448         Length mr = style()->marginRight();
    00449
    00450         int cw;
    00451         RenderObject *cb = containingBlock();
    00452         if ( style()->flowAroundFloats() && cb->isFlow() )
    00453             cw = static_cast<RenderFlow *>(cb)->lineWidth( m_y );
    00454         else
    00455             cw = cb->contentWidth();
    00456
    00457         if (cw<0) cw = 0;
    00458
    00459         m_marginLeft = 0;
    00460         m_marginRight = 0;
    00461
    00462         if (isInline())
    00463         {
    00464             // just calculate margins
    00465             m_marginLeft = ml.minWidth(cw);
    00466             m_marginRight = mr.minWidth(cw);
    00467             if (isReplaced())
    00468             {
    00469                 m_width = w.width(cw);
    00470                 m_width += paddingLeft() + paddingRight() + style()->borderLeftWidth() + style()->borderRightWidth();
    00471
    00472                 if(m_width < m_minWidth) m_width = m_minWidth;
    00473             }
    00474
    00475             return;
    00476         }
    00477         else if (w.isVariable())
    00478         {
    00479 //          kdDebug( 6040 ) << "variable" << endl;
    00480             m_marginLeft = ml.minWidth(cw);
    00481             m_marginRight = mr.minWidth(cw);
    00482             if (cw) m_width = cw - m_marginLeft - m_marginRight;
    00483
    00484 //          kdDebug( 6040 ) <<  m_width <<"," << cw <<"," <<
    00485 //              m_marginLeft <<"," <<  m_marginRight << endl;
    00486
    00487             if (isFloating()) {
    00488                 if(m_width < m_minWidth) m_width = m_minWidth;
    00489                 if(m_width > m_maxWidth) m_width = m_maxWidth;
    00490             }
    00491         }
    00492         else
    00493         {
    00494 //          kdDebug( 6040 ) << "non-variable " << w.type << ","<< w.value << endl;
    00495             m_width = w.width(cw);
    00496             m_width += paddingLeft() + paddingRight() + style()->borderLeftWidth() + style()->borderRightWidth();
    00497
    00498             calcHorizontalMargins(ml,mr,cw);
    00499         }
    00500
    00501         if (cw && cw != m_width + m_marginLeft + m_marginRight && !isFloating() && !isInline())
    00502         {
    00503             if (style()->direction()==LTR)
    00504                 m_marginRight = cw - m_width - m_marginLeft;
    00505             else
    00506                 m_marginLeft = cw - m_width - m_marginRight;
    00507         }
    00508     }
    00509
    00510 #ifdef DEBUG_LAYOUT
    00511     kdDebug( 6040 ) << "RenderBox::calcWidth(): m_width=" << m_width << " containingBlockWidth()=" << containingBlockWidth() << endl;
    00512     kdDebug( 6040 ) << "m_marginLeft=" << m_marginLeft << " m_marginRight=" << m_marginRight << endl;
    00513 #endif
    00514 }
    00515
    00516 void RenderBox::calcHorizontalMargins(const Length& ml, const Length& mr, int cw)
    00517 {
    00518     if (isFloating())
    00519     {
    00520         m_marginLeft = ml.minWidth(cw);
    00521         m_marginRight = mr.minWidth(cw);
    00522     }
    00523     else
    00524     {
    00525         if ( (ml.isVariable() && mr.isVariable()) ||
    00526              (!ml.isVariable() && containingBlock()->style()->textAlign() == KONQ_CENTER ) )
    00527         {
    00528             m_marginLeft = (cw - m_width)/2;
    00529             if (m_marginLeft<0) m_marginLeft=0;
    00530             m_marginRight = cw - m_width - m_marginLeft;
    00531         }
    00532         else if (mr.isVariable())
    00533         {
    00534             m_marginLeft = ml.width(cw);
    00535             m_marginRight = cw - m_width - m_marginLeft;
    00536         }
    00537         else if (ml.isVariable())
    00538         {
    00539             m_marginRight = mr.width(cw);
    00540             m_marginLeft = cw - m_width - m_marginRight;
    00541         }
    00542         else
    00543         {
    00544             m_marginLeft = ml.minWidth(cw);
    00545             m_marginRight = mr.minWidth(cw);
    00546         }
    00547     }
    00548 }
    00549
    00550 void RenderBox::calcHeight()
    00551 {
    00552
    00553 #ifdef DEBUG_LAYOUT
    00554     kdDebug( 6040 ) << "RenderBox::calcHeight()" << endl;
    00555 #endif
    00556
    00557     //cell height is managed by table, inline elements do not have a height property.
    00558     if ( isTableCell() || (isInline() && !isReplaced()) )
    00559         return;
    00560
    00561     if (isPositioned())
    00562         calcAbsoluteVertical();
    00563     else
    00564     {
    00565         Length h;
    00566         if ( isReplaced() && !isFlow() )
    00567             h = Length( calcReplacedHeight(), Fixed );
    00568         else
    00569             h = style()->height();
    00570
    00571         calcVerticalMargins();
    00572
    00573         // for tables, calculate margins only
    00574         if (isTable())
    00575             return;
    00576
    00577         if (!h.isVariable())
    00578         {
    00579             int fh=-1;
    00580             if (h.isFixed())
    00581                 fh = h.value() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
    00582             else if (h.isPercent()) {
    00583                 Length ch = containingBlock()->style()->height();
    00584                 if (ch.isFixed())
    00585                     fh = h.width(ch.value()) + borderTop() + paddingTop() + borderBottom() + paddingBottom();
    00586             }
    00587             if (fh!=-1)
    00588             {
    00589                 if (fh<m_height && !overhangingContents() && style()->overflow()==OVISIBLE)
    00590                     setOverhangingContents();
    00591
    00592                 m_height = fh;
    00593             }
    00594         }
    00595     }
    00596 }
    00597
    00598 short RenderBox::calcReplacedWidth() const
    00599 {
    00600     Length w = style()->width();
    00601
    00602     switch( w.type() ) {
    00603     case Fixed:
    00604         return w.value();
    00605     case Percent:
    00606     {
    00607         const int cw = containingBlockWidth();
    00608         if (cw > 0)
    00609             return w.minWidth(cw);
    00610     }
    00611     // fall through
    00612     default:
    00613         return intrinsicWidth();
    00614     }
    00615 }
    00616
    00617 int RenderBox::calcReplacedHeight() const
    00618 {
    00619     const Length& h = style()->height();
    00620     switch( h.type() ) {
    00621     case Percent:
    00622         return availableHeight();
    00623     case Fixed:
    00624         return h.value();
    00625     default:
    00626         return intrinsicHeight();
    00627     };
    00628 }
    00629
    00630 int RenderBox::availableHeight() const
    00631 {
    00632     Length h = style()->height();
    00633
    00634     if (h.isFixed())
    00635         return h.value();
    00636
    00637     if (isRoot())
    00638         return static_cast<const RenderRoot*>(this)->viewportHeight();
    00639
    00640     if (h.isPercent())
    00641         return h.width(containingBlock()->availableHeight());
    00642
    00643     return containingBlock()->availableHeight();
    00644 }
    00645
    00646 void RenderBox::calcVerticalMargins()
    00647 {
    00648     if( isTableCell() ) {
    00649         // table margins are basically infinite
    00650         m_marginTop = TABLECELLMARGIN;
    00651         m_marginBottom = TABLECELLMARGIN;
    00652         return;
    00653     }
    00654
    00655     Length tm = style()->marginTop();
    00656     Length bm = style()->marginBottom();
    00657
    00658     // margins are calculated with respect to the _width_ of
    00659     // the containing block (8.3)
    00660     int cw = containingBlock()->contentWidth();
    00661
    00662     m_marginTop = tm.minWidth(cw);
    00663     m_marginBottom = bm.minWidth(cw);
    00664 }
    00665
    00666 void RenderBox::calcAbsoluteHorizontal()
    00667 {
    00668     const int AUTO = -666666;
    00669     int l,r,w,ml,mr,cw;
    00670
    00671     RenderObject* cb = containingBlock();
    00672     int pab = borderLeft()+ borderRight()+ paddingLeft()+ paddingRight();
    00673
    00674     l=r=ml=mr=w=AUTO;
    00675     cw = containingBlock()->width();
    00676
    00677     if(!style()->left().isVariable())
    00678         l = style()->left().width(cw) + cb->borderLeft();
    00679     if(!style()->right().isVariable())
    00680         r = style()->right().width(cw) + cb->borderRight();
    00681     if(!style()->width().isVariable())
    00682         w = style()->width().width(cw);
    00683     else if (isReplaced())
    00684         w = intrinsicWidth();
    00685     if(!style()->marginLeft().isVariable())
    00686         ml = style()->marginLeft().width(cw);
    00687     if(!style()->marginRight().isVariable())
    00688         mr = style()->marginRight().width(cw);
    00689
    00690
    00691     //qDebug("h1: w=%d, l=%d, r=%d, ml=%d, mr=%d",w,l,r,ml,mr);
    00692
    00693     int static_distance=0;
    00694     if ((style()->direction()==LTR && (l==AUTO && r==AUTO ))
    00695             || style()->left().isStatic())
    00696     {
    00697         // calc hypothetical location in the normal flow
    00698         // used for 1) left=static-position
    00699         //          2) left, right, width are all auto -> calc top -> 3.
    00700         //          3) precalc for case 2 below
    00701
    00702         // all positioned elements are blocks, so that
    00703         // would be at the left edge
    00704         for (RenderObject* po = parent(); po && po != cb; po = po->parent())
    00705             static_distance += po->xPos();
    00706
    00707         static_distance += parent()->paddingLeft() + parent()->borderLeft();
    00708
    00709         if (l==AUTO || style()->left().isStatic())
    00710             l = static_distance;
    00711     }
    00712
    00713     else if ((style()->direction()==RTL && (l==AUTO && r==AUTO ))
    00714             || style()->right().isStatic())
    00715     {
    00716         static_distance = cw - parent()->width();
    00717
    00718         for (RenderObject* po = parent(); po && po != cb; po = po->parent())
    00719             static_distance -= po->xPos();
    00720
    00721         static_distance -= parent()->paddingRight() + parent()->borderRight();
    00722         if (r==AUTO || style()->right().isStatic())
    00723             r = static_distance;
    00724     }
    00725
    00726
    00727     if (l!=AUTO && w!=AUTO && r!=AUTO)
    00728     {
    00729         // left, width, right all given, play with margins
    00730         int ot = l + w + r + pab;
    00731
    00732         if (ml==AUTO && mr==AUTO)
    00733         {
    00734             // both margins auto, solve for equality
    00735             ml = (cw - ot)/2;
    00736             mr = cw - ot - ml;
    00737         }
    00738         else if (ml==AUTO)
    00739             // solve for left margin
    00740             ml = cw - ot - mr;
    00741         else if (mr==AUTO)
    00742             // solve for right margin
    00743             mr = cw - ot - ml;
    00744         else
    00745         {
    00746             // overconstrained, solve according to dir
    00747             if (style()->direction()==LTR)
    00748                 r = cw - ( l + w + ml + mr + pab);
    00749             else
    00750                 l = cw - ( r + w + ml + mr + pab);
    00751         }
    00752     }
    00753     else
    00754     {
    00755         // one or two of (left, width, right) missing, solve
    00756
    00757         // auto margins are ignored
    00758         if (ml==AUTO) ml = 0;
    00759         if (mr==AUTO) mr = 0;
    00760
    00761         //1. solve left & width.
    00762         if (l==AUTO && w==AUTO && r!=AUTO) {
    00763             w = kMin( int ( m_maxWidth ), kMax(cw - ( r + ml + mr + pab), int ( m_minWidth ) ));
    00764             l = cw - ( r + w + ml + mr + pab);
    00765         }
    00766         else
    00767         //2. solve left & right. use static positioning.
    00768         if (l==AUTO && w!=AUTO && r==AUTO) {
    00769             if (style()->direction()==RTL) {
    00770                 r = static_distance;
    00771                 l = cw - ( r + w + ml + mr + pab);
    00772             }
    00773             else {
    00774                 l = static_distance;
    00775                 r = cw - ( l + w + ml + mr + pab);
    00776             }
    00777         }
    00778         else
    00779         //3. solve width & right.
    00780         if (l!=AUTO && w==AUTO && r==AUTO) {
    00781             w = kMin(int ( m_maxWidth ), kMax( int ( m_minWidth ), cw - ( l + ml + mr + pab)));
    00782             r = cw - ( l + w + ml + mr + pab);
    00783         }
    00784         else
    00785
    00786         //4. solve left
    00787         if (l==AUTO && w!=AUTO && r!=AUTO)
    00788             l = cw - ( r + w + ml + mr + pab);
    00789         else
    00790
    00791         //5. solve width
    00792         if (l!=AUTO && w==AUTO && r!=AUTO)
    00793             w = cw - ( r + l + ml + mr + pab);
    00794         else
    00795
    00796         //6. solve right
    00797         if (l!=AUTO && w!=AUTO && r==AUTO)
    00798             r = cw - ( l + w + ml + mr + pab);
    00799     }
    00800
    00801     m_width = w + pab;
    00802     m_marginLeft = ml;
    00803     m_marginRight = mr;
    00804     m_x = l + ml;
    00805
    00806     //qDebug("h: w=%d, l=%d, r=%d, ml=%d, mr=%d",w,l,r,ml,mr);
    00807 }
    00808
    00809
    00810 void RenderBox::calcAbsoluteVertical()
    00811 {
    00812     // css2 spec 10.6.4 & 10.6.5
    00813
    00814     // based on
    00815     // http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata
    00816     // (actually updated 2000-10-24)
    00817     // that introduces static-position value for top, left & right
    00818
    00819     const int AUTO = -666666;
    00820     int t,b,h,mt,mb,ch;
    00821
    00822     t=b=h=mt=mb=AUTO;
    00823
    00824     int pab = borderTop()+borderBottom()+paddingTop()+paddingBottom();
    00825     RenderObject* cb = containingBlock();
    00826
    00827     Length hl = cb->style()->height();
    00828     if (hl.isFixed())
    00829         ch = hl.value() + cb->paddingTop() + cb->paddingBottom()
    00830              + cb->borderTop() + cb->borderBottom();
    00831     else if (cb->isHtml())
    00832         ch = cb->availableHeight();
    00833     else
    00834         ch = cb->height();
    00835
    00836     if(!style()->top().isVariable())
    00837         t = style()->top().width(ch) + cb->borderTop();
    00838     if(!style()->bottom().isVariable())
    00839         b = style()->bottom().width(ch) + cb->borderBottom();
    00840     if(!style()->height().isVariable())
    00841     {
    00842         h = style()->height().width(ch);
    00843         if (m_height-pab>h)
    00844             h=m_height-pab;
    00845     }
    00846     else if (isReplaced())
    00847         h = intrinsicHeight();
    00848
    00849     if(!style()->marginTop().isVariable())
    00850         mt = style()->marginTop().width(ch);
    00851     if(!style()->marginBottom().isVariable())
    00852         mb = style()->marginBottom().width(ch);
    00853
    00854     int static_top=0;
    00855     if ((t==AUTO && b==AUTO ) || style()->top().isStatic())
    00856     {
    00857         // calc hypothetical location in the normal flow
    00858         // used for 1) top=static-position
    00859         //          2) top, bottom, height are all auto -> calc top -> 3.
    00860         //          3) precalc for case 2 below
    00861
    00862         RenderObject* ro = previousSibling();
    00863         while ( ro && ro->isPositioned())
    00864             ro = ro->previousSibling();
    00865
    00866         if (ro)
    00867             static_top = ro->yPos()+ro->marginBottom()+ro->height();
    00868         else {
    00869             // we're only dealing with blocklevel positioned elements
    00870             // currently, so this is easy
    00871             for (RenderObject* po = parent(); po && po != cb; po = po->parent())
    00872                 static_top += po->yPos();
    00873
    00874             static_top += parent()->paddingTop() + parent()->borderTop();
    00875         }
    00876
    00877         if (h==AUTO || style()->top().isStatic())
    00878             t = static_top;
    00879     }
    00880
    00881     if (t!=AUTO && h!=AUTO && b!=AUTO)
    00882     {
    00883         // top, height, bottom all given, play with margins
    00884         int ot = h + t + b + pab;
    00885
    00886         if (mt==AUTO && mb==AUTO)
    00887         {
    00888             // both margins auto, solve for equality
    00889             mt = (ch - ot)/2;
    00890             mb = ch - ot - mt;
    00891         }
    00892         else if (mt==AUTO)
    00893             // solve for top margin
    00894             mt = ch - ot - mb;
    00895         else if (mb==AUTO)
    00896             // solve for bottom margin
    00897             mb = ch - ot - mt;
    00898         else
    00899             // overconstrained, solve for bottom
    00900             b = ch - ( h+t+mt+mb+pab);
    00901     }
    00902     else
    00903     {
    00904         // one or two of (top, height, bottom) missing, solve
    00905
    00906         // auto margins are ignored
    00907         if (mt==AUTO) mt = 0;
    00908         if (mb==AUTO) mb = 0;
    00909
    00910         //1. solve top & height. use content height.
    00911         if (t==AUTO && h==AUTO && b!=AUTO)
    00912         {
    00913             h = m_height-pab;
    00914             t = ch - ( h+b+mt+mb+pab);
    00915         }
    00916         else
    00917
    00918         //2. solve top & bottom. use static positioning.
    00919         if (t==AUTO && h!=AUTO && b==AUTO)
    00920         {
    00921             t = static_top;
    00922             b = ch - ( h+t+mt+mb+pab);
    00923         }
    00924         else
    00925
    00926         //3. solve height & bottom. use content height.
    00927         if (t!=AUTO && h==AUTO && b==AUTO)
    00928         {
    00929             h = m_height-pab;
    00930             b = ch - ( h+t+mt+mb+pab);
    00931         }
    00932         else
    00933
    00934         //4. solve top
    00935         if (t==AUTO && h!=AUTO && b!=AUTO)
    00936             t = ch - ( h+b+mt+mb+pab);
    00937         else
    00938
    00939         //5. solve height
    00940         if (t!=AUTO && h==AUTO && b!=AUTO)
    00941             h = ch - ( t+b+mt+mb+pab);
    00942         else
    00943
    00944         //6. solve bottom
    00945         if (t!=AUTO && h!=AUTO && b==AUTO)
    00946             b = ch - ( h+t+mt+mb+pab);
    00947     }
    00948
    00949
    00950     if (m_height<h+pab) //content must still fit
    00951         m_height = h+pab;
    00952
    00953     m_marginTop = mt;
    00954     m_marginBottom = mb;
    00955     m_y = t + mt;
    00956
    00957     //paintf("v: h=%d, t=%d, b=%d, mt=%d, mb=%d, m_y=%d\n",h,t,b,mt,mb,m_y);
    00958
    00959 }
    00960
    00961
    00962 int RenderBox::lowestPosition() const
    00963 {
    00964     return m_height + marginBottom();
    00965 }
    00966
    00967 int RenderBox::rightmostPosition() const
    00968 {
    00969     return m_width;
    00970 }
    00971
    00972 #undef DEBUG_LAYOUT

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:30 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001