render_object.cpp Source File (khtml Library)

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

# render_object.cpp

    00001
    00026 #include "rendering/render_object.h"
    00027 #include "rendering/render_table.h"
    00028 #include "rendering/render_list.h"
    00029 #include "rendering/render_root.h"
    00030 #include "xml/dom_elementimpl.h"
    00031 #include "misc/htmlhashes.h"
    00032 #include <kdebug.h>
    00033 #include <qpainter.h>
    00034 #include "khtmlview.h"
    00035
    00036 #include <assert.h>
    00037 using namespace DOM;
    00038 using namespace khtml;
    00039
    00040 RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* style)
    00041 {
    00042     RenderObject *o = 0;
    00043     switch(style->display())
    00044     {
    00045     case NONE:
    00046         break;
    00047     case INLINE:
    00048     case BLOCK:
    00049     case TABLE_CAPTION:
    00050         o = new RenderFlow(node);
    00051         break;
    00052     case LIST_ITEM:
    00053         o = new RenderListItem(node);
    00054         break;
    00055     case RUN_IN:
    00056     case INLINE_BLOCK:
    00057         break;
    00058     case TABLE:
    00059     case INLINE_TABLE:
    00060         style->setFlowAroundFloats(true);
    00061         o = new RenderTable(node);
    00062         break;
    00063     case TABLE_ROW_GROUP:
    00064     case TABLE_HEADER_GROUP:
    00065     case TABLE_FOOTER_GROUP:
    00066         o = new RenderTableSection(node);
    00067         break;
    00068     case TABLE_ROW:
    00069         o = new RenderTableRow(node);
    00070         break;
    00071     case TABLE_COLUMN_GROUP:
    00072     case TABLE_COLUMN:
    00073         o = new RenderTableCol(node);
    00074         break;
    00075     case TABLE_CELL:
    00076         o = new RenderTableCell(node);
    00077         break;
    00078     }
    00079     if(o) o->setStyle(style);
    00080     return o;
    00081 }
    00082
    00083
    00084 RenderObject::RenderObject(DOM::NodeImpl* node)
    00085     : CachedObjectClient(),
    00086 m_style( 0 ),
    00087 m_node( node ),
    00088 m_parent( 0 ),
    00089 m_previous( 0 ),
    00090 m_next( 0 ),
    00091 m_verticalPosition( PositionUndefined ),
    00092 m_layouted( false ),
    00093 m_unused( false ),
    00094 m_minMaxKnown( false ),
    00095 m_floating( false ),
    00096
    00097 m_positioned( false ),
    00098 m_overhangingContents( false ),
    00099 m_relPositioned( false ),
    00100 m_paintSpecial( false ),
    00101
    00102 m_isAnonymous( false ),
    00103 m_recalcMinMax( false ),
    00104 m_isText( false ),
    00105 m_inline( true ),
    00106
    00107 m_replaced( false ),
    00108 m_mouseInside( false ),
    00109 m_hasFirstLine( false ),
    00110 m_isSelectionBorder( false )
    00111 {
    00112 }
    00113
    00114 RenderObject::~RenderObject()
    00115 {
    00116     if(m_style->backgroundImage())
    00117         m_style->backgroundImage()->deref(this);
    00118
    00119     if (m_style)
    00120         m_style->deref();
    00121 }
    00122
    00123
    00124
    00125 RenderObject* RenderObject::objectBelow() const
    00126 {
    00127     RenderObject* obj = firstChild();
    00128     if ( !obj ) {
    00129         obj = nextSibling();
    00130         if ( !obj )
    00131         {
    00132             obj = parent();
    00133             while (obj && !obj->nextSibling())
    00134                 obj = obj->parent();
    00135             if (obj)
    00136                 obj = obj->nextSibling();
    00137         }
    00138     }
    00139     return obj;
    00140 }
    00141
    00142 RenderObject* RenderObject::objectAbove() const
    00143 {
    00144     RenderObject* obj = previousSibling();
    00145     if ( !obj )
    00146         return parent();
    00147
    00148     RenderObject* last = obj->lastChild();
    00149     while ( last )
    00150     {
    00151         obj = last;
    00152         last = last->lastChild();
    00153     }
    00154     return obj;
    00155 }
    00156
    00157 void RenderObject::addChild(RenderObject* , RenderObject *)
    00158 {
    00159     KHTMLAssert(0);
    00160 }
    00161
    00162 RenderObject* RenderObject::removeChildNode(RenderObject* )
    00163 {
    00164     KHTMLAssert(0);
    00165     return 0;
    00166 }
    00167
    00168 void RenderObject::removeChild(RenderObject *o )
    00169 {
    00170     setLayouted(false);
    00171     removeChildNode( o );
    00172 }
    00173
    00174 void RenderObject::appendChildNode(RenderObject*)
    00175 {
    00176     KHTMLAssert(0);
    00177 }
    00178
    00179 void RenderObject::insertChildNode(RenderObject*, RenderObject*)
    00180 {
    00181     KHTMLAssert(0);
    00182 }
    00183
    00184 RenderObject *RenderObject::containingBlock() const
    00185 {
    00186     if(isTableCell())
    00187         return parent()->parent()->parent();
    00188
    00189     RenderObject *o = parent();
    00190     if(m_style->position() == FIXED) {
    00191         while ( o && !o->isRoot() )
    00192             o = o->parent();
    00193     }
    00194     else if(m_style->position() == ABSOLUTE) {
    00195         while (o && o->style()->position() == STATIC && !o->isHtml() && !o->isRoot())
    00196             o = o->parent();
    00197     } else {
    00198         while(o && o->isInline())
    00199             o = o->parent();
    00200     }
    00201     // this is just to make sure we return a valid element.
    00202     // the case below should never happen...
    00203     if(!o) {
    00204         if(!isRoot()) {
    00205 #ifndef NDEBUG
    00206             kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject): No containingBlock!" << endl;
    00207             const RenderObject* p = this;
    00208             while (p->parent()) p = p->parent();
    00209             p->printTree();
    00210 #endif
    00211         }
    00212         return const_cast<RenderObject *>(this);
    00213     } else
    00214         return o;
    00215 }
    00216
    00217 short RenderObject::containingBlockWidth() const
    00218 {
    00219     // ###
    00220     return containingBlock()->contentWidth();
    00221 }
    00222
    00223 int RenderObject::containingBlockHeight() const
    00224 {
    00225     // ###
    00226     return containingBlock()->contentHeight();
    00227 }
    00228
    00229 void RenderObject::drawBorder(QPainter *p, int x1, int y1, int x2, int y2,
    00230                               BorderSide s, QColor c, const QColor& textcolor, EBorderStyle style,
    00231                               int adjbw1, int adjbw2, bool invalidisInvert)
    00232 {
    00233     int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
    00234
    00235     if(style == DOUBLE && width < 3)
    00236         style = SOLID;
    00237
    00238     if(!c.isValid()) {
    00239         if(invalidisInvert)
    00240         {
    00241             p->setRasterOp(Qt::XorROP);
    00242             c = Qt::white;
    00243         }
    00244         else {
    00245             if(style == INSET || style == OUTSET || style == RIDGE || style ==
    00246             GROOVE)
    00247                 c.setRgb(238, 238, 238);
    00248             else
    00249                 c = textcolor;
    00250         }
    00251     }
    00252
    00253     switch(style)
    00254     {
    00255     case BNONE:
    00256     case BHIDDEN:
    00257         // should not happen
    00258         if(invalidisInvert && p->rasterOp() == Qt::XorROP)
    00259             p->setRasterOp(Qt::CopyROP);
    00260
    00261         return;
    00262     case DOTTED:
    00263         p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DotLine));
    00264         /* nobreak; */
    00265     case DASHED:
    00266         if(style == DASHED)
    00267             p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DashLine));
    00268
    00269         if (width > 0)
    00270             switch(s) {
    00271             case BSBottom:
    00272             case BSTop:
    00273                 p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
    00274             case BSRight:
    00275             case BSLeft:
    00276                 p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
    00277             }
    00278
    00279         break;
    00280     case DOUBLE:
    00281     {
    00282         int third = (width+1)/3;
    00283
    00284         if (adjbw1 == 0 && adjbw2 == 0)
    00285         {
    00286             p->setPen(Qt::NoPen);
    00287             p->setBrush(c);
    00288             switch(s)
    00289             {
    00290             case BSTop:
    00291             case BSBottom:
    00292                 p->drawRect(x1, y1      , x2-x1, third);
    00293                 p->drawRect(x1, y2-third, x2-x1, third);
    00294                 break;
    00295             case BSLeft:
    00296                 p->drawRect(x1      , y1+1, third, y2-y1-1);
    00297                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
    00298                 break;
    00299             case BSRight:
    00300                 p->drawRect(x1      , y1+1, third, y2-y1-1);
    00301                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
    00302                 break;
    00303             }
    00304         }
    00305         else
    00306         {
    00307             int adjbw1bigthird;
    00308             if (adjbw1>0) adjbw1bigthird = adjbw1+1;
    00309             else adjbw1bigthird = adjbw1 - 1;
    00310             adjbw1bigthird /= 3;
    00311
    00312             int adjbw2bigthird;
    00313             if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
    00314             else adjbw2bigthird = adjbw2 - 1;
    00315             adjbw2bigthird /= 3;
    00316
    00317           switch(s)
    00318             {
    00319             case BSTop:
    00320               drawBorder(p, x1+QMAX((-adjbw1*2+1)/3,0), y1        , x2-QMAX((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00321               drawBorder(p, x1+QMAX(( adjbw1*2+1)/3,0), y2 - third, x2-QMAX(( adjbw2*2+1)/3,0), y2        , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00322               break;
    00323             case BSLeft:
    00324               drawBorder(p, x1        , y1+QMAX((-adjbw1*2+1)/3,0), x1+third, y2-QMAX((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00325               drawBorder(p, x2 - third, y1+QMAX(( adjbw1*2+1)/3,0), x2      , y2-QMAX(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00326               break;
    00327             case BSBottom:
    00328               drawBorder(p, x1+QMAX(( adjbw1*2+1)/3,0), y1      , x2-QMAX(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00329               drawBorder(p, x1+QMAX((-adjbw1*2+1)/3,0), y2-third, x2-QMAX((-adjbw2*2+1)/3,0), y2      , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00330               break;
    00331             case BSRight:
    00332             drawBorder(p, x1      , y1+QMAX(( adjbw1*2+1)/3,0), x1+third, y2-QMAX(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00333             drawBorder(p, x2-third, y1+QMAX((-adjbw1*2+1)/3,0), x2      , y2-QMAX((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
    00334               break;
    00335             default:
    00336               break;
    00337             }
    00338         }
    00339         break;
    00340     }
    00341     case RIDGE:
    00342     case GROOVE:
    00343     {
    00344         EBorderStyle s1;
    00345         EBorderStyle s2;
    00346         if (style==GROOVE)
    00347         {
    00348             s1 = INSET;
    00349             s2 = OUTSET;
    00350         }
    00351         else
    00352         {
    00353             s1 = OUTSET;
    00354             s2 = INSET;
    00355         }
    00356
    00357         int adjbw1bighalf;
    00358         int adjbw2bighalf;
    00359         if (adjbw1>0) adjbw1bighalf=adjbw1+1;
    00360         else adjbw1bighalf=adjbw1-1;
    00361         adjbw1bighalf/=2;
    00362
    00363         if (adjbw2>0) adjbw2bighalf=adjbw2+1;
    00364         else adjbw2bighalf=adjbw2-1;
    00365         adjbw2bighalf/=2;
    00366
    00367         switch (s)
    00368         {
    00369         case BSTop:
    00370             drawBorder(p, x1+QMAX(-adjbw1  ,0)/2,  y1        , x2-QMAX(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
    00371             drawBorder(p, x1+QMAX( adjbw1+1,0)/2, (y1+y2+1)/2, x2-QMAX( adjbw2+1,0)/2,  y2        , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
    00372             break;
    00373         case BSLeft:
    00374             drawBorder(p,  x1        , y1+QMAX(-adjbw1  ,0)/2, (x1+x2+1)/2, y2-QMAX(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
    00375             drawBorder(p, (x1+x2+1)/2, y1+QMAX( adjbw1+1,0)/2,  x2        , y2-QMAX( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
    00376             break;
    00377         case BSBottom:
    00378             drawBorder(p, x1+QMAX( adjbw1  ,0)/2,  y1        , x2-QMAX( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2,  adjbw1bighalf, adjbw2bighalf);
    00379             drawBorder(p, x1+QMAX(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-QMAX(-adjbw2+1,0)/2,  y2        , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
    00380             break;
    00381         case BSRight:
    00382             drawBorder(p,  x1        , y1+QMAX( adjbw1  ,0)/2, (x1+x2+1)/2, y2-QMAX( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
    00383             drawBorder(p, (x1+x2+1)/2, y1+QMAX(-adjbw1+1,0)/2,  x2        , y2-QMAX(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
    00384             break;
    00385         }
    00386         break;
    00387     }
    00388     case INSET:
    00389         if(s == BSTop || s == BSLeft)
    00390             c = c.dark();
    00391
    00392         /* nobreak; */
    00393     case OUTSET:
    00394         if(style == OUTSET && (s == BSBottom || s == BSRight))
    00395             c = c.dark();
    00396         /* nobreak; */
    00397     case SOLID:
    00398         p->setPen(Qt::NoPen);
    00399         p->setBrush(c);
    00400         Q_ASSERT(x2>=x1);
    00401         Q_ASSERT(y2>=y1);
    00402         if (adjbw1==0 && adjbw2 == 0) {
    00403             p->drawRect(x1,y1,x2-x1,y2-y1);
    00404             return;
    00405         }
    00406         QPointArray quad(4);
    00407         switch(s) {
    00408         case BSTop:
    00409             quad.setPoints(4,
    00410                            x1+QMAX(-adjbw1,0), y1,
    00411                            x1+QMAX( adjbw1,0), y2,
    00412                            x2-QMAX( adjbw2,0), y2,
    00413                            x2-QMAX(-adjbw2,0), y1);
    00414             break;
    00415         case BSBottom:
    00416             quad.setPoints(4,
    00417                            x1+QMAX( adjbw1,0), y1,
    00418                            x1+QMAX(-adjbw1,0), y2,
    00419                            x2-QMAX(-adjbw2,0), y2,
    00420                            x2-QMAX( adjbw2,0), y1);
    00421             break;
    00422         case BSLeft:
    00423           quad.setPoints(4,
    00424                          x1, y1+QMAX(-adjbw1,0),
    00425                          x1, y2-QMAX(-adjbw2,0),
    00426                          x2, y2-QMAX( adjbw2,0),
    00427                          x2, y1+QMAX( adjbw1,0));
    00428             break;
    00429         case BSRight:
    00430           quad.setPoints(4,
    00431                          x1, y1+QMAX( adjbw1,0),
    00432                          x1, y2-QMAX( adjbw2,0),
    00433                          x2, y2-QMAX(-adjbw2,0),
    00434                          x2, y1+QMAX(-adjbw1,0));
    00435             break;
    00436         }
    00437         p->drawConvexPolygon(quad);
    00438         break;
    00439     }
    00440
    00441     if(invalidisInvert && p->rasterOp() == Qt::XorROP)
    00442         p->setRasterOp(Qt::CopyROP);
    00443 }
    00444
    00445 void RenderObject::paintBorder(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
    00446 {
    00447     const QColor& tc = style->borderTopColor();
    00448     const QColor& bc = style->borderBottomColor();
    00449
    00450     EBorderStyle ts = style->borderTopStyle();
    00451     EBorderStyle bs = style->borderBottomStyle();
    00452     EBorderStyle ls = style->borderLeftStyle();
    00453     EBorderStyle rs = style->borderRightStyle();
    00454
    00455     bool render_t = ts > BHIDDEN;
    00456     bool render_l = ls > BHIDDEN && begin;
    00457     bool render_r = rs > BHIDDEN && end;
    00458     bool render_b = bs > BHIDDEN;
    00459
    00460     if(render_t)
    00461         drawBorder(p, _tx, _ty, _tx + w, _ty +  style->borderTopWidth(), BSTop, tc, style->color(), ts,
    00462                    (render_l && ls<=DOUBLE?style->borderLeftWidth():0),
    00463                    (render_r && rs<=DOUBLE?style->borderRightWidth():0));
    00464
    00465     if(render_b)
    00466         drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
    00467                    (render_l && ls<=DOUBLE?style->borderLeftWidth():0),
    00468                    (render_r && rs<=DOUBLE?style->borderRightWidth():0));
    00469
    00470     if(render_l)
    00471     {
    00472         const QColor& lc = style->borderLeftColor();
    00473
    00474         bool ignore_top =
    00475           (tc == lc) &&
    00476           (ls <= OUTSET) &&
    00477           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
    00478
    00479         bool ignore_bottom =
    00480           (bc == lc) &&
    00481           (ls <= OUTSET) &&
    00482           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
    00483
    00484         drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
    00485                    ignore_top?0:style->borderTopWidth(),
    00486                    ignore_bottom?0:style->borderBottomWidth());
    00487     }
    00488
    00489     if(render_r)
    00490     {
    00491         const QColor& rc = style->borderRightColor();
    00492
    00493         bool ignore_top =
    00494           (tc == rc) &&
    00495           (rs <= SOLID || rs == INSET) &&
    00496           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
    00497
    00498         bool ignore_bottom =
    00499           (bc == rc) &&
    00500           (rs <= SOLID || rs == INSET) &&
    00501           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
    00502
    00503         drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
    00504                    ignore_top?0:style->borderTopWidth(),
    00505                    ignore_bottom?0:style->borderBottomWidth());
    00506     }
    00507 }
    00508
    00509 void RenderObject::paintOutline(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style)
    00510 {
    00511     int ow = style->outlineWidth();
    00512     if(!ow) return;
    00513
    00514     const QColor& oc = style->outlineColor();
    00515     EBorderStyle os = style->outlineStyle();
    00516
    00517     drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
    00518                QColor(oc), style->color(),
    00519                os, ow, ow, true);
    00520
    00521     drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
    00522                QColor(oc), style->color(),
    00523                os, ow, ow, true);
    00524
    00525     drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
    00526                QColor(oc), style->color(),
    00527                os, ow, ow, true);
    00528
    00529     drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
    00530                QColor(oc), style->color(),
    00531                os, ow, ow, true);
    00532
    00533 }
    00534
    00535 void RenderObject::paint( QPainter *p, int x, int y, int w, int h, int tx, int ty)
    00536 {
    00537     paintObject(p, x, y, w, h, tx, ty);
    00538 }
    00539
    00540 void RenderObject::repaintRectangle(int x, int y, int w, int h, bool f)
    00541 {
    00542     if(parent()) parent()->repaintRectangle(x, y, w, h, f);
    00543 }
    00544
    00545 #ifndef NDEBUG
    00546
    00547 QString RenderObject::information() const
    00548 {
    00549     QString str;
    00550     QTextStream ts( &str, IO_WriteOnly );
    00551     ts << renderName()
    00552         << "(" << (style() ? style()->refCount() : 0) << ")"
    00553        << ": " << (void*)this << "  ";
    00554     if (isInline()) ts << "il ";
    00555     if (childrenInline()) ts << "ci ";
    00556     if (isFloating()) ts << "fl ";
    00557     if (isAnonymousBox()) ts << "an ";
    00558     if (isRelPositioned()) ts << "rp ";
    00559     if (isPositioned()) ts << "ps ";
    00560     if (overhangingContents()) ts << "oc ";
    00561     if (layouted()) ts << "lt ";
    00562     if (minMaxKnown()) ts << "mmk ";
    00563     if (m_recalcMinMax) ts << "rmm ";
    00564     if (mouseInside()) ts << "mi ";
    00565     if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
    00566     if (element() && element()->active()) ts << "act ";
    00567     if (element() && element()->hasAnchor()) ts << "anchor ";
    00568     if (element() && element()->focused()) ts << "focus ";
    00569     if (element()) ts << " <" <<  getTagName(element()->id()).string() << ">";
    00570     ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
    00571        << " [" << minWidth() << "-" << maxWidth() << "]"
    00572         << (isTableCell() ?
    00573             ( QString::fromLatin1(" [r=") +
    00574               QString::number( static_cast<const RenderTableCell *>(this)->row() ) +
    00575               QString::fromLatin1(" c=") +
    00576               QString::number( static_cast<const RenderTableCell *>(this)->col() ) +
    00577               QString::fromLatin1(" rs=") +
    00578               QString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
    00579               QString::fromLatin1(" cs=") +
    00580               QString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
    00581               QString::fromLatin1("]") ) : QString::null );
    00582         return str;
    00583 }
    00584
    00585 void RenderObject::printTree(int indent) const
    00586 {
    00587     QString ind;
    00588     ind.fill(' ', indent);
    00589
    00590     kdDebug() << ind << information() << endl;
    00591
    00592     RenderObject *child = firstChild();
    00593     while( child != 0 )
    00594     {
    00595         child->printTree(indent+2);
    00596         child = child->nextSibling();
    00597     }
    00598 }
    00599
    00600 void RenderObject::dump(QTextStream *stream, QString ind) const
    00601 {
    00602     if (isAnonymousBox()) { *stream << " anonymousBox"; }
    00603     if (isFloating()) { *stream << " floating"; }
    00604     if (isPositioned()) { *stream << " positioned"; }
    00605     if (isRelPositioned()) { *stream << " relPositioned"; }
    00606     if (isText()) { *stream << " text"; }
    00607     if (isInline()) { *stream << " inline"; }
    00608     if (isReplaced()) { *stream << " replaced"; }
    00609     if (hasSpecialObjects()) { *stream << " specialObjects"; }
    00610     if (layouted()) { *stream << " layouted"; }
    00611     if (minMaxKnown()) { *stream << " minMaxKnown"; }
    00612     if (overhangingContents()) { *stream << " overhangingContents"; }
    00613     if (hasFirstLine()) { *stream << " hasFirstLine"; }
    00614     *stream << endl;
    00615
    00616     RenderObject *child = firstChild();
    00617     while( child != 0 )
    00618     {
    00619         *stream << ind << child->renderName() << ": ";
    00620         child->dump(stream,ind+"  ");
    00621         child = child->nextSibling();
    00622     }
    00623 }
    00624 #endif
    00625
    00626 void RenderObject::selectionStartEnd(int& spos, int& epos)
    00627 {
    00628     if (parent())
    00629         parent()->selectionStartEnd(spos, epos);
    00630 }
    00631
    00632 void RenderObject::setStyle(RenderStyle *style)
    00633 {
    00634     if (m_style == style)
    00635         return;
    00636
    00637     RenderStyle::Diff d = m_style ? m_style->diff( style ) : RenderStyle::Layout;
    00638     //qDebug("new style, diff=%d", d);
    00639     // reset style flags
    00640     m_floating = false;
    00641     m_positioned = false;
    00642     m_relPositioned = false;
    00643     m_paintSpecial = false;
    00644     // no support for changing the display type dynamically... object must be
    00645     // detached and re-attached as a different type
    00646     //m_inline = true;
    00647
    00648     RenderStyle *oldStyle = m_style;
    00649     m_style = style;
    00650
    00651     CachedImage* ob = 0;
    00652     CachedImage* nb = 0;
    00653
    00654     if (m_style)
    00655     {
    00656         m_style->ref();
    00657         nb = m_style->backgroundImage();
    00658     }
    00659     if (oldStyle)
    00660     {
    00661         ob = oldStyle->backgroundImage();
    00662         oldStyle->deref();
    00663     }
    00664
    00665     if( ob != nb ) {
    00666         if(ob) ob->deref(this);
    00667         if(nb) nb->ref(this);
    00668     }
    00669
    00670     setSpecialObjects( m_style->backgroundColor().isValid() || m_style->hasBorder() || nb );
    00671     m_hasFirstLine = (style->getPseudoStyle(RenderStyle::FIRST_LINE) != 0);
    00672
    00673     if ( d >= RenderStyle::Position && m_parent ) {
    00674         //qDebug("triggering relayout");
    00675         setMinMaxKnown(false);
    00676         setLayouted(false);
    00677     } else if ( m_parent ) {
    00678         //qDebug("triggering repaint");
    00679         repaint();
    00680     }
    00681 }
    00682
    00683 void RenderObject::setOverhangingContents(bool p)
    00684 {
    00685     if (m_overhangingContents == p)
    00686         return;
    00687
    00688     RenderObject *cb = containingBlock();
    00689     if (p)
    00690     {
    00691         m_overhangingContents = true;
    00692         if (cb!=this)
    00693             cb->setOverhangingContents();
    00694     }
    00695     else
    00696     {
    00697         RenderObject *n;
    00698         bool c=false;
    00699
    00700         for( n = firstChild(); n != 0; n = n->nextSibling() )
    00701         {
    00702             if (n->isPositioned() || n->overhangingContents())
    00703                 c=true;
    00704         }
    00705
    00706         if (c)
    00707             return;
    00708         else
    00709         {
    00710             m_overhangingContents = false;
    00711             if (cb!=this)
    00712                 cb->setOverhangingContents(false);
    00713         }
    00714     }
    00715 }
    00716
    00717 QRect RenderObject::viewRect() const
    00718 {
    00719     return containingBlock()->viewRect();
    00720 }
    00721
    00722 bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
    00723 {
    00724     if(parent())
    00725         return parent()->absolutePosition(xPos, yPos, f);
    00726     else
    00727     {
    00728         xPos = yPos = 0;
    00729         return false;
    00730     }
    00731 }
    00732
    00733 void RenderObject::cursorPos(int /*offset*/, int &_x, int &_y, int &height)
    00734 {
    00735     _x = _y = height = -1;
    00736 }
    00737
    00738 int RenderObject::paddingTop() const
    00739 {
    00740     int w = 0;
    00741     Length padding = m_style->paddingTop();
    00742     if (padding.isPercent())
    00743         w = containingBlock()->contentWidth();
    00744     w = padding.minWidth(w);
    00745     if ( isTableCell() && padding.isVariable() )
    00746         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    00747     return w;
    00748 }
    00749
    00750 int RenderObject::paddingBottom() const
    00751 {
    00752     int w = 0;
    00753     Length padding = style()->paddingBottom();
    00754     if (padding.isPercent())
    00755         w = containingBlock()->contentWidth();
    00756     w = padding.minWidth(w);
    00757     if ( isTableCell() && padding.isVariable() )
    00758         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    00759     return w;
    00760 }
    00761
    00762 int RenderObject::paddingLeft() const
    00763 {
    00764     int w = 0;
    00765     Length padding = style()->paddingLeft();
    00766     if (padding.isPercent())
    00767         w = containingBlock()->contentWidth();
    00768     w = padding.minWidth(w);
    00769     if ( isTableCell() && padding.isVariable() )
    00770         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    00771     return w;
    00772 }
    00773
    00774 int RenderObject::paddingRight() const
    00775 {
    00776     int w = 0;
    00777     Length padding = style()->paddingRight();
    00778     if (padding.isPercent())
    00779         w = containingBlock()->contentWidth();
    00780     w = padding.minWidth(w);
    00781     if ( isTableCell() && padding.isVariable() )
    00782         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
    00783     return w;
    00784 }
    00785
    00786 RenderRoot* RenderObject::root() const
    00787 {
    00788     RenderObject* o = const_cast<RenderObject*>( this );
    00789     while ( o->parent() ) o = o->parent();
    00790
    00791     KHTMLAssert( o->isRoot() );
    00792     return static_cast<RenderRoot*>( o );
    00793 }
    00794
    00795 RenderObject *RenderObject::container() const
    00796 {
    00797     EPosition pos = m_style->position();
    00798     RenderObject *o = 0;
    00799     if( pos == FIXED )
    00800         o = root();
    00801     else if ( pos == ABSOLUTE )
    00802         o = containingBlock();
    00803     else
    00804         o = parent();
    00805     return o;
    00806 }
    00807
    00808 #if 0
    00809 void RenderObject::invalidateLayout()
    00810 {
    00811     kdDebug() << "RenderObject::invalidateLayout " << renderName() << endl;
    00812     setLayouted(false);
    00813     if (m_parent && m_parent->layouted())
    00814         m_parent->invalidateLayout();
    00815 }
    00816 #endif
    00817
    00818 void RenderObject::removeFromSpecialObjects()
    00819 {
    00820     if (isPositioned() || isFloating()) {
    00821         RenderObject *p;
    00822         for (p = parent(); p; p = p->parent()) {
    00823             if (p->isFlow())
    00824                 static_cast<RenderFlow*>(p)->removeSpecialObject(this);
    00825         }
    00826     }
    00827 }
    00828
    00829 void RenderObject::detach()
    00830 {
    00831     remove();
    00832     // by default no refcounting
    00833     delete this;
    00834 }
    00835
    00836 FindSelectionResult RenderObject::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset )
    00837 {
    00838     NodeInfo info(true, false);
    00839     if ( nodeAtPoint( info, _x, _y, _tx, _ty ) && info.innerNode() )
    00840     {
    00841         RenderObject* r = info.innerNode()->renderer();
    00842         if ( r ) {
    00843             if ( r == this ) {
    00844                 node = info.innerNode();
    00845                 offset = 0; // we have no text...
    00846                 return SelectionPointInside;
    00847             }
    00848             else
    00849                 return r->checkSelectionPoint( _x, _y, _tx, _ty, node, offset );
    00850         }
    00851     }
    00852     //kdDebug(6030) << "nodeAtPoint Failed. Fallback - hmm, SelectionPointAfter" << endl;
    00853     node = 0;
    00854     offset = 0;
    00855     return SelectionPointAfter;
    00856 }
    00857
    00858 bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty)
    00859 {
    00860     int tx = _tx + xPos();
    00861     int ty = _ty + yPos();
    00862     if (isRelPositioned())
    00863         static_cast<RenderBox*>(this)->relativePositionOffset(tx, ty);
    00864
    00865     bool checkPoint = style()->visibility() != HIDDEN && (_y >= ty) && (_y < ty + height());
    00866     bool inside = (checkPoint && (_x >= tx) && (_x < tx + width())) || isBody() || isHtml();
    00867     bool inner = !info.innerNode();
    00868
    00869     // ### table should have its own, more performant method
    00870     if (overhangingContents() || isInline() || isRoot() || isTableRow() || isTableSection() || isPositioned() || checkPoint || mouseInside() ) {
    00871         for (RenderObject* child = lastChild(); child; child = child->previousSibling())
    00872             if (!child->isSpecial() && child->nodeAtPoint(info, _x, _y, tx, ty))
    00873                 inside = true;
    00874     }
    00875
    00876     if (inside && element()) {
    00877         if (!info.innerNode())
    00878             info.setInnerNode(element());
    00879
    00880         if (!info.URLElement()) {
    00881             RenderObject* p = this;
    00882             while (p) {
    00883                 if (p->element() && p->element()->hasAnchor()) {
    00884                     info.setURLElement(p->element());
    00885                     break;
    00886                 }
    00887                 if (!isSpecial()) break;
    00888                 p = p->parent();
    00889             }
    00890         }
    00891     }
    00892
    00893     if (!info.readonly()) {
    00894         // lets see if we need a new style
    00895         bool oldinside = mouseInside();
    00896         setMouseInside(inside && inner);
    00897         if (element()) {
    00898             bool oldactive = element()->active();
    00899             if (oldactive != (inside && info.active() && element() == info.innerNode()))
    00900                 element()->setActive(inside && info.active() && element() == info.innerNode());
    00901             if ( ((oldinside != mouseInside()) && style()->hasHover()) ||
    00902                  ((oldactive != element()->active()) && style()->hasActive()))
    00903                 element()->setChanged();
    00904         }
    00905     }
    00906
    00907     return inside;
    00908 }
    00909
    00910 short RenderObject::verticalPositionHint( bool firstLine ) const
    00911 {
    00912     short vpos = m_verticalPosition;
    00913     if ( m_verticalPosition == PositionUndefined || firstLine ) {
    00914         vpos = getVerticalPosition( firstLine );
    00915         if ( !firstLine )
    00916             const_cast<RenderObject *>(this)->m_verticalPosition = vpos;
    00917     }
    00918     return vpos;
    00919
    00920 }
    00921
    00922 short RenderObject::getVerticalPosition( bool firstLine ) const
    00923 {
    00924     // vertical align for table cells has a different meaning
    00925     int vpos = 0;
    00926     if ( !isTableCell() ) {
    00927         EVerticalAlign va = style()->verticalAlign();
    00928         if ( va == TOP ) {
    00929             vpos = PositionTop;
    00930         } else if ( va == BOTTOM ) {
    00931             vpos = PositionBottom;
    00932         } else if ( va == LENGTH ) {
    00933             vpos = -style()->verticalAlignLength().width( lineHeight( firstLine ) );
    00934         } else if ( parent() && parent()->childrenInline() ) {
    00935             vpos = parent()->verticalPositionHint( firstLine );
    00936             // don't allow elements nested inside text-top to have a different valignment.
    00937             if ( va == BASELINE )
    00938                 return vpos;
    00939
    00940         //     if ( vpos == PositionTop )
    00941 //                 vpos = 0;
    00942
    00943             const QFont &f = parent()->font( firstLine );
    00944             int fontheight = parent()->lineHeight( firstLine );
    00945             int fontsize = f.pixelSize();
    00946             int halfleading = ( fontheight - fontsize ) / 2;
    00947
    00948             if ( va == SUB )
    00949                 vpos += fontsize/5 + 1;
    00950             else if ( va == SUPER )
    00951                 vpos -= fontsize/3 + 1;
    00952             else if ( va == TEXT_TOP ) {
    00953 //                 qDebug( "got TEXT_TOP vertical pos hint" );
    00954 //                 qDebug( "parent:" );
    00955 //                 qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", fontheight, fontsize, parent()->baselinePosition( firstLine ) );
    00956 //                 qDebug( "this:" );
    00957 //                 qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", lineHeight( firstLine ), style()->font().pixelSize(), baselinePosition( firstLine ) );
    00958                 vpos += ( baselinePosition( firstLine ) - parent()->baselinePosition( firstLine ) +
    00959                         halfleading );
    00960             } else if ( va == MIDDLE ) {
    00961                 QRect b = QFontMetrics(f).boundingRect('x');
    00962                 vpos += -b.height()/2 - lineHeight( firstLine )/2 + baselinePosition( firstLine );
    00963             } else if ( va == TEXT_BOTTOM ) {
    00964                 vpos += QFontMetrics(f).descent();
    00965                 if ( !isReplaced() )
    00966                     vpos -= fontMetrics(firstLine).descent();
    00967             } else if ( va == BASELINE_MIDDLE )
    00968                 vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
    00969         }
    00970     }
    00971     return vpos;
    00972 }
    00973
    00974 short RenderObject::lineHeight( bool firstLine ) const
    00975 {
    00976     Length lh;
    00977     if( firstLine && hasFirstLine() ) {
    00978         RenderStyle *pseudoStyle  = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
    00979         if ( pseudoStyle )
    00980             lh = pseudoStyle->lineHeight();
    00981     }
    00982     else
    00983         lh = style()->lineHeight();
    00984
    00985     // its "unset", choose nice default
    00986     if ( lh.value() < 0 )
    00987         return style()->fontMetrics().lineSpacing();
    00988
    00989     if ( lh.isPercent() )
    00990         return lh.minWidth( style()->font().pixelSize() );
    00991
    00992     // its fixed
    00993     return lh.value();
    00994 }
    00995
    00996 short RenderObject::baselinePosition( bool firstLine ) const
    00997 {
    00998     const QFontMetrics &fm = fontMetrics( firstLine );
    00999     return fm.ascent() + ( lineHeight( firstLine ) - fm.height() ) / 2;
    01000 }
    01001
    01002 void RenderObject::invalidateVerticalPositions()
    01003 {
    01004     m_verticalPosition = PositionUndefined;
    01005     RenderObject *child = firstChild();
    01006     while( child ) {
    01007         child->invalidateVerticalPositions();
    01008         child = child->nextSibling();
    01009     }
    01010 }
    01011
    01012 void RenderObject::recalcMinMaxWidths()
    01013 {
    01014     KHTMLAssert( m_recalcMinMax );
    01015
    01016 #ifdef DEBUG_LAYOUT
    01017     kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
    01018 #endif
    01019
    01020     RenderObject *child = firstChild();
    01021     while( child ) {
    01022         // gcc sucks. if anybody knows a trick to get rid of the
    01023         // warning without adding an extra (unneeded) initialisation,
    01024         // go ahead
    01025         int cmin, cmax;
    01026         bool test = false;
    01027         if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
    01028             cmin = child->minWidth();
    01029             cmax = child->maxWidth();
    01030             test = true;
    01031         }
    01032         if ( child->m_recalcMinMax )
    01033             child->recalcMinMaxWidths();
    01034         if ( !child->m_minMaxKnown )
    01035             child->calcMinMaxWidth();
    01036         if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
    01037             m_minMaxKnown = false;
    01038         child = child->nextSibling();
    01039     }
    01040
    01041     // we need to recalculate, if the contains inline children, as the change could have
    01042     // happened somewhere deep inside the child tree
    01043     if ( !isInline() && childrenInline() )
    01044         m_minMaxKnown = false;
    01045
    01046     if ( !m_minMaxKnown )
    01047         calcMinMaxWidth();
    01048     m_recalcMinMax = false;
    01049 }
    01050
    01051 void RenderObject::scheduleRelayout()
    01052 {
    01053     if (!isRoot()) return;
    01054     KHTMLView *view = static_cast<RenderRoot *>(this)->view();
    01055     if ( view )
    01056         view->scheduleRelayout();
    01057 }
    01058
    01059
    01060 void RenderObject::removeLeftoverAnonymousBoxes()
    01061 {
    01062 }

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:38 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001