void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBox::styleDidChange(diff, oldStyle); // If border was changed, notify table. if (parent()) { RenderTable* table = this->table(); if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style().border()) table->invalidateCollapsedBorders(); else if (oldStyle->width() != style().width()) { table->recalcSectionsIfNeeded(); for (auto& section : childrenOfType<RenderTableSection>(*table)) { unsigned nEffCols = table->numEffCols(); for (unsigned j = 0; j < nEffCols; j++) { unsigned rowCount = section.numRows(); for (unsigned i = 0; i < rowCount; i++) { RenderTableCell* cell = section.primaryCellAt(i, j); if (!cell) continue; cell->setPreferredLogicalWidthsDirty(true); } } } } } }
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; }