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
00202
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
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
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
00393 case OUTSET:
00394 if(style == OUTSET && (s == BSBottom || s == BSRight))
00395 c = c.dark();
00396
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
00639
00640 m_floating = false;
00641 m_positioned = false;
00642 m_relPositioned = false;
00643 m_paintSpecial = false;
00644
00645
00646
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
00675 setMinMaxKnown(false);
00676 setLayouted(false);
00677 } else if ( m_parent ) {
00678
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 , 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
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;
00846 return SelectionPointInside;
00847 }
00848 else
00849 return r->checkSelectionPoint( _x, _y, _tx, _ty, node, offset );
00850 }
00851 }
00852
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
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
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
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
00937 if ( va == BASELINE )
00938 return vpos;
00939
00940
00941
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
00954
00955
00956
00957
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
00986 if ( lh.value < 0 )
00987 return style()->fontMetrics().lineSpacing();
00988
00989 if ( lh.isPercent() )
00990 return lh.minWidth( style()->font().pixelSize() );
00991
00992
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
01023
01024
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
01042
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 }