예제 #1
0
void LayoutTableCol::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    LayoutBox::styleDidChange(diff, oldStyle);

    // If border was changed, notify table.
    if (parent()) {
        LayoutTable* table = this->table();
        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border()) {
            table->invalidateCollapsedBorders();
        } else if (oldStyle && oldStyle->logicalWidth() != style()->logicalWidth()) {
            // FIXME : setPreferredLogicalWidthsDirty is done for all cells as of now.
            // Need to find a better way so that only the cells which are changed by
            // the col width should have preferred logical widths recomputed.
            for (LayoutObject* child = table->children()->firstChild(); child; child = child->nextSibling()) {
                if (!child->isTableSection())
                    continue;
                LayoutTableSection* section = toLayoutTableSection(child);
                for (LayoutTableRow* row = section->firstRow(); row; row = row->nextRow()) {
                    for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
                        cell->setPreferredLogicalWidthsDirty();
                }
            }
        }
    }
}
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;
}