, m_column(-1)
, m_rowSpan(1)
, m_columnSpan(1)
- , m_intrinsicPaddingTop(0)
- , m_intrinsicPaddingBottom(0)
+ , m_intrinsicPaddingBefore(0)
+ , m_intrinsicPaddingAfter(0)
, m_percentageHeight(0)
{
updateFromElement();
}
}
-Length RenderTableCell::styleOrColWidth() const
+Length RenderTableCell::styleOrColLogicalWidth() const
{
- Length w = style()->width();
- if (colSpan() > 1 || !w.isAuto())
+ Length w = style()->logicalWidth();
+ if (!w.isAuto())
return w;
- RenderTableCol* tableCol = table()->colElement(col());
- if (tableCol) {
- w = tableCol->style()->width();
-
+
+ if (RenderTableCol* tableCol = table()->colElement(col())) {
+ int colSpanCount = colSpan();
+
+ Length colWidthSum = Length(0, Fixed);
+ for (int i = 1; i <= colSpanCount; i++) {
+ Length colWidth = tableCol->style()->logicalWidth();
+
+ // Percentage value should be returned only for colSpan == 1.
+ // Otherwise we return original width for the cell.
+ if (!colWidth.isFixed()) {
+ if (colSpanCount > 1)
+ return w;
+ return colWidth;
+ }
+
+ colWidthSum = Length(colWidthSum.value() + colWidth.value(), Fixed);
+
+ tableCol = table()->nextColElement(tableCol);
+ // If no next <col> tag found for the span we just return what we have for now.
+ if (!tableCol)
+ break;
+ }
+
// 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);
+ if (colWidthSum.isFixed() && colWidthSum.value() > 0)
+ colWidthSum = Length(max(0, colWidthSum.value() - borderAndPaddingLogicalWidth()), Fixed);
+ return colWidthSum;
}
+
return w;
}
-void RenderTableCell::calcPrefWidths()
+void RenderTableCell::computePreferredLogicalWidths()
{
- // 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
+ // The child cells rely on the grids up in the sections to do their computePreferredLogicalWidths 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();
+ RenderBlock::computePreferredLogicalWidths();
if (node() && style()->autoWrap()) {
// See if nowrap was set.
- Length w = styleOrColWidth();
+ Length w = styleOrColLogicalWidth();
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
// 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);
+ m_minPreferredLogicalWidth = max(w.value(), m_minPreferredLogicalWidth);
}
}
-void RenderTableCell::calcWidth()
+void RenderTableCell::computeLogicalWidth()
{
#ifdef ANDROID_LAYOUT
- if (view()->frameView()) {
- const Settings* settings = document()->settings();
- ASSERT(settings);
- if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
- m_visibleWidth = view()->frameView()->screenWidth();
- }
- }
+ if (view()->frameView())
+ setVisibleWidth(view()->frameView()->textWrapWidth());
#endif
}
-void RenderTableCell::updateWidth(int w)
+void RenderTableCell::updateLogicalWidth(int w)
{
- if (w != width()) {
- setWidth(w);
- setCellWidthChanged(true);
- }
+ if (w == logicalWidth())
+ return;
+
+ setLogicalWidth(w);
+ setCellWidthChanged(true);
}
void RenderTableCell::layout()
int RenderTableCell::paddingTop(bool includeIntrinsicPadding) const
{
- return RenderBlock::paddingTop() + (includeIntrinsicPadding ? intrinsicPaddingTop() : 0);
+ int result = RenderBlock::paddingTop();
+ if (!includeIntrinsicPadding || !style()->isHorizontalWritingMode())
+ return result;
+ return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
}
int RenderTableCell::paddingBottom(bool includeIntrinsicPadding) const
{
- return RenderBlock::paddingBottom() + (includeIntrinsicPadding ? intrinsicPaddingBottom() : 0);
+ int result = RenderBlock::paddingBottom();
+ if (!includeIntrinsicPadding || !style()->isHorizontalWritingMode())
+ return result;
+ return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
+}
+
+int RenderTableCell::paddingLeft(bool includeIntrinsicPadding) const
+{
+ int result = RenderBlock::paddingLeft();
+ if (!includeIntrinsicPadding || style()->isHorizontalWritingMode())
+ return result;
+ return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
+
+}
+
+int RenderTableCell::paddingRight(bool includeIntrinsicPadding) const
+{
+ int result = RenderBlock::paddingRight();
+ if (!includeIntrinsicPadding || style()->isHorizontalWritingMode())
+ return result;
+ return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
+}
+
+int RenderTableCell::paddingBefore(bool includeIntrinsicPadding) const
+{
+ int result = RenderBlock::paddingBefore();
+ if (!includeIntrinsicPadding)
+ return result;
+ return result + intrinsicPaddingBefore();
+}
+
+int RenderTableCell::paddingAfter(bool includeIntrinsicPadding) const
+{
+ int result = RenderBlock::paddingAfter();
+ if (!includeIntrinsicPadding)
+ return result;
+ return result + intrinsicPaddingAfter();
}
void RenderTableCell::setOverrideSize(int size)
RenderBlock::setOverrideSize(size);
}
-IntSize RenderTableCell::offsetFromContainer(RenderObject* o) const
+IntSize RenderTableCell::offsetFromContainer(RenderObject* o, const IntPoint& point) const
{
ASSERT(o == container());
- IntSize offset = RenderBlock::offsetFromContainer(o);
+ IntSize offset = RenderBlock::offsetFromContainer(o, point);
if (parent())
offset.expand(-parentBox()->x(), -parentBox()->y());
if (!table()->collapseBorders() || table()->needsSectionRecalc())
return RenderBlock::clippedOverflowRectForRepaint(repaintContainer);
- bool rtl = table()->style()->direction() == RTL;
+ bool rtl = !table()->style()->isLeftToRightDirection();
int outlineSize = style()->outlineSize();
int left = max(borderHalfLeft(true), outlineSize);
int right = max(borderHalfRight(true), outlineSize);
return;
r.setY(r.y());
RenderView* v = view();
- if ((!v || !v->layoutStateEnabled()) && parent())
+ if ((!v || !v->layoutStateEnabled() || repaintContainer) && 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);
}
-int RenderTableCell::baselinePosition(bool firstLine, bool isRootLineBox) const
+int RenderTableCell::baselinePosition(bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
{
- if (isRootLineBox)
- return RenderBox::baselinePosition(firstLine, isRootLineBox);
+ // FIXME: This function still needs to be patched for writing-mode.
+ if (linePositionMode == PositionOfInteriorLineBoxes)
+ return RenderBlock::baselinePosition(firstLine, lineDirection, linePositionMode);
// <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
// (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)
+static int 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;
+ // Sanity check the values passed in. The null border have lowest priority.
+ if (!border2.exists()) {
+ if (!border1.exists())
+ return 0;
+ return 1;
+ }
if (!border1.exists())
- return border2;
+ return -1;
// Rule #1 above.
- if (border1.style() == BHIDDEN || border2.style() == BHIDDEN)
- return CollapsedBorderValue(); // No border should exist at this location.
+ if (border2.style() == BHIDDEN) {
+ if (border1.style() == BHIDDEN)
+ return 0;
+ return -1;
+ }
+ if (border1.style() == BHIDDEN)
+ return 1;
// Rule #2 above. A style of 'none' has lowest priority and always loses to any other border.
- if (border2.style() == BNONE)
- return border1;
+ if (border2.style() == BNONE) {
+ if (border1.style() == BNONE)
+ return 0;
+ return 1;
+ }
if (border1.style() == BNONE)
- return border2;
+ return -1;
// The first part of rule #3 above. Wider borders win.
if (border1.width() != border2.width())
- return border1.width() > border2.width() ? border1 : border2;
+ return border1.width() < border2.width() ? -1 : 1;
// The borders have equal width. Sort by border style.
if (border1.style() != border2.style())
- return border1.style() > border2.style() ? border1 : border2;
+ return border1.style() < border2.style() ? -1 : 1;
// The border have the same width and style. Rely on precedence (cell over row over row group, etc.)
- return border1.precedence >= border2.precedence ? border1 : border2;
+ if (border1.precedence() == border2.precedence())
+ return 0;
+ return border1.precedence() < border2.precedence() ? -1 : 1;
}
-CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const
+static CollapsedBorderValue chooseBorder(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
{
- RenderTable* tableElt = table();
- bool leftmostColumn;
- if (!rtl)
- leftmostColumn = col() == 0;
- else {
- int effCol = tableElt->colToEffCol(col() + colSpan() - 1);
- leftmostColumn = effCol == tableElt->numEffCols() - 1;
- }
-
- // For border left, we need to check, in order of precedence:
- // (1) Our left border.
- CollapsedBorderValue result(&style()->borderLeft(), BCELL);
-
- // (2) The right border of the cell to the left.
- RenderTableCell* prevCell = rtl ? tableElt->cellAfter(this) : tableElt->cellBefore(this);
- if (prevCell) {
- result = rtl ? compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL)) : compareBorders(CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL), result);
+ const CollapsedBorderValue& border = compareBorders(border1, border2) < 0 ? border2 : border1;
+ return border.style() == BHIDDEN ? CollapsedBorderValue() : border;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedStartBorder() const
+{
+ RenderTable* table = this->table();
+ bool isStartColumn = col() == 0;
+
+ // For the start border, we need to check, in order of precedence:
+ // (1) Our start border.
+ int start = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, table->style()->direction(), table->style()->writingMode());
+ int end = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, table->style()->direction(), table->style()->writingMode());
+ CollapsedBorderValue result(&style()->borderStart(), style()->visitedDependentColor(start), BCELL);
+
+ // (2) The end border of the preceding cell.
+ if (RenderTableCell* prevCell = table->cellBefore(this)) {
+ CollapsedBorderValue prevCellBorder = CollapsedBorderValue(&prevCell->style()->borderEnd(), prevCell->style()->visitedDependentColor(end), BCELL);
+ result = chooseBorder(prevCellBorder, result);
if (!result.exists())
return result;
- } else if (leftmostColumn) {
- // (3) Our row's left border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW));
+ } else if (isStartColumn) {
+ // (3) Our row's start border.
+ result = chooseBorder(result, CollapsedBorderValue(&parent()->style()->borderStart(), parent()->style()->visitedDependentColor(start), BROW));
if (!result.exists())
return result;
- // (4) Our row group's left border.
- result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderLeft(), BROWGROUP));
+ // (4) Our row group's start border.
+ result = chooseBorder(result, CollapsedBorderValue(§ion()->style()->borderStart(), section()->style()->visitedDependentColor(start), BROWGROUP));
if (!result.exists())
return result;
}
- // (5) Our column and column group's left borders.
+ // (5) Our column and column group's start borders.
bool startColEdge;
bool endColEdge;
- RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? colSpan() - 1 : 0), &startColEdge, &endColEdge);
- if (colElt && (!rtl ? startColEdge : endColEdge)) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+ RenderTableCol* colElt = table->colElement(col(), &startColEdge, &endColEdge);
+ if (colElt && startColEdge) {
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->style()->borderStart(), colElt->style()->visitedDependentColor(start), BCOL));
if (!result.exists())
return result;
- if (colElt->parent()->isTableCol() && (!rtl ? !colElt->previousSibling() : !colElt->nextSibling())) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderLeft(), BCOLGROUP));
+ if (colElt->parent()->isTableCol() && !colElt->previousSibling()) {
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->parent()->style()->borderStart(), colElt->parent()->style()->visitedDependentColor(start), BCOLGROUP));
if (!result.exists())
return result;
}
}
- // (6) The right border of the column to the left.
- if (!leftmostColumn) {
- colElt = tableElt->colElement(col() + (rtl ? colSpan() : -1), &startColEdge, &endColEdge);
- if (colElt && (!rtl ? endColEdge : startColEdge)) {
- result = rtl ? compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL)) : compareBorders(CollapsedBorderValue(&colElt->style()->borderRight(), BCOL), result);
+ // (6) The end border of the preceding column.
+ if (!isStartColumn) {
+ colElt = table->colElement(col() -1, &startColEdge, &endColEdge);
+ if (colElt && endColEdge) {
+ CollapsedBorderValue endBorder = CollapsedBorderValue(&colElt->style()->borderEnd(), colElt->style()->visitedDependentColor(end), BCOL);
+ result = chooseBorder(endBorder, result);
if (!result.exists())
return result;
}
} else {
- // (7) The table's left border.
- result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderLeft(), BTABLE));
+ // (7) The table's start border.
+ result = chooseBorder(result, CollapsedBorderValue(&table->style()->borderStart(), table->style()->visitedDependentColor(start), BTABLE));
if (!result.exists())
return result;
}
return result;
}
-CollapsedBorderValue RenderTableCell::collapsedRightBorder(bool rtl) const
+CollapsedBorderValue RenderTableCell::collapsedEndBorder() const
{
- RenderTable* tableElt = table();
- bool rightmostColumn;
- if (rtl)
- rightmostColumn = col() == 0;
- else {
- int effCol = tableElt->colToEffCol(col() + colSpan() - 1);
- rightmostColumn = effCol == tableElt->numEffCols() - 1;
- }
-
- // For border right, we need to check, in order of precedence:
- // (1) Our right border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL);
+ RenderTable* table = this->table();
+ bool isEndColumn = table->colToEffCol(col() + colSpan() - 1) == table->numEffCols() - 1;
+
+ // For end border, we need to check, in order of precedence:
+ // (1) Our end border.
+ int start = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, table->style()->direction(), table->style()->writingMode());
+ int end = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, table->style()->direction(), table->style()->writingMode());
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderEnd(), style()->visitedDependentColor(end), BCELL);
- // (2) The left border of the cell to the right.
- if (!rightmostColumn) {
- RenderTableCell* nextCell = rtl ? tableElt->cellBefore(this) : tableElt->cellAfter(this);
+ // (2) The start border of the following cell.
+ if (!isEndColumn) {
+ RenderTableCell* nextCell = table->cellAfter(this);
if (nextCell && nextCell->style()) {
- result = rtl ? compareBorders(CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL), result) : compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL));
+ CollapsedBorderValue startBorder = CollapsedBorderValue(&nextCell->style()->borderStart(), nextCell->style()->visitedDependentColor(start), BCELL);
+ result = chooseBorder(result, startBorder);
if (!result.exists())
return result;
}
} else {
- // (3) Our row's right border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW));
+ // (3) Our row's end border.
+ result = chooseBorder(result, CollapsedBorderValue(&parent()->style()->borderEnd(), parent()->style()->visitedDependentColor(end), BROW));
if (!result.exists())
return result;
- // (4) Our row group's right border.
- result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderRight(), BROWGROUP));
+ // (4) Our row group's end border.
+ result = chooseBorder(result, CollapsedBorderValue(§ion()->style()->borderEnd(), section()->style()->visitedDependentColor(end), BROWGROUP));
if (!result.exists())
return result;
}
- // (5) Our column and column group's right borders.
+ // (5) Our column and column group's end borders.
bool startColEdge;
bool endColEdge;
- RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? 0 : colSpan() - 1), &startColEdge, &endColEdge);
- if (colElt && (!rtl ? endColEdge : startColEdge)) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
+ RenderTableCol* colElt = table->colElement(col() + colSpan() - 1, &startColEdge, &endColEdge);
+ if (colElt && endColEdge) {
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->style()->borderEnd(), colElt->style()->visitedDependentColor(end), BCOL));
if (!result.exists())
return result;
- if (colElt->parent()->isTableCol() && (!rtl ? !colElt->nextSibling() : !colElt->previousSibling())) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderRight(), BCOLGROUP));
+ if (colElt->parent()->isTableCol() && !colElt->nextSibling()) {
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->parent()->style()->borderEnd(), colElt->parent()->style()->visitedDependentColor(end), BCOLGROUP));
if (!result.exists())
return result;
}
}
- // (6) The left border of the column to the right.
- if (!rightmostColumn) {
- colElt = tableElt->colElement(col() + (rtl ? -1 : colSpan()), &startColEdge, &endColEdge);
- if (colElt && (!rtl ? startColEdge : endColEdge)) {
- result = rtl ? compareBorders(CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL), result) : compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+ // (6) The start border of the next column.
+ if (!isEndColumn) {
+ colElt = table->colElement(col() + colSpan(), &startColEdge, &endColEdge);
+ if (colElt && startColEdge) {
+ CollapsedBorderValue startBorder = CollapsedBorderValue(&colElt->style()->borderStart(), colElt->style()->visitedDependentColor(start), BCOL);
+ result = chooseBorder(result, startBorder);
if (!result.exists())
return result;
}
} else {
- // (7) The table's right border.
- result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE));
+ // (7) The table's end border.
+ result = chooseBorder(result, CollapsedBorderValue(&table->style()->borderEnd(), table->style()->visitedDependentColor(end), BTABLE));
if (!result.exists())
return result;
}
return result;
}
-CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
+CollapsedBorderValue RenderTableCell::collapsedBeforeBorder() const
{
- // For border top, we need to check, in order of precedence:
- // (1) Our top border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL);
+ RenderTable* table = this->table();
+
+ // For before border, we need to check, in order of precedence:
+ // (1) Our before border.
+ int before = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, table->style()->direction(), table->style()->writingMode());
+ int after = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, table->style()->direction(), table->style()->writingMode());
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBefore(), style()->visitedDependentColor(before), BCELL);
- RenderTableCell* prevCell = table()->cellAbove(this);
+ RenderTableCell* prevCell = table->cellAbove(this);
if (prevCell) {
- // (2) A previous cell's bottom border.
- result = compareBorders(CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL), result);
- if (!result.exists())
+ // (2) A before cell's after border.
+ result = chooseBorder(CollapsedBorderValue(&prevCell->style()->borderAfter(), prevCell->style()->visitedDependentColor(after), BCELL), result);
+ if (!result.exists())
return result;
}
- // (3) Our row's top border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW));
+ // (3) Our row's before border.
+ result = chooseBorder(result, CollapsedBorderValue(&parent()->style()->borderBefore(), parent()->style()->visitedDependentColor(before), BROW));
if (!result.exists())
return result;
- // (4) The previous row's bottom border.
+ // (4) The previous row's after border.
if (prevCell) {
RenderObject* prevRow = 0;
if (prevCell->section() == section())
prevRow = prevCell->section()->lastChild();
if (prevRow) {
- result = compareBorders(CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW), result);
+ result = chooseBorder(CollapsedBorderValue(&prevRow->style()->borderAfter(), prevRow->style()->visitedDependentColor(after), BROW), result);
if (!result.exists())
return result;
}
// Now check row groups.
RenderTableSection* currSection = section();
if (!row()) {
- // (5) Our row group's top border.
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+ // (5) Our row group's before border.
+ result = chooseBorder(result, CollapsedBorderValue(&currSection->style()->borderBefore(), currSection->style()->visitedDependentColor(before), BROWGROUP));
if (!result.exists())
return result;
- // (6) Previous row group's bottom border.
- currSection = table()->sectionAbove(currSection);
+ // (6) Previous row group's after border.
+ currSection = table->sectionAbove(currSection);
if (currSection) {
- result = compareBorders(CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP), result);
+ result = chooseBorder(CollapsedBorderValue(&currSection->style()->borderAfter(), currSection->style()->visitedDependentColor(after), BROWGROUP), result);
if (!result.exists())
return result;
}
}
if (!currSection) {
- // (8) Our column and column group's top borders.
- RenderTableCol* colElt = table()->colElement(col());
+ // (8) Our column and column group's before borders.
+ RenderTableCol* colElt = table->colElement(col());
if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), BCOL));
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->style()->borderBefore(), colElt->style()->visitedDependentColor(before), BCOL));
if (!result.exists())
return result;
if (colElt->parent()->isTableCol()) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderTop(), BCOLGROUP));
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->parent()->style()->borderBefore(), colElt->parent()->style()->visitedDependentColor(before), BCOLGROUP));
if (!result.exists())
return result;
}
}
- // (9) The table's top border.
- result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderTop(), BTABLE));
+ // (9) The table's before border.
+ result = chooseBorder(result, CollapsedBorderValue(&table->style()->borderBefore(), table->style()->visitedDependentColor(before), BTABLE));
if (!result.exists())
return result;
}
return result;
}
-CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
+CollapsedBorderValue RenderTableCell::collapsedAfterBorder() const
{
- // For border top, we need to check, in order of precedence:
- // (1) Our bottom border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), BCELL);
+ RenderTable* table = this->table();
+
+ // For after border, we need to check, in order of precedence:
+ // (1) Our after border.
+ int before = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, table->style()->direction(), table->style()->writingMode());
+ int after = CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, table->style()->direction(), table->style()->writingMode());
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderAfter(), style()->visitedDependentColor(after), BCELL);
- RenderTableCell* nextCell = table()->cellBelow(this);
+ RenderTableCell* nextCell = table->cellBelow(this);
if (nextCell) {
- // (2) A following cell's top border.
- result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), BCELL));
+ // (2) An after cell's before border.
+ result = chooseBorder(result, CollapsedBorderValue(&nextCell->style()->borderBefore(), nextCell->style()->visitedDependentColor(before), BCELL));
if (!result.exists())
return result;
}
- // (3) Our row's bottom border. (FIXME: Deal with rowspan!)
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), BROW));
+ // (3) Our row's after border. (FIXME: Deal with rowspan!)
+ result = chooseBorder(result, CollapsedBorderValue(&parent()->style()->borderAfter(), parent()->style()->visitedDependentColor(after), BROW));
if (!result.exists())
return result;
- // (4) The next row's top border.
+ // (4) The next row's before border.
if (nextCell) {
- result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), BROW));
+ result = chooseBorder(result, CollapsedBorderValue(&nextCell->parent()->style()->borderBefore(), nextCell->parent()->style()->visitedDependentColor(before), BROW));
if (!result.exists())
return result;
}
// Now check row groups.
RenderTableSection* currSection = section();
if (row() + rowSpan() >= currSection->numRows()) {
- // (5) Our row group's bottom border.
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
+ // (5) Our row group's after border.
+ result = chooseBorder(result, CollapsedBorderValue(&currSection->style()->borderAfter(), currSection->style()->visitedDependentColor(after), BROWGROUP));
if (!result.exists())
return result;
- // (6) Following row group's top border.
- currSection = table()->sectionBelow(currSection);
+ // (6) Following row group's before border.
+ currSection = table->sectionBelow(currSection);
if (currSection) {
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+ result = chooseBorder(result, CollapsedBorderValue(&currSection->style()->borderBefore(), currSection->style()->visitedDependentColor(before), BROWGROUP));
if (!result.exists())
return result;
}
}
if (!currSection) {
- // (8) Our column and column group's bottom borders.
- RenderTableCol* colElt = table()->colElement(col());
+ // (8) Our column and column group's after borders.
+ RenderTableCol* colElt = table->colElement(col());
if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), BCOL));
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->style()->borderAfter(), colElt->style()->visitedDependentColor(after), BCOL));
if (!result.exists()) return result;
if (colElt->parent()->isTableCol()) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderBottom(), BCOLGROUP));
+ result = chooseBorder(result, CollapsedBorderValue(&colElt->parent()->style()->borderAfter(), colElt->parent()->style()->visitedDependentColor(after), BCOLGROUP));
if (!result.exists())
return result;
}
}
- // (9) The table's bottom border.
- result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderBottom(), BTABLE));
+ // (9) The table's after border.
+ result = chooseBorder(result, CollapsedBorderValue(&table->style()->borderAfter(), table->style()->visitedDependentColor(after), BTABLE));
if (!result.exists())
return result;
}
return result;
}
+CollapsedBorderValue RenderTableCell::collapsedLeftBorder() const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isLeftToRightDirection() ? collapsedStartBorder() : collapsedEndBorder();
+ return tableStyle->isFlippedBlocksWritingMode() ? collapsedAfterBorder() : collapsedBeforeBorder();
+}
+
+CollapsedBorderValue RenderTableCell::collapsedRightBorder() const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isLeftToRightDirection() ? collapsedEndBorder() : collapsedStartBorder();
+ return tableStyle->isFlippedBlocksWritingMode() ? collapsedBeforeBorder() : collapsedAfterBorder();
+}
+
+CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isFlippedBlocksWritingMode() ? collapsedAfterBorder() : collapsedBeforeBorder();
+ return tableStyle->isLeftToRightDirection() ? collapsedStartBorder() : collapsedEndBorder();
+}
+
+CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isFlippedBlocksWritingMode() ? collapsedBeforeBorder() : collapsedAfterBorder();
+ return tableStyle->isLeftToRightDirection() ? collapsedEndBorder() : collapsedStartBorder();
+}
+
int RenderTableCell::borderLeft() const
{
return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlock::borderLeft();
return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlock::borderBottom();
}
+// FIXME: https://bugs.webkit.org/show_bug.cgi?id=46191, make the collapsed border drawing
+// work with different block flow values instead of being hard-coded to top-to-bottom.
+int RenderTableCell::borderStart() const
+{
+ return table()->collapseBorders() ? borderHalfStart(false) : RenderBlock::borderStart();
+}
+
+int RenderTableCell::borderEnd() const
+{
+ return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlock::borderEnd();
+}
+
+int RenderTableCell::borderBefore() const
+{
+ return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlock::borderBefore();
+}
+
+int RenderTableCell::borderAfter() const
+{
+ return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlock::borderAfter();
+}
+
int RenderTableCell::borderHalfLeft(bool outer) const
{
- CollapsedBorderValue border = collapsedLeftBorder(table()->style()->direction() == RTL);
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
+ return tableStyle->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
+}
+
+int RenderTableCell::borderHalfRight(bool outer) const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
+ return tableStyle->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
+}
+
+int RenderTableCell::borderHalfTop(bool outer) const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
+ return tableStyle->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
+}
+
+int RenderTableCell::borderHalfBottom(bool outer) const
+{
+ RenderStyle* tableStyle = table()->style();
+ if (tableStyle->isHorizontalWritingMode())
+ return tableStyle->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
+ return tableStyle->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
+}
+
+int RenderTableCell::borderHalfStart(bool outer) const
+{
+ CollapsedBorderValue border = collapsedStartBorder();
if (border.exists())
- return (border.width() + (outer ? 0 : 1)) / 2; // Give the extra pixel to top and left.
+ return (border.width() + ((table()->style()->isLeftToRightDirection() ^ outer) ? 1 : 0)) / 2; // Give the extra pixel to top and left.
return 0;
}
-int RenderTableCell::borderHalfRight(bool outer) const
+int RenderTableCell::borderHalfEnd(bool outer) const
{
- CollapsedBorderValue border = collapsedRightBorder(table()->style()->direction() == RTL);
+ CollapsedBorderValue border = collapsedEndBorder();
if (border.exists())
- return (border.width() + (outer ? 1 : 0)) / 2;
+ return (border.width() + ((table()->style()->isLeftToRightDirection() ^ outer) ? 0 : 1)) / 2;
return 0;
}
-int RenderTableCell::borderHalfTop(bool outer) const
+int RenderTableCell::borderHalfBefore(bool outer) const
{
- CollapsedBorderValue border = collapsedTopBorder();
+ CollapsedBorderValue border = collapsedBeforeBorder();
if (border.exists())
- return (border.width() + (outer ? 0 : 1)) / 2; // Give the extra pixel to top and left.
+ return (border.width() + ((table()->style()->isFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / 2; // Give the extra pixel to top and left.
return 0;
}
-int RenderTableCell::borderHalfBottom(bool outer) const
+int RenderTableCell::borderHalfAfter(bool outer) const
{
- CollapsedBorderValue border = collapsedBottomBorder();
+ CollapsedBorderValue border = collapsedAfterBorder();
if (border.exists())
- return (border.width() + (outer ? 1 : 0)) / 2;
+ return (border.width() + ((table()->style()->isFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / 2;
return 0;
}
void RenderTableCell::paint(PaintInfo& paintInfo, int tx, int ty)
{
if (paintInfo.phase == PaintPhaseCollapsedTableBorders && style()->visibility() == VISIBLE) {
+ if (!paintInfo.shouldPaintWithinRoot(this))
+ return;
+
tx += x();
ty += y();
int os = 2 * maximalOutlineSize(paintInfo.phase);
void RenderTableCell::collectBorderStyles(CollapsedBorderStyles& borderStyles) const
{
- bool rtl = table()->style()->direction() == RTL;
- addBorderStyle(borderStyles, collapsedLeftBorder(rtl));
- addBorderStyle(borderStyles, collapsedRightBorder(rtl));
- addBorderStyle(borderStyles, collapsedTopBorder());
- addBorderStyle(borderStyles, collapsedBottomBorder());
+ addBorderStyle(borderStyles, collapsedStartBorder());
+ addBorderStyle(borderStyles, collapsedEndBorder());
+ addBorderStyle(borderStyles, collapsedBeforeBorder());
+ addBorderStyle(borderStyles, collapsedAfterBorder());
}
static int compareBorderStylesForQSort(const void* pa, const void* pb)
const CollapsedBorderValue* b = static_cast<const CollapsedBorderValue*>(pb);
if (*a == *b)
return 0;
- CollapsedBorderValue borderWithHigherPrecedence = compareBorders(*a, *b);
-#ifdef ANDROID_FIX
- if (*a == borderWithHigherPrecedence) {
- // klibc uses a combsort for quicksort and requires that two values always give the same answer
- // regardless of comparison order. Unfortunately, compareBorders does not honor that requirement.
- // Call compareBorders again with reversed parameters. If it returns the first value again then
- // we can assume the values are equal. http://bugs.webkit.org/show_bug.cgi?id=13147
- CollapsedBorderValue qSortHack = compareBorders(*b, *a);
- if (*b == qSortHack)
- return 0;
- return 1;
- }
-#else
- if (*a == borderWithHigherPrecedence)
- return 1;
-#endif
- return -1;
+ return compareBorders(*a, *b);
}
void RenderTableCell::sortBorderStyles(CollapsedBorderStyles& borderStyles)
if (!table()->currentBorderStyle())
return;
- bool rtl = table()->style()->direction() == RTL;
- CollapsedBorderValue leftVal = collapsedLeftBorder(rtl);
- CollapsedBorderValue rightVal = collapsedRightBorder(rtl);
+ CollapsedBorderValue leftVal = collapsedLeftBorder();
+ CollapsedBorderValue rightVal = collapsedRightBorder();
CollapsedBorderValue topVal = collapsedTopBorder();
CollapsedBorderValue bottomVal = collapsedBottomBorder();
for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
if (border->borderValue == *table()->currentBorderStyle())
drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
- border->borderValue.color(), style()->color(), border->style, 0, 0);
+ border->borderValue.color(), border->style, 0, 0);
}
}
void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, int ty, RenderObject* backgroundObject)
{
+ if (!paintInfo.shouldPaintWithinRoot(this))
+ return;
+
if (!backgroundObject)
return;
int w = width();
int h = height();
- Color c = backgroundObject->style()->backgroundColor();
+ Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
if (bgLayer->hasImage() || c.isValid()) {
paintInfo.context->save();
paintInfo.context->clip(clipRect);
}
- paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h);
+ paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h, CompositeSourceOver, backgroundObject);
if (shouldClip)
paintInfo.context->restore();
}
void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
+ if (!paintInfo.shouldPaintWithinRoot(this))
+ return;
+
RenderTable* tableElt = table();
if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
return;