LayoutTableCol* LayoutTableCol::enclosingColumnGroup() const { if (!parent()->isLayoutTableCol()) return nullptr; LayoutTableCol* parentColumnGroup = toLayoutTableCol(parent()); ASSERT(parentColumnGroup->isTableColumnGroup()); ASSERT(isTableColumn()); return parentColumnGroup; }
void TableSectionPainter::paintCell(LayoutTableCell* cell, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cell, paintOffset); PaintPhase paintPhase = paintInfo.phase; LayoutTableRow* row = toLayoutTableRow(cell->parent()); if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && BlockPainter(*cell).intersectsPaintRect(paintInfo, paintOffset)) { // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of // the column group, column, row group, row, and then the cell. LayoutTableCol* column = m_layoutTableSection.table()->colElement(cell->col()); LayoutTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0; bool columnHasBackground = column && column->hasBackground(); bool columnGroupHasBackground = columnGroup && columnGroup->hasBackground(); bool sectionHasBackground = m_layoutTableSection.hasBackground(); bool rowHasBackground = row->hasBackground(); if (columnHasBackground || columnGroupHasBackground || sectionHasBackground || rowHasBackground) { TableCellPainter tableCellPainter(*cell); if (!LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, paintOffset)) { LayoutObjectDrawingRecorder recorder(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, tableCellPainter.paintBounds(cellPoint, TableCellPainter::AddOffsetFromParent), paintOffset); // Column groups and columns first. // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in // the stack, since we have already opened a transparency layer (potentially) for the table row group. // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the // cell. if (columnGroupHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup); if (columnHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, column); // Paint the row group next. if (sectionHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, &m_layoutTableSection); // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for // painting the row background for the cell. if (rowHasBackground && !row->hasSelfPaintingLayer()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, row); } } } if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) cell->paint(paintInfo, cellPoint); }
void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset); PaintPhase paintPhase = paintInfo.phase; const LayoutTableRow* row = toLayoutTableRow(cell.parent()); if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhaseBlockBackground) && BlockPainter(cell).intersectsPaintRect(paintInfo, paintOffset)) { // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of // the column group, column, row group, row, and then the cell. LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table()->colElement(cell.col()); LayoutTableCol* column = colAndColGroup.col; LayoutTableCol* columnGroup = colAndColGroup.colgroup; TableCellPainter tableCellPainter(cell); // Column groups and columns first. // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in // the stack, since we have already opened a transparency layer (potentially) for the table row group. // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the // cell. if (columnGroup && columnGroup->hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup, DisplayItem::TableCellBackgroundFromColumnGroup); if (column && column->hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, column, DisplayItem::TableCellBackgroundFromColumn); // Paint the row group next. if (m_layoutTableSection.hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, &m_layoutTableSection, DisplayItem::TableCellBackgroundFromSection); // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for // painting the row background for the cell. if (row->hasBackground() && !row->hasSelfPaintingLayer()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, row, DisplayItem::TableCellBackgroundFromRow); } if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) cell.paint(paintInfo, cellPoint); }
int TableLayoutAlgorithmFixed::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->numEffectiveColumns(); m_width.resize(nEffCols); m_width.fill(Length(Auto)); unsigned currentEffectiveColumn = 0; for (LayoutTableCol* col = m_table->firstColumn(); col; col = col->nextColumn()) { // LayoutTableCols 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->appendEffectiveColumn(span); nEffCols++; m_width.append(Length()); spanInCurrentEffectiveColumn = span; } else { if (span < m_table->spanOfEffectiveColumn(currentEffectiveColumn)) { m_table->splitEffectiveColumn(currentEffectiveColumn, span); nEffCols++; m_width.append(Length()); } spanInCurrentEffectiveColumn = m_table->spanOfEffectiveColumn(currentEffectiveColumn); } // TODO(alancutter): Make this work correctly for calc lengths. if ((colStyleLogicalWidth.isFixed() || colStyleLogicalWidth.hasPercent()) && 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. LayoutTableSection* section = m_table->topNonEmptySection(); if (!section) return usedWidth; unsigned currentColumn = 0; LayoutTableRow* firstRow = section->firstRow(); for (LayoutTableCell* cell = firstRow->firstCell(); cell; cell = cell->nextCell()) { Length logicalWidth = cell->styleOrColLogicalWidth(); // FIXME: calc() on tables should be handled consistently with other lengths. See bug: https://crbug.com/382725 if (logicalWidth.isCalculated()) logicalWidth = Length(); // Make it Auto unsigned span = cell->colSpan(); int fixedBorderBoxLogicalWidth = 0; // FIXME: Support other length types. If the width is non-auto, it should probably just use // LayoutBox::computeLogicalWidthUsing to compute the width. if (logicalWidth.isFixed() && logicalWidth.isPositive()) { fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value()); logicalWidth.setValue(fixedBorderBoxLogicalWidth); } unsigned usedSpan = 0; while (usedSpan < span && currentColumn < nEffCols) { float eSpan = m_table->spanOfEffectiveColumn(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; } // TableLayoutAlgorithmFixed 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() on it later. if (cell->preferredLogicalWidthsDirty()) cell->clearPreferredLogicalWidthsDirty(); } return usedWidth; }