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

📄 render_table.cpp

📁 将konqueror浏览器移植到ARM9 2410中
💻 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.133 2001/07/30 19:45:49 koivisto Exp $ *///#define TABLE_DEBUG//#define TABLE_PRINT//#define DEBUG_LAYOUT//#define BOX_DEBUG#include "render_table.h"#include <qlist.h>#include <qstack.h>#include <qbrush.h>#include <qpainter.h>#include <qpalette.h>#include <qdrawutil.h>#include <kglobal.h>#include "dom_string.h"#include "misc/helper.h"#include "misc/khtmllayout.h"#include <kdebug.h>#include <assert.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()    : RenderFlow(){    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);    _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 * ));    }    needsCellsRecalc = false;}RenderTable::~RenderTable(){    for ( unsigned int r = 0; r < allocRows; r++ )        delete [] cells[r];    delete [] cells;}void RenderTable::setStyle(RenderStyle *_style){    RenderFlow::setStyle(_style);    // init RenderObject attributes    setInline(style()->display()==INLINE_TABLE);    setReplaced(style()->display()==INLINE_TABLE);    spacing = style()->borderSpacing();    collapseBorders = style()->borderCollapse();}void RenderTable::position(int x, int y, int, int, int, bool, bool){    //for inline tables only    m_x = x + marginLeft();    m_y = y + marginTop();}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:        {        RenderContainer::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();            newStyle->inheritFrom(style());            newStyle->setDisplay(TABLE_ROW_GROUP);            o->setStyle(newStyle);            o->setIsAnonymousBox(true);            addChild(o, beforeChild);        }        o->addChild(child);        return;    }    RenderContainer::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(){    while ( col < totalCols && cells[row][col] != 0L )        col++;    if (col<=0) return;    RenderTableCell* cell = cells[row][col-1];    if (!cell) return;}void RenderTable::addCell( RenderTableCell *cell ){    while ( col < totalCols && cells[row][col] != 0L )        col++;    setCells( row, col, cell );    setMinMaxKnown(false);    setLayouted(false);    col++;}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();    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));    }    totalCols = newCols;}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();    if (_width.type==Fixed)        _maxSize=_width.value;    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 = cell->colSpan();    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    // Netscape ignores width values of "0" or "0%"    if ( style()->htmlHacks() && _width.value == 0 && (_width.type == Percent || _width.type == Fixed) )	    _width = Length();    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;        col->maxCell = _cell;        if (_colSpan>maxColSpan)            maxColSpan=_colSpan;        colInfos[_colSpan-1]->insert(_startCol,col);    }    if (_minSize > col->min)    {        col->min = _minSize;        col->minCell = _cell;    }    if (_maxSize > col->max)    {        col->max = _maxSize;        col->maxCell = _cell;    }        // Fixed width is treated as variable     if (_width.type == col->type)        col->value = _width.value > col->value ? _width.value : col->value;            if ( (_width.type > col->type && (_width.type!=Fixed || col->type<=Variable))            || ( col->type == Fixed && _width.type!=Variable) )    {        col->type = _width.type;        col->value = _width.value;    }    setMinMaxKnown(false);#ifdef TABLE_DEBUG    kdDebug( 6040 ) << "  end: min=" << colMinWidth[_startCol] << " max=" << colMaxWidth[_startCol] << " act=" << actColWidth[_startCol] << endl;#endif}void RenderTable::spreadSpanMinMax(int col, int span, int distmin,    int distmax, LengthType type){#ifdef TABLE_DEBUG    kdDebug( 6040 ) << "RenderTable::spreadSpanMinMax() " << type << " " << distmin << " " << distmax << endl;#endif    if (distmin<1)        distmin=0;    if (distmax<1)        distmax=0;    if (distmin<1 && distmax<1)        return;    bool hasUsableCols=false;    int tmax=distmax;    int tmin=distmin;    int c;    for (c=col; c < col+span ; ++c)    {        if (colType[c]<=type || (type == Variable && distmax==0))        {            hasUsableCols=true;            break;        }    }    if (hasUsableCols)    {        // spread span maxWidth        LengthType tt = Undefined;        bool out=false;        while (tt<=type && !out && tmax)        {            tmax = distributeMaxWidth(tmax,type,tt,col,span);            switch (tt)            {

⌨️ 快捷键说明

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