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

📄 render_table.cpp

📁 monqueror一个很具有参考价值的源玛
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/** * 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) * * 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_table.cpp,v 1.1.1.1 2002/01/16 10:39:56 ymwei Exp $ *///#define TABLE_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_table.h"#include "khtmllayout.h"#include "kdebug.h"using namespace khtml;template class QArray<LengthType>;#define FOR_EACH_CELL(r,c,cell) \    for ( unsigned int r = 0; r < totalRows; r++ )                    \    {                                                                 \        for ( unsigned int c = 0; c < totalCols; c++ )                \        {                                                             \            RenderTableCell *cell = cells[r][c];             \            if (!cell)                                                \                continue;                                             \            if ( (c < totalCols - 1) && (cell == cells[r][c+1]) )     \                continue;                                             \            if ( (r < totalRows - 1) && (cells[r+1][c] == cell) )     \                continue;#define END_FOR_EACH } }RenderTable::RenderTable()    : RenderBox(){    tCaption = 0;    _oldColElem = 0;    head = 0;    foot = 0;    firstBody = 0;    incremental = false;    m_maxWidth = 0;    rules = None;    frame = Void;    row = 0;    col = 0;    maxColSpan = 0;    totalColInfos = 0;    colInfos.setAutoDelete(true);    setParsing();    _currentCol=0;    _lastParentWidth = 0;    columnPos.resize( 2 );    colMaxWidth.resize( 1 );    colMinWidth.resize( 1 );    colValue.resize(1);    colType.resize(1);    actColWidth.resize(1);    columnPos.fill( 0 );    colMaxWidth.fill( 0 );    colMinWidth.fill( 0 );    colValue.fill(0);    colType.fill(Variable);    actColWidth.fill(0);    columnPos[0] = spacing;    totalCols = 0;   // this should be expanded to the maximum number of cols                     // by the first row parsed    totalRows = 1;    allocRows = 5;   // allocate five rows initially    cells = new RenderTableCell ** [allocRows];    for ( unsigned int r = 0; r < allocRows; r++ )    {        cells[r] = new RenderTableCell * [totalCols];        memset( cells[r], 0, totalCols * sizeof( RenderTableCell * ));    }}RenderTable::~RenderTable(){    for ( unsigned int r = 0; r < allocRows; r++ )        delete [] cells[r];    delete [] cells;}void RenderTable::setStyle(RenderStyle *style){    RenderBox::setStyle(style);    // init RenderObject attributes    m_inline = (style->display()==INLINE_TABLE);    m_replaced = (style->display()==INLINE_TABLE);    spacing = style->borderSpacing();    collapseBorders = style->borderCollapse();}inline voidRenderTable::ColInfo::update(){    if (minCell)        min = minCell->minWidth();    if (maxCell)        max = maxCell->maxWidth();}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;    switch(child->style()->display())    {    case TABLE_CAPTION:        tCaption = static_cast<RenderTableCaption *>(child);        break;    case TABLE_COLUMN:    case TABLE_COLUMN_GROUP:        {        RenderObject::addChild(child,beforeChild);        RenderTableCol* colel = static_cast<RenderTableCol *>(child);        if (_oldColElem && _oldColElem->style()->display() == TABLE_COLUMN_GROUP)            _currentCol = _oldColElem->lastCol();        _oldColElem = colel;        colel->setStartCol(_currentCol);        if (child->style()->display() == TABLE_COLUMN)            _currentCol++;        else            _currentCol+=colel->span();        addColInfo(colel);        incremental = true;        colel->setTable(this);        }        return;    case TABLE_HEADER_GROUP:        if(incremental && !columnPos[totalCols]);// calcColWidth();//      setTHead(static_cast<RenderTableSection *>(child));        break;    case TABLE_FOOTER_GROUP:        if(incremental && !columnPos[totalCols]);// calcColWidth();//      setTFoot(static_cast<RenderTableSection *>(child));        break;    case TABLE_ROW_GROUP:        if(incremental && !columnPos[totalCols]);// calcColWidth();        if(!firstBody)            firstBody = static_cast<RenderTableSection *>(child);        break;    default:        if ( !beforeChild )            beforeChild = lastChild();        if ( beforeChild && beforeChild->isAnonymousBox() )            o = beforeChild;        else {//          kdDebug( 6040 ) << "creating anonymous table section" << endl;            o = new RenderTableSection();            RenderStyle *newStyle = new RenderStyle(m_style);            newStyle->setDisplay(TABLE_ROW_GROUP);            o->setPart(m_part);            o->setStyle(newStyle);            o->setIsAnonymousBox(true);            addChild(o, beforeChild);        }        o->addChild(child);        return;    }    RenderObject::addChild(child,beforeChild);    child->setTable(this);}void RenderTable::startRow(){    while ( col < totalCols && cells[row][col] != 0 )        col++;    if ( col )        row++;    col = 0;    if(row > totalRows) totalRows = row;}void RenderTable::closeRow(){    bool recalc = false;        while ( col < totalCols && cells[row][col] != 0L )        col++;        if (col<=0) return;        RenderTableCell* cell = cells[row][col-1];        if (!cell) return;            while ( col < totalCols && cells[row][col] == 0L )    {                  cells[row][col] = cell;        col++;          recalc = true;    }    if (recalc)    {        recalcColInfos();    }    }void RenderTable::addCell( RenderTableCell *cell ){    while ( col < totalCols && cells[row][col] != 0L )        col++;    setCells( row, col, cell );    setMinMaxKnown(false);    setLayouted(false);    col++;}int RenderTable::realSpan( RenderTableCell* cell){    unsigned int r = cell->row();    unsigned int c = cell->col();    unsigned int sp = cell->colSpan();        int span=1;        if (c+sp==totalCols || cells[r][c+sp]!=cell)        span = sp;    else    {        while (c>0 && cells[r][c-1]==cell) c--;        while (c<totalCols && cells[r][c+1]==cell) { c++ ; span++; }    }//    kdDebug(0) << "realspan(" << r << "," << c << ")=" << span << endl;            return span;}int RenderTable::realSpan( unsigned int r, unsigned int c){    return realSpan(cells[r][c]);}void RenderTable::setCells( unsigned int r, unsigned int c,                                     RenderTableCell *cell ){#ifdef TABLE_DEBUG    kdDebug( 6040 ) << "span = " << cell->rowSpan() << "d/" << cell->colSpan() << "d" << endl;#endif    cell->setRow(r);    cell->setCol(c);    unsigned int endRow = r + cell->rowSpan();    unsigned int endCol = c + cell->colSpan();    // The first row sets the number of columns.  Do not allow subsequent    // rows to change the number of columns.//WABA: Why not? Let's give crappy HTML a chance//    if ( row != 0 && endCol > totalCols )//      endCol = totalCols;    if ( endCol > totalCols )        addColumns( endCol - totalCols );    if ( endRow >= allocRows )        addRows( endRow - allocRows + 10 );    if ( endRow > totalRows )        totalRows = endRow;    for ( ; r < endRow; r++ )    {        for ( unsigned int tc = c; tc < endCol; tc++ )        {            cells[r][tc] = cell;        }    }}void RenderTable::addRows( int num ){    RenderTableCell ***newRows =        new RenderTableCell ** [allocRows + num];    memcpy( newRows, cells, allocRows * sizeof(RenderTableCell **) );    delete [] cells;    cells = newRows;    for ( unsigned int r = allocRows; r < allocRows + num; r++ )    {        cells[r] = new RenderTableCell * [totalCols];        memset( cells[r], 0, totalCols * sizeof( RenderTableCell * ));    }    allocRows += num;}void RenderTable::addColumns( int num ){#ifdef TABLE_DEBUG    kdDebug( 6040 ) << "addColumns() totalCols=" << totalCols << " new=" << num << endl;#endif    RenderTableCell **newCells;    int newCols = totalCols + num;    // resize the col structs to the number of columns    columnPos.resize(newCols+1);    memset( columnPos.data() + totalCols + 1, 0, num*sizeof(int));    colMaxWidth.resize(newCols);    memset( colMaxWidth.data() + totalCols , 0, num*sizeof(int));    colMinWidth.resize(newCols);    memset( colMinWidth.data() + totalCols , 0, num*sizeof(int));    colValue.resize(newCols);    memset( colValue.data() + totalCols , 0, num*sizeof(int));    colType.resize(newCols);    memset( colType.data() + totalCols , 0, num*sizeof(LengthType));    actColWidth.resize(newCols);    memset( actColWidth.data() + totalCols , 0, num*sizeof(LengthType));    for ( unsigned int r = 0; r < allocRows; r++ )    {        newCells = new RenderTableCell * [newCols];        memcpy( newCells, cells[r],                totalCols * sizeof( RenderTableCell * ) );        memset( newCells + totalCols, 0,                num * sizeof( RenderTableCell * ) );        delete [] cells[r];        cells[r] = newCells;    }    int mSpan = newCols;    colInfos.resize(mSpan);    for ( unsigned int c =0 ; c < totalCols; c++ )    {        colInfos[c]->resize(newCols);    }    for ( unsigned int c = totalCols; (int)c < newCols; c++ )    {        colInfos.insert(c, new ColInfoLine(newCols-c+1));    }    // check if adding of cols means that we have to    // spread some existing columns to cover the new cols    bool recalc = false;        for ( unsigned int r=0 ; r < row ; r++)    {        RenderTableCell* cell = cells[r][totalCols-1];        if (cell && cell->rowSpan()==1) //might need to be more generic        {            for ( unsigned int c = totalCols; (int)c < newCols; c++ )            {                if (cells[r][c]==0L)                {                    cells[r][c] = cell;                    recalc=true;                }            }        }    }        totalCols = newCols;        if (recalc)    {        recalcColInfos();    }       }void RenderTable::recalcColInfos(){//    kdDebug(0) << "RenderTable::recalcColInfos()" << endl;        for (int s=0 ; s<maxColSpan; s++)    {        for (unsigned int c=0 ; c<totalCols; c++)            if (c<colInfos[s]->size())                colInfos[s]->remove(c);                     }                maxColSpan = 0;        FOR_EACH_CELL(r,c,cell)        addColInfo(cell);                             END_FOR_EACH    }void RenderTable::addColInfo(RenderTableCol *colel){    int _startCol = colel->col();    int span = colel->span();    int _minSize=0;    int _maxSize=0;    Length _width = colel->width();    for (int n=0; n<span; ++n)    {#ifdef TABLE_DEBUG        kdDebug( 6040 ) << "COL" << endl;        kdDebug( 6040 ) << "    startCol=" << _startCol << " span=" << span << endl;        kdDebug( 6040 ) << "    min=" << _minSize << " max=" << _maxSize << " val=" << _width.value << endl;#endif        addColInfo(_startCol+n, 1 , _minSize, _maxSize, _width ,0);    }}void RenderTable::addColInfo(RenderTableCell *cell){    int _startCol = cell->col();    int _colSpan = realSpan(cell);    int _minSize = cell->minWidth();    int _maxSize = cell->maxWidth();    if (collapseBorders)    {        int bw = cell->borderLeft() + cell->borderRight();        _minSize -= bw;        _maxSize -= bw;    }    Length _width = cell->style()->width();    addColInfo(_startCol, _colSpan, _minSize, _maxSize, _width ,cell);}void RenderTable::addColInfo(int _startCol, int _colSpan,                                      int _minSize, int _maxSize,                                      Length _width, RenderTableCell* _cell){#ifdef TABLE_DEBUG    kdDebug( 6040 ) << "addColInfo():" << endl;    kdDebug( 6040 ) << "    startCol=" << _startCol << " span=" << _colSpan << endl;    kdDebug( 6040 ) << "    min=" << _minSize << " max=" << _maxSize << endl;    kdDebug( 6040 ) << "    totalCols=" << totalCols << endl;#endif    if (_startCol + _colSpan > (int) totalCols)        addColumns(totalCols - _startCol + _colSpan);    ColInfo* col = colInfos[_colSpan-1]->at(_startCol);    if (!col)    {        col = new ColInfo;        col->span = _colSpan;        col->start = _startCol;        col->minCell = _cell;

⌨️ 快捷键说明

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