00001
00023
00024
00025
00026
00027
00028
00029 #include <kdebug.h>
00030 #include <assert.h>
00031 #include <qpainter.h>
00032 #include <kglobal.h>
00033 #include <limits.h>
00034
00035 #include "rendering/render_flow.h"
00036 #include "rendering/render_text.h"
00037 #include "rendering/render_table.h"
00038 #include "rendering/render_root.h"
00039 #include "xml/dom_nodeimpl.h"
00040 #include "khtmlview.h"
00041 using namespace DOM;
00042 using namespace khtml;
00043
00044 #define TABLECELLMARGIN -0x4000
00045
00046
00047 static inline int collapseMargins(int a, int b)
00048 {
00049 if ( a == TABLECELLMARGIN || b == TABLECELLMARGIN ) return TABLECELLMARGIN;
00050 if(a >= 0 && b >= 0) return (a > b ? a : b );
00051 if(a > 0 && b < 0) return a + b;
00052 if(a < 0 && b > 0) return b + a;
00053 return ( a > b ? b : a);
00054 }
00055
00056
00057 bool RenderFlow::SpecialObject::operator < ( const RenderFlow::SpecialObject &o ) const
00058 {
00059 int zIndex1 = node->style()->zIndex();
00060 int zIndex2 = o.node->style()->zIndex();
00061
00062 if ( !node->isPositioned() )
00063 zIndex1 = -INT_MAX;
00064 if ( !o.node->isPositioned() )
00065 zIndex2 = -INT_MAX;
00066 if(zIndex1 == zIndex2)
00067 return count < o.count;
00068 return zIndex1 < zIndex2;
00069 }
00070
00071
00072 RenderFlow::RenderFlow(DOM::NodeImpl* node)
00073 : RenderBox(node)
00074 {
00075 m_childrenInline = true;
00076 m_pre = false;
00077 firstLine = false;
00078 m_clearStatus = CNONE;
00079
00080 specialObjects = 0;
00081 }
00082
00083 void RenderFlow::setStyle(RenderStyle *_style)
00084 {
00085
00086
00087
00088 RenderBox::setStyle(_style);
00089
00090 if(isPositioned())
00091 setInline(false);
00092
00093 if(isFloating() || !style()->display() == INLINE)
00094 setInline(false);
00095
00096 if (isInline() && !m_childrenInline)
00097 setInline(false);
00098
00099 m_pre = (style()->whiteSpace() == PRE);
00100
00101
00102 RenderObject*child = firstChild();
00103 RenderStyle* newStyle;
00104 if (!isInline() && child &&
00105 ( newStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER) ) ) {
00106 child->setStyle(newStyle);
00107 child = child->nextSibling();
00108 }
00109
00110 while(child != 0)
00111 {
00112 if(child->isAnonymousBox())
00113 {
00114 RenderStyle* newStyle = new RenderStyle();
00115 newStyle->inheritFrom(style());
00116 newStyle->setDisplay(BLOCK);
00117 child->setStyle(newStyle);
00118 child->setIsAnonymousBox(true);
00119 }
00120 child = child->nextSibling();
00121 }
00122 }
00123
00124 RenderFlow::~RenderFlow()
00125 {
00126 delete specialObjects;
00127 }
00128
00129 FindSelectionResult RenderFlow::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset )
00130 {
00131 int lastOffset=0;
00132 int off = offset;
00133 DOM::NodeImpl* nod = node;
00134 DOM::NodeImpl* lastNode = 0;
00135 for (RenderObject *child = firstChild(); child; child=child->nextSibling()) {
00136 khtml::FindSelectionResult pos = child->checkSelectionPoint(_x, _y, _tx+xPos(), _ty+yPos(), nod, off);
00137
00138 switch(pos) {
00139 case SelectionPointBeforeInLine:
00140 case SelectionPointAfterInLine:
00141 case SelectionPointInside:
00142
00143 node = nod;
00144 offset = off;
00145 return SelectionPointInside;
00146 case SelectionPointBefore:
00147
00148 if ( lastNode ) {
00149 node = lastNode;
00150 offset = lastOffset;
00151
00152
00153 return SelectionPointInside;
00154 } else {
00155 node = nod;
00156 offset = off;
00157
00158 return SelectionPointBefore;
00159 }
00160 break;
00161 case SelectionPointAfter:
00162
00163 lastNode = nod;
00164 lastOffset = off;
00165
00166 break;
00167 }
00168 }
00169
00170
00171 if ( lastNode )
00172 {
00173 node = lastNode;
00174 offset = lastOffset;
00175 }
00176
00177 return SelectionPointAfter;
00178 }
00179
00180 void RenderFlow::paint(QPainter *p, int _x, int _y, int _w, int _h,
00181 int _tx, int _ty)
00182 {
00183
00184 #ifdef DEBUG_LAYOUT
00185
00186 #endif
00187
00188 if(!isInline())
00189 {
00190 _tx += m_x;
00191 _ty += m_y;
00192 }
00193
00194
00195 if(!isInline() && !overhangingContents() && !isRelPositioned() && !isPositioned() )
00196 {
00197 int h = m_height;
00198 if(specialObjects && floatBottom() > h) h = floatBottom();
00199 if((_ty > _y + _h) || (_ty + h < _y))
00200 {
00201
00202 return;
00203 }
00204 }
00205
00206 paintObject(p, _x, _y, _w, _h, _tx, _ty);
00207 }
00208
00209 void RenderFlow::paintObject(QPainter *p, int _x, int _y,
00210 int _w, int _h, int _tx, int _ty)
00211 {
00212 if(isRelPositioned())
00213 relativePositionOffset(_tx, _ty);
00214
00215 bool clipped = false;
00216
00217 if (style()->overflow()==OHIDDEN || (style()->position() == ABSOLUTE && style()->clipSpecified()) ) {
00218 calcClip(p, _tx, _ty);
00219 clipped = true;
00220 }
00221
00222
00223 if(hasSpecialObjects() && !isInline() && style()->visibility() == VISIBLE )
00224 paintBoxDecorations(p, _x, _y, _w, _h, _tx, _ty);
00225
00226
00227 for ( RenderObject* child = firstChild(); child; child = child->nextSibling() )
00228 if(!child->isSpecial())
00229 child->paint(p, _x, _y, _w, _h, _tx, _ty);
00230
00231
00232 if(specialObjects)
00233 paintSpecialObjects( p, _x, _y, _w, _h, _tx , _ty);
00234
00235
00236
00237 if ( clipped ) {
00238 p->restore();
00239 }
00240
00241 if(!isInline() && !childrenInline() && style()->outlineWidth())
00242 paintOutline(p, _tx, _ty, width(), height(), style());
00243
00244 #ifdef BOX_DEBUG
00245 if ( style() && style()->visibility() == VISIBLE ) {
00246 if(isAnonymousBox())
00247 outlineBox(p, _tx, _ty, "green");
00248 if(isFloating())
00249 outlineBox(p, _tx, _ty, "yellow");
00250 else
00251 outlineBox(p, _tx, _ty);
00252 }
00253 #endif
00254
00255 }
00256
00257 void RenderFlow::paintSpecialObjects( QPainter *p, int x, int y, int w, int h, int tx, int ty)
00258 {
00259 SpecialObject* r;
00260 QPtrListIterator<SpecialObject> it(*specialObjects);
00261 for ( ; (r = it.current()); ++it ) {
00262
00263
00264 if (r->node->isPositioned() && r->node->containingBlock() == this) {
00265 r->node->paint(p, x, y, w, h, tx , ty);
00266 } else if ( ( r->node->isFloating() && !r->noPaint ) ) {
00267 r->node->paint(p, x, y, w, h, tx + r->left - r->node->xPos() + r->node->marginLeft(),
00268 ty + r->startY - r->node->yPos() + r->node->marginTop() );
00269 }
00270 #ifdef FLOAT_DEBUG
00271 p->save();
00272 if ( r->node->isPositioned() )
00273 p->setPen( QPen( Qt::red, 4) );
00274 else
00275 p->setPen( QPen( Qt::magenta, 4) );
00276 p->setBrush( QPainter::NoBrush );
00277 qDebug("(%p): special object at (%d/%d-%d/%d)", this, r->left, r->startY, r->width, r->endY - r->startY );
00278 p->drawRect( QRect( r->left+tx, r->startY+ty, r->width, r->endY - r->startY) );
00279 p->restore();
00280 #endif
00281 }
00282 }
00283
00284
00285 void RenderFlow::layout()
00286 {
00287
00288
00289
00290
00291 KHTMLAssert( !layouted() );
00292 KHTMLAssert( minMaxKnown() );
00293 KHTMLAssert(!isInline());
00294
00295 int oldWidth = m_width;
00296
00297 calcWidth();
00298
00299 bool relayoutChildren = false;
00300 if ( oldWidth != m_width )
00301 relayoutChildren = true;
00302
00303
00304 if ( isTableCell() )
00305 relayoutChildren = true;
00306
00307
00308
00309
00310
00311 #ifdef DEBUG_LAYOUT
00312 kdDebug( 6040 ) << renderName() << "(RenderFlow) " << this << " ::layout() width=" << m_width << ", layouted=" << layouted() << endl;
00313 if(containingBlock() == static_cast<RenderObject *>(this))
00314 kdDebug( 6040 ) << renderName() << ": containingBlock == this" << endl;
00315 #endif
00316
00317 if(m_width<=0 && !isPositioned() && !overhangingContents()) {
00318 if(m_y < 0) m_y = 0;
00319 setLayouted();
00320 return;
00321 }
00322
00323 clearFloats();
00324
00325 m_height = 0;
00326 m_clearStatus = CNONE;
00327
00328
00329 if(childrenInline())
00330 layoutInlineChildren( relayoutChildren );
00331 else
00332 layoutBlockChildren( relayoutChildren );
00333
00334 int oldHeight = m_height;
00335 calcHeight();
00336 if ( oldHeight != m_height )
00337 relayoutChildren = true;
00338
00339 if ( isTableCell() && lastChild() && lastChild()->hasOverhangingFloats() ) {
00340 m_height = lastChild()->yPos() + static_cast<RenderFlow*>(lastChild())->floatBottom();
00341 m_height += borderBottom() + paddingBottom();
00342 }
00343 if( hasOverhangingFloats() && (isFloating() || isTableCell()) ) {
00344 m_height = floatBottom();
00345 m_height += borderBottom() + paddingBottom();
00346 }
00347
00348 layoutSpecialObjects( relayoutChildren );
00349
00350
00351
00352 setLayouted();
00353 }
00354
00355 void RenderFlow::layoutSpecialObjects( bool relayoutChildren )
00356 {
00357 if(specialObjects) {
00358
00359 SpecialObject* r;
00360 QPtrListIterator<SpecialObject> it(*specialObjects);
00361 for ( ; (r = it.current()); ++it ) {
00362
00363 if (r->type == SpecialObject::Positioned) {
00364 if ( relayoutChildren ) {
00365 r->node->setLayoutedLocal( false );
00366 }
00367 if ( !r->node->layouted() )
00368 r->node->layout();
00369 }
00370 }
00371 specialObjects->sort();
00372 }
00373 }
00374
00375 void RenderFlow::layoutBlockChildren( bool relayoutChildren )
00376 {
00377 #ifdef DEBUG_LAYOUT
00378 kdDebug( 6040 ) << renderName() << " layoutBlockChildren( " << this <<" ), relayoutChildren="<< relayoutChildren << endl;
00379 #endif
00380
00381 int xPos = 0;
00382 int toAdd = 0;
00383
00384 m_height = 0;
00385
00386 xPos += borderLeft() + paddingLeft();
00387 m_height += borderTop() + paddingTop();
00388 toAdd += borderBottom() + paddingBottom();
00389
00390 if( style()->direction() == RTL ) {
00391 xPos = marginLeft() + m_width - paddingRight() - borderRight();
00392 }
00393
00394 RenderObject *child = firstChild();
00395 RenderFlow *prevFlow = 0;
00396
00397 int prevMargin = 0;
00398 if(isTableCell() ) {
00399 prevMargin = TABLECELLMARGIN;
00400 } else if ( m_height == 0 ) {
00401
00402 prevMargin = marginTop();
00403 if ( parent() )
00404 prevMargin = collapseMargins( prevMargin, parent()->marginTop() );
00405 if ( prevMargin != TABLECELLMARGIN )
00406 m_height = -prevMargin;
00407 }
00408
00409
00410
00411
00412
00413 while( child != 0 )
00414 {
00415
00416
00417
00418 if ( relayoutChildren || floatBottom() > m_height ||
00419 ( ( child->isReplaced() || child->isFloating() ) &&
00420 ( child->style()->width().isPercent() || child->style()->height().isPercent() ) )
00421 )
00422 child->setLayouted(false);
00423
00424 if ( child->style()->flowAroundFloats() && !child->isFloating() &&
00425 style()->width().isFixed() ) {
00426
00427 int available = style()->direction() == LTR
00428 ? m_width - leftOffset( m_height )
00429 : rightOffset( m_height );
00430 if ( child->minWidth() > available ) {
00431
00432 m_height = QMAX( m_height, style()->direction() == LTR ? leftBottom() : rightBottom() );
00433 prevMargin = 0;
00434 }
00435 }
00436
00437
00438
00439
00440
00441 if (child->isPositioned())
00442 {
00443 static_cast<RenderFlow*>(child->containingBlock())->insertSpecialObject(child);
00444
00445 child = child->nextSibling();
00446 continue;
00447 } else if ( child->isReplaced() ) {
00448 if ( !child->layouted() )
00449 child->layout();
00450 } else if ( child->isFloating() ) {
00451 if ( !child->layouted() )
00452 child->layout();
00453
00454 if ( prevMargin != TABLECELLMARGIN )
00455 m_height += prevMargin;
00456 insertSpecialObject( child );
00457 positionNewFloats();
00458
00459 if ( prevMargin != TABLECELLMARGIN )
00460 m_height -= prevMargin;
00461 child = child->nextSibling();
00462 continue;
00463 }
00464
00465 child->calcVerticalMargins();
00466
00467 if(checkClear(child)) prevMargin = 0;
00468
00469
00470 int margin = child->marginTop();
00471
00472 margin = collapseMargins(margin, prevMargin);
00473
00474 if ( margin != TABLECELLMARGIN )
00475 m_height += margin;
00476
00477
00478
00479 if(prevFlow)
00480 {
00481 if (prevFlow->yPos()+prevFlow->floatBottom() > m_height)
00482 child->setLayouted(false);
00483 else
00484 prevFlow=0;
00485 }
00486
00487
00488
00489 int owidth = child->width();
00490 child->calcWidth();
00491 int chPos = xPos;
00492
00493 if(style()->direction() == LTR) {
00494
00495 if ( ( style()->htmlHacks() || child->isTable() ) && child->style()->flowAroundFloats() )
00496 chPos = leftOffset(m_height);
00497 chPos += child->marginLeft();
00498 } else {
00499 if ( ( style()->htmlHacks() || child->isTable() ) && child->style()->flowAroundFloats() )
00500 chPos = rightOffset(m_height);
00501 chPos -= child->width() + child->marginRight();
00502 }
00503 child->setWidth( owidth );
00504 child->setPos(chPos, m_height);
00505
00506 if ( !child->layouted() )
00507 child->layout();
00508
00509 m_height += child->height();
00510
00511 prevMargin = child->marginBottom();
00512
00513 if (child->isFlow())
00514 prevFlow = static_cast<RenderFlow*>(child);
00515
00516 if ( child->hasOverhangingFloats() ) {
00517
00518 addOverHangingFloats( static_cast<RenderFlow *>(child), -child->xPos(), -child->yPos(), true );
00519 }
00520
00521 child = child->nextSibling();
00522 }
00523
00524 if( !isTableCell() && toAdd != 0 )
00525 m_height += prevMargin;
00526 if ( isPositioned() || isRelPositioned() )
00527 m_height = QMAX( m_height, floatBottom() );
00528 m_height += toAdd;
00529
00530 setLayouted();
00531
00532
00533 }
00534
00535 bool RenderFlow::checkClear(RenderObject *child)
00536 {
00537
00538 int bottom = 0;
00539 switch(child->style()->clear())
00540 {
00541 case CNONE:
00542 return false;
00543 case CLEFT:
00544 bottom = leftBottom();
00545 break;
00546 case CRIGHT:
00547 bottom = rightBottom();
00548 break;
00549 case CBOTH:
00550 bottom = floatBottom();
00551 break;
00552 }
00553 if(m_height < bottom)
00554 m_height = bottom;
00555 return true;
00556 }
00557
00558 void RenderFlow::insertSpecialObject(RenderObject *o)
00559 {
00560
00561 if (!specialObjects) {
00562 specialObjects = new QSortedList<SpecialObject>;
00563 specialObjects->setAutoDelete(true);
00564 }
00565 else {
00566
00567 QPtrListIterator<SpecialObject> it(*specialObjects);
00568 SpecialObject *f;
00569 while ( (f = it.current()) ) {
00570 if (f->node == o) return;
00571 ++it;
00572 }
00573 }
00574
00575
00576
00577 SpecialObject *newObj = 0;
00578 if (o->isPositioned()) {
00579
00580 newObj = new SpecialObject(SpecialObject::Positioned);
00581 setOverhangingContents();
00582 }
00583 else if (o->isFloating()) {
00584
00585 if ( !o->layouted() )
00586 o->layout();
00587
00588 if(o->style()->floating() == FLEFT)
00589 newObj = new SpecialObject(SpecialObject::FloatLeft);
00590 else
00591 newObj = new SpecialObject(SpecialObject::FloatRight);
00592
00593 newObj->startY = -1;
00594 newObj->endY = -1;
00595 newObj->width = o->width() + o->marginLeft() + o->marginRight();
00596 }
00597 else {
00598
00599
00600 KHTMLAssert(newObj);
00601 }
00602
00603 newObj->count = specialObjects->count();
00604 newObj->node = o;
00605
00606 specialObjects->append(newObj);
00607 }
00608
00609 void RenderFlow::removeSpecialObject(RenderObject *o)
00610 {
00611 if (specialObjects) {
00612 QPtrListIterator<SpecialObject> it(*specialObjects);
00613 while (it.current()) {
00614 if (it.current()->node == o)
00615 specialObjects->removeRef(it.current());
00616 ++it;
00617 }
00618 }
00619 }
00620
00621 void RenderFlow::positionNewFloats()
00622 {
00623 if(!specialObjects) return;
00624 SpecialObject *f = specialObjects->getLast();
00625 if(!f || f->startY != -1) return;
00626 SpecialObject *lastFloat;
00627 while(1)
00628 {
00629 lastFloat = specialObjects->prev();
00630 if(!lastFloat || (lastFloat->startY != -1 && !(lastFloat->type==SpecialObject::Positioned) )) {
00631 specialObjects->next();
00632 break;
00633 }
00634 f = lastFloat;
00635 }
00636
00637
00638 int y = m_height;
00639
00640
00641
00642 if(lastFloat && lastFloat->startY > y)
00643 y = lastFloat->startY;
00644
00645 while(f)
00646 {
00647
00648 if (f->node->containingBlock()!=this || f->type==SpecialObject::Positioned)
00649 {
00650 f = specialObjects->next();
00651 continue;
00652 }
00653
00654 RenderObject *o = f->node;
00655 int _height = o->height() + o->marginTop() + o->marginBottom();
00656
00657 int ro = rightOffset();
00658 int lo = leftOffset();
00659 int fwidth = f->width;
00660
00661 if (ro - lo < fwidth)
00662 fwidth = ro - lo;
00663 if (o->style()->floating() == FLEFT)
00664 {
00665 if ( o->style()->clear() & CLEFT )
00666 y = QMAX( leftBottom(), y );
00667 int heightRemainingLeft = 1;
00668 int heightRemainingRight = 1;
00669 int fx = leftRelOffset(y,lo, &heightRemainingLeft);
00670 while (rightRelOffset(y,ro, &heightRemainingRight)-fx < fwidth)
00671 {
00672 y += QMIN( heightRemainingLeft, heightRemainingRight );
00673 fx = leftRelOffset(y,lo, &heightRemainingLeft);
00674 }
00675 if (fx<0) fx=0;
00676 f->left = fx;
00677
00678 o->setPos(fx + o->marginLeft(), y + o->marginTop());
00679 }
00680 else
00681 {
00682 if ( o->style()->clear() & CRIGHT )
00683 y = QMAX( rightBottom(), y );
00684 int heightRemainingLeft = 1;
00685 int heightRemainingRight = 1;
00686 int fx = rightRelOffset(y,ro, &heightRemainingRight);
00687 while (fx - leftRelOffset(y,lo, &heightRemainingLeft) < fwidth)
00688 {
00689 y += QMIN(heightRemainingLeft, heightRemainingRight);
00690 fx = rightRelOffset(y,ro, &heightRemainingRight);
00691 }
00692 if (fx<f->width) fx=f->width;
00693 f->left = fx - f->width;
00694
00695 o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
00696 }
00697 f->startY = y;
00698 f->endY = f->startY + _height;
00699
00700
00701
00702
00703 f = specialObjects->next();
00704 }
00705 }
00706
00707 void RenderFlow::newLine()
00708 {
00709 positionNewFloats();
00710
00711 int newY = 0;
00712 switch(m_clearStatus)
00713 {
00714 case CLEFT:
00715 newY = leftBottom();
00716 break;
00717 case CRIGHT:
00718 newY = rightBottom();
00719 break;
00720 case CBOTH:
00721 newY = floatBottom();
00722 default:
00723 break;
00724 }
00725 if(m_height < newY)
00726 {
00727
00728 m_height = newY;
00729 }
00730 m_clearStatus = CNONE;
00731 }
00732
00733
00734 int
00735 RenderFlow::leftOffset() const
00736 {
00737 int left = 0;
00738
00739 left += borderLeft() + paddingLeft();
00740
00741 if ( firstLine && style()->direction() == LTR ) {
00742 int cw=0;
00743 if (style()->textIndent().isPercent())
00744 cw = containingBlock()->contentWidth();
00745 left += style()->textIndent().minWidth(cw);
00746 }
00747
00748 return left;
00749 }
00750
00751 int
00752 RenderFlow::leftRelOffset(int y, int fixedOffset, int *heightRemaining ) const
00753 {
00754 int left = fixedOffset;
00755 if(!specialObjects)
00756 return left;
00757
00758 if ( heightRemaining ) *heightRemaining = 1;
00759 SpecialObject* r;
00760 QPtrListIterator<SpecialObject> it(*specialObjects);
00761 for ( ; (r = it.current()); ++it )
00762 {
00763
00764 if (r->startY <= y && r->endY > y &&
00765 r->type == SpecialObject::FloatLeft &&
00766 r->left + r->width > left) {
00767 left = r->left + r->width;
00768 if ( heightRemaining ) *heightRemaining = r->endY - y;
00769 }
00770 }
00771
00772 return left;
00773 }
00774
00775 int
00776 RenderFlow::rightOffset() const
00777 {
00778 int right = m_width;
00779
00780 right -= borderRight() + paddingRight();
00781
00782 if ( firstLine && style()->direction() == RTL ) {
00783 int cw=0;
00784 if (style()->textIndent().isPercent())
00785 cw = containingBlock()->contentWidth();
00786 right += style()->textIndent().minWidth(cw);
00787 }
00788
00789 return right;
00790 }
00791
00792 int
00793 RenderFlow::rightRelOffset(int y, int fixedOffset, int *heightRemaining ) const
00794 {
00795 int right = fixedOffset;
00796
00797 if (!specialObjects) return right;
00798
00799 if (heightRemaining) *heightRemaining = 1;
00800 SpecialObject* r;
00801 QPtrListIterator<SpecialObject> it(*specialObjects);
00802 for ( ; (r = it.current()); ++it )
00803 {
00804
00805 if (r->startY <= y && r->endY > y &&
00806 r->type == SpecialObject::FloatRight &&
00807 r->left < right) {
00808 right = r->left;
00809 if ( heightRemaining ) *heightRemaining = r->endY - y;
00810 }
00811 }
00812
00813 return right;
00814 }
00815
00816 short
00817 RenderFlow::lineWidth(int y) const
00818 {
00819
00820 return rightOffset(y) - leftOffset(y);
00821 }
00822
00823 int
00824 RenderFlow::floatBottom() const
00825 {
00826 if (!specialObjects) return 0;
00827 int bottom=0;
00828 SpecialObject* r;
00829 QPtrListIterator<SpecialObject> it(*specialObjects);
00830 for ( ; (r = it.current()); ++it )
00831 if (r->endY>bottom && (int)r->type <= (int)SpecialObject::FloatRight)
00832 bottom=r->endY;
00833 return bottom;
00834 }
00835
00836 int
00837 RenderFlow::lowestPosition() const
00838 {
00839 int bottom = RenderBox::lowestPosition();
00840
00841 int lp = 0;
00842 if ( !m_childrenInline ) {
00843 RenderObject *last = lastChild();
00844 while( last && (last->isPositioned() || last->isFloating()) )
00845 last = last->previousSibling();
00846 if( last )
00847 lp = last->yPos() + last->lowestPosition();
00848 }
00849
00850 if( lp > bottom )
00851 bottom = lp;
00852
00853
00854
00855 if (specialObjects) {
00856 SpecialObject* r;
00857 QPtrListIterator<SpecialObject> it(*specialObjects);
00858 for ( ; (r = it.current()); ++it ) {
00859 lp = 0;
00860 if ( r->type == SpecialObject::FloatLeft || r->type == SpecialObject::FloatRight ){
00861 lp = r->startY + r->node->lowestPosition();
00862
00863 } else if ( r->type == SpecialObject::Positioned ) {
00864 lp = r->node->yPos() + r->node->lowestPosition();
00865 }
00866 if( lp > bottom)
00867 bottom = lp;
00868 }
00869 }
00870
00871 if ( overhangingContents() ) {
00872 RenderObject *child = firstChild();
00873 while( child ) {
00874 if ( child->overhangingContents() ) {
00875 int lp = child->yPos() + child->lowestPosition();
00876 if ( lp > bottom ) bottom = lp;
00877 }
00878 child = child->nextSibling();
00879 }
00880 }
00881
00882
00883 return bottom;
00884 }
00885
00886 int RenderFlow::rightmostPosition() const
00887 {
00888 int right = RenderBox::rightmostPosition();
00889
00890 RenderObject *c;
00891 for (c = firstChild(); c; c = c->nextSibling()) {
00892 if (!c->isPositioned() && !c->isFloating()) {
00893 int childRight = c->xPos() + c->rightmostPosition();
00894 if (childRight > right)
00895 right = childRight;
00896 }
00897 }
00898
00899 if (specialObjects) {
00900 SpecialObject* r;
00901 QPtrListIterator<SpecialObject> it(*specialObjects);
00902 for ( ; (r = it.current()); ++it ) {
00903 int specialRight=0;
00904 if ( r->type == SpecialObject::FloatLeft || r->type == SpecialObject::FloatRight ){
00905 specialRight = r->left + r->node->rightmostPosition();
00906 } else if ( r->type == SpecialObject::Positioned ) {
00907 specialRight = r->node->xPos() + r->node->rightmostPosition();
00908 }
00909 if (specialRight > right)
00910 right = specialRight;
00911 }
00912 }
00913
00914 if ( overhangingContents() ) {
00915 RenderObject *child = firstChild();
00916 while( child ) {
00917 if ( child->overhangingContents() ) {
00918 int r = child->xPos() + child->rightmostPosition();
00919 if ( r > right ) right = r;
00920 }
00921 child = child->nextSibling();
00922 }
00923 }
00924
00925 return right;
00926 }
00927
00928
00929 int
00930 RenderFlow::leftBottom()
00931 {
00932 if (!specialObjects) return 0;
00933 int bottom=0;
00934 SpecialObject* r;
00935 QPtrListIterator<SpecialObject> it(*specialObjects);
00936 for ( ; (r = it.current()); ++it )
00937 if (r->endY>bottom && r->type == SpecialObject::FloatLeft)
00938 bottom=r->endY;
00939
00940 return bottom;
00941 }
00942
00943 int
00944 RenderFlow::rightBottom()
00945 {
00946 if (!specialObjects) return 0;
00947 int bottom=0;
00948 SpecialObject* r;
00949 QPtrListIterator<SpecialObject> it(*specialObjects);
00950 for ( ; (r = it.current()); ++it )
00951 if (r->endY>bottom && r->type == SpecialObject::FloatRight)
00952 bottom=r->endY;
00953
00954 return bottom;
00955 }
00956
00957 void
00958 RenderFlow::clearFloats()
00959 {
00960
00961
00962 if (specialObjects) {
00963 if( overhangingContents() ) {
00964 specialObjects->first();
00965 while ( specialObjects->current()) {
00966 if ( !(specialObjects->current()->type == SpecialObject::Positioned) )
00967 specialObjects->remove();
00968 else
00969 specialObjects->next();
00970 }
00971 } else
00972 specialObjects->clear();
00973 }
00974
00975 if (isFloating() || isPositioned()) return;
00976
00977 RenderObject *prev = previousSibling();
00978
00979
00980
00981
00982 bool parentHasFloats = false;
00983 while (prev) {
00984 if (!prev->isFlow() || prev->isFloating() ||
00985 (prev->style()->flowAroundFloats() &&
00986 (static_cast<RenderFlow *>(prev)->floatBottom()+prev->yPos() < m_y ))) {
00987 if ( prev->isFloating() && parent()->isFlow() ) {
00988 parentHasFloats = true;
00989 }
00990 prev = prev->previousSibling();
00991 } else
00992 break;
00993 }
00994
00995 int offset = m_y;
00996
00997 if ( parentHasFloats ) {
00998 addOverHangingFloats( static_cast<RenderFlow *>( parent() ), parent()->borderLeft() + parent()->paddingLeft() , offset, false );
00999 }
01000
01001 if(prev ) {
01002 if(prev->isTableCell()) return;
01003
01004 offset -= prev->yPos();
01005 } else {
01006 prev = parent();
01007 if(!prev) return;
01008 }
01009
01010
01011
01012 if(!prev->isFlow()) return;
01013 RenderFlow * flow = static_cast<RenderFlow *>(prev);
01014 if(!flow->specialObjects) return;
01015 if( ( style()->htmlHacks() || isTable() ) && style()->flowAroundFloats())
01016 return;
01017
01018 if(flow->floatBottom() > offset) {
01019 int xoff = flow == parent() ? xPos() : xPos() - flow->xPos();
01020 addOverHangingFloats( flow, xoff, offset );
01021 }
01022 }
01023
01024 void RenderFlow::addOverHangingFloats( RenderFlow *flow, int xoff, int offset, bool child )
01025 {
01026 #ifdef DEBUG_LAYOUT
01027 kdDebug( 6040 ) << (void *)this << ": adding overhanging floats xoff=" << xoff << " offset=" << offset << " child=" << child << endl;
01028 #endif
01029 if ( !flow->specialObjects )
01030 return;
01031
01032
01033 if(!specialObjects) {
01034 specialObjects = new QSortedList<SpecialObject>;
01035 specialObjects->setAutoDelete(true);
01036 }
01037
01038 QPtrListIterator<SpecialObject> it(*flow->specialObjects);
01039 SpecialObject *r;
01040 for ( ; (r = it.current()); ++it ) {
01041 if ( (int)r->type <= (int)SpecialObject::FloatRight &&
01042 ( ( !child && r->endY > offset ) ||
01043 ( child && flow->yPos() + r->endY > height() ) ) ) {
01044
01045 if ( child )
01046 r->noPaint = true;
01047
01048 SpecialObject* f = 0;
01049
01050 QPtrListIterator<SpecialObject> it(*specialObjects);
01051 while ( (f = it.current()) ) {
01052 if (f->node == r->node) break;
01053 ++it;
01054 }
01055 if ( !f ) {
01056 SpecialObject *special = new SpecialObject(r->type);
01057 special->count = specialObjects->count();
01058 special->startY = r->startY - offset;
01059 special->endY = r->endY - offset;
01060 special->left = r->left - xoff;
01061 if ( !child ) {
01062 special->left -= marginLeft();
01063 special->noPaint = true;
01064 }
01065 special->width = r->width;
01066 special->node = r->node;
01067 specialObjects->append(special);
01068 #ifdef DEBUG_LAYOUT
01069 kdDebug( 6040 ) << "addOverHangingFloats x/y= (" << special->left << "/" << special->startY << "-" << special->width << "/" << special->endY - special->startY << ")" << endl;
01070 #endif
01071 }
01072 }
01073 }
01074 }
01075
01076
01077 static inline RenderObject *next(RenderObject *par, RenderObject *current)
01078 {
01079 RenderObject *next = 0;
01080 while(current != 0)
01081 {
01082
01083 if(!current->isFloating() && !current->isReplaced() && !current->isPositioned())
01084 next = current->firstChild();
01085 if(!next) {
01086 while(current && current != par) {
01087 next = current->nextSibling();
01088 if(next) break;
01089 current = current->parent();
01090 }
01091 }
01092
01093 if(!next) break;
01094
01095 if(next->isText() || next->isBR() || next->isFloating() || next->isReplaced() || next->isPositioned())
01096 break;
01097 current = next;
01098 }
01099 return next;
01100 }
01101
01102
01103 void RenderFlow::calcMinMaxWidth()
01104 {
01105 KHTMLAssert( !minMaxKnown() );
01106
01107 #ifdef DEBUG_LAYOUT
01108 kdDebug( 6040 ) << renderName() << "(RenderBox)::calcMinMaxWidth() this=" << this << endl;
01109 #endif
01110
01111 m_minWidth = 0;
01112 m_maxWidth = 0;
01113
01114 if (isInline()) {
01115 setMinMaxKnown();
01116 return;
01117 }
01118
01119 int cw = containingBlock()->contentWidth();
01120
01121
01122 bool tableCell = (isTableCell() && !style()->width().isFixed());
01123
01124
01125 bool nowrap = style()->whiteSpace() == NOWRAP ||
01126 ( tableCell && static_cast<RenderTableCell *>(this)->noWrap() );
01127
01128
01129 const QChar nbsp = 0xa0;
01130
01131 RenderObject *child = firstChild();
01132 RenderObject *prevchild = 0;
01133
01134 if(childrenInline()) {
01135 int inlineMax=0;
01136 int currentMin=0;
01137 int inlineMin=0;
01138 bool noBreak=false;
01139
01140 while(child != 0) {
01141
01142 if (child->isPositioned()) {
01143 child = next(this, child);
01144 continue;
01145 }
01146
01147 if( !child->isBR() ) {
01148 RenderStyle* cstyle = child->style();
01149 int margins = 0;
01150 LengthType type = cstyle->marginLeft().type;
01151 if ( type != Variable )
01152 margins += (type == Fixed ? cstyle->marginLeft().value : child->marginLeft());
01153 type = cstyle->marginRight().type;
01154 if ( type != Variable )
01155 margins += (type == Fixed ? cstyle->marginRight().value : child->marginRight());
01156 int childMin = child->minWidth() + margins;
01157 int childMax = child->maxWidth() + margins;
01158
01159 if (child->isText() && static_cast<RenderText *>(child)->stringLength() > 0) {
01160
01161 int ti = cstyle->textIndent().minWidth(cw);
01162 childMin+=ti;
01163 childMax+=ti;
01164
01165 RenderText* t = static_cast<RenderText *>(child);
01166
01167 if (noBreak || t->text()[0] == nbsp) {
01168 currentMin += t->startMin();
01169
01170 }
01171 noBreak = false;
01172 if ( t->hasBreakableChar() ) {
01173 inlineMin = QMAX( inlineMin, currentMin );
01174 currentMin = t->endMin();
01175 }
01176 if ( t->text()[t->stringLength()-1]==nbsp ) {
01177 noBreak = true;
01178 }
01179
01180 } else if (noBreak || tableCell ||
01181 (prevchild && prevchild->isFloating() && child->isFloating())) {
01182 currentMin += childMin;
01183 noBreak = false;
01184 }
01185 inlineMin = QMAX( inlineMin, childMin );
01186 inlineMax += childMax;
01187 }
01188 else
01189 {
01190 inlineMin = QMAX( currentMin, inlineMin );
01191 if(m_minWidth < inlineMin) m_minWidth = inlineMin;
01192 if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
01193 inlineMin = currentMin = inlineMax = 0;
01194 }
01195 prevchild = child;
01196 child = next(this, child);
01197 }
01198 inlineMin = QMAX( currentMin, inlineMin );
01199 if(m_minWidth < inlineMin) m_minWidth = inlineMin;
01200 if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
01201
01202
01203 if ( nowrap )
01204 m_minWidth = m_maxWidth;
01205 }
01206 else
01207 {
01208 while(child != 0)
01209 {
01210
01211 if (child->isPositioned())
01212 {
01213 child = child->nextSibling();
01214 continue;
01215 }
01216
01217 int margin=0;
01218
01219
01220 Length ml = child->style()->marginLeft();
01221 Length mr = child->style()->marginRight();
01222
01223 if (style()->textAlign() == KONQ_CENTER)
01224 {
01225 if (ml.type==Fixed) margin+=ml.value;
01226 if (mr.type==Fixed) margin+=mr.value;
01227 }
01228 else
01229 {
01230 if (!(ml.type==Variable) && !(mr.type==Variable))
01231 {
01232 if (!(child->style()->width().type==Variable))
01233 {
01234 if (child->style()->direction()==LTR)
01235 margin = child->marginLeft();
01236 else
01237 margin = child->marginRight();
01238 }
01239 else
01240 margin = child->marginLeft()+child->marginRight();
01241
01242 }
01243 else if (!(ml.type == Variable))
01244 margin = child->marginLeft();
01245 else if (!(mr.type == Variable))
01246 margin = child->marginRight();
01247 }
01248
01249 if (margin<0) margin=0;
01250
01251 int w = child->minWidth() + margin;
01252 if(m_minWidth < w) m_minWidth = w;
01253
01254 if ( nowrap && !child->isTable() && m_maxWidth < w )
01255 m_maxWidth = w;
01256 w = child->maxWidth() + margin;
01257 if(m_maxWidth < w) m_maxWidth = w;
01258 child = child->nextSibling();
01259 }
01260 }
01261 if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
01262
01263 if (style()->width().isFixed() && style()->width().value > 0)
01264 m_maxWidth = KMAX(m_minWidth,short(style()->width().value));
01265
01266 int toAdd = 0;
01267 toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
01268
01269 m_minWidth += toAdd;
01270 m_maxWidth += toAdd;
01271
01272 setMinMaxKnown();
01273
01274
01275
01276 }
01277
01278 void RenderFlow::close()
01279 {
01280 if(lastChild() && lastChild()->isAnonymousBox()) {
01281 lastChild()->close();
01282 }
01283
01284 RenderBox::close();
01285 }
01286
01287 void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
01288 {
01289 #ifdef DEBUG_LAYOUT
01290 kdDebug( 6040 ) << renderName() << "(RenderFlow)::addChild( " << newChild->renderName() <<
01291 ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
01292 kdDebug( 6040 ) << "current height = " << m_height << endl;
01293 #endif
01294 setLayouted( false );
01295
01296 bool madeBoxesNonInline = FALSE;
01297
01298 RenderStyle* pseudoStyle=0;
01299 if ( !isInline() && ( !firstChild() || firstChild() == beforeChild )
01300 && ( pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER) ) )
01301 {
01302
01303 if (newChild->isText() && !newChild->isBR()) {
01304 RenderText* newTextChild = static_cast<RenderText*>(newChild);
01305
01306
01307
01308 RenderFlow* firstLetter = new RenderFlow(0 );
01309 pseudoStyle->setDisplay( INLINE );
01310 firstLetter->setStyle(pseudoStyle);
01311 firstLetter->setIsAnonymousBox(true);
01312
01313 addChild(firstLetter);
01314
01315 DOMStringImpl* oldText = newTextChild->string();
01316
01317 if(oldText->l >= 1) {
01318 unsigned int length = 0;
01319 while ( length < oldText->l &&
01320 ( (oldText->s+length)->isSpace() || (oldText->s+length)->isPunct() ) )
01321 length++;
01322 length++;
01323 RenderText* letter = new RenderText(0 , oldText->substring(0,length));
01324 RenderStyle* newStyle = new RenderStyle();
01325 newStyle->inheritFrom(pseudoStyle);
01326 letter->setStyle(newStyle);
01327 letter->setIsAnonymousBox(true);
01328 firstLetter->addChild(letter);
01329 newTextChild->setText(oldText->substring(length,oldText->l-length));
01330 }
01331 firstLetter->close();
01332
01333 }
01334 }
01335
01336 insertPseudoChild(RenderStyle::BEFORE, newChild, beforeChild);
01337
01338
01339
01340
01341 if (beforeChild && beforeChild->parent() != this) {
01342 KHTMLAssert(beforeChild->parent());
01343 KHTMLAssert(beforeChild->parent()->isAnonymousBox());
01344 KHTMLAssert(beforeChild->parent()->parent() == this);
01345
01346 if (newChild->isInline()) {
01347 beforeChild->parent()->addChild(newChild,beforeChild);
01348 newChild->setLayouted( false );
01349 newChild->setMinMaxKnown( false );
01350 return;
01351 }
01352 else {
01353
01354
01355
01356
01357 RenderObject *anonBox = beforeChild->parent();
01358 KHTMLAssert (anonBox->isFlow());
01359
01360
01361 if ( anonBox->childrenInline() ) {
01362 static_cast<RenderFlow*>(anonBox)->makeChildrenNonInline(beforeChild);
01363 madeBoxesNonInline = true;
01364 }
01365 beforeChild = beforeChild->parent();
01366
01367
01368 anonBox->setIsAnonymousBox(false);
01369
01370 RenderObject *child;
01371 while ((child = anonBox->firstChild()) != 0) {
01372 anonBox->removeChild(child);
01373 addChild(child,anonBox);
01374 }
01375 anonBox->setIsAnonymousBox(true);
01376 removeChildNode(anonBox);
01377 anonBox->detach();
01378 KHTMLAssert(beforeChild->parent() == this);
01379
01380 }
01381 }
01382
01383
01384
01385 if (!newChild->isInline())
01386 newChild->setPos(newChild->xPos(), -500000);
01387
01388 if (!newChild->isText())
01389 {
01390 if (newChild->style()->position() != STATIC)
01391 setOverhangingContents();
01392 }
01393
01394
01395
01396
01397 if ( m_childrenInline && !newChild->isInline() && !newChild->isSpecial() )
01398 {
01399 if ( m_childrenInline ) {
01400 makeChildrenNonInline(beforeChild);
01401 madeBoxesNonInline = true;
01402 }
01403 if (beforeChild) {
01404 if ( beforeChild->parent() != this ) {
01405 beforeChild = beforeChild->parent();
01406 KHTMLAssert(beforeChild->isAnonymousBox());
01407 KHTMLAssert(beforeChild->parent() == this);
01408 }
01409 }
01410 }
01411 else if (!m_childrenInline)
01412 {
01413
01414
01415
01416 if(newChild->isInline()) {
01417 if (beforeChild) {
01418 if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousBox()) {
01419 beforeChild->previousSibling()->addChild(newChild);
01420 newChild->setLayouted( false );
01421 newChild->setMinMaxKnown( false );
01422 return;
01423 }
01424 }
01425 else{
01426 if (m_last && m_last->isAnonymousBox()) {
01427 m_last->addChild(newChild);
01428 newChild->setLayouted( false );
01429 newChild->setMinMaxKnown( false );
01430 return;
01431 }
01432 }
01433
01434
01435 RenderStyle *newStyle = new RenderStyle();
01436 newStyle->inheritFrom(style());
01437 newStyle->setDisplay(BLOCK);
01438
01439 RenderFlow *newBox = new RenderFlow(0 );
01440 newBox->setStyle(newStyle);
01441 newBox->setIsAnonymousBox(true);
01442
01443 RenderBox::addChild(newBox,beforeChild);
01444 newBox->addChild(newChild);
01445 newBox->setPos(newBox->xPos(), -500000);
01446
01447 newChild->setLayouted( false );
01448 newChild->setMinMaxKnown( false );
01449 return;
01450 }
01451 else {
01452
01453
01454
01455 if (lastChild() && lastChild()->isAnonymousBox()) {
01456 lastChild()->close();
01457 }
01458 }
01459 }
01460
01461 if(!newChild->isInline() && !newChild->isPositioned())
01462 {
01463
01464
01465
01466 if (style()->display() == INLINE)
01467 {
01468 setInline(false);
01469 RenderObject *p = parent();
01470 if (p && p->isFlow() && p->childrenInline() ) {
01471 static_cast<RenderFlow*>(p)->makeChildrenNonInline();
01472 madeBoxesNonInline = true;
01473 }
01474 }
01475 }
01476
01477 RenderBox::addChild(newChild,beforeChild);
01478
01479
01480 newChild->setLayouted( false );
01481 newChild->setMinMaxKnown( false );
01482 insertPseudoChild(RenderStyle::AFTER, newChild, beforeChild);
01483
01484 if ( madeBoxesNonInline )
01485 removeLeftoverAnonymousBoxes();
01486 }
01487
01488 void RenderFlow::makeChildrenNonInline(RenderObject *box2Start)
01489 {
01490 KHTMLAssert(!box2Start || box2Start->parent() == this);
01491
01492 m_childrenInline = false;
01493
01494 RenderObject *child = firstChild();
01495 RenderObject *next;
01496 RenderObject *boxFirst = 0;
01497 RenderObject *boxLast = 0;
01498 while (child) {
01499 next = child->nextSibling();
01500
01501 if (child->isInline()) {
01502 if ( !boxFirst )
01503 boxFirst = child;
01504 boxLast = child;
01505 }
01506
01507 if ( boxFirst &&
01508 ( !child->isInline() || !next || child == box2Start ) ) {
01509
01510
01511 RenderStyle *newStyle = new RenderStyle();
01512 newStyle->inheritFrom(style());
01513 newStyle->setDisplay(BLOCK);
01514
01515 RenderFlow *box = new RenderFlow(0 );
01516 box->setStyle(newStyle);
01517 box->setIsAnonymousBox(true);
01518
01519
01520
01521
01522 insertChildNode(box, boxFirst);
01523 RenderObject* o = boxFirst;
01524 while(o && o != boxLast)
01525 {
01526 RenderObject* no = o;
01527 o = no->nextSibling();
01528 box->appendChildNode(removeChildNode(no));
01529 }
01530 box->appendChildNode(removeChildNode(boxLast));
01531 box->close();
01532 box->setPos(box->xPos(), -500000);
01533 box->setLayouted(false);
01534 boxFirst = boxLast = next;
01535 }
01536
01537 child = next;
01538 }
01539
01540 if (isInline()) {
01541 setInline(false);
01542 if (parent()->isFlow()) {
01543 KHTMLAssert(parent()->childrenInline());
01544 static_cast<RenderFlow *>(parent())->makeChildrenNonInline();
01545 }
01546 }
01547
01548 setLayouted(false);
01549 }
01550
01551 bool RenderFlow::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty)
01552 {
01553 bool inBox = false;
01554 if (specialObjects) {
01555 int stx = _tx + xPos();
01556 int sty = _ty + yPos();
01557 if (isRelPositioned())
01558 static_cast<RenderBox*>(this)->relativePositionOffset(stx, sty);
01559
01560 if (isRoot()) {
01561 stx += static_cast<RenderRoot*>(this)->view()->contentsX();
01562 sty += static_cast<RenderRoot*>(this)->view()->contentsY();
01563 }
01564 SpecialObject* o;
01565 QPtrListIterator<SpecialObject> it(*specialObjects);
01566 for (it.toLast(); (o = it.current()); --it)
01567 if ( o->node->isPositioned() && o->node->containingBlock() == this)
01568 inBox |= o->node->nodeAtPoint(info, _x, _y, stx, sty);
01569 else if ( o->node->isFloating() && !o->noPaint )
01570 inBox |= o->node->nodeAtPoint( info, _x, _y,
01571 stx + o->left + o->node->marginLeft() - o->node->xPos(),
01572 sty + o->startY + o->node->marginTop() - o->node->yPos() );
01573 }
01574
01575 inBox |= RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty);
01576 return inBox;
01577 }
01578
01579 #ifndef NDEBUG
01580 void RenderFlow::printTree(int indent) const
01581 {
01582 RenderBox::printTree(indent);
01583
01584 if(specialObjects)
01585 {
01586 QPtrListIterator<SpecialObject> it(*specialObjects);
01587 SpecialObject *r;
01588 for ( ; (r = it.current()); ++it )
01589 {
01590 QString s;
01591 s.fill(' ', indent);
01592 kdDebug() << s << renderName() << ": " <<
01593 (r->type == SpecialObject::FloatLeft ? "FloatLeft" : (r->type == SpecialObject::FloatRight ? "FloatRight" : "Positioned")) <<
01594 "[" << r->node->renderName() << ": " << (void*)r->node << "] (" << r->startY << " - " << r->endY << ")" <<
01595 (r->noPaint ? " noPaint " : " ") << "left: " << r->left << " width: " << r->width <<
01596 endl;
01597 }
01598 }
01599 }
01600
01601 void RenderFlow::dump(QTextStream *stream, QString ind) const
01602 {
01603 if (m_childrenInline) { *stream << " childrenInline"; }
01604 if (m_pre) { *stream << " pre"; }
01605 if (firstLine) { *stream << " firstLine"; }
01606
01607 if(specialObjects && !specialObjects->isEmpty())
01608 {
01609 *stream << " special(";
01610 QPtrListIterator<SpecialObject> it(*specialObjects);
01611 SpecialObject *r;
01612 bool first = true;
01613 for ( ; (r = it.current()); ++it )
01614 {
01615 if (!first)
01616 *stream << ",";
01617 *stream << r->node->renderName();
01618 first = false;
01619 }
01620 *stream << ")";
01621 }
01622
01623
01624
01625 RenderBox::dump(stream,ind);
01626 }
01627 #endif
01628
01629 #undef DEBUG
01630 #undef DEBUG_LAYOUT
01631 #undef BOX_DEBUG