void RenderTableRow::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); // Table rows do not add translation. LayoutStateMaintainer statePusher(view(), *this, LayoutSize(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode()); bool paginated = view().layoutState()->isPaginated(); for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) { if (!cell->needsLayout() && paginated && (view().layoutState()->pageLogicalHeightChanged() || (view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset()))) cell->setChildNeedsLayout(MarkOnlyThis); if (cell->needsLayout()) { cell->computeAndSetBlockDirectionMargins(table()); cell->layout(); } } // We only ever need to repaint if our cells didn't, which menas that they didn't need // layout, so we know that our bounds didn't change. This code is just making up for // the fact that we did not repaint in setStyle() because we had a layout hint. // We cannot call repaint() because our clippedOverflowRectForRepaint() is taken from the // parent table, and being mid-layout, that is invalid. Instead, we repaint our cells. if (selfNeedsLayout() && checkForRepaintDuringLayout()) { for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) cell->repaint(); } statePusher.pop(); // RenderTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform(). clearNeedsLayout(); }
void RenderTableRow::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ASSERT(hasSelfPaintingLayer()); paintOutlineForRowIfNeeded(paintInfo, paintOffset); for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) { // Paint the row background behind the cell. if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground) cell->paintBackgroundsBehindCell(paintInfo, paintOffset, this); if (!cell->hasSelfPaintingLayer()) cell->paint(paintInfo, paintOffset); } }
LayoutRect RenderTableRow::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { ASSERT(parent()); // Rows and cells are in the same coordinate space. We need to both compute our overflow rect (which // will accommodate a row outline and any visual effects on the row itself), but we also need to add in // the repaint rects of cells. LayoutRect result = RenderBox::clippedOverflowRectForRepaint(repaintContainer); for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) { // Even if a cell is a repaint container, it's the row that paints the background behind it. // So we don't care if a cell is a repaintContainer here. result.uniteIfNonZero(cell->clippedOverflowRectForRepaint(repaintContainer)); } return result; }
void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { ASSERT(style().display() == TABLE_ROW); RenderBox::styleDidChange(diff, oldStyle); propagateStyleToAnonymousChildren(PropagateToAllChildren); if (section() && oldStyle && style().logicalHeight() != oldStyle->logicalHeight()) section()->rowLogicalHeightChanged(rowIndex()); // If border was changed, notify table. if (RenderTable* table = this->table()) { if (oldStyle && oldStyle->border() != style().border()) table->invalidateCollapsedBorders(); if (oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, &style())) { // If the border width changes on a row, we need to make sure the cells in the row know to lay out again. // This only happens when borders are collapsed, since they end up affecting the border sides of the cell // itself. for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) cell->setChildNeedsLayout(MarkOnlyThis); } } }
int FixedTableLayout::calcWidthArray() { // FIXME: We might want to wait until we have all of the first row before computing for the first time. int usedWidth = 0; // iterate over all <col> elements unsigned nEffCols = m_table->numEffCols(); m_width.resize(nEffCols); m_width.fill(Length(Auto)); unsigned currentEffectiveColumn = 0; for (RenderTableCol* col = m_table->firstColumn(); col; col = col->nextColumn()) { // RenderTableCols don't have the concept of preferred logical width, but we need to clear their dirty bits // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's // ancestors as dirty. col->clearPreferredLogicalWidthsDirtyBits(); // Width specified by column-groups that have column child does not affect column width in fixed layout tables if (col->isTableColumnGroupWithColumnChildren()) continue; Length colStyleLogicalWidth = col->style().logicalWidth(); int effectiveColWidth = 0; if (colStyleLogicalWidth.isFixed() && colStyleLogicalWidth.value() > 0) effectiveColWidth = colStyleLogicalWidth.value(); unsigned span = col->span(); while (span) { unsigned spanInCurrentEffectiveColumn; if (currentEffectiveColumn >= nEffCols) { m_table->appendColumn(span); nEffCols++; m_width.append(Length()); spanInCurrentEffectiveColumn = span; } else { if (span < m_table->spanOfEffCol(currentEffectiveColumn)) { m_table->splitColumn(currentEffectiveColumn, span); nEffCols++; m_width.append(Length()); } spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn); } if ((colStyleLogicalWidth.isFixed() || colStyleLogicalWidth.isPercent()) && colStyleLogicalWidth.isPositive()) { m_width[currentEffectiveColumn] = colStyleLogicalWidth; m_width[currentEffectiveColumn] *= spanInCurrentEffectiveColumn; usedWidth += effectiveColWidth * spanInCurrentEffectiveColumn; } span -= spanInCurrentEffectiveColumn; currentEffectiveColumn++; } } // Iterate over the first row in case some are unspecified. RenderTableSection* section = m_table->topNonEmptySection(); if (!section) return usedWidth; unsigned currentColumn = 0; RenderTableRow* firstRow = section->firstRow(); for (RenderTableCell* cell = firstRow->firstCell(); cell; cell = cell->nextCell()) { Length logicalWidth = cell->styleOrColLogicalWidth(); unsigned span = cell->colSpan(); int fixedBorderBoxLogicalWidth = 0; // FIXME: Support other length types. If the width is non-auto, it should probably just use // RenderBox::computeLogicalWidthInRegionUsing to compute the width. if (logicalWidth.isFixed() && logicalWidth.isPositive()) { fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value()); logicalWidth.setValue(Fixed, fixedBorderBoxLogicalWidth); } unsigned usedSpan = 0; while (usedSpan < span && currentColumn < nEffCols) { float eSpan = m_table->spanOfEffCol(currentColumn); // Only set if no col element has already set it. if (m_width[currentColumn].isAuto() && logicalWidth.type() != Auto) { m_width[currentColumn] = logicalWidth; m_width[currentColumn] *= eSpan / span; usedWidth += fixedBorderBoxLogicalWidth * eSpan / span; } usedSpan += eSpan; ++currentColumn; } // FixedTableLayout doesn't use min/maxPreferredLogicalWidths, but we need to clear the // dirty bit on the cell so that we'll correctly mark its ancestors dirty // in case we later call setPreferredLogicalWidthsDirty(true) on it later. if (cell->preferredLogicalWidthsDirty()) cell->setPreferredLogicalWidthsDirty(false); } return usedWidth; }