forked from mirrors/gecko-dev
I'm not aware of any reason we shouldn't do this, as it is interoperable with other browsers, and it causes compat issues from sites that forget to use the prefixed version. Note this removes some #[parse(aliases)]. These only affect devtools autocomplete behavior, and we avoid autocompleting -moz-prefixed keywords when possible, so even though it's a slight behavior change, it's worth it. Differential Revision: https://phabricator.services.mozilla.com/D126718
1019 lines
38 KiB
C++
1019 lines
38 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
// vim:cindent:ts=2:et:sw=2:
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* Web-compatible algorithms that determine column and table widths,
|
|
* used for CSS2's 'table-layout: auto'.
|
|
*/
|
|
|
|
#include "BasicTableLayoutStrategy.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "nsTableFrame.h"
|
|
#include "nsTableColFrame.h"
|
|
#include "nsTableCellFrame.h"
|
|
#include "nsLayoutUtils.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "SpanningCellSorter.h"
|
|
#include "nsIContent.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::layout;
|
|
|
|
#undef DEBUG_TABLE_STRATEGY
|
|
|
|
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame* aTableFrame)
|
|
: nsITableLayoutStrategy(nsITableLayoutStrategy::Auto),
|
|
mTableFrame(aTableFrame) {
|
|
MarkIntrinsicISizesDirty();
|
|
}
|
|
|
|
/* virtual */
|
|
BasicTableLayoutStrategy::~BasicTableLayoutStrategy() = default;
|
|
|
|
/* virtual */
|
|
nscoord BasicTableLayoutStrategy::GetMinISize(gfxContext* aRenderingContext) {
|
|
DISPLAY_MIN_INLINE_SIZE(mTableFrame, mMinISize);
|
|
if (mMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) {
|
|
ComputeIntrinsicISizes(aRenderingContext);
|
|
}
|
|
return mMinISize;
|
|
}
|
|
|
|
/* virtual */
|
|
nscoord BasicTableLayoutStrategy::GetPrefISize(gfxContext* aRenderingContext,
|
|
bool aComputingSize) {
|
|
DISPLAY_PREF_INLINE_SIZE(mTableFrame, mPrefISize);
|
|
NS_ASSERTION((mPrefISize == NS_INTRINSIC_ISIZE_UNKNOWN) ==
|
|
(mPrefISizePctExpand == NS_INTRINSIC_ISIZE_UNKNOWN),
|
|
"dirtyness out of sync");
|
|
if (mPrefISize == NS_INTRINSIC_ISIZE_UNKNOWN) {
|
|
ComputeIntrinsicISizes(aRenderingContext);
|
|
}
|
|
return aComputingSize ? mPrefISizePctExpand : mPrefISize;
|
|
}
|
|
|
|
struct CellISizeInfo {
|
|
CellISizeInfo(nscoord aMinCoord, nscoord aPrefCoord, float aPrefPercent,
|
|
bool aHasSpecifiedISize)
|
|
: hasSpecifiedISize(aHasSpecifiedISize),
|
|
minCoord(aMinCoord),
|
|
prefCoord(aPrefCoord),
|
|
prefPercent(aPrefPercent) {}
|
|
|
|
bool hasSpecifiedISize;
|
|
nscoord minCoord;
|
|
nscoord prefCoord;
|
|
float prefPercent;
|
|
};
|
|
|
|
// Used for both column and cell calculations. The parts needed only
|
|
// for cells are skipped when aIsCell is false.
|
|
static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
|
|
nsIFrame* aFrame, WritingMode aWM,
|
|
bool aIsCell) {
|
|
nscoord minCoord, prefCoord;
|
|
const nsStylePosition* stylePos = aFrame->StylePosition();
|
|
bool isQuirks =
|
|
aFrame->PresContext()->CompatibilityMode() == eCompatibility_NavQuirks;
|
|
nscoord boxSizingToBorderEdge = 0;
|
|
if (aIsCell) {
|
|
// If aFrame is a container for font size inflation, then shrink
|
|
// wrapping inside of it should not apply font size inflation.
|
|
AutoMaybeDisableFontInflation an(aFrame);
|
|
|
|
minCoord = aFrame->GetMinISize(aRenderingContext);
|
|
prefCoord = aFrame->GetPrefISize(aRenderingContext);
|
|
// Until almost the end of this function, minCoord and prefCoord
|
|
// represent the box-sizing based isize values (which mean they
|
|
// should include inline padding and border width when
|
|
// box-sizing is set to border-box).
|
|
// Note that this function returns border-box isize, we add the
|
|
// outer edges near the end of this function.
|
|
|
|
// XXX Should we ignore percentage padding?
|
|
nsIFrame::IntrinsicSizeOffsetData offsets = aFrame->IntrinsicISizeOffsets();
|
|
|
|
// In quirks mode, table cell isize should be content-box,
|
|
// but bsize should be border box.
|
|
// Because of this historic anomaly, we do not use quirk.css.
|
|
// (We can't specify one value of box-sizing for isize and another
|
|
// for bsize).
|
|
// For this reason, we also do not use box-sizing for just one of
|
|
// them, as this may be confusing.
|
|
if (isQuirks || stylePos->mBoxSizing == StyleBoxSizing::Content) {
|
|
boxSizingToBorderEdge = offsets.padding + offsets.border;
|
|
} else {
|
|
// StyleBoxSizing::Border and standards-mode
|
|
minCoord += offsets.padding + offsets.border;
|
|
prefCoord += offsets.padding + offsets.border;
|
|
}
|
|
} else {
|
|
minCoord = 0;
|
|
prefCoord = 0;
|
|
}
|
|
float prefPercent = 0.0f;
|
|
bool hasSpecifiedISize = false;
|
|
|
|
const auto& iSize = stylePos->ISize(aWM);
|
|
// NOTE: We're ignoring calc() units with both lengths and percentages here,
|
|
// for lack of a sensible idea for what to do with them. This means calc()
|
|
// with percentages is basically handled like 'auto' for table cells and
|
|
// columns.
|
|
if (iSize.ConvertsToLength()) {
|
|
hasSpecifiedISize = true;
|
|
nscoord c = iSize.ToLength();
|
|
// Quirk: A cell with "nowrap" set and a coord value for the
|
|
// isize which is bigger than the intrinsic minimum isize uses
|
|
// that coord value as the minimum isize.
|
|
// This is kept up-to-date with dynamic changes to nowrap by code in
|
|
// nsTableCellFrame::AttributeChanged
|
|
if (aIsCell && c > minCoord && isQuirks &&
|
|
aFrame->GetContent()->AsElement()->HasAttr(kNameSpaceID_None,
|
|
nsGkAtoms::nowrap)) {
|
|
minCoord = c;
|
|
}
|
|
prefCoord = std::max(c, minCoord);
|
|
} else if (iSize.ConvertsToPercentage()) {
|
|
prefPercent = iSize.ToPercentage();
|
|
} else if (aIsCell) {
|
|
switch (iSize.tag) {
|
|
case StyleSize::Tag::MaxContent:
|
|
// 'inline-size' only affects pref isize, not min
|
|
// isize, so don't change anything
|
|
break;
|
|
case StyleSize::Tag::MinContent:
|
|
prefCoord = minCoord;
|
|
break;
|
|
case StyleSize::Tag::MozAvailable:
|
|
case StyleSize::Tag::FitContent:
|
|
case StyleSize::Tag::FitContentFunction:
|
|
// TODO: Bug 1708310: Make sure fit-content() work properly in table.
|
|
case StyleSize::Tag::Auto:
|
|
case StyleSize::Tag::LengthPercentage:
|
|
break;
|
|
}
|
|
}
|
|
|
|
StyleMaxSize maxISize = stylePos->MaxISize(aWM);
|
|
if (nsIFrame::ToExtremumLength(maxISize)) {
|
|
if (!aIsCell || maxISize.IsMozAvailable()) {
|
|
maxISize = StyleMaxSize::None();
|
|
} else if (maxISize.IsFitContent() || maxISize.IsFitContentFunction()) {
|
|
// TODO: Bug 1708310: Make sure fit-content() work properly in table.
|
|
// for 'max-inline-size', '-moz-fit-content' is like 'max-content'
|
|
maxISize = StyleMaxSize::MaxContent();
|
|
}
|
|
}
|
|
// XXX To really implement 'max-inline-size' well, we'd need to store
|
|
// it separately on the columns.
|
|
const LogicalSize zeroSize(aWM);
|
|
if (maxISize.ConvertsToLength() || nsIFrame::ToExtremumLength(maxISize)) {
|
|
nscoord c = aFrame
|
|
->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
|
|
zeroSize, 0, maxISize)
|
|
.mISize;
|
|
minCoord = std::min(c, minCoord);
|
|
prefCoord = std::min(c, prefCoord);
|
|
} else if (maxISize.ConvertsToPercentage()) {
|
|
float p = maxISize.ToPercentage();
|
|
if (p < prefPercent) {
|
|
prefPercent = p;
|
|
}
|
|
}
|
|
|
|
StyleSize minISize = stylePos->MinISize(aWM);
|
|
if (nsIFrame::ToExtremumLength(maxISize)) {
|
|
if (!aIsCell || minISize.IsMozAvailable()) {
|
|
minISize = StyleSize::LengthPercentage(LengthPercentage::Zero());
|
|
} else if (minISize.IsFitContent() || minISize.IsFitContentFunction()) {
|
|
// TODO: Bug 1708310: Make sure fit-content() work properly in table.
|
|
// for 'min-inline-size', '-moz-fit-content' is like 'min-content'
|
|
minISize = StyleSize::MinContent();
|
|
}
|
|
}
|
|
|
|
if (minISize.ConvertsToLength() || nsIFrame::ToExtremumLength(minISize)) {
|
|
nscoord c = aFrame
|
|
->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
|
|
zeroSize, 0, minISize)
|
|
.mISize;
|
|
minCoord = std::max(c, minCoord);
|
|
prefCoord = std::max(c, prefCoord);
|
|
} else if (minISize.ConvertsToPercentage()) {
|
|
float p = minISize.ToPercentage();
|
|
if (p > prefPercent) {
|
|
prefPercent = p;
|
|
}
|
|
}
|
|
|
|
// XXX Should col frame have border/padding considered?
|
|
if (aIsCell) {
|
|
minCoord += boxSizingToBorderEdge;
|
|
prefCoord = NSCoordSaturatingAdd(prefCoord, boxSizingToBorderEdge);
|
|
}
|
|
|
|
return CellISizeInfo(minCoord, prefCoord, prefPercent, hasSpecifiedISize);
|
|
}
|
|
|
|
static inline CellISizeInfo GetCellISizeInfo(gfxContext* aRenderingContext,
|
|
nsTableCellFrame* aCellFrame,
|
|
WritingMode aWM) {
|
|
return GetISizeInfo(aRenderingContext, aCellFrame, aWM, true);
|
|
}
|
|
|
|
static inline CellISizeInfo GetColISizeInfo(gfxContext* aRenderingContext,
|
|
nsIFrame* aFrame, WritingMode aWM) {
|
|
return GetISizeInfo(aRenderingContext, aFrame, aWM, false);
|
|
}
|
|
|
|
/**
|
|
* The algorithm in this function, in addition to meeting the
|
|
* requirements of Web-compatibility, is also invariant under reordering
|
|
* of the rows within a table (something that most, but not all, other
|
|
* browsers are).
|
|
*/
|
|
void BasicTableLayoutStrategy::ComputeColumnIntrinsicISizes(
|
|
gfxContext* aRenderingContext) {
|
|
nsTableFrame* tableFrame = mTableFrame;
|
|
nsTableCellMap* cellMap = tableFrame->GetCellMap();
|
|
WritingMode wm = tableFrame->GetWritingMode();
|
|
|
|
mozilla::AutoStackArena arena;
|
|
SpanningCellSorter spanningCells;
|
|
|
|
// Loop over the columns to consider the columns and cells *without*
|
|
// a colspan.
|
|
int32_t col, col_end;
|
|
for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
|
|
nsTableColFrame* colFrame = tableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
colFrame->ResetIntrinsics();
|
|
colFrame->ResetSpanIntrinsics();
|
|
|
|
// Consider the isizes on the column.
|
|
CellISizeInfo colInfo = GetColISizeInfo(aRenderingContext, colFrame, wm);
|
|
colFrame->AddCoords(colInfo.minCoord, colInfo.prefCoord,
|
|
colInfo.hasSpecifiedISize);
|
|
colFrame->AddPrefPercent(colInfo.prefPercent);
|
|
|
|
// Consider the isizes on the column-group. Note that we follow
|
|
// what the HTML spec says here, and make the isize apply to
|
|
// each column in the group, not the group as a whole.
|
|
|
|
// If column has isize, column-group doesn't override isize.
|
|
if (colInfo.minCoord == 0 && colInfo.prefCoord == 0 &&
|
|
colInfo.prefPercent == 0.0f) {
|
|
NS_ASSERTION(colFrame->GetParent()->IsTableColGroupFrame(),
|
|
"expected a column-group");
|
|
colInfo = GetColISizeInfo(aRenderingContext, colFrame->GetParent(), wm);
|
|
colFrame->AddCoords(colInfo.minCoord, colInfo.prefCoord,
|
|
colInfo.hasSpecifiedISize);
|
|
colFrame->AddPrefPercent(colInfo.prefPercent);
|
|
}
|
|
|
|
// Consider the contents of and the isizes on the cells without
|
|
// colspans.
|
|
nsCellMapColumnIterator columnIter(cellMap, col);
|
|
int32_t row, colSpan;
|
|
nsTableCellFrame* cellFrame;
|
|
while ((cellFrame = columnIter.GetNextFrame(&row, &colSpan))) {
|
|
if (colSpan > 1) {
|
|
spanningCells.AddCell(colSpan, row, col);
|
|
continue;
|
|
}
|
|
|
|
CellISizeInfo info = GetCellISizeInfo(aRenderingContext, cellFrame, wm);
|
|
|
|
colFrame->AddCoords(info.minCoord, info.prefCoord,
|
|
info.hasSpecifiedISize);
|
|
colFrame->AddPrefPercent(info.prefPercent);
|
|
}
|
|
#ifdef DEBUG_dbaron_off
|
|
printf("table %p col %d nonspan: min=%d pref=%d spec=%d pct=%f\n",
|
|
mTableFrame, col, colFrame->GetMinCoord(), colFrame->GetPrefCoord(),
|
|
colFrame->GetHasSpecifiedCoord(), colFrame->GetPrefPercent());
|
|
#endif
|
|
}
|
|
#ifdef DEBUG_TABLE_STRATEGY
|
|
printf("ComputeColumnIntrinsicISizes single\n");
|
|
mTableFrame->Dump(false, true, false);
|
|
#endif
|
|
|
|
// Consider the cells with a colspan that we saved in the loop above
|
|
// into the spanning cell sorter. We consider these cells by seeing
|
|
// if they require adding to the isizes resulting only from cells
|
|
// with a smaller colspan, and therefore we must process them sorted
|
|
// in increasing order by colspan. For each colspan group, we
|
|
// accumulate new values to accumulate in the column frame's Span*
|
|
// members.
|
|
//
|
|
// Considering things only relative to the isizes resulting from
|
|
// cells with smaller colspans (rather than incrementally including
|
|
// the results from spanning cells, or doing spanning and
|
|
// non-spanning cells in a single pass) means that layout remains
|
|
// row-order-invariant and (except for percentage isizes that add to
|
|
// more than 100%) column-order invariant.
|
|
//
|
|
// Starting with smaller colspans makes it more likely that we
|
|
// satisfy all the constraints given and don't distribute space to
|
|
// columns where we don't need it.
|
|
SpanningCellSorter::Item* item;
|
|
int32_t colSpan;
|
|
while ((item = spanningCells.GetNext(&colSpan))) {
|
|
NS_ASSERTION(colSpan > 1,
|
|
"cell should not have been put in spanning cell sorter");
|
|
do {
|
|
int32_t row = item->row;
|
|
col = item->col;
|
|
CellData* cellData = cellMap->GetDataAt(row, col);
|
|
NS_ASSERTION(cellData && cellData->IsOrig(),
|
|
"bogus result from spanning cell sorter");
|
|
|
|
nsTableCellFrame* cellFrame = cellData->GetCellFrame();
|
|
NS_ASSERTION(cellFrame, "bogus result from spanning cell sorter");
|
|
|
|
CellISizeInfo info = GetCellISizeInfo(aRenderingContext, cellFrame, wm);
|
|
|
|
if (info.prefPercent > 0.0f) {
|
|
DistributePctISizeToColumns(info.prefPercent, col, colSpan);
|
|
}
|
|
DistributeISizeToColumns(info.minCoord, col, colSpan, BTLS_MIN_ISIZE,
|
|
info.hasSpecifiedISize);
|
|
DistributeISizeToColumns(info.prefCoord, col, colSpan, BTLS_PREF_ISIZE,
|
|
info.hasSpecifiedISize);
|
|
} while ((item = item->next));
|
|
|
|
// Combine the results of the span analysis into the main results,
|
|
// for each increment of colspan.
|
|
|
|
for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
|
|
nsTableColFrame* colFrame = tableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
|
|
colFrame->AccumulateSpanIntrinsics();
|
|
colFrame->ResetSpanIntrinsics();
|
|
|
|
#ifdef DEBUG_dbaron_off
|
|
printf("table %p col %d span %d: min=%d pref=%d spec=%d pct=%f\n",
|
|
mTableFrame, col, colSpan, colFrame->GetMinCoord(),
|
|
colFrame->GetPrefCoord(), colFrame->GetHasSpecifiedCoord(),
|
|
colFrame->GetPrefPercent());
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Prevent percentages from adding to more than 100% by (to be
|
|
// compatible with other browsers) treating any percentages that would
|
|
// increase the total percentage to more than 100% as the number that
|
|
// would increase it to only 100% (which is 0% if we've already hit
|
|
// 100%). This means layout depends on the order of columns.
|
|
float pct_used = 0.0f;
|
|
for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
|
|
nsTableColFrame* colFrame = tableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
|
|
colFrame->AdjustPrefPercent(&pct_used);
|
|
}
|
|
|
|
#ifdef DEBUG_TABLE_STRATEGY
|
|
printf("ComputeColumnIntrinsicISizes spanning\n");
|
|
mTableFrame->Dump(false, true, false);
|
|
#endif
|
|
}
|
|
|
|
void BasicTableLayoutStrategy::ComputeIntrinsicISizes(
|
|
gfxContext* aRenderingContext) {
|
|
ComputeColumnIntrinsicISizes(aRenderingContext);
|
|
|
|
nsTableCellMap* cellMap = mTableFrame->GetCellMap();
|
|
nscoord min = 0, pref = 0, max_small_pct_pref = 0, nonpct_pref_total = 0;
|
|
float pct_total = 0.0f; // always from 0.0f - 1.0f
|
|
int32_t colCount = cellMap->GetColCount();
|
|
// add a total of (colcount + 1) lots of cellSpacingX for columns where a
|
|
// cell originates
|
|
nscoord add = mTableFrame->GetColSpacing(colCount);
|
|
|
|
for (int32_t col = 0; col < colCount; ++col) {
|
|
nsTableColFrame* colFrame = mTableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
if (mTableFrame->ColumnHasCellSpacingBefore(col)) {
|
|
add += mTableFrame->GetColSpacing(col - 1);
|
|
}
|
|
min += colFrame->GetMinCoord();
|
|
pref = NSCoordSaturatingAdd(pref, colFrame->GetPrefCoord());
|
|
|
|
// Percentages are of the table, so we have to reverse them for
|
|
// intrinsic isizes.
|
|
float p = colFrame->GetPrefPercent();
|
|
if (p > 0.0f) {
|
|
nscoord colPref = colFrame->GetPrefCoord();
|
|
nscoord new_small_pct_expand =
|
|
(colPref == nscoord_MAX ? nscoord_MAX : nscoord(float(colPref) / p));
|
|
if (new_small_pct_expand > max_small_pct_pref) {
|
|
max_small_pct_pref = new_small_pct_expand;
|
|
}
|
|
pct_total += p;
|
|
} else {
|
|
nonpct_pref_total =
|
|
NSCoordSaturatingAdd(nonpct_pref_total, colFrame->GetPrefCoord());
|
|
}
|
|
}
|
|
|
|
nscoord pref_pct_expand = pref;
|
|
|
|
// Account for small percentages expanding the preferred isize of
|
|
// *other* columns.
|
|
if (max_small_pct_pref > pref_pct_expand) {
|
|
pref_pct_expand = max_small_pct_pref;
|
|
}
|
|
|
|
// Account for large percentages expanding the preferred isize of
|
|
// themselves. There's no need to iterate over the columns multiple
|
|
// times, since when there is such a need, the small percentage
|
|
// effect is bigger anyway. (I think!)
|
|
NS_ASSERTION(0.0f <= pct_total && pct_total <= 1.0f,
|
|
"column percentage inline-sizes not adjusted down to 100%");
|
|
if (pct_total == 1.0f) {
|
|
if (nonpct_pref_total > 0) {
|
|
pref_pct_expand = nscoord_MAX;
|
|
// XXX Or should I use some smaller value? (Test this using
|
|
// nested tables!)
|
|
}
|
|
} else {
|
|
nscoord large_pct_pref =
|
|
(nonpct_pref_total == nscoord_MAX
|
|
? nscoord_MAX
|
|
: nscoord(float(nonpct_pref_total) / (1.0f - pct_total)));
|
|
if (large_pct_pref > pref_pct_expand) pref_pct_expand = large_pct_pref;
|
|
}
|
|
|
|
// border-spacing isn't part of the basis for percentages
|
|
if (colCount > 0) {
|
|
min += add;
|
|
pref = NSCoordSaturatingAdd(pref, add);
|
|
pref_pct_expand = NSCoordSaturatingAdd(pref_pct_expand, add);
|
|
}
|
|
|
|
mMinISize = min;
|
|
mPrefISize = pref;
|
|
mPrefISizePctExpand = pref_pct_expand;
|
|
}
|
|
|
|
/* virtual */
|
|
void BasicTableLayoutStrategy::MarkIntrinsicISizesDirty() {
|
|
mMinISize = NS_INTRINSIC_ISIZE_UNKNOWN;
|
|
mPrefISize = NS_INTRINSIC_ISIZE_UNKNOWN;
|
|
mPrefISizePctExpand = NS_INTRINSIC_ISIZE_UNKNOWN;
|
|
mLastCalcISize = nscoord_MIN;
|
|
}
|
|
|
|
/* virtual */
|
|
void BasicTableLayoutStrategy::ComputeColumnISizes(
|
|
const ReflowInput& aReflowInput) {
|
|
nscoord iSize = aReflowInput.ComputedISize();
|
|
|
|
if (mLastCalcISize == iSize) {
|
|
return;
|
|
}
|
|
mLastCalcISize = iSize;
|
|
|
|
NS_ASSERTION((mMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) ==
|
|
(mPrefISize == NS_INTRINSIC_ISIZE_UNKNOWN),
|
|
"dirtyness out of sync");
|
|
NS_ASSERTION((mMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) ==
|
|
(mPrefISizePctExpand == NS_INTRINSIC_ISIZE_UNKNOWN),
|
|
"dirtyness out of sync");
|
|
// XXX Is this needed?
|
|
if (mMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) {
|
|
ComputeIntrinsicISizes(aReflowInput.mRenderingContext);
|
|
}
|
|
|
|
nsTableCellMap* cellMap = mTableFrame->GetCellMap();
|
|
int32_t colCount = cellMap->GetColCount();
|
|
if (colCount <= 0) return; // nothing to do
|
|
|
|
DistributeISizeToColumns(iSize, 0, colCount, BTLS_FINAL_ISIZE, false);
|
|
|
|
#ifdef DEBUG_TABLE_STRATEGY
|
|
printf("ComputeColumnISizes final\n");
|
|
mTableFrame->Dump(false, true, false);
|
|
#endif
|
|
}
|
|
|
|
void BasicTableLayoutStrategy::DistributePctISizeToColumns(float aSpanPrefPct,
|
|
int32_t aFirstCol,
|
|
int32_t aColCount) {
|
|
// First loop to determine:
|
|
int32_t nonPctColCount = 0; // number of spanned columns without % isize
|
|
nscoord nonPctTotalPrefISize = 0; // total pref isize of those columns
|
|
// and to reduce aSpanPrefPct by columns that already have % isize
|
|
|
|
int32_t scol, scol_end;
|
|
nsTableCellMap* cellMap = mTableFrame->GetCellMap();
|
|
for (scol = aFirstCol, scol_end = aFirstCol + aColCount; scol < scol_end;
|
|
++scol) {
|
|
nsTableColFrame* scolFrame = mTableFrame->GetColFrame(scol);
|
|
if (!scolFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
float scolPct = scolFrame->GetPrefPercent();
|
|
if (scolPct == 0.0f) {
|
|
nonPctTotalPrefISize += scolFrame->GetPrefCoord();
|
|
if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
|
|
++nonPctColCount;
|
|
}
|
|
} else {
|
|
aSpanPrefPct -= scolPct;
|
|
}
|
|
}
|
|
|
|
if (aSpanPrefPct <= 0.0f || nonPctColCount == 0) {
|
|
// There's no %-isize on the colspan left over to distribute,
|
|
// or there are no columns to which we could distribute %-isize
|
|
return;
|
|
}
|
|
|
|
// Second loop, to distribute what remains of aSpanPrefPct
|
|
// between the non-percent-isize spanned columns
|
|
const bool spanHasNonPctPref = nonPctTotalPrefISize > 0; // Loop invariant
|
|
for (scol = aFirstCol, scol_end = aFirstCol + aColCount; scol < scol_end;
|
|
++scol) {
|
|
nsTableColFrame* scolFrame = mTableFrame->GetColFrame(scol);
|
|
if (!scolFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
|
|
if (scolFrame->GetPrefPercent() == 0.0f) {
|
|
NS_ASSERTION((!spanHasNonPctPref || nonPctTotalPrefISize != 0) &&
|
|
nonPctColCount != 0,
|
|
"should not be zero if we haven't allocated "
|
|
"all pref percent");
|
|
|
|
float allocatedPct; // % isize to be given to this column
|
|
if (spanHasNonPctPref) {
|
|
// Group so we're multiplying by 1.0f when we need
|
|
// to use up aSpanPrefPct.
|
|
allocatedPct = aSpanPrefPct * (float(scolFrame->GetPrefCoord()) /
|
|
float(nonPctTotalPrefISize));
|
|
} else if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
|
|
// distribute equally when all pref isizes are 0
|
|
allocatedPct = aSpanPrefPct / float(nonPctColCount);
|
|
} else {
|
|
allocatedPct = 0.0f;
|
|
}
|
|
// Allocate the percent
|
|
scolFrame->AddSpanPrefPercent(allocatedPct);
|
|
|
|
// To avoid accumulating rounding error from division,
|
|
// subtract this column's values from the totals.
|
|
aSpanPrefPct -= allocatedPct;
|
|
nonPctTotalPrefISize -= scolFrame->GetPrefCoord();
|
|
if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
|
|
--nonPctColCount;
|
|
}
|
|
|
|
if (!aSpanPrefPct) {
|
|
// No more span-percent-isize to distribute --> we're done.
|
|
NS_ASSERTION(
|
|
spanHasNonPctPref ? nonPctTotalPrefISize == 0 : nonPctColCount == 0,
|
|
"No more pct inline-size to distribute, "
|
|
"but there are still cols that need some.");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
// Bypass some assertions for tables inside XUL which we're realistically not
|
|
// going to investigate unless they cause havoc. Thunderbird hits these very
|
|
// often.
|
|
static bool IsCloseToXULBox(nsTableFrame* aTableFrame) {
|
|
// NOTE: GetParent() is guaranteed to be the table wrapper (thus non-null).
|
|
nsIFrame* f = aTableFrame->GetParent()->GetParent();
|
|
for (size_t i = 0; f && i < 2; ++i) {
|
|
if (f->IsXULBoxFrame()) {
|
|
return true;
|
|
}
|
|
f = f->GetParent();
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
void BasicTableLayoutStrategy::DistributeISizeToColumns(
|
|
nscoord aISize, int32_t aFirstCol, int32_t aColCount,
|
|
BtlsISizeType aISizeType, bool aSpanHasSpecifiedISize) {
|
|
NS_ASSERTION(
|
|
aISizeType != BTLS_FINAL_ISIZE ||
|
|
(aFirstCol == 0 &&
|
|
aColCount == mTableFrame->GetCellMap()->GetColCount()),
|
|
"Computing final column isizes, but didn't get full column range");
|
|
|
|
nscoord subtract = 0;
|
|
// aISize initially includes border-spacing for the boundaries in between
|
|
// each of the columns. We start at aFirstCol + 1 because the first
|
|
// in-between boundary would be at the left edge of column aFirstCol + 1
|
|
for (int32_t col = aFirstCol + 1; col < aFirstCol + aColCount; ++col) {
|
|
if (mTableFrame->ColumnHasCellSpacingBefore(col)) {
|
|
// border-spacing isn't part of the basis for percentages.
|
|
subtract += mTableFrame->GetColSpacing(col - 1);
|
|
}
|
|
}
|
|
if (aISizeType == BTLS_FINAL_ISIZE) {
|
|
// If we're computing final col-isize, then aISize initially includes
|
|
// border spacing on the table's far istart + far iend edge, too. Need
|
|
// to subtract those out, too.
|
|
subtract += (mTableFrame->GetColSpacing(-1) +
|
|
mTableFrame->GetColSpacing(aColCount));
|
|
}
|
|
aISize = NSCoordSaturatingSubtract(aISize, subtract, nscoord_MAX);
|
|
|
|
/*
|
|
* The goal of this function is to distribute |aISize| between the
|
|
* columns by making an appropriate AddSpanCoords or SetFinalISize
|
|
* call for each column. (We call AddSpanCoords if we're
|
|
* distributing a column-spanning cell's minimum or preferred isize
|
|
* to its spanned columns. We call SetFinalISize if we're
|
|
* distributing a table's final isize to its columns.)
|
|
*
|
|
* The idea is to either assign one of the following sets of isizes
|
|
* or a weighted average of two adjacent sets of isizes. It is not
|
|
* possible to assign values smaller than the smallest set of
|
|
* isizes. However, see below for handling the case of assigning
|
|
* values larger than the largest set of isizes. From smallest to
|
|
* largest, these are:
|
|
*
|
|
* 1. [guess_min] Assign all columns their min isize.
|
|
*
|
|
* 2. [guess_min_pct] Assign all columns with percentage isizes
|
|
* their percentage isize, and all other columns their min isize.
|
|
*
|
|
* 3. [guess_min_spec] Assign all columns with percentage isizes
|
|
* their percentage isize, all columns with specified coordinate
|
|
* isizes their pref isize (since it doesn't matter whether it's the
|
|
* largest contributor to the pref isize that was the specified
|
|
* contributor), and all other columns their min isize.
|
|
*
|
|
* 4. [guess_pref] Assign all columns with percentage isizes their
|
|
* specified isize, and all other columns their pref isize.
|
|
*
|
|
* If |aISize| is *larger* than what we would assign in (4), then we
|
|
* expand the columns:
|
|
*
|
|
* a. if any columns without a specified coordinate isize or
|
|
* percent isize have nonzero pref isize, in proportion to pref
|
|
* isize [total_flex_pref]
|
|
*
|
|
* b. otherwise, if any columns without a specified coordinate
|
|
* isize or percent isize, but with cells originating in them,
|
|
* have zero pref isize, equally between these
|
|
* [numNonSpecZeroISizeCols]
|
|
*
|
|
* c. otherwise, if any columns without percent isize have nonzero
|
|
* pref isize, in proportion to pref isize [total_fixed_pref]
|
|
*
|
|
* d. otherwise, if any columns have nonzero percentage isizes, in
|
|
* proportion to the percentage isizes [total_pct]
|
|
*
|
|
* e. otherwise, equally.
|
|
*/
|
|
|
|
// Loop #1 over the columns, to figure out the four values above so
|
|
// we know which case we're dealing with.
|
|
|
|
nscoord guess_min = 0, guess_min_pct = 0, guess_min_spec = 0, guess_pref = 0,
|
|
total_flex_pref = 0, total_fixed_pref = 0;
|
|
float total_pct = 0.0f; // 0.0f to 1.0f
|
|
int32_t numInfiniteISizeCols = 0;
|
|
int32_t numNonSpecZeroISizeCols = 0;
|
|
|
|
int32_t col;
|
|
nsTableCellMap* cellMap = mTableFrame->GetCellMap();
|
|
for (col = aFirstCol; col < aFirstCol + aColCount; ++col) {
|
|
nsTableColFrame* colFrame = mTableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
nscoord min_iSize = colFrame->GetMinCoord();
|
|
guess_min += min_iSize;
|
|
if (colFrame->GetPrefPercent() != 0.0f) {
|
|
float pct = colFrame->GetPrefPercent();
|
|
total_pct += pct;
|
|
nscoord val = nscoord(float(aISize) * pct);
|
|
if (val < min_iSize) {
|
|
val = min_iSize;
|
|
}
|
|
guess_min_pct = NSCoordSaturatingAdd(guess_min_pct, val);
|
|
guess_pref = NSCoordSaturatingAdd(guess_pref, val);
|
|
} else {
|
|
nscoord pref_iSize = colFrame->GetPrefCoord();
|
|
if (pref_iSize == nscoord_MAX) {
|
|
++numInfiniteISizeCols;
|
|
}
|
|
guess_pref = NSCoordSaturatingAdd(guess_pref, pref_iSize);
|
|
guess_min_pct = NSCoordSaturatingAdd(guess_min_pct, min_iSize);
|
|
if (colFrame->GetHasSpecifiedCoord()) {
|
|
// we'll add on the rest of guess_min_spec outside the
|
|
// loop
|
|
nscoord delta = NSCoordSaturatingSubtract(pref_iSize, min_iSize, 0);
|
|
guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, delta);
|
|
total_fixed_pref = NSCoordSaturatingAdd(total_fixed_pref, pref_iSize);
|
|
} else if (pref_iSize == 0) {
|
|
if (cellMap->GetNumCellsOriginatingInCol(col) > 0) {
|
|
++numNonSpecZeroISizeCols;
|
|
}
|
|
} else {
|
|
total_flex_pref = NSCoordSaturatingAdd(total_flex_pref, pref_iSize);
|
|
}
|
|
}
|
|
}
|
|
guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, guess_min_pct);
|
|
|
|
// Determine what we're flexing:
|
|
enum Loop2Type {
|
|
FLEX_PCT_SMALL, // between (1) and (2) above
|
|
FLEX_FIXED_SMALL, // between (2) and (3) above
|
|
FLEX_FLEX_SMALL, // between (3) and (4) above
|
|
FLEX_FLEX_LARGE, // greater than (4) above, case (a)
|
|
FLEX_FLEX_LARGE_ZERO, // greater than (4) above, case (b)
|
|
FLEX_FIXED_LARGE, // greater than (4) above, case (c)
|
|
FLEX_PCT_LARGE, // greater than (4) above, case (d)
|
|
FLEX_ALL_LARGE // greater than (4) above, case (e)
|
|
};
|
|
|
|
Loop2Type l2t;
|
|
// These are constants (over columns) for each case's math. We use
|
|
// a pair of nscoords rather than a float so that we can subtract
|
|
// each column's allocation so we avoid accumulating rounding error.
|
|
nscoord space; // the amount of extra isize to allocate
|
|
union {
|
|
nscoord c;
|
|
float f;
|
|
} basis; // the sum of the statistic over columns to divide it
|
|
if (aISize < guess_pref) {
|
|
if (aISizeType != BTLS_FINAL_ISIZE && aISize <= guess_min) {
|
|
// Return early -- we don't have any extra space to distribute.
|
|
return;
|
|
}
|
|
NS_ASSERTION(!(aISizeType == BTLS_FINAL_ISIZE && aISize < guess_min) ||
|
|
IsCloseToXULBox(mTableFrame),
|
|
"Table inline-size is less than the "
|
|
"sum of its columns' min inline-sizes");
|
|
if (aISize < guess_min_pct) {
|
|
l2t = FLEX_PCT_SMALL;
|
|
space = aISize - guess_min;
|
|
basis.c = guess_min_pct - guess_min;
|
|
} else if (aISize < guess_min_spec) {
|
|
l2t = FLEX_FIXED_SMALL;
|
|
space = aISize - guess_min_pct;
|
|
basis.c =
|
|
NSCoordSaturatingSubtract(guess_min_spec, guess_min_pct, nscoord_MAX);
|
|
} else {
|
|
l2t = FLEX_FLEX_SMALL;
|
|
space = aISize - guess_min_spec;
|
|
basis.c =
|
|
NSCoordSaturatingSubtract(guess_pref, guess_min_spec, nscoord_MAX);
|
|
}
|
|
} else {
|
|
space = NSCoordSaturatingSubtract(aISize, guess_pref, nscoord_MAX);
|
|
if (total_flex_pref > 0) {
|
|
l2t = FLEX_FLEX_LARGE;
|
|
basis.c = total_flex_pref;
|
|
} else if (numNonSpecZeroISizeCols > 0) {
|
|
l2t = FLEX_FLEX_LARGE_ZERO;
|
|
basis.c = numNonSpecZeroISizeCols;
|
|
} else if (total_fixed_pref > 0) {
|
|
l2t = FLEX_FIXED_LARGE;
|
|
basis.c = total_fixed_pref;
|
|
} else if (total_pct > 0.0f) {
|
|
l2t = FLEX_PCT_LARGE;
|
|
basis.f = total_pct;
|
|
} else {
|
|
l2t = FLEX_ALL_LARGE;
|
|
basis.c = aColCount;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG_dbaron_off
|
|
printf(
|
|
"ComputeColumnISizes: %d columns in isize %d,\n"
|
|
" guesses=[%d,%d,%d,%d], totals=[%d,%d,%f],\n"
|
|
" l2t=%d, space=%d, basis.c=%d\n",
|
|
aColCount, aISize, guess_min, guess_min_pct, guess_min_spec, guess_pref,
|
|
total_flex_pref, total_fixed_pref, total_pct, l2t, space, basis.c);
|
|
#endif
|
|
|
|
for (col = aFirstCol; col < aFirstCol + aColCount; ++col) {
|
|
nsTableColFrame* colFrame = mTableFrame->GetColFrame(col);
|
|
if (!colFrame) {
|
|
NS_ERROR("column frames out of sync with cell map");
|
|
continue;
|
|
}
|
|
nscoord col_iSize;
|
|
|
|
float pct = colFrame->GetPrefPercent();
|
|
if (pct != 0.0f) {
|
|
col_iSize = nscoord(float(aISize) * pct);
|
|
nscoord col_min = colFrame->GetMinCoord();
|
|
if (col_iSize < col_min) {
|
|
col_iSize = col_min;
|
|
}
|
|
} else {
|
|
col_iSize = colFrame->GetPrefCoord();
|
|
}
|
|
|
|
nscoord col_iSize_before_adjust = col_iSize;
|
|
|
|
switch (l2t) {
|
|
case FLEX_PCT_SMALL:
|
|
col_iSize = col_iSize_before_adjust = colFrame->GetMinCoord();
|
|
if (pct != 0.0f) {
|
|
nscoord pct_minus_min = nscoord(float(aISize) * pct) - col_iSize;
|
|
if (pct_minus_min > 0) {
|
|
float c = float(space) / float(basis.c);
|
|
basis.c -= pct_minus_min;
|
|
col_iSize = NSCoordSaturatingAdd(
|
|
col_iSize, NSToCoordRound(float(pct_minus_min) * c));
|
|
}
|
|
}
|
|
break;
|
|
case FLEX_FIXED_SMALL:
|
|
if (pct == 0.0f) {
|
|
NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
|
|
"wrong inline-size assigned");
|
|
if (colFrame->GetHasSpecifiedCoord()) {
|
|
nscoord col_min = colFrame->GetMinCoord();
|
|
nscoord pref_minus_min = col_iSize - col_min;
|
|
col_iSize = col_iSize_before_adjust = col_min;
|
|
if (pref_minus_min != 0) {
|
|
float c = float(space) / float(basis.c);
|
|
basis.c -= pref_minus_min;
|
|
col_iSize = NSCoordSaturatingAdd(
|
|
col_iSize, NSToCoordRound(float(pref_minus_min) * c));
|
|
}
|
|
} else
|
|
col_iSize = col_iSize_before_adjust = colFrame->GetMinCoord();
|
|
}
|
|
break;
|
|
case FLEX_FLEX_SMALL:
|
|
if (pct == 0.0f && !colFrame->GetHasSpecifiedCoord()) {
|
|
NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
|
|
"wrong inline-size assigned");
|
|
nscoord col_min = colFrame->GetMinCoord();
|
|
nscoord pref_minus_min =
|
|
NSCoordSaturatingSubtract(col_iSize, col_min, 0);
|
|
col_iSize = col_iSize_before_adjust = col_min;
|
|
if (pref_minus_min != 0) {
|
|
float c = float(space) / float(basis.c);
|
|
// If we have infinite-isize cols, then the standard
|
|
// adjustment to col_iSize using 'c' won't work,
|
|
// because basis.c and pref_minus_min are both
|
|
// nscoord_MAX and will cancel each other out in the
|
|
// col_iSize adjustment (making us assign all the
|
|
// space to the first inf-isize col). To correct for
|
|
// this, we'll also divide by numInfiniteISizeCols to
|
|
// spread the space equally among the inf-isize cols.
|
|
if (numInfiniteISizeCols) {
|
|
if (colFrame->GetPrefCoord() == nscoord_MAX) {
|
|
c = c / float(numInfiniteISizeCols);
|
|
--numInfiniteISizeCols;
|
|
} else {
|
|
c = 0.0f;
|
|
}
|
|
}
|
|
basis.c =
|
|
NSCoordSaturatingSubtract(basis.c, pref_minus_min, nscoord_MAX);
|
|
col_iSize = NSCoordSaturatingAdd(
|
|
col_iSize, NSToCoordRound(float(pref_minus_min) * c));
|
|
}
|
|
}
|
|
break;
|
|
case FLEX_FLEX_LARGE:
|
|
if (pct == 0.0f && !colFrame->GetHasSpecifiedCoord()) {
|
|
NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
|
|
"wrong inline-size assigned");
|
|
if (col_iSize != 0) {
|
|
if (space == nscoord_MAX) {
|
|
basis.c -= col_iSize;
|
|
col_iSize = nscoord_MAX;
|
|
} else {
|
|
float c = float(space) / float(basis.c);
|
|
basis.c -= col_iSize;
|
|
col_iSize = NSCoordSaturatingAdd(
|
|
col_iSize, NSToCoordRound(float(col_iSize) * c));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case FLEX_FLEX_LARGE_ZERO:
|
|
if (pct == 0.0f && !colFrame->GetHasSpecifiedCoord() &&
|
|
cellMap->GetNumCellsOriginatingInCol(col) > 0) {
|
|
NS_ASSERTION(col_iSize == 0 && colFrame->GetPrefCoord() == 0,
|
|
"Since we're in FLEX_FLEX_LARGE_ZERO case, "
|
|
"all auto-inline-size cols should have zero "
|
|
"pref inline-size.");
|
|
float c = float(space) / float(basis.c);
|
|
col_iSize += NSToCoordRound(c);
|
|
--basis.c;
|
|
}
|
|
break;
|
|
case FLEX_FIXED_LARGE:
|
|
if (pct == 0.0f) {
|
|
NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
|
|
"wrong inline-size assigned");
|
|
NS_ASSERTION(
|
|
colFrame->GetHasSpecifiedCoord() || colFrame->GetPrefCoord() == 0,
|
|
"wrong case");
|
|
if (col_iSize != 0) {
|
|
float c = float(space) / float(basis.c);
|
|
basis.c -= col_iSize;
|
|
col_iSize = NSCoordSaturatingAdd(
|
|
col_iSize, NSToCoordRound(float(col_iSize) * c));
|
|
}
|
|
}
|
|
break;
|
|
case FLEX_PCT_LARGE:
|
|
NS_ASSERTION(pct != 0.0f || colFrame->GetPrefCoord() == 0,
|
|
"wrong case");
|
|
if (pct != 0.0f) {
|
|
float c = float(space) / basis.f;
|
|
col_iSize = NSCoordSaturatingAdd(col_iSize, NSToCoordRound(pct * c));
|
|
basis.f -= pct;
|
|
}
|
|
break;
|
|
case FLEX_ALL_LARGE: {
|
|
float c = float(space) / float(basis.c);
|
|
col_iSize = NSCoordSaturatingAdd(col_iSize, NSToCoordRound(c));
|
|
--basis.c;
|
|
} break;
|
|
}
|
|
|
|
// Only subtract from space if it's a real number.
|
|
if (space != nscoord_MAX) {
|
|
NS_ASSERTION(col_iSize != nscoord_MAX,
|
|
"How is col_iSize nscoord_MAX if space isn't?");
|
|
NS_ASSERTION(
|
|
col_iSize_before_adjust != nscoord_MAX,
|
|
"How is col_iSize_before_adjust nscoord_MAX if space isn't?");
|
|
space -= col_iSize - col_iSize_before_adjust;
|
|
}
|
|
|
|
NS_ASSERTION(col_iSize >= colFrame->GetMinCoord(),
|
|
"assigned inline-size smaller than min");
|
|
|
|
// Apply the new isize
|
|
switch (aISizeType) {
|
|
case BTLS_MIN_ISIZE: {
|
|
// Note: AddSpanCoords requires both a min and pref isize.
|
|
// For the pref isize, we'll just pass in our computed
|
|
// min isize, because the real pref isize will be at least
|
|
// as big
|
|
colFrame->AddSpanCoords(col_iSize, col_iSize, aSpanHasSpecifiedISize);
|
|
} break;
|
|
case BTLS_PREF_ISIZE: {
|
|
// Note: AddSpanCoords requires both a min and pref isize.
|
|
// For the min isize, we'll just pass in 0, because
|
|
// the real min isize will be at least 0
|
|
colFrame->AddSpanCoords(0, col_iSize, aSpanHasSpecifiedISize);
|
|
} break;
|
|
case BTLS_FINAL_ISIZE: {
|
|
nscoord old_final = colFrame->GetFinalISize();
|
|
colFrame->SetFinalISize(col_iSize);
|
|
|
|
if (old_final != col_iSize) {
|
|
mTableFrame->DidResizeColumns();
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
if (!IsCloseToXULBox(mTableFrame)) {
|
|
NS_ASSERTION((space == 0 || space == nscoord_MAX) &&
|
|
((l2t == FLEX_PCT_LARGE)
|
|
? (-0.001f < basis.f && basis.f < 0.001f)
|
|
: (basis.c == 0 || basis.c == nscoord_MAX)),
|
|
"didn't subtract all that we added");
|
|
}
|
|
#endif
|
|
}
|