Example #1
0
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();
}
Example #2
0
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);
    }
}
Example #3
0
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;
}
Example #4
0
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;
}