⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_flow.cpp

📁 monqueror一个很具有参考价值的源玛
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/** * This file is part of the html renderer for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: render_flow.cpp,v 1.2 2002/01/28 04:31:02 leon Exp $ */// -------------------------------------------------------------------------//#define DEBUG//#define DEBUG_LAYOUT//#define BOX_DEBUG#include <assert.h>#include "render_interface.h"#include "mgcolor.h"#include "mgpen.h"#include "mgbrush.h"#include "mgsize.h"#include "mgrect.h"#include "mgfontmetrics.h"#include "mgpainter.h"#include "mghtml_part.h"#include "dom_string.h"#include "render_flow.h"#include "render_text.h"#include "render_style.h"#include "render_root.h"#include "render_replaced.h"#include "htmlhashes.h"#include "kdebug.h"using namespace DOM;using namespace khtml;#define DEBUG_BY_XHTANG 1static inline int collapseMargins(int a, int b){    if(a >= 0 && b >= 0) return (a > b ? a : b );    if(a > 0 && b < 0) return a + b;    if(a < 0 && b > 0) return b + a;    return ( a > b ? b : a);}void RenderFlow::mysetLayouted(bool f){    RenderObject *child = firstChild();	while(child){//		child->mysetLayouted(false);		child->setLayouted(false);		child = child->nextSibling();	}}RenderFlow::RenderFlow()    : RenderBox(){    m_inline = true;    m_childrenInline = true;    m_haveAnonymous = false;    specialObjects = 0;}void RenderFlow::setStyle(RenderStyle *style){//    kdDebug( 6040 ) << (void*)this<< " renderFlow::setstyle()" << endl;    RenderBox::setStyle(style);    if(m_positioned)        m_style->setDisplay(BLOCK);    if( m_floating || !style->display() == INLINE)        m_inline = false;    if (m_inline == true && m_childrenInline==false)        m_inline = false;    m_pre = false;    if(m_style->whiteSpace() == PRE)        m_pre = true;    if (haveAnonymousBox())    {        RenderObject *child = firstChild();        while(child != 0)        {            if(child->isAnonymousBox())            {                if (child->style())                    delete child->style();                RenderStyle* newStyle = new RenderStyle(style);                newStyle->setDisplay(BLOCK);                child->setPart(m_part);                child->setStyle(newStyle);                child->setIsAnonymousBox(true);            }            child = child->nextSibling();        }    }}RenderFlow::~RenderFlow(){    if (specialObjects)        delete specialObjects;    if(isAnonymousBox()) // usually the style object is deleted by the DOM tree, but        // since anonymous boxes don't have a corresponding DOM element...        delete m_style;}void RenderFlow::print(MGPainter *p, int _x, int _y, int _w, int _h,                                 int _tx, int _ty){#ifdef DEBUG_LAYOUT    //kdDebug( 6040 ) << renderName() << "(RenderFlow) " << this << " ::print() x/y/w/h = ("  << xPos() << "/" << yPos() << "/" << width() << "/" << height()  << ")" << endl;#endif    if(!isInline())    {        _tx += m_x;        _ty += m_y;    }    // check if we need to do anything at all...    if(!isInline() && !containsPositioned() && !isRelPositioned() && !isPositioned() )    {        int h = m_height;        if(specialObjects && floatBottom() > h) h = floatBottom();        if((_ty > _y + _h) || (_ty + h < _y))        {            //kdDebug( 6040 ) << "cut!" << endl;            return;        }    }    printObject(p, _x, _y, _w, _h, _tx, _ty);}void RenderFlow::printObject(MGPainter *p, int _x, int _y,                                       int _w, int _h, int _tx, int _ty){#ifdef DEBUG_LAYOUT    //kdDebug( 6040 ) << renderName() << "(RenderFlow) " << this << " ::printObject() w/h = (" << width() << "/" << height() << ")" << endl;#endif    // add offset for relative positioning    if(isRelPositioned())	{        relativePositionOffset(_tx, _ty);//		kdDebug(0) << "flow " << _tx << ", " << _ty << endl;	}    // 1. print background, borders etc    if(m_printSpecial && !isInline() && m_visible)        printBoxDecorations(p, _x, _y, _w, _h, _tx, _ty);    // 2. print contents    RenderObject *child = firstChild();    while(child != 0)    {		if(!child->isFloating() && !child->isPositioned())			{			child->print(p, _x, _y, _w, _h, _tx, _ty);		}        child = child->nextSibling();    }	    // 3. print floats and other non-flow objects    if(specialObjects)    {        SpecialObject* r;        QListIterator<SpecialObject> it(*specialObjects);        for ( ; (r = it.current()); ++it ) {            if (r->node->containingBlock()==this) {                RenderObject *o = r->node;                //kdDebug(0) << renderName() << "printing positioned at " << _tx + o->xPos() << "/" << _ty + o->yPos()<< endl;                o->print(p, _x, _y, _w, _h, _tx , _ty);            }        }    }#ifdef BOX_DEBUG    if(isAnonymousBox())	outlineBox(p, _tx, _ty, "green");    else	outlineBox(p, _tx, _ty);#endif}void RenderFlow::setPos( int xPos, int yPos ){    m_y = yPos;    setXPos(xPos);}void RenderFlow::setXPos( int xPos ){    m_x = xPos;}void RenderFlow::layout(){    //kdDebug( 6040 ) << renderName() << " " << this << "::layout() start" << endl;    //QTime t;    //t.start();    assert(!isInline());    int oldWidth = m_width;    calcWidth();//    kdDebug( 6040 ) << specialObjects << "," << oldWidth << ","//            << m_width << ","<< layouted() << "," << isAnonymousBox() << endl;    if ( (!specialObjects || (isListItem() && specialObjects->count() == 1) ) && oldWidth == m_width && layouted() && !isAnonymousBox()            && !containsPositioned() && !isPositioned()) return;#ifdef DEBUG_LAYOUT    //kdDebug( 6040 ) << renderName() << "(RenderFlow) " << this << " ::layout() width=" << m_width << ", layouted=" << layouted() << endl;    //if(containingBlock() == static_cast<RenderObject *>(this))        //kdDebug( 6040 ) << renderName() << ": containingBlock == this" << endl;#endif    if(m_width<=0) {        if(m_y < 0) m_y = 0;        setLayouted();        return;    }    clearFloats();    m_height = 0;    m_clearStatus = CNONE;//    kdDebug( 6040 ) << "childrenInline()=" << childrenInline() << endl;    if(childrenInline())        layoutInlineChildren();    else        layoutBlockChildren();    calcHeight();        if(hasOverhangingFloats())    {        if(isFloating() || isTableCell())        {            m_height = floatBottom();            m_height += borderBottom() + paddingBottom();        }    }        else if (isTableCell() && m_last && m_last->hasOverhangingFloats())     {        m_height = m_last->yPos() + static_cast<RenderFlow*>(m_last)->floatBottom();        m_height += borderBottom() + paddingBottom();           }        layoutSpecialObjects();    //kdDebug() << renderName() << " layout width=" << m_width << " height=" << m_height << endl;         setLayouted();}void RenderFlow::layoutSpecialObjects(){    if(specialObjects) {	//kdDebug( 6040 ) << renderName() << " " << this << "::layoutSpecialObjects() start" << endl;        SpecialObject* r;        QListIterator<SpecialObject> it(*specialObjects);        for ( ; (r = it.current()); ++it ) {            //kdDebug(6040) << "have a positioned object" << endl;            if (r->type == SpecialObject::Positioned)                r->node->layout();        }        specialObjects->sort();    }}void RenderFlow::layoutBlockChildren(){#ifdef DEBUG_LAYOUT    //kdDebug( 6040 ) << renderName() << " layoutBlockChildren( )" << endl;#endif    bool _layouted = true;    int xPos = 0;    int toAdd = 0;    m_height = 0;    if(m_style->hasBorder())    {        xPos += borderLeft();        m_height += borderTop();        toAdd += borderBottom();    }    if(m_style->hasPadding())    {        xPos += paddingLeft();        m_height += paddingTop();        toAdd += paddingBottom();    }    if( m_style->direction() == RTL ) {        xPos = marginLeft() + m_width - paddingRight() - borderRight();    }    RenderObject *child = firstChild();    RenderFlow *prevFlow = 0;        int prevMargin = 0;    if(isTableCell() && child)        prevMargin = -child->marginTop();    //QTime t;    //t.start();    while( child != 0 )    {        //kdDebug( 6040 ) << "   " << child->renderName() << " loop " << child << ", " << child->isInline() << ", " << child->layouted() << endl;        //kdDebug( 6040 ) << t.elapsed() << endl;        // ### might be some layouts are done two times... FIX that.        if (child->isPositioned())        {            child->layout();            static_cast<RenderFlow*>(child->containingBlock())->insertPositioned(child);	    //kdDebug() << "RenderFlow::layoutBlockChildren inserting positioned into " << child->containingBlock()->renderName() << endl;             child = child->nextSibling();            continue;        } else if ( child->isReplaced() )            child->layout();        if(checkClear(child)) prevMargin = 0; // ### should only be 0        // if oldHeight+prevMargin < newHeight        int margin = child->marginTop();        //kdDebug(0) << "margin = " << margin << " prevMargin = " << prevMargin << endl;        margin = collapseMargins(margin, prevMargin);        m_height += margin;        //kdDebug(0) << "margin = " << margin << " yPos = " << m_height << endl;        if(prevFlow)        {            if (prevFlow->yPos()+prevFlow->floatBottom() > m_height)                child->setLayouted(false);            else                prevFlow=0;        }                          child->setYPos(m_height);        child->layout();                                                             int chPos = xPos + child->marginLeft();        if( m_style->textAlign() == KONQ_CENTER && !child->style()->marginLeft().isVariable()) {            //kdDebug() << "should align to center" << endl;            chPos += ( width() - child->width() )/2;        } else if(m_style->direction() == LTR) {            // html blocks flow around floats            if (style()->htmlHacks() && child->style()->flowAroundFloats() )                chPos = leftOffset(m_height) + child->marginLeft();        } else {            chPos -= child->width() + child->marginLeft() + child->marginRight();            if (style()->htmlHacks() && child->style()->flowAroundFloats() )                chPos -= leftOffset(m_height);        }        child->setXPos(chPos);        m_height += child->height();        prevMargin = child->marginBottom();                if (child->isFlow())            prevFlow = static_cast<RenderFlow*>(child);				//kdDebug() << "In function: RenderFlow::layoutBlockChildren" << endl;		//kdDebug() << "child name is " << child->renderName() << endl;                        child = child->nextSibling();    }    if(!isTableCell())	m_height += prevMargin;    m_height += toAdd;    setLayouted(_layouted);    // kdDebug( 6040 ) << "layouted = " << layouted_ << endl;}bool RenderFlow::checkClear(RenderObject *child){    //kdDebug( 6040 ) << "checkClear oldheight=" << m_height << endl;    RenderObject *o = child->previousSibling();    while(o && !o->isFlow())        o = o->previousSibling();    if(!o) o = this;    RenderFlow *prev = static_cast<RenderFlow *>(o);    switch(child->style()->clear())    {    case CNONE:        return false;    case CLEFT:    {        int bottom = prev->leftBottom() + prev->yPos();        if(m_height < bottom)            m_height = bottom; //###  + lastFloat()->marginBotton()?        break;    }    case CRIGHT:    {        int bottom = prev->rightBottom() + prev->yPos();        if(m_height < bottom)            m_height = bottom; //###  + lastFloat()->marginBotton()?        break;    }    case CBOTH:    {        int bottom = prev->floatBottom() + prev->yPos();        if(m_height < bottom)            m_height = bottom; //###  + lastFloat()->marginBotton()?        break;    }    }    //kdDebug( 6040 ) << "    newHeight = " << m_height << endl;    return true;}voidRenderFlow::insertPositioned(RenderObject *o){    //kdDebug() << renderName() << "::insertPositioned " << this<< isAnonymousBox() << " " << o << endl;    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) return;        ++it;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -