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

📄 rendertablesection.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * 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, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "RenderTableSection.h"#include "CachedImage.h"#include "Document.h"#include "HTMLNames.h"#include "RenderTableCell.h"#include "RenderTableCol.h"#include "RenderTableRow.h"#include "RenderView.h"#include <limits>#include <wtf/Vector.h>using namespace std;namespace WebCore {using namespace HTMLNames;RenderTableSection::RenderTableSection(Node* node)    : RenderBox(node)    , m_gridRows(0)    , m_cCol(0)    , m_cRow(-1)    , m_needsCellRecalc(false)    , m_outerBorderLeft(0)    , m_outerBorderRight(0)    , m_outerBorderTop(0)    , m_outerBorderBottom(0)    , m_overflowLeft(0)    , m_overflowWidth(0)    , m_overflowTop(0)    , m_overflowHeight(0)    , m_hasOverflowingCell(false){    // init RenderObject attributes    setInline(false);   // our object is not Inline}RenderTableSection::~RenderTableSection(){    clearGrid();}void RenderTableSection::destroy(){    RenderTable* recalcTable = table();        RenderBox::destroy();        // recalc cell info because RenderTable has unguarded pointers    // stored that point to this RenderTableSection.    if (recalcTable)        recalcTable->setNeedsSectionRecalc();}void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild){    // Make sure we don't append things after :after-generated content if we have it.    if (!beforeChild && isAfterContent(lastChild()))        beforeChild = lastChild();    bool isTableSection = node() && (node()->hasTagName(theadTag) || node()->hasTagName(tbodyTag) || node()->hasTagName(tfootTag));    if (!child->isTableRow()) {        if (isTableSection && child->node() && child->node()->hasTagName(formTag) && document()->isHTMLDocument()) {            RenderBox::addChild(child, beforeChild);            return;        }        RenderObject* last = beforeChild;        if (!last)            last = lastChild();        if (last && last->isAnonymous()) {            last->addChild(child);            return;        }        // If beforeChild is inside an anonymous cell/row, insert into the cell or into        // the anonymous row containing it, if there is one.        RenderObject* lastBox = last;        while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())            lastBox = lastBox->parent();        if (lastBox && lastBox->isAnonymous()) {            lastBox->addChild(child, beforeChild);            return;        }        RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);        RefPtr<RenderStyle> newStyle = RenderStyle::create();        newStyle->inheritFrom(style());        newStyle->setDisplay(TABLE_ROW);        row->setStyle(newStyle.release());        addChild(row, beforeChild);        row->addChild(child);        return;    }    if (beforeChild)        setNeedsCellRecalc();    ++m_cRow;    m_cCol = 0;    // make sure we have enough rows    if (!ensureRows(m_cRow + 1))        return;    m_grid[m_cRow].rowRenderer = static_cast<RenderTableRow*>(child);    if (!beforeChild) {        m_grid[m_cRow].height = child->style()->height();        if (m_grid[m_cRow].height.isRelative())            m_grid[m_cRow].height = Length();    }    // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.    while (beforeChild && beforeChild->parent() != this)        beforeChild = beforeChild->parent();    ASSERT(!beforeChild || beforeChild->isTableRow() || isTableSection && beforeChild->node() && beforeChild->node()->hasTagName(formTag) && document()->isHTMLDocument());    RenderBox::addChild(child, beforeChild);}void RenderTableSection::removeChild(RenderObject* oldChild){    setNeedsCellRecalc();    RenderBox::removeChild(oldChild);}bool RenderTableSection::ensureRows(int numRows){    int nRows = m_gridRows;    if (numRows > nRows) {        if (numRows > static_cast<int>(m_grid.size())) {            size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);            if (static_cast<size_t>(numRows) > maxSize)                return false;            m_grid.grow(numRows);        }        m_gridRows = numRows;        int nCols = max(1, table()->numEffCols());        CellStruct emptyCellStruct;        emptyCellStruct.cell = 0;        emptyCellStruct.inColSpan = false;        for (int r = nRows; r < numRows; r++) {            m_grid[r].row = new Row(nCols);            m_grid[r].row->fill(emptyCellStruct);            m_grid[r].rowRenderer = 0;            m_grid[r].baseline = 0;            m_grid[r].height = Length();        }    }    return true;}void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row){    int rSpan = cell->rowSpan();    int cSpan = cell->colSpan();    Vector<RenderTable::ColumnStruct>& columns = table()->columns();    int nCols = columns.size();    // ### mozilla still seems to do the old HTML way, even for strict DTD    // (see the annotation on table cell layouting in the CSS specs and the testcase below:    // <TABLE border>    // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4    // <TR><TD colspan="2">5    // </TABLE>    while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).cell || cellAt(m_cRow, m_cCol).inColSpan))        m_cCol++;    if (rSpan == 1) {        // we ignore height settings on rowspan cells        Length height = cell->style()->height();        if (height.isPositive() || (height.isRelative() && height.value() >= 0)) {            Length cRowHeight = m_grid[m_cRow].height;            switch (height.type()) {                case Percent:                    if (!(cRowHeight.isPercent()) ||                        (cRowHeight.isPercent() && cRowHeight.rawValue() < height.rawValue()))                        m_grid[m_cRow].height = height;                        break;                case Fixed:                    if (cRowHeight.type() < Percent ||                        (cRowHeight.isFixed() && cRowHeight.value() < height.value()))                        m_grid[m_cRow].height = height;                    break;                case Relative:                default:                    break;            }        }    }    // make sure we have enough rows    if (!ensureRows(m_cRow + rSpan))        return;    m_grid[m_cRow].rowRenderer = row;    int col = m_cCol;    // tell the cell where it is    CellStruct currentCell;    currentCell.cell = cell;    currentCell.inColSpan = false;    while (cSpan) {        int currentSpan;        if (m_cCol >= nCols) {            table()->appendColumn(cSpan);            currentSpan = cSpan;        } else {            if (cSpan < columns[m_cCol].span)                table()->splitColumn(m_cCol, cSpan);            currentSpan = columns[m_cCol].span;        }        for (int r = 0; r < rSpan; r++) {            CellStruct& c = cellAt(m_cRow + r, m_cCol);            if (currentCell.cell && !c.cell)                c.cell = currentCell.cell;            if (currentCell.inColSpan)                c.inColSpan = true;        }        m_cCol++;        cSpan -= currentSpan;        currentCell.cell = 0;        currentCell.inColSpan = true;    }    if (cell) {        cell->setRow(m_cRow);        cell->setCol(table()->effColToCol(col));    }}void RenderTableSection::setCellWidths(){    Vector<int>& columnPos = table()->columnPositions();    LayoutStateMaintainer statePusher(view());        for (int i = 0; i < m_gridRows; i++) {        Row& row = *m_grid[i].row;        int cols = row.size();        for (int j = 0; j < cols; j++) {            CellStruct current = row[j];            RenderTableCell* cell = current.cell;            if (!cell)                continue;            int endCol = j;            int cspan = cell->colSpan();            while (cspan && endCol < cols) {                cspan -= table()->columns()[endCol].span;                endCol++;            }            int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();            int oldWidth = cell->width();            if (w != oldWidth) {                cell->setNeedsLayout(true);                if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {                    if (!statePusher.didPush()) {                        // Technically, we should also push state for the row, but since                        // rows don't push a coordinate transform, that's not necessary.                        statePusher.push(this, IntSize(x(), y()));                    }                    cell->repaint();                }                cell->updateWidth(w);            }        }    }        statePusher.pop();  // only pops if we pushed}int RenderTableSection::calcRowHeight(){#ifndef NDEBUG    setNeedsLayoutIsForbidden(true);#endif    ASSERT(!needsLayout());    RenderTableCell* cell;    int spacing = table()->vBorderSpacing();    LayoutStateMaintainer statePusher(view());    m_rowPos.resize(m_gridRows + 1);    m_rowPos[0] = spacing;    for (int r = 0; r < m_gridRows; r++) {        m_rowPos[r + 1] = 0;        m_grid[r].baseline = 0;        int baseline = 0;        int bdesc = 0;        int ch = m_grid[r].height.calcMinValue(0);        int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);        m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);        Row* row = m_grid[r].row;        int totalCols = row->size();        for (int c = 0; c < totalCols; c++) {            CellStruct current = cellAt(r, c);            cell = current.cell;            if (!cell || current.inColSpan)                continue;            if (r < m_gridRows - 1 && cellAt(r + 1, c).cell == cell)                continue;            int indx = max(r - cell->rowSpan() + 1, 0);            if (cell->overrideSize() != -1) {                if (!statePusher.didPush()) {                    // Technically, we should also push state for the row, but since                    // rows don't push a coordinate transform, that's not necessary.                    statePusher.push(this, IntSize(x(), y()));                }                cell->setOverrideSize(-1);                cell->setChildNeedsLayout(true, false);                cell->layoutIfNeeded();            }                        int adjustedPaddingTop = cell->paddingTop() - cell->intrinsicPaddingTop();            int adjustedPaddingBottom = cell->paddingBottom() - cell->intrinsicPaddingBottom();            int adjustedHeight = cell->height() - (cell->intrinsicPaddingTop() + cell->intrinsicPaddingBottom());                    // Explicit heights use the border box in quirks mode.  In strict mode do the right            // thing and actually add in the border and padding.            ch = cell->style()->height().calcValue(0) +                 (cell->style()->htmlHacks() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom +                                                   cell->borderTop() + cell->borderBottom()));            ch = max(ch, adjustedHeight);            pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);            m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);            // find out the baseline            EVerticalAlign va = cell->style()->verticalAlign();            if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {                int b = cell->baselinePosition();                if (b > cell->borderTop() + cell->paddingTop()) {                    baseline = max(baseline, b - cell->intrinsicPaddingTop());                    bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingTop()));                }            }        }        //do we have baseline aligned elements?        if (baseline) {            // increase rowheight if baseline requires            m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));            m_grid[r].baseline = baseline;        }

⌨️ 快捷键说明

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