void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth)
{
    // FIXME: This entire calculation is incorrect for both minwidth and maxwidth.
    
    // we might want to wait until we have all of the first row before
    // layouting for the first time.

    // only need to calculate the minimum width as the sum of the
    // cols/cells with a fixed width.
    //
    // The maximum width is max(minWidth, tableWidth).
    int bs = m_table->bordersPaddingAndSpacing();
    
    int tableWidth = m_table->style()->width().isFixed() ? m_table->style()->width().value() - bs : 0;
    int mw = calcWidthArray(tableWidth) + bs;

    minWidth = max(mw, tableWidth);
    maxWidth = minWidth;
}
void FixedTableLayout::calcPrefWidths(int& minWidth, int& maxWidth)
{
    // FIXME: This entire calculation is incorrect for both minwidth and maxwidth.
    
    // we might want to wait until we have all of the first row before
    // layouting for the first time.

    // only need to calculate the minimum width as the sum of the
    // cols/cells with a fixed width.
    //
    // The maximum width is max(minWidth, tableWidth).
    int bs = m_table->bordersPaddingAndSpacing();
    
    int tableWidth = m_table->style()->width().isFixed() ? m_table->style()->width().value() - bs : 0;
    int mw = calcWidthArray(tableWidth) + bs;

    minWidth = max(mw, tableWidth);
    maxWidth = minWidth;

    // This quirk is very similar to one that exists in RenderBlock::calcBlockPrefWidths().
    // Here's the example for this one:
    /*
        <table style="width:100%; background-color:red"><tr><td>
            <table style="background-color:blue"><tr><td>
                <table style="width:100%; background-color:green; table-layout:fixed"><tr><td>
                    Content
                </td></tr></table>
            </td></tr></table>
        </td></tr></table>
    */ 
    // In this example, the two inner tables should be as large as the outer table. 
    // We can achieve this effect by making the maxwidth of fixed tables with percentage
    // widths be infinite.
    if (m_table->document()->inQuirksMode() && m_table->style()->width().isPercent() 
        && maxWidth < TABLE_MAX_WIDTH)
        maxWidth = TABLE_MAX_WIDTH;
}
void FixedTableLayout::layout()
{
    int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection();
    unsigned nEffCols = m_table->numEffCols();

    // FIXME: It is possible to be called without having properly updated our internal representation.
    // This means that our preferred logical widths were not recomputed as expected.
    if (nEffCols != m_width.size()) {
        calcWidthArray();
        // FIXME: Table layout shouldn't modify our table structure (but does due to columns and column-groups).
        nEffCols = m_table->numEffCols();
    }

    Vector<int> calcWidth(nEffCols, 0);

    unsigned numAuto = 0;
    unsigned autoSpan = 0;
    int totalFixedWidth = 0;
    int totalPercentWidth = 0;
    float totalPercent = 0;

    // Compute requirements and try to satisfy fixed and percent widths.
    // Percentages are of the table's width, so for example
    // for a table width of 100px with columns (40px, 10%), the 10% compute
    // to 10px here, and will scale up to 20px in the final (80px, 20px).
    for (unsigned i = 0; i < nEffCols; i++) {
        if (m_width[i].isFixed()) {
            calcWidth[i] = m_width[i].value();
            totalFixedWidth += calcWidth[i];
        } else if (m_width[i].isPercentNotCalculated()) {
            calcWidth[i] = valueForLength(m_width[i], tableLogicalWidth);
            totalPercentWidth += calcWidth[i];
            totalPercent += m_width[i].percent();
        } else if (m_width[i].isAuto()) {
            numAuto++;
            autoSpan += m_table->spanOfEffCol(i);
        }
    }

    int hspacing = m_table->hBorderSpacing();
    int totalWidth = totalFixedWidth + totalPercentWidth;
    if (!numAuto || totalWidth > tableLogicalWidth) {
        // If there are no auto columns, or if the total is too wide, take
        // what we have and scale it to fit as necessary.
        if (totalWidth != tableLogicalWidth) {
            // Fixed widths only scale up
            if (totalFixedWidth && totalWidth < tableLogicalWidth) {
                totalFixedWidth = 0;
                for (unsigned i = 0; i < nEffCols; i++) {
                    if (m_width[i].isFixed()) {
                        calcWidth[i] = calcWidth[i] * tableLogicalWidth / totalWidth;
                        totalFixedWidth += calcWidth[i];
                    }
                }
            }
            if (totalPercent) {
                totalPercentWidth = 0;
                for (unsigned i = 0; i < nEffCols; i++) {
                    if (m_width[i].isPercentNotCalculated()) {
                        calcWidth[i] = m_width[i].percent() * (tableLogicalWidth - totalFixedWidth) / totalPercent;
                        totalPercentWidth += calcWidth[i];
                    }
                }
            }
            totalWidth = totalFixedWidth + totalPercentWidth;
        }
    } else {
        // Divide the remaining width among the auto columns.
        ASSERT(autoSpan >= numAuto);
        int remainingWidth = tableLogicalWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto);
        int lastAuto = 0;
        for (unsigned i = 0; i < nEffCols; i++) {
            if (m_width[i].isAuto()) {
                unsigned span = m_table->spanOfEffCol(i);
                int w = remainingWidth * span / autoSpan;
                calcWidth[i] = w + hspacing * (span - 1);
                remainingWidth -= w;
                if (!remainingWidth)
                    break;
                lastAuto = i;
                numAuto--;
                ASSERT(autoSpan >= span);
                autoSpan -= span;
            }
        }
        // Last one gets the remainder.
        if (remainingWidth)
            calcWidth[lastAuto] += remainingWidth;
        totalWidth = tableLogicalWidth;
    }

    if (totalWidth < tableLogicalWidth) {
        // Spread extra space over columns.
        int remainingWidth = tableLogicalWidth - totalWidth;
        int total = nEffCols;
        while (total) {
            int w = remainingWidth / total;
            remainingWidth -= w;
            calcWidth[--total] += w;
        }
        if (nEffCols > 0)
            calcWidth[nEffCols - 1] += remainingWidth;
    }
    
    int pos = 0;
    for (unsigned i = 0; i < nEffCols; i++) {
        m_table->setColumnPosition(i, pos);
        pos += calcWidth[i] + hspacing;
    }
    int colPositionsSize = m_table->columnPositions().size();
    if (colPositionsSize > 0)
        m_table->setColumnPosition(colPositionsSize - 1, pos);
}
void FixedTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
{
    minWidth = maxWidth = calcWidthArray();
}
void TableLayoutAlgorithmFixed::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
{
    minWidth = maxWidth = LayoutUnit(calcWidthArray());
}