📄 render_flow.cpp
字号:
if (!f) f = new SpecialObject; f->type = SpecialObject::Positioned; f->node = o; f->count = specialObjects->count(); specialObjects->append(f); setContainsPositioned(true);}voidRenderFlow::insertFloat(RenderObject *o){// kdDebug( 6040 ) << renderName() << " " << this << "::insertFloat()" << endl; // a floating element if(!specialObjects) { specialObjects = new QSortedList<SpecialObject>; specialObjects->setAutoDelete(true); } // don't insert it twice! QListIterator<SpecialObject> it(*specialObjects); SpecialObject* f; while ( (f = it.current()) ) { if (f->node == o) { f->width = o->width() + o->marginLeft() + o->marginRight(); f->startY = -1; f->endY = -1; return; } ++it; } o->layout(); if(!f) f = new SpecialObject; f->count = specialObjects->count(); f->startY = -1; f->endY = -1; f->width = o->width() + o->marginLeft() + o->marginRight(); if(o->style()->floating() == FLEFT) f->type = SpecialObject::FloatLeft; else f->type = SpecialObject::FloatRight; f->node = o; specialObjects->append(f);// kdDebug( 6040 ) << "inserting node " << o << " number of specialobject = " << // specialObjects->count() << endl;}void RenderFlow::positionNewFloats(){ if(!specialObjects) return; SpecialObject *f = specialObjects->getLast(); if(!f || f->startY != -1) return; SpecialObject *lastFloat; while(1) { lastFloat = specialObjects->prev(); if(!lastFloat || (lastFloat->startY != -1 && lastFloat->type!=SpecialObject::Positioned)) { specialObjects->next(); break; } f = lastFloat; } int y = m_height; // the float can not start above the y position of the last positioned float. if(lastFloat && lastFloat->startY > y) y = lastFloat->startY; while(f) { //skip elements copied from elsewhere and positioned elements if (f->node->containingBlock()!=this || f->type==SpecialObject::Positioned) { f = specialObjects->next(); continue; } RenderObject *o = f->node; //kdDebug() << "In function: RenderFlow::positionNewFloats" << endl; //kdDebug() << "child name is " << o->renderName() << endl; int _height = o->height() + o->marginTop() + o->marginBottom(); if (o->style()->floating() == FLEFT) { int fx = leftOffset(y); if (contentWidth() >= f->width) { while (rightOffset(y)-fx < f->width) { y++; fx = leftOffset(y); } } f->left = fx; //kdDebug() << "positioning left aligned float at (" << fx + o->marginLeft() << "/" << y + o->marginTop() << ")" << endl; o->setXPos(fx + o->marginLeft()); o->setYPos(y + o->marginTop()); } else { int fx = rightOffset(y); if (contentWidth() >= f->width) { while (fx - leftOffset(y) < f->width) { y++; fx = rightOffset(y); } } f->left = fx - f->width; //kdDebug() << "positioning right aligned float at (" << fx - o->marginRight() - o->width() << "/" << y + o->marginTop() << ")" << endl; o->setXPos(fx - o->marginRight() - o->width()); o->setYPos(y + o->marginTop()); } f->startY = y; f->endY = f->startY + _height; // Copy float to the containing block // In case of anonymous box, copy to containing block _and_ it's containing block, // so the creation of anonymous box does not prevent elements dom parent // of getting the float. // // The whole thing is a hack to support html behaviour, where certain block // elements (tables, lists) flow around floats as if they were inlines. // Khtml float layouting is modeled after css2, and implementing this has // been somewhat messy // if(style()->htmlHacks() && childrenInline() && !style()->flowAroundFloats()) { RenderObject* obj = this; for (int n = 0 ; n < (isAnonymousBox()?2:1); n++ ) { obj = obj->containingBlock(); if (obj && obj->isFlow() ) { RenderFlow* par = static_cast<RenderFlow*>(obj); if (par->isFloating()) break; else { if(!par->specialObjects) { par->specialObjects = new QSortedList<SpecialObject>; par->specialObjects->setAutoDelete(true); } QListIterator<SpecialObject> it(*par->specialObjects); SpecialObject* tt; while ( (tt = it.current()) ) { if (tt->node == o) break; ++it; } if (!tt || tt->node==o) { SpecialObject* so = new SpecialObject(*f); so->count = specialObjects->count(); so->startY += m_y; so->endY += m_y; par->specialObjects->append(so); } } } } }// kdDebug( 6040 ) << "specialObject y= (" << f->startY << "-" << f->endY << ")" << endl; f = specialObjects->next(); }}void RenderFlow::newLine(){ positionNewFloats(); // set y position int newY = 0; switch(m_clearStatus) { case CLEFT: newY = leftBottom(); break; case CRIGHT: newY = rightBottom(); break; case CBOTH: newY = floatBottom(); default: break; } if(m_height < newY) {// kdDebug( 6040 ) << "adjusting y position" << endl; m_height = newY; } m_clearStatus = CNONE;}shortRenderFlow::leftOffset(int y) const{ int left = 0; if ( firstLine && m_style->direction() == LTR ) { int cw=0; if (style()->width().isPercent()) cw = containingBlock()->contentWidth(); left += m_style->textIndent().minWidth(cw); } if(m_style->hasBorder()) left = borderLeft(); if(m_style->hasPadding()) left += paddingLeft(); if(!specialObjects) return left; SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) {// kdDebug( 6040 ) << "left: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl; if (r->startY <= y && r->endY > y && r->type == SpecialObject::FloatLeft && r->left + r->width > left) left = r->left + r->width; }// kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl; return left;}intRenderFlow::rightOffset(int y) const{ int right = m_width; if ( firstLine && m_style->direction() == RTL ) { int cw=0; if (style()->width().isPercent()) cw = containingBlock()->contentWidth(); right += m_style->textIndent().minWidth(cw); } if(m_style->hasBorder()) right -= borderRight(); if(m_style->hasPadding()) right -= paddingRight(); if (!specialObjects) return right; SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) {// kdDebug( 6040 ) << "right: sy, ey, x, w " << // r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl; if (r->startY <= y && r->endY > y && r->type == SpecialObject::FloatRight && r->left < right) right = r->left; }// kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl; return right;}unsigned shortRenderFlow::lineWidth(int y) const{// kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl; return rightOffset(y) - leftOffset(y);}intRenderFlow::floatBottom() const{ if (!specialObjects) return 0; int bottom=0; SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) if (r->endY>bottom && r->type <= SpecialObject::FloatRight) bottom=r->endY; return bottom;}intRenderFlow::lowestPosition() const{ int bottom = m_height + marginBottom(); int lp = 0; if ( !m_childrenInline ) { RenderObject *last = lastChild(); while( last && (last->isPositioned() || last->isFloating()) ) last = last->previousSibling(); if( last ) lp = yPos() + last->lowestPosition(); } if( lp > bottom ) bottom = lp; //kdDebug(0) << renderName() << " bottom = " << bottom << endl; if (specialObjects) { SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) { lp = 0; if ( r->type < SpecialObject::Positioned ) { lp = r->startY + r->node->lowestPosition(); //kdDebug(0) << r->node->renderName() << " lp = " << lp << "startY=" << r->startY << endl; } else if ( r->type <= SpecialObject::Positioned ) { lp = r->node->yPos() + r->node->lowestPosition(); } if( lp > bottom) bottom = lp; } } //kdDebug(0) << renderName() << " bottom = " << bottom << endl; return bottom;}intRenderFlow::leftBottom(){ if (!specialObjects) return 0; int bottom=0; SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) if (r->endY>bottom && r->type == SpecialObject::FloatLeft) bottom=r->endY; return bottom;}intRenderFlow::rightBottom(){ if (!specialObjects) return 0; int bottom=0; SpecialObject* r; QListIterator<SpecialObject> it(*specialObjects); for ( ; (r = it.current()); ++it ) if (r->endY>bottom && r->type == SpecialObject::FloatRight) bottom=r->endY; return bottom;}voidRenderFlow::clearFloats(){// kdDebug( 6040 ) << "clearFloats" << endl; if (specialObjects) { if( containsPositioned() ) { specialObjects->first(); while ( specialObjects->current()) { if ( specialObjects->current()->type != SpecialObject::Positioned ) specialObjects->remove(); else specialObjects->next(); } } else specialObjects->clear(); } if (isFloating()) return; RenderObject *prev = m_previous; // find the element to copy the floats from // pass non-flows // pass fAF's unless they contain overhanging stuff while (prev && (!prev->isFlow() || (prev->style()->flowAroundFloats() && (static_cast<RenderFlow *>(prev)->floatBottom()+prev->yPos() < m_y )))) prev = prev->previousSibling(); int offset = m_y; if(prev ) { if(prev->isTableCell()) return; offset -= prev->yPos(); } else { prev = m_parent; if(!prev) return; } // add overhanging special objects from the previous RenderFlow if(!prev->isFlow()) return; RenderFlow * flow = static_cast<RenderFlow *>(prev); if(!flow->specialObjects) return; if(style()->htmlHacks() && style()->flowAroundFloats()) return; //html tables and lists flow as blocks if(flow->floatBottom() > offset) {#ifdef DEBUG_LAYOUT// kdDebug( 6040 ) << this << ": adding overhanging floats" << endl;#endif // we have overhanging floats if(!specialObjects) { specialObjects = new QSortedList<SpecialObject>; specialObjects->setAutoDelete(true); } QListIterator<SpecialObject> it(*flow->specialObjects); SpecialObject *r; for ( ; (r = it.current()); ++it ) { if (r->endY > offset && r->type <= SpecialObject::FloatRight) { // we need to add the float here too SpecialObject *special = new SpecialObject; special->count = specialObjects->count(); special->startY = r->startY - offset; special->endY = r->endY - offset; special->left = r->left - marginLeft(); if (prev!=m_parent) special->left += prev->marginLeft(); special->width = r->width; special->node = r->node; special->type = r->type; specialObjects->append(special);#ifdef DEBUG_LAYOUT// kdDebug( 6040 ) << " y: " << special->startY << "-" << special->endY << " left: " << special->left << " width: " << special->width << endl;#endif } } }}short RenderFlow::baselineOffset() const{ switch(m_style->verticalAlign()) { case BASELINE: { int r = 0; if (firstChild()) r = firstChild()->yPos() + firstChild()->baselineOffset();//kdDebug( 6040 ) << "aligned to baseline " << r << endl; return r; } case SUB: // ### case SUPER: // ### case TOP: return 0; case TEXT_TOP: return MGFontMetrics(m_style->font(), m_part).ascent(); case MIDDLE: return contentHeight()/2; case BOTTOM: return contentHeight(); case TEXT_BOTTOM: return contentHeight() - MGFontMetrics(m_style->font(), m_part).descent();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -