📄 rendertablecell.cpp
字号:
/* * 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, 2007 Apple Inc. All rights reserved. * * 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 "RenderTableCell.h"#include "FloatQuad.h"#include "GraphicsContext.h"#include "HTMLNames.h"#include "HTMLTableCellElement.h"#include "RenderTableCol.h"#include "RenderView.h"#include "TransformState.h"using namespace std;namespace WebCore {using namespace HTMLNames;RenderTableCell::RenderTableCell(Node* node) : RenderBlock(node) , m_row(-1) , m_column(-1) , m_rowSpan(1) , m_columnSpan(1) , m_intrinsicPaddingTop(0) , m_intrinsicPaddingBottom(0) , m_percentageHeight(0){ updateFromElement();}void RenderTableCell::destroy(){ RenderTableSection* recalcSection = parent() ? section() : 0; RenderBlock::destroy(); if (recalcSection) recalcSection->setNeedsCellRecalc();}void RenderTableCell::updateFromElement(){ Node* n = node(); if (n && (n->hasTagName(tdTag) || n->hasTagName(thTag))) { HTMLTableCellElement* tc = static_cast<HTMLTableCellElement*>(n); int oldRSpan = m_rowSpan; int oldCSpan = m_columnSpan; m_columnSpan = tc->colSpan(); m_rowSpan = tc->rowSpan(); if ((oldRSpan != m_rowSpan || oldCSpan != m_columnSpan) && style() && parent()) { setNeedsLayoutAndPrefWidthsRecalc(); if (section()) section()->setNeedsCellRecalc(); } }}Length RenderTableCell::styleOrColWidth() const{ Length w = style()->width(); if (colSpan() > 1 || !w.isAuto()) return w; RenderTableCol* tableCol = table()->colElement(col()); if (tableCol) { w = tableCol->style()->width(); // Column widths specified on <col> apply to the border box of the cell. // Percentages don't need to be handled since they're always treated this way (even when specified on the cells). // See Bugzilla bug 8126 for details. if (w.isFixed() && w.value() > 0) w = Length(max(0, w.value() - borderLeft() - borderRight() - paddingLeft() - paddingRight()), Fixed); } return w;}void RenderTableCell::calcPrefWidths(){ // The child cells rely on the grids up in the sections to do their calcPrefWidths work. Normally the sections are set up early, as table // cells are added, but relayout can cause the cells to be freed, leaving stale pointers in the sections' // grids. We must refresh those grids before the child cells try to use them. table()->recalcSectionsIfNeeded(); RenderBlock::calcPrefWidths(); if (node() && style()->autoWrap()) { // See if nowrap was set. Length w = styleOrColWidth(); String nowrap = static_cast<Element*>(node())->getAttribute(nowrapAttr); if (!nowrap.isNull() && w.isFixed()) // Nowrap is set, but we didn't actually use it because of the // fixed width set on the cell. Even so, it is a WinIE/Moz trait // to make the minwidth of the cell into the fixed width. They do this // even in strict mode, so do not make this a quirk. Affected the top // of hiptop.com. m_minPrefWidth = max(w.value(), m_minPrefWidth); }}void RenderTableCell::calcWidth(){}void RenderTableCell::updateWidth(int w){ if (w != width()) { setWidth(w); setCellWidthChanged(true); }}void RenderTableCell::layout(){ layoutBlock(cellWidthChanged()); setCellWidthChanged(false);}int RenderTableCell::paddingTop(bool includeIntrinsicPadding) const{ return RenderBlock::paddingTop() + (includeIntrinsicPadding ? intrinsicPaddingTop() : 0);}int RenderTableCell::paddingBottom(bool includeIntrinsicPadding) const{ return RenderBlock::paddingBottom() + (includeIntrinsicPadding ? intrinsicPaddingBottom() : 0);}void RenderTableCell::setOverrideSize(int size){ clearIntrinsicPadding(); RenderBlock::setOverrideSize(size);}IntRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer){ // If the table grid is dirty, we cannot get reliable information about adjoining cells, // so we ignore outside borders. This should not be a problem because it means that // the table is going to recalculate the grid, relayout and repaint its current rect, which // includes any outside borders of this cell. if (!table()->collapseBorders() || table()->needsSectionRecalc()) return RenderBlock::clippedOverflowRectForRepaint(repaintContainer); bool rtl = table()->style()->direction() == RTL; int outlineSize = style()->outlineSize(); int left = max(borderHalfLeft(true), outlineSize); int right = max(borderHalfRight(true), outlineSize); int top = max(borderHalfTop(true), outlineSize); int bottom = max(borderHalfBottom(true), outlineSize); if (left && !rtl || right && rtl) { if (RenderTableCell* before = table()->cellBefore(this)) { top = max(top, before->borderHalfTop(true)); bottom = max(bottom, before->borderHalfBottom(true)); } } if (left && rtl || right && !rtl) { if (RenderTableCell* after = table()->cellAfter(this)) { top = max(top, after->borderHalfTop(true)); bottom = max(bottom, after->borderHalfBottom(true)); } } if (top) { if (RenderTableCell* above = table()->cellAbove(this)) { left = max(left, above->borderHalfLeft(true)); right = max(right, above->borderHalfRight(true)); } } if (bottom) { if (RenderTableCell* below = table()->cellBelow(this)) { left = max(left, below->borderHalfLeft(true)); right = max(right, below->borderHalfRight(true)); } } left = max(left, -overflowLeft(false)); top = max(top, -overflowTop(false)); IntRect r(-left, - top, left + max(width() + right, overflowWidth(false)), top + max(height() + bottom, overflowHeight(false))); if (RenderView* v = view()) { // FIXME: layoutDelta needs to be applied in parts before/after transforms and // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308 r.move(v->layoutDelta()); } computeRectForRepaint(repaintContainer, r); return r;}void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& r, bool fixed){ if (repaintContainer == this) return; r.setY(r.y()); RenderView* v = view(); if ((!v || !v->layoutStateEnabled()) && parent()) r.move(-parentBox()->x(), -parentBox()->y()); // Rows are in the same coordinate space, so don't add their offset in. RenderBlock::computeRectForRepaint(repaintContainer, r, fixed);}void RenderTableCell::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const{ if (repaintContainer == this) return; RenderView* v = view(); if ((!v || !v->layoutStateEnabled()) && parent()) { // Rows are in the same coordinate space, so don't add their offset in. // FIXME: this is wrong with transforms transformState.move(-parentBox()->x(), -parentBox()->y()); } RenderBlock::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);}void RenderTableCell::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const{ RenderBlock::mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); if (parent()) { // Rows are in the same coordinate space, so add their offset back in. // FIXME: this is wrong with transforms transformState.move(parentBox()->x(), parentBox()->y()); }}int RenderTableCell::baselinePosition(bool firstLine, bool isRootLineBox) const{ if (isRootLineBox) return RenderBox::baselinePosition(firstLine, isRootLineBox); // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of // the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there // is no such line box or table-row, the baseline is the bottom of content edge of the cell box. int firstLineBaseline = firstLineBoxBaseline(); if (firstLineBaseline != -1) return firstLineBaseline; return paddingTop() + borderTop() + contentHeight();}void RenderTableCell::styleWillChange(StyleDifference diff, const RenderStyle* newStyle){ if (parent() && section() && style() && style()->height() != newStyle->height()) section()->setNeedsCellRecalc(); ASSERT(newStyle->display() == TABLE_CELL); RenderBlock::styleWillChange(diff, newStyle);}void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle){ RenderBlock::styleDidChange(diff, oldStyle); setHasBoxDecorations(true);}// The following rules apply for resolving conflicts and figuring out which border// to use.// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting // borders. Any border with this value suppresses all borders at this location.// (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all // the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is // the default value for the border style.)// (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders // are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred // in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.// (4) If border styles differ only in color, then a style set on a cell wins over one on a row, // which wins over a row group, column, column group and, lastly, table. It is undefined which color // is used when two elements of the same type disagree.static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2){ // Sanity check the values passed in. If either is null, return the other. if (!border2.exists()) return border1; if (!border1.exists()) return border2; // Rule #1 above.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -