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

📄 render_table.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1997 Martin Jones (mjones@kde.org) *           (C) 1997 Torben Weis (weis@kde.org) *           (C) 1998 Waldo Bastian (bastian@kde.org) *           (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * 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. *///#define TABLE_DEBUG//#define TABLE_PRINT//#define DEBUG_LAYOUT//#define BOX_DEBUG#include "rendering/render_table.h"#include "rendering/table_layout.h"#include "html/html_tableimpl.h"#include "misc/htmltags.h"#include "misc/htmlattrs.h"#include "xml/dom_docimpl.h"#include <kglobal.h>#include <qapplication.h>#include <qstyle.h>#include <kdebug.h>#include <assert.h>#include "khtmlview.h"using namespace khtml;using namespace DOM;RenderTable::RenderTable(DOM::NodeImpl* node)    : RenderBlock(node){    tCaption = 0;    head = foot = firstBody = 0;    tableLayout = 0;    m_currentBorder = 0;        rules = None;    frame = Void;    has_col_elems = false;    hspacing = 0;    vspacing = 0;    padding = 0;    needSectionRecalc = false;    padding = 0;    columnPos.resize( 2 );    columnPos.fill( 0 );    columns.resize( 1 );    columns.fill( ColumnStruct() );    columnPos[0] = 0;}RenderTable::~RenderTable(){    delete tableLayout;}void RenderTable::setStyle(RenderStyle *_style){    ETableLayout oldTableLayout = style() ? style()->tableLayout() : TAUTO;    RenderBlock::setStyle(_style);    // In the collapsed border model, there is no cell spacing.    hspacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();    vspacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();    columnPos[0] = hspacing;    if ( !tableLayout || style()->tableLayout() != oldTableLayout ) {	delete tableLayout;        // According to the CSS2 spec, you only use fixed table layout if an        // explicit width is specified on the table.  Auto width implies auto table layout.	if (style()->tableLayout() == TFIXED && !style()->width().isVariable()) {	    tableLayout = new FixedTableLayout(this);#ifdef DEBUG_LAYOUT	    kdDebug( 6040 ) << "using fixed table layout" << endl;#endif	} else	    tableLayout = new AutoTableLayout(this);    }}void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild){#ifdef DEBUG_LAYOUT    kdDebug( 6040 ) << renderName() << "(Table)::addChild( " << child->renderName() << ", " <<                       (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;#endif    RenderObject *o = child;    if (child->element() && child->element()->id() == ID_FORM) {        RenderContainer::addChild(child,beforeChild);        return;    }    switch(child->style()->display())    {    case TABLE_CAPTION:        tCaption = static_cast<RenderBlock *>(child);        break;    case TABLE_COLUMN:    case TABLE_COLUMN_GROUP:	has_col_elems = true;        break;    case TABLE_HEADER_GROUP:	if ( !head )	    head = static_cast<RenderTableSection *>(child);	else if ( !firstBody )            firstBody = static_cast<RenderTableSection *>(child);        break;    case TABLE_FOOTER_GROUP:	if ( !foot ) {	    foot = static_cast<RenderTableSection *>(child);	    break;	}	// fall through    case TABLE_ROW_GROUP:        if(!firstBody)            firstBody = static_cast<RenderTableSection *>(child);        break;    default:        if ( !beforeChild && lastChild() &&	     lastChild()->isTableSection() && lastChild()->isAnonymous() ) {            o = lastChild();        } else {	    RenderObject *lastBox = beforeChild;	    while ( lastBox && lastBox->parent()->isAnonymous() &&		    !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION )		lastBox = lastBox->parent();	    if ( lastBox && lastBox->isAnonymous() ) {		lastBox->addChild( child, beforeChild );		return;	    } else {		if ( beforeChild && !beforeChild->isTableSection() )		    beforeChild = 0;  		//kdDebug( 6040 ) << this <<" creating anonymous table section beforeChild="<< beforeChild << endl;		o = new (renderArena()) RenderTableSection(document() /* anonymous */);		RenderStyle *newStyle = new (renderArena()) RenderStyle();		newStyle->inheritFrom(style());                newStyle->setDisplay(TABLE_ROW_GROUP);		o->setStyle(newStyle);		addChild(o, beforeChild);	    }        }        o->addChild(child);        child->setNeedsLayoutAndMinMaxRecalc();	return;    }    RenderContainer::addChild(child,beforeChild);}void RenderTable::calcWidth(){    if ( isPositioned() ) {        calcAbsoluteHorizontal();    }    RenderBlock *cb = containingBlock();    int availableWidth = cb->contentWidth();    LengthType widthType = style()->width().type;    if (widthType > Relative && style()->width().value > 0) {	// Percent or fixed table        m_width = style()->width().minWidth( availableWidth );        if(m_minWidth > m_width) m_width = m_minWidth;    }    else {        // An auto width table should shrink to fit within the line width if necessary in order to         // avoid overlapping floats.        availableWidth = cb->lineWidth( m_y );                // Subtract out any fixed margins from our available width for auto width tables.        int marginTotal = 0;        if (style()->marginLeft().type != Variable)            marginTotal += style()->marginLeft().width(availableWidth);        if (style()->marginRight().type != Variable)            marginTotal += style()->marginRight().width(availableWidth);                    // Subtract out our margins to get the available content width.        int availContentWidth = kMax(0, availableWidth - marginTotal);                // Ensure we aren't bigger than our max width or smaller than our min width.        m_width = kMin(availContentWidth, m_maxWidth);    }        m_width = kMax(m_width, m_minWidth);    // Finally, with our true width determined, compute our margins for real.    m_marginRight = 0;    m_marginLeft = 0;    calcHorizontalMargins(style()->marginLeft(),style()->marginRight(),availableWidth);}void RenderTable::layout(){    KHTMLAssert( needsLayout() );    KHTMLAssert( minMaxKnown() );    KHTMLAssert( !needSectionRecalc );    if (posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {        // All we have to is lay out our positioned objects.        layoutPositionedObjects(true);        setNeedsLayout(false);        return;    }    QRect oldBounds, oldFullBounds;    bool checkForRepaint = checkForRepaintDuringLayout();    if (checkForRepaint)        getAbsoluteRepaintRectIncludingFloats(oldBounds, oldFullBounds);        //kdDebug( 6040 ) << renderName() << "(Table)"<< this << " ::layout0() width=" << width() << ", needsLayout=" << needsLayout() << endl;        m_height = 0;    initMaxMarginValues();        //int oldWidth = m_width;    calcWidth();    // the optimisation below doesn't work since the internal table    // layout could have changed.  we need to add a flag to the table    // layout that tells us if something has changed in the min max    // calculations to do it correctly.//     if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )    tableLayout->layout();#ifdef DEBUG_LAYOUT    kdDebug( 6040 ) << renderName() << "(Table)::layout1() width=" << width() << ", marginLeft=" << marginLeft() << " marginRight=" << marginRight() << endl;#endif    setCellWidths();    // layout child objects    int calculatedHeight = 0;    RenderObject *child = firstChild();    while( child ) {	if ( child->needsLayout() && !(child->element() && child->element()->id() == ID_FORM))	    child->layout();	if ( child->isTableSection() ) {	    static_cast<RenderTableSection *>(child)->calcRowHeight();	    calculatedHeight += static_cast<RenderTableSection *>(child)->layoutRows( 0 );	}	child = child->nextSibling();    }    // ### collapse caption margin    if(tCaption && tCaption->style()->captionSide() != CAPBOTTOM) {        tCaption->setPos(tCaption->marginLeft(), m_height);        m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();    }    int bpTop = borderTop() + (collapseBorders() ? 0 : paddingTop());    int bpBottom = borderBottom() + (collapseBorders() ? 0 : paddingBottom());        m_height += bpTop;    int oldHeight = m_height;    calcHeight();    int newHeight = m_height;    m_height = oldHeight;    // html tables with percent height are relative to view    Length h = style()->height();    int th = -(bpTop + bpBottom); // Tables size as though CSS height includes border/padding.    if (isPositioned())        th = newHeight; // FIXME: Leave this alone for now but investigate later.    else if (h.isFixed())        th += h.value;    else if (h.isPercent())    {        RenderObject* c = containingBlock();        for ( ; 	     !c->isCanvas() && !c->isBody() && !c->isTableCell() && !c->isPositioned() && !c->isFloating();              c = c->containingBlock()) {            Length ch = c->style()->height();            if (ch.isFixed()) {                th += h.width(ch.value);                break;            }        }        if (c->isTableCell()) {            RenderTableCell* cell = static_cast<RenderTableCell*>(c);            int cellHeight = cell->getCellPercentageHeight();            if (cellHeight)                th += h.width(cellHeight);        }        else  {            Length ch = c->style()->height();            if (ch.isFixed())                th += h.width(ch.value);            else                // FIXME: Investigate this.  Seems wrong to always expand to fill the viewRect.                // We need to substract out the margins of this block. -dwh                th += h.width(viewRect().height() - c->marginBottom() - c->marginTop());        }    }    th = kMax(0, th);    // layout rows    if ( th > calculatedHeight ) {	// we have to redistribute that height to get the constraint correctly	// just force the first body to the height needed	// ### FIXME This should take height constraints on all table sections into account and distribute	// accordingly. For now this should be good enough        if (firstBody) {            firstBody->calcRowHeight();            firstBody->layoutRows( th - calculatedHeight );        }    }        int bl = borderLeft();    if (!collapseBorders())        bl += paddingLeft();    // position the table sections    if ( head ) {	head->setPos(bl, m_height);	m_height += head->height();    }    RenderObject *body = firstBody;    while ( body ) {	if ( body != head && body != foot && body->isTableSection() ) {	    body->setPos(bl, m_height);	    m_height += body->height();	}	body = body->nextSibling();    }    if ( foot ) {	foot->setPos(bl, m_height);	m_height += foot->height();    }    m_height += bpBottom;                   if(tCaption && tCaption->style()->captionSide()==CAPBOTTOM) {        tCaption->setPos(tCaption->marginLeft(), m_height);        m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();    }    //kdDebug(0) << "table height: " << m_height << endl;    // table can be containing block of positioned elements.    // ### only pass true if width or height changed.    layoutPositionedObjects( true );    // Repaint with our new bounds if they are different from our old bounds.    if (checkForRepaint)        repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);        setNeedsLayout(false);}void RenderTable::setCellWidths(){#ifdef DEBUG_LAYOUT    kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;#endif    RenderObject *child = firstChild();    while( child ) {	if ( child->isTableSection() )	    static_cast<RenderTableSection *>(child)->setCellWidths();	child = child->nextSibling();    }}void RenderTable::paint(PaintInfo& i, int _tx, int _ty){    if (needsLayout())        return;            _tx += xPos();    _ty += yPos();    PaintAction paintAction = i.phase;    #ifdef TABLE_PRINT    kdDebug( 6040 ) << "RenderTable::paint() w/h = (" << width() << "/" << height() << ")" << endl;#endif    if (!isRelPositioned() && !isPositioned()) {        int os = 2*maximalOutlineSize(paintAction);        if ((_ty >= i.r.y() + i.r.height() + os) || (_ty + height() <= i.r.y() - os)) return;        if ((_tx >= i.r.x() + i.r.width() + os) || (_tx + width() <= i.r.x() - os)) return;    }

⌨️ 快捷键说明

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