Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/tables/BasicTableLayoutStrategy.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
// vim:cindent:ts=4:et:sw=4:
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * Web-compatible algorithms that determine column and table widths,
9
 * used for CSS2's 'table-layout: auto'.
10
 */
11
12
#include "BasicTableLayoutStrategy.h"
13
14
#include <algorithm>
15
16
#include "nsTableFrame.h"
17
#include "nsTableColFrame.h"
18
#include "nsTableCellFrame.h"
19
#include "nsLayoutUtils.h"
20
#include "nsGkAtoms.h"
21
#include "SpanningCellSorter.h"
22
#include "nsIContent.h"
23
24
using namespace mozilla;
25
using namespace mozilla::layout;
26
27
namespace css = mozilla::css;
28
29
#undef  DEBUG_TABLE_STRATEGY
30
31
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aTableFrame)
32
  : nsITableLayoutStrategy(nsITableLayoutStrategy::Auto)
33
  , mTableFrame(aTableFrame)
34
0
{
35
0
    MarkIntrinsicISizesDirty();
36
0
}
37
38
/* virtual */
39
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
40
0
{
41
0
}
42
43
/* virtual */ nscoord
44
BasicTableLayoutStrategy::GetMinISize(gfxContext* aRenderingContext)
45
0
{
46
0
    DISPLAY_MIN_INLINE_SIZE(mTableFrame, mMinISize);
47
0
    if (mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
48
0
        ComputeIntrinsicISizes(aRenderingContext);
49
0
    }
50
0
    return mMinISize;
51
0
}
52
53
/* virtual */ nscoord
54
BasicTableLayoutStrategy::GetPrefISize(gfxContext* aRenderingContext,
55
                                       bool aComputingSize)
56
0
{
57
0
    DISPLAY_PREF_INLINE_SIZE(mTableFrame, mPrefISize);
58
0
    NS_ASSERTION((mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
59
0
                 (mPrefISizePctExpand == NS_INTRINSIC_WIDTH_UNKNOWN),
60
0
                 "dirtyness out of sync");
61
0
    if (mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
62
0
        ComputeIntrinsicISizes(aRenderingContext);
63
0
    }
64
0
    return aComputingSize ? mPrefISizePctExpand : mPrefISize;
65
0
}
66
67
struct CellISizeInfo {
68
    CellISizeInfo(nscoord aMinCoord, nscoord aPrefCoord,
69
                  float aPrefPercent, bool aHasSpecifiedISize)
70
        : hasSpecifiedISize(aHasSpecifiedISize)
71
        , minCoord(aMinCoord)
72
        , prefCoord(aPrefCoord)
73
        , prefPercent(aPrefPercent)
74
0
    {
75
0
    }
76
77
    bool hasSpecifiedISize;
78
    nscoord minCoord;
79
    nscoord prefCoord;
80
    float prefPercent;
81
};
82
83
// Used for both column and cell calculations.  The parts needed only
84
// for cells are skipped when aIsCell is false.
85
static CellISizeInfo
86
GetISizeInfo(gfxContext *aRenderingContext,
87
             nsIFrame *aFrame, WritingMode aWM, bool aIsCell)
88
0
{
89
0
    nscoord minCoord, prefCoord;
90
0
    const nsStylePosition *stylePos = aFrame->StylePosition();
91
0
    bool isQuirks = aFrame->PresContext()->CompatibilityMode() ==
92
0
                    eCompatibility_NavQuirks;
93
0
    nscoord boxSizingToBorderEdge = 0;
94
0
    if (aIsCell) {
95
0
        // If aFrame is a container for font size inflation, then shrink
96
0
        // wrapping inside of it should not apply font size inflation.
97
0
        AutoMaybeDisableFontInflation an(aFrame);
98
0
99
0
        minCoord = aFrame->GetMinISize(aRenderingContext);
100
0
        prefCoord = aFrame->GetPrefISize(aRenderingContext);
101
0
        // Until almost the end of this function, minCoord and prefCoord
102
0
        // represent the box-sizing based isize values (which mean they
103
0
        // should include inline padding and border width when
104
0
        // box-sizing is set to border-box).
105
0
        // Note that this function returns border-box isize, we add the
106
0
        // outer edges near the end of this function.
107
0
108
0
        // XXX Should we ignore percentage padding?
109
0
        nsIFrame::IntrinsicISizeOffsetData offsets =
110
0
            aFrame->IntrinsicISizeOffsets();
111
0
112
0
        // In quirks mode, table cell isize should be content-box,
113
0
        // but bsize should be border box.
114
0
        // Because of this historic anomaly, we do not use quirk.css.
115
0
        // (We can't specify one value of box-sizing for isize and another
116
0
        // for bsize).
117
0
        // For this reason, we also do not use box-sizing for just one of
118
0
        // them, as this may be confusing.
119
0
        if (isQuirks || stylePos->mBoxSizing == StyleBoxSizing::Content) {
120
0
            boxSizingToBorderEdge = offsets.hPadding + offsets.hBorder;
121
0
        }
122
0
        else {
123
0
            // StyleBoxSizing::Border and standards-mode
124
0
            minCoord += offsets.hPadding + offsets.hBorder;
125
0
            prefCoord += offsets.hPadding + offsets.hBorder;
126
0
        }
127
0
    } else {
128
0
        minCoord = 0;
129
0
        prefCoord = 0;
130
0
    }
131
0
    float prefPercent = 0.0f;
132
0
    bool hasSpecifiedISize = false;
133
0
134
0
    const nsStyleCoord& iSize = stylePos->ISize(aWM);
135
0
    nsStyleUnit unit = iSize.GetUnit();
136
0
    // NOTE: We're ignoring calc() units with percentages here, for lack of a
137
0
    // sensible idea for what to do with them.  This means calc() with
138
0
    // percentages is basically handled like 'auto' for table cells and
139
0
    // columns.
140
0
    if (iSize.ConvertsToLength()) {
141
0
        hasSpecifiedISize = true;
142
0
        // Note: since ComputeISizeValue was designed to return content-box
143
0
        // isize, it will (in some cases) subtract the box-sizing edges.
144
0
        // We prevent this unwanted behavior by calling it with
145
0
        // aContentEdgeToBoxSizing and aBoxSizingToMarginEdge set to 0.
146
0
        nscoord c = aFrame->ComputeISizeValue(aRenderingContext, 0, 0, 0, iSize);
147
0
        // Quirk: A cell with "nowrap" set and a coord value for the
148
0
        // isize which is bigger than the intrinsic minimum isize uses
149
0
        // that coord value as the minimum isize.
150
0
        // This is kept up-to-date with dynamic changes to nowrap by code in
151
0
        // nsTableCellFrame::AttributeChanged
152
0
        if (aIsCell && c > minCoord && isQuirks &&
153
0
            aFrame->GetContent()->AsElement()->HasAttr(kNameSpaceID_None,
154
0
                                                       nsGkAtoms::nowrap)) {
155
0
            minCoord = c;
156
0
        }
157
0
        prefCoord = std::max(c, minCoord);
158
0
    } else if (unit == eStyleUnit_Percent) {
159
0
        prefPercent = iSize.GetPercentValue();
160
0
    } else if (unit == eStyleUnit_Enumerated && aIsCell) {
161
0
        switch (iSize.GetIntValue()) {
162
0
            case NS_STYLE_WIDTH_MAX_CONTENT:
163
0
                // 'inline-size' only affects pref isize, not min
164
0
                // isize, so don't change anything
165
0
                break;
166
0
            case NS_STYLE_WIDTH_MIN_CONTENT:
167
0
                prefCoord = minCoord;
168
0
                break;
169
0
            case NS_STYLE_WIDTH_FIT_CONTENT:
170
0
            case NS_STYLE_WIDTH_AVAILABLE:
171
0
                // act just like 'inline-size: auto'
172
0
                break;
173
0
            default:
174
0
                MOZ_ASSERT_UNREACHABLE("unexpected enumerated value");
175
0
        }
176
0
    }
177
0
178
0
    nsStyleCoord maxISize(stylePos->MaxISize(aWM));
179
0
    if (maxISize.GetUnit() == eStyleUnit_Enumerated) {
180
0
        if (!aIsCell || maxISize.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE) {
181
0
            maxISize.SetNoneValue();
182
0
        } else if (maxISize.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT) {
183
0
            // for 'max-inline-size', '-moz-fit-content' is like
184
0
            // '-moz-max-content'
185
0
            maxISize.SetIntValue(NS_STYLE_WIDTH_MAX_CONTENT,
186
0
                                 eStyleUnit_Enumerated);
187
0
        }
188
0
    }
189
0
    unit = maxISize.GetUnit();
190
0
    // XXX To really implement 'max-inline-size' well, we'd need to store
191
0
    // it separately on the columns.
192
0
    if (maxISize.ConvertsToLength() || unit == eStyleUnit_Enumerated) {
193
0
        nscoord c = aFrame->ComputeISizeValue(aRenderingContext,
194
0
                                              0, 0, 0, maxISize);
195
0
        minCoord = std::min(c, minCoord);
196
0
        prefCoord = std::min(c, prefCoord);
197
0
    } else if (unit == eStyleUnit_Percent) {
198
0
        float p = stylePos->MaxISize(aWM).GetPercentValue();
199
0
        if (p < prefPercent) {
200
0
            prefPercent = p;
201
0
        }
202
0
    }
203
0
    // treat calc() with percentages on max-inline-size just like 'none'.
204
0
205
0
    nsStyleCoord minISize(stylePos->MinISize(aWM));
206
0
    if (minISize.GetUnit() == eStyleUnit_Enumerated) {
207
0
        if (!aIsCell || minISize.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE) {
208
0
            minISize.SetCoordValue(0);
209
0
        } else if (minISize.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT) {
210
0
            // for 'min-inline-size', '-moz-fit-content' is like
211
0
            // '-moz-min-content'
212
0
            minISize.SetIntValue(NS_STYLE_WIDTH_MIN_CONTENT,
213
0
                                 eStyleUnit_Enumerated);
214
0
        }
215
0
    }
216
0
    unit = minISize.GetUnit();
217
0
    if (minISize.ConvertsToLength() || unit == eStyleUnit_Enumerated) {
218
0
        nscoord c = aFrame->ComputeISizeValue(aRenderingContext,
219
0
                                              0, 0, 0, minISize);
220
0
        minCoord = std::max(c, minCoord);
221
0
        prefCoord = std::max(c, prefCoord);
222
0
    } else if (unit == eStyleUnit_Percent) {
223
0
        float p = stylePos->MinISize(aWM).GetPercentValue();
224
0
        if (p > prefPercent) {
225
0
            prefPercent = p;
226
0
        }
227
0
    }
228
0
    // treat calc() with percentages on min-inline-size just like '0'.
229
0
230
0
    // XXX Should col frame have border/padding considered?
231
0
    if (aIsCell) {
232
0
        minCoord += boxSizingToBorderEdge;
233
0
        prefCoord = NSCoordSaturatingAdd(prefCoord, boxSizingToBorderEdge);
234
0
    }
235
0
236
0
    return CellISizeInfo(minCoord, prefCoord, prefPercent, hasSpecifiedISize);
237
0
}
238
239
static inline CellISizeInfo
240
GetCellISizeInfo(gfxContext *aRenderingContext,
241
                 nsTableCellFrame *aCellFrame, WritingMode aWM)
242
0
{
243
0
    return GetISizeInfo(aRenderingContext, aCellFrame, aWM, true);
244
0
}
245
246
static inline CellISizeInfo
247
GetColISizeInfo(gfxContext *aRenderingContext,
248
                nsIFrame *aFrame, WritingMode aWM)
249
0
{
250
0
    return GetISizeInfo(aRenderingContext, aFrame, aWM, false);
251
0
}
252
253
254
/**
255
 * The algorithm in this function, in addition to meeting the
256
 * requirements of Web-compatibility, is also invariant under reordering
257
 * of the rows within a table (something that most, but not all, other
258
 * browsers are).
259
 */
260
void
261
BasicTableLayoutStrategy::ComputeColumnIntrinsicISizes(gfxContext* aRenderingContext)
262
0
{
263
0
    nsTableFrame *tableFrame = mTableFrame;
264
0
    nsTableCellMap *cellMap = tableFrame->GetCellMap();
265
0
    WritingMode wm = tableFrame->GetWritingMode();
266
0
267
0
    mozilla::AutoStackArena arena;
268
0
    SpanningCellSorter spanningCells;
269
0
270
0
    // Loop over the columns to consider the columns and cells *without*
271
0
    // a colspan.
272
0
    int32_t col, col_end;
273
0
    for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
274
0
        nsTableColFrame *colFrame = tableFrame->GetColFrame(col);
275
0
        if (!colFrame) {
276
0
            NS_ERROR("column frames out of sync with cell map");
277
0
            continue;
278
0
        }
279
0
        colFrame->ResetIntrinsics();
280
0
        colFrame->ResetSpanIntrinsics();
281
0
282
0
        // Consider the isizes on the column.
283
0
        CellISizeInfo colInfo = GetColISizeInfo(aRenderingContext,
284
0
                                                colFrame, wm);
285
0
        colFrame->AddCoords(colInfo.minCoord, colInfo.prefCoord,
286
0
                            colInfo.hasSpecifiedISize);
287
0
        colFrame->AddPrefPercent(colInfo.prefPercent);
288
0
289
0
        // Consider the isizes on the column-group.  Note that we follow
290
0
        // what the HTML spec says here, and make the isize apply to
291
0
        // each column in the group, not the group as a whole.
292
0
293
0
        // If column has isize, column-group doesn't override isize.
294
0
        if (colInfo.minCoord == 0 && colInfo.prefCoord == 0 &&
295
0
            colInfo.prefPercent == 0.0f) {
296
0
          NS_ASSERTION(colFrame->GetParent()->IsTableColGroupFrame(),
297
0
                       "expected a column-group");
298
0
          colInfo =
299
0
            GetColISizeInfo(aRenderingContext, colFrame->GetParent(), wm);
300
0
          colFrame->AddCoords(
301
0
            colInfo.minCoord, colInfo.prefCoord, colInfo.hasSpecifiedISize);
302
0
          colFrame->AddPrefPercent(colInfo.prefPercent);
303
0
        }
304
0
305
0
        // Consider the contents of and the isizes on the cells without
306
0
        // colspans.
307
0
        nsCellMapColumnIterator columnIter(cellMap, col);
308
0
        int32_t row, colSpan;
309
0
        nsTableCellFrame* cellFrame;
310
0
        while ((cellFrame = columnIter.GetNextFrame(&row, &colSpan))) {
311
0
            if (colSpan > 1) {
312
0
                spanningCells.AddCell(colSpan, row, col);
313
0
                continue;
314
0
            }
315
0
316
0
            CellISizeInfo info = GetCellISizeInfo(aRenderingContext,
317
0
                                                  cellFrame, wm);
318
0
319
0
            colFrame->AddCoords(info.minCoord, info.prefCoord,
320
0
                                info.hasSpecifiedISize);
321
0
            colFrame->AddPrefPercent(info.prefPercent);
322
0
        }
323
#ifdef DEBUG_dbaron_off
324
        printf("table %p col %d nonspan: min=%d pref=%d spec=%d pct=%f\n",
325
               mTableFrame, col, colFrame->GetMinCoord(),
326
               colFrame->GetPrefCoord(), colFrame->GetHasSpecifiedCoord(),
327
               colFrame->GetPrefPercent());
328
#endif
329
    }
330
#ifdef DEBUG_TABLE_STRATEGY
331
    printf("ComputeColumnIntrinsicISizes single\n");
332
    mTableFrame->Dump(false, true, false);
333
#endif
334
335
0
    // Consider the cells with a colspan that we saved in the loop above
336
0
    // into the spanning cell sorter.  We consider these cells by seeing
337
0
    // if they require adding to the isizes resulting only from cells
338
0
    // with a smaller colspan, and therefore we must process them sorted
339
0
    // in increasing order by colspan.  For each colspan group, we
340
0
    // accumulate new values to accumulate in the column frame's Span*
341
0
    // members.
342
0
    //
343
0
    // Considering things only relative to the isizes resulting from
344
0
    // cells with smaller colspans (rather than incrementally including
345
0
    // the results from spanning cells, or doing spanning and
346
0
    // non-spanning cells in a single pass) means that layout remains
347
0
    // row-order-invariant and (except for percentage isizes that add to
348
0
    // more than 100%) column-order invariant.
349
0
    //
350
0
    // Starting with smaller colspans makes it more likely that we
351
0
    // satisfy all the constraints given and don't distribute space to
352
0
    // columns where we don't need it.
353
0
    SpanningCellSorter::Item *item;
354
0
    int32_t colSpan;
355
0
    while ((item = spanningCells.GetNext(&colSpan))) {
356
0
        NS_ASSERTION(colSpan > 1,
357
0
                     "cell should not have been put in spanning cell sorter");
358
0
        do {
359
0
            int32_t row = item->row;
360
0
            col = item->col;
361
0
            CellData *cellData = cellMap->GetDataAt(row, col);
362
0
            NS_ASSERTION(cellData && cellData->IsOrig(),
363
0
                         "bogus result from spanning cell sorter");
364
0
365
0
            nsTableCellFrame *cellFrame = cellData->GetCellFrame();
366
0
            NS_ASSERTION(cellFrame, "bogus result from spanning cell sorter");
367
0
368
0
            CellISizeInfo info =
369
0
                GetCellISizeInfo(aRenderingContext, cellFrame, wm);
370
0
371
0
            if (info.prefPercent > 0.0f) {
372
0
                DistributePctISizeToColumns(info.prefPercent,
373
0
                                            col, colSpan);
374
0
            }
375
0
            DistributeISizeToColumns(info.minCoord, col, colSpan,
376
0
                                     BTLS_MIN_ISIZE, info.hasSpecifiedISize);
377
0
            DistributeISizeToColumns(info.prefCoord, col, colSpan,
378
0
                                     BTLS_PREF_ISIZE, info.hasSpecifiedISize);
379
0
        } while ((item = item->next));
380
0
381
0
        // Combine the results of the span analysis into the main results,
382
0
        // for each increment of colspan.
383
0
384
0
        for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
385
0
            nsTableColFrame *colFrame = tableFrame->GetColFrame(col);
386
0
            if (!colFrame) {
387
0
                NS_ERROR("column frames out of sync with cell map");
388
0
                continue;
389
0
            }
390
0
391
0
            colFrame->AccumulateSpanIntrinsics();
392
0
            colFrame->ResetSpanIntrinsics();
393
0
394
#ifdef DEBUG_dbaron_off
395
            printf("table %p col %d span %d: min=%d pref=%d spec=%d pct=%f\n",
396
                   mTableFrame, col, colSpan, colFrame->GetMinCoord(),
397
                   colFrame->GetPrefCoord(), colFrame->GetHasSpecifiedCoord(),
398
                   colFrame->GetPrefPercent());
399
#endif
400
        }
401
0
    }
402
0
403
0
    // Prevent percentages from adding to more than 100% by (to be
404
0
    // compatible with other browsers) treating any percentages that would
405
0
    // increase the total percentage to more than 100% as the number that
406
0
    // would increase it to only 100% (which is 0% if we've already hit
407
0
    // 100%).  This means layout depends on the order of columns.
408
0
    float pct_used = 0.0f;
409
0
    for (col = 0, col_end = cellMap->GetColCount(); col < col_end; ++col) {
410
0
        nsTableColFrame *colFrame = tableFrame->GetColFrame(col);
411
0
        if (!colFrame) {
412
0
            NS_ERROR("column frames out of sync with cell map");
413
0
            continue;
414
0
        }
415
0
416
0
        colFrame->AdjustPrefPercent(&pct_used);
417
0
    }
418
0
419
#ifdef DEBUG_TABLE_STRATEGY
420
    printf("ComputeColumnIntrinsicISizes spanning\n");
421
    mTableFrame->Dump(false, true, false);
422
#endif
423
}
424
425
void
426
BasicTableLayoutStrategy::ComputeIntrinsicISizes(gfxContext* aRenderingContext)
427
0
{
428
0
    ComputeColumnIntrinsicISizes(aRenderingContext);
429
0
430
0
    nsTableCellMap *cellMap = mTableFrame->GetCellMap();
431
0
    nscoord min = 0, pref = 0, max_small_pct_pref = 0, nonpct_pref_total = 0;
432
0
    float pct_total = 0.0f; // always from 0.0f - 1.0f
433
0
    int32_t colCount = cellMap->GetColCount();
434
0
    // add a total of (colcount + 1) lots of cellSpacingX for columns where a
435
0
    // cell originates
436
0
    nscoord add = mTableFrame->GetColSpacing(colCount);
437
0
438
0
    for (int32_t col = 0; col < colCount; ++col) {
439
0
        nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
440
0
        if (!colFrame) {
441
0
            NS_ERROR("column frames out of sync with cell map");
442
0
            continue;
443
0
        }
444
0
        if (mTableFrame->ColumnHasCellSpacingBefore(col)) {
445
0
            add += mTableFrame->GetColSpacing(col - 1);
446
0
        }
447
0
        min += colFrame->GetMinCoord();
448
0
        pref = NSCoordSaturatingAdd(pref, colFrame->GetPrefCoord());
449
0
450
0
        // Percentages are of the table, so we have to reverse them for
451
0
        // intrinsic isizes.
452
0
        float p = colFrame->GetPrefPercent();
453
0
        if (p > 0.0f) {
454
0
            nscoord colPref = colFrame->GetPrefCoord();
455
0
            nscoord new_small_pct_expand =
456
0
                (colPref == nscoord_MAX ?
457
0
                 nscoord_MAX : nscoord(float(colPref) / p));
458
0
            if (new_small_pct_expand > max_small_pct_pref) {
459
0
                max_small_pct_pref = new_small_pct_expand;
460
0
            }
461
0
            pct_total += p;
462
0
        } else {
463
0
            nonpct_pref_total = NSCoordSaturatingAdd(nonpct_pref_total,
464
0
                                                     colFrame->GetPrefCoord());
465
0
        }
466
0
    }
467
0
468
0
    nscoord pref_pct_expand = pref;
469
0
470
0
    // Account for small percentages expanding the preferred isize of
471
0
    // *other* columns.
472
0
    if (max_small_pct_pref > pref_pct_expand) {
473
0
        pref_pct_expand = max_small_pct_pref;
474
0
    }
475
0
476
0
    // Account for large percentages expanding the preferred isize of
477
0
    // themselves.  There's no need to iterate over the columns multiple
478
0
    // times, since when there is such a need, the small percentage
479
0
    // effect is bigger anyway.  (I think!)
480
0
    NS_ASSERTION(0.0f <= pct_total && pct_total <= 1.0f,
481
0
                 "column percentage inline-sizes not adjusted down to 100%");
482
0
    if (pct_total == 1.0f) {
483
0
        if (nonpct_pref_total > 0) {
484
0
            pref_pct_expand = nscoord_MAX;
485
0
            // XXX Or should I use some smaller value?  (Test this using
486
0
            // nested tables!)
487
0
        }
488
0
    } else {
489
0
        nscoord large_pct_pref =
490
0
            (nonpct_pref_total == nscoord_MAX ?
491
0
             nscoord_MAX :
492
0
             nscoord(float(nonpct_pref_total) / (1.0f - pct_total)));
493
0
        if (large_pct_pref > pref_pct_expand)
494
0
            pref_pct_expand = large_pct_pref;
495
0
    }
496
0
497
0
    // border-spacing isn't part of the basis for percentages
498
0
    if (colCount > 0) {
499
0
        min += add;
500
0
        pref = NSCoordSaturatingAdd(pref, add);
501
0
        pref_pct_expand = NSCoordSaturatingAdd(pref_pct_expand, add);
502
0
    }
503
0
504
0
    mMinISize = min;
505
0
    mPrefISize = pref;
506
0
    mPrefISizePctExpand = pref_pct_expand;
507
0
}
508
509
/* virtual */ void
510
BasicTableLayoutStrategy::MarkIntrinsicISizesDirty()
511
0
{
512
0
    mMinISize = NS_INTRINSIC_WIDTH_UNKNOWN;
513
0
    mPrefISize = NS_INTRINSIC_WIDTH_UNKNOWN;
514
0
    mPrefISizePctExpand = NS_INTRINSIC_WIDTH_UNKNOWN;
515
0
    mLastCalcISize = nscoord_MIN;
516
0
}
517
518
/* virtual */ void
519
BasicTableLayoutStrategy::ComputeColumnISizes(const ReflowInput& aReflowInput)
520
0
{
521
0
    nscoord iSize = aReflowInput.ComputedISize();
522
0
523
0
    if (mLastCalcISize == iSize) {
524
0
        return;
525
0
    }
526
0
    mLastCalcISize = iSize;
527
0
528
0
    NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
529
0
                 (mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN),
530
0
                 "dirtyness out of sync");
531
0
    NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
532
0
                 (mPrefISizePctExpand == NS_INTRINSIC_WIDTH_UNKNOWN),
533
0
                 "dirtyness out of sync");
534
0
    // XXX Is this needed?
535
0
    if (mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
536
0
        ComputeIntrinsicISizes(aReflowInput.mRenderingContext);
537
0
    }
538
0
539
0
    nsTableCellMap *cellMap = mTableFrame->GetCellMap();
540
0
    int32_t colCount = cellMap->GetColCount();
541
0
    if (colCount <= 0)
542
0
        return; // nothing to do
543
0
544
0
    DistributeISizeToColumns(iSize, 0, colCount, BTLS_FINAL_ISIZE, false);
545
0
546
#ifdef DEBUG_TABLE_STRATEGY
547
    printf("ComputeColumnISizes final\n");
548
    mTableFrame->Dump(false, true, false);
549
#endif
550
}
551
552
void
553
BasicTableLayoutStrategy::DistributePctISizeToColumns(float aSpanPrefPct,
554
                                                      int32_t aFirstCol,
555
                                                      int32_t aColCount)
556
0
{
557
0
    // First loop to determine:
558
0
    int32_t nonPctColCount = 0; // number of spanned columns without % isize
559
0
    nscoord nonPctTotalPrefISize = 0; // total pref isize of those columns
560
0
    // and to reduce aSpanPrefPct by columns that already have % isize
561
0
562
0
    int32_t scol, scol_end;
563
0
    nsTableCellMap *cellMap = mTableFrame->GetCellMap();
564
0
    for (scol = aFirstCol, scol_end = aFirstCol + aColCount;
565
0
         scol < scol_end; ++scol) {
566
0
        nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol);
567
0
        if (!scolFrame) {
568
0
            NS_ERROR("column frames out of sync with cell map");
569
0
            continue;
570
0
        }
571
0
        float scolPct = scolFrame->GetPrefPercent();
572
0
        if (scolPct == 0.0f) {
573
0
            nonPctTotalPrefISize += scolFrame->GetPrefCoord();
574
0
            if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
575
0
                ++nonPctColCount;
576
0
            }
577
0
        } else {
578
0
            aSpanPrefPct -= scolPct;
579
0
        }
580
0
    }
581
0
582
0
    if (aSpanPrefPct <= 0.0f || nonPctColCount == 0) {
583
0
        // There's no %-isize on the colspan left over to distribute,
584
0
        // or there are no columns to which we could distribute %-isize
585
0
        return;
586
0
    }
587
0
588
0
    // Second loop, to distribute what remains of aSpanPrefPct
589
0
    // between the non-percent-isize spanned columns
590
0
    const bool spanHasNonPctPref = nonPctTotalPrefISize > 0; // Loop invariant
591
0
    for (scol = aFirstCol, scol_end = aFirstCol + aColCount;
592
0
         scol < scol_end; ++scol) {
593
0
        nsTableColFrame *scolFrame = mTableFrame->GetColFrame(scol);
594
0
        if (!scolFrame) {
595
0
            NS_ERROR("column frames out of sync with cell map");
596
0
            continue;
597
0
        }
598
0
599
0
        if (scolFrame->GetPrefPercent() == 0.0f) {
600
0
            NS_ASSERTION((!spanHasNonPctPref ||
601
0
                          nonPctTotalPrefISize != 0) &&
602
0
                         nonPctColCount != 0,
603
0
                         "should not be zero if we haven't allocated "
604
0
                         "all pref percent");
605
0
606
0
            float allocatedPct; // % isize to be given to this column
607
0
            if (spanHasNonPctPref) {
608
0
                // Group so we're multiplying by 1.0f when we need
609
0
                // to use up aSpanPrefPct.
610
0
                allocatedPct = aSpanPrefPct *
611
0
                    (float(scolFrame->GetPrefCoord()) /
612
0
                     float(nonPctTotalPrefISize));
613
0
            } else if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
614
0
                // distribute equally when all pref isizes are 0
615
0
                allocatedPct = aSpanPrefPct / float(nonPctColCount);
616
0
            } else {
617
0
                allocatedPct = 0.0f;
618
0
            }
619
0
            // Allocate the percent
620
0
            scolFrame->AddSpanPrefPercent(allocatedPct);
621
0
622
0
            // To avoid accumulating rounding error from division,
623
0
            // subtract this column's values from the totals.
624
0
            aSpanPrefPct -= allocatedPct;
625
0
            nonPctTotalPrefISize -= scolFrame->GetPrefCoord();
626
0
            if (cellMap->GetNumCellsOriginatingInCol(scol) > 0) {
627
0
                --nonPctColCount;
628
0
            }
629
0
630
0
            if (!aSpanPrefPct) {
631
0
                // No more span-percent-isize to distribute --> we're done.
632
0
                NS_ASSERTION(spanHasNonPctPref ?
633
0
                             nonPctTotalPrefISize == 0 :
634
0
                             nonPctColCount == 0,
635
0
                             "No more pct inline-size to distribute, "
636
0
                             "but there are still cols that need some.");
637
0
                return;
638
0
            }
639
0
        }
640
0
    }
641
0
}
642
643
void
644
BasicTableLayoutStrategy::DistributeISizeToColumns(nscoord aISize,
645
                                                   int32_t aFirstCol,
646
                                                   int32_t aColCount,
647
                                                   BtlsISizeType aISizeType,
648
                                                   bool aSpanHasSpecifiedISize)
649
0
{
650
0
    NS_ASSERTION(aISizeType != BTLS_FINAL_ISIZE ||
651
0
                 (aFirstCol == 0 &&
652
0
                  aColCount == mTableFrame->GetCellMap()->GetColCount()),
653
0
            "Computing final column isizes, but didn't get full column range");
654
0
655
0
    nscoord subtract = 0;
656
0
    // aISize initially includes border-spacing for the boundaries in between
657
0
    // each of the columns. We start at aFirstCol + 1 because the first
658
0
    // in-between boundary would be at the left edge of column aFirstCol + 1
659
0
    for (int32_t col = aFirstCol + 1; col < aFirstCol + aColCount; ++col) {
660
0
        if (mTableFrame->ColumnHasCellSpacingBefore(col)) {
661
0
            // border-spacing isn't part of the basis for percentages.
662
0
            subtract += mTableFrame->GetColSpacing(col - 1);
663
0
        }
664
0
    }
665
0
    if (aISizeType == BTLS_FINAL_ISIZE) {
666
0
        // If we're computing final col-isize, then aISize initially includes
667
0
        // border spacing on the table's far istart + far iend edge, too.  Need
668
0
        // to subtract those out, too.
669
0
        subtract += (mTableFrame->GetColSpacing(-1) +
670
0
                     mTableFrame->GetColSpacing(aColCount));
671
0
    }
672
0
    aISize = NSCoordSaturatingSubtract(aISize, subtract, nscoord_MAX);
673
0
674
0
    /*
675
0
     * The goal of this function is to distribute |aISize| between the
676
0
     * columns by making an appropriate AddSpanCoords or SetFinalISize
677
0
     * call for each column.  (We call AddSpanCoords if we're
678
0
     * distributing a column-spanning cell's minimum or preferred isize
679
0
     * to its spanned columns.  We call SetFinalISize if we're
680
0
     * distributing a table's final isize to its columns.)
681
0
     *
682
0
     * The idea is to either assign one of the following sets of isizes
683
0
     * or a weighted average of two adjacent sets of isizes.  It is not
684
0
     * possible to assign values smaller than the smallest set of
685
0
     * isizes.  However, see below for handling the case of assigning
686
0
     * values larger than the largest set of isizes.  From smallest to
687
0
     * largest, these are:
688
0
     *
689
0
     * 1. [guess_min] Assign all columns their min isize.
690
0
     *
691
0
     * 2. [guess_min_pct] Assign all columns with percentage isizes
692
0
     * their percentage isize, and all other columns their min isize.
693
0
     *
694
0
     * 3. [guess_min_spec] Assign all columns with percentage isizes
695
0
     * their percentage isize, all columns with specified coordinate
696
0
     * isizes their pref isize (since it doesn't matter whether it's the
697
0
     * largest contributor to the pref isize that was the specified
698
0
     * contributor), and all other columns their min isize.
699
0
     *
700
0
     * 4. [guess_pref] Assign all columns with percentage isizes their
701
0
     * specified isize, and all other columns their pref isize.
702
0
     *
703
0
     * If |aISize| is *larger* than what we would assign in (4), then we
704
0
     * expand the columns:
705
0
     *
706
0
     *   a. if any columns without a specified coordinate isize or
707
0
     *   percent isize have nonzero pref isize, in proportion to pref
708
0
     *   isize [total_flex_pref]
709
0
     *
710
0
     *   b. otherwise, if any columns without a specified coordinate
711
0
     *   isize or percent isize, but with cells originating in them,
712
0
     *   have zero pref isize, equally between these
713
0
     *   [numNonSpecZeroISizeCols]
714
0
     *
715
0
     *   c. otherwise, if any columns without percent isize have nonzero
716
0
     *   pref isize, in proportion to pref isize [total_fixed_pref]
717
0
     *
718
0
     *   d. otherwise, if any columns have nonzero percentage isizes, in
719
0
     *   proportion to the percentage isizes [total_pct]
720
0
     *
721
0
     *   e. otherwise, equally.
722
0
     */
723
0
724
0
    // Loop #1 over the columns, to figure out the four values above so
725
0
    // we know which case we're dealing with.
726
0
727
0
    nscoord guess_min = 0,
728
0
            guess_min_pct = 0,
729
0
            guess_min_spec = 0,
730
0
            guess_pref = 0,
731
0
            total_flex_pref = 0,
732
0
            total_fixed_pref = 0;
733
0
    float total_pct = 0.0f; // 0.0f to 1.0f
734
0
    int32_t numInfiniteISizeCols = 0;
735
0
    int32_t numNonSpecZeroISizeCols = 0;
736
0
737
0
    int32_t col;
738
0
    nsTableCellMap *cellMap = mTableFrame->GetCellMap();
739
0
    for (col = aFirstCol; col < aFirstCol + aColCount; ++col) {
740
0
        nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
741
0
        if (!colFrame) {
742
0
            NS_ERROR("column frames out of sync with cell map");
743
0
            continue;
744
0
        }
745
0
        nscoord min_iSize = colFrame->GetMinCoord();
746
0
        guess_min += min_iSize;
747
0
        if (colFrame->GetPrefPercent() != 0.0f) {
748
0
            float pct = colFrame->GetPrefPercent();
749
0
            total_pct += pct;
750
0
            nscoord val = nscoord(float(aISize) * pct);
751
0
            if (val < min_iSize) {
752
0
                val = min_iSize;
753
0
            }
754
0
            guess_min_pct += val;
755
0
            guess_pref = NSCoordSaturatingAdd(guess_pref, val);
756
0
        } else {
757
0
            nscoord pref_iSize = colFrame->GetPrefCoord();
758
0
            if (pref_iSize == nscoord_MAX) {
759
0
                ++numInfiniteISizeCols;
760
0
            }
761
0
            guess_pref = NSCoordSaturatingAdd(guess_pref, pref_iSize);
762
0
            guess_min_pct += min_iSize;
763
0
            if (colFrame->GetHasSpecifiedCoord()) {
764
0
                // we'll add on the rest of guess_min_spec outside the
765
0
                // loop
766
0
                nscoord delta = NSCoordSaturatingSubtract(pref_iSize,
767
0
                                                          min_iSize, 0);
768
0
                guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, delta);
769
0
                total_fixed_pref = NSCoordSaturatingAdd(total_fixed_pref,
770
0
                                                        pref_iSize);
771
0
            } else if (pref_iSize == 0) {
772
0
                if (cellMap->GetNumCellsOriginatingInCol(col) > 0) {
773
0
                    ++numNonSpecZeroISizeCols;
774
0
                }
775
0
            } else {
776
0
                total_flex_pref = NSCoordSaturatingAdd(total_flex_pref,
777
0
                                                       pref_iSize);
778
0
            }
779
0
        }
780
0
    }
781
0
    guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, guess_min_pct);
782
0
783
0
    // Determine what we're flexing:
784
0
    enum Loop2Type {
785
0
        FLEX_PCT_SMALL, // between (1) and (2) above
786
0
        FLEX_FIXED_SMALL, // between (2) and (3) above
787
0
        FLEX_FLEX_SMALL, // between (3) and (4) above
788
0
        FLEX_FLEX_LARGE, // greater than (4) above, case (a)
789
0
        FLEX_FLEX_LARGE_ZERO, // greater than (4) above, case (b)
790
0
        FLEX_FIXED_LARGE, // greater than (4) above, case (c)
791
0
        FLEX_PCT_LARGE, // greater than (4) above, case (d)
792
0
        FLEX_ALL_LARGE // greater than (4) above, case (e)
793
0
    };
794
0
795
0
    Loop2Type l2t;
796
0
    // These are constants (over columns) for each case's math.  We use
797
0
    // a pair of nscoords rather than a float so that we can subtract
798
0
    // each column's allocation so we avoid accumulating rounding error.
799
0
    nscoord space; // the amount of extra isize to allocate
800
0
    union {
801
0
        nscoord c;
802
0
        float f;
803
0
    } basis; // the sum of the statistic over columns to divide it
804
0
    if (aISize < guess_pref) {
805
0
        if (aISizeType != BTLS_FINAL_ISIZE && aISize <= guess_min) {
806
0
            // Return early -- we don't have any extra space to distribute.
807
0
            return;
808
0
        }
809
0
        NS_ASSERTION(!(aISizeType == BTLS_FINAL_ISIZE && aISize < guess_min),
810
0
                     "Table inline-size is less than the "
811
0
                     "sum of its columns' min inline-sizes");
812
0
        if (aISize < guess_min_pct) {
813
0
            l2t = FLEX_PCT_SMALL;
814
0
            space = aISize - guess_min;
815
0
            basis.c = guess_min_pct - guess_min;
816
0
        } else if (aISize < guess_min_spec) {
817
0
            l2t = FLEX_FIXED_SMALL;
818
0
            space = aISize - guess_min_pct;
819
0
            basis.c = NSCoordSaturatingSubtract(guess_min_spec, guess_min_pct,
820
0
                                                nscoord_MAX);
821
0
        } else {
822
0
            l2t = FLEX_FLEX_SMALL;
823
0
            space = aISize - guess_min_spec;
824
0
            basis.c = NSCoordSaturatingSubtract(guess_pref, guess_min_spec,
825
0
                                                nscoord_MAX);
826
0
        }
827
0
    } else {
828
0
        space = NSCoordSaturatingSubtract(aISize, guess_pref, nscoord_MAX);
829
0
        if (total_flex_pref > 0) {
830
0
            l2t = FLEX_FLEX_LARGE;
831
0
            basis.c = total_flex_pref;
832
0
        } else if (numNonSpecZeroISizeCols > 0) {
833
0
            l2t = FLEX_FLEX_LARGE_ZERO;
834
0
            basis.c = numNonSpecZeroISizeCols;
835
0
        } else if (total_fixed_pref > 0) {
836
0
            l2t = FLEX_FIXED_LARGE;
837
0
            basis.c = total_fixed_pref;
838
0
        } else if (total_pct > 0.0f) {
839
0
            l2t = FLEX_PCT_LARGE;
840
0
            basis.f = total_pct;
841
0
        } else {
842
0
            l2t = FLEX_ALL_LARGE;
843
0
            basis.c = aColCount;
844
0
        }
845
0
    }
846
0
847
#ifdef DEBUG_dbaron_off
848
    printf("ComputeColumnISizes: %d columns in isize %d,\n"
849
           "  guesses=[%d,%d,%d,%d], totals=[%d,%d,%f],\n"
850
           "  l2t=%d, space=%d, basis.c=%d\n",
851
           aColCount, aISize,
852
           guess_min, guess_min_pct, guess_min_spec, guess_pref,
853
           total_flex_pref, total_fixed_pref, total_pct,
854
           l2t, space, basis.c);
855
#endif
856
857
0
    for (col = aFirstCol; col < aFirstCol + aColCount; ++col) {
858
0
        nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
859
0
        if (!colFrame) {
860
0
            NS_ERROR("column frames out of sync with cell map");
861
0
            continue;
862
0
        }
863
0
        nscoord col_iSize;
864
0
865
0
        float pct = colFrame->GetPrefPercent();
866
0
        if (pct != 0.0f) {
867
0
            col_iSize = nscoord(float(aISize) * pct);
868
0
            nscoord col_min = colFrame->GetMinCoord();
869
0
            if (col_iSize < col_min) {
870
0
                col_iSize = col_min;
871
0
            }
872
0
        } else {
873
0
            col_iSize = colFrame->GetPrefCoord();
874
0
        }
875
0
876
0
        nscoord col_iSize_before_adjust = col_iSize;
877
0
878
0
        switch (l2t) {
879
0
            case FLEX_PCT_SMALL:
880
0
                col_iSize = col_iSize_before_adjust = colFrame->GetMinCoord();
881
0
                if (pct != 0.0f) {
882
0
                    nscoord pct_minus_min =
883
0
                        nscoord(float(aISize) * pct) - col_iSize;
884
0
                    if (pct_minus_min > 0) {
885
0
                        float c = float(space) / float(basis.c);
886
0
                        basis.c -= pct_minus_min;
887
0
                        col_iSize += NSToCoordRound(float(pct_minus_min) * c);
888
0
                    }
889
0
                }
890
0
                break;
891
0
            case FLEX_FIXED_SMALL:
892
0
                if (pct == 0.0f) {
893
0
                    NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
894
0
                                 "wrong inline-size assigned");
895
0
                    if (colFrame->GetHasSpecifiedCoord()) {
896
0
                        nscoord col_min = colFrame->GetMinCoord();
897
0
                        nscoord pref_minus_min = col_iSize - col_min;
898
0
                        col_iSize = col_iSize_before_adjust = col_min;
899
0
                        if (pref_minus_min != 0) {
900
0
                            float c = float(space) / float(basis.c);
901
0
                            basis.c -= pref_minus_min;
902
0
                            col_iSize += NSToCoordRound(
903
0
                                float(pref_minus_min) * c);
904
0
                        }
905
0
                    } else
906
0
                        col_iSize = col_iSize_before_adjust =
907
0
                            colFrame->GetMinCoord();
908
0
                }
909
0
                break;
910
0
            case FLEX_FLEX_SMALL:
911
0
                if (pct == 0.0f &&
912
0
                    !colFrame->GetHasSpecifiedCoord()) {
913
0
                    NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
914
0
                                 "wrong inline-size assigned");
915
0
                    nscoord col_min = colFrame->GetMinCoord();
916
0
                    nscoord pref_minus_min =
917
0
                        NSCoordSaturatingSubtract(col_iSize, col_min, 0);
918
0
                    col_iSize = col_iSize_before_adjust = col_min;
919
0
                    if (pref_minus_min != 0) {
920
0
                        float c = float(space) / float(basis.c);
921
0
                        // If we have infinite-isize cols, then the standard
922
0
                        // adjustment to col_iSize using 'c' won't work,
923
0
                        // because basis.c and pref_minus_min are both
924
0
                        // nscoord_MAX and will cancel each other out in the
925
0
                        // col_iSize adjustment (making us assign all the
926
0
                        // space to the first inf-isize col).  To correct for
927
0
                        // this, we'll also divide by numInfiniteISizeCols to
928
0
                        // spread the space equally among the inf-isize cols.
929
0
                        if (numInfiniteISizeCols) {
930
0
                            if (colFrame->GetPrefCoord() == nscoord_MAX) {
931
0
                                c = c / float(numInfiniteISizeCols);
932
0
                                --numInfiniteISizeCols;
933
0
                            } else {
934
0
                                c = 0.0f;
935
0
                            }
936
0
                        }
937
0
                        basis.c = NSCoordSaturatingSubtract(basis.c,
938
0
                                                            pref_minus_min,
939
0
                                                            nscoord_MAX);
940
0
                        col_iSize += NSToCoordRound(
941
0
                            float(pref_minus_min) * c);
942
0
                    }
943
0
                }
944
0
                break;
945
0
            case FLEX_FLEX_LARGE:
946
0
                if (pct == 0.0f &&
947
0
                    !colFrame->GetHasSpecifiedCoord()) {
948
0
                    NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
949
0
                                 "wrong inline-size assigned");
950
0
                    if (col_iSize != 0) {
951
0
                        if (space == nscoord_MAX) {
952
0
                            basis.c -= col_iSize;
953
0
                            col_iSize = nscoord_MAX;
954
0
                        } else {
955
0
                            float c = float(space) / float(basis.c);
956
0
                            basis.c -= col_iSize;
957
0
                            col_iSize += NSToCoordRound(float(col_iSize) * c);
958
0
                        }
959
0
                    }
960
0
                }
961
0
                break;
962
0
            case FLEX_FLEX_LARGE_ZERO:
963
0
                if (pct == 0.0f &&
964
0
                    !colFrame->GetHasSpecifiedCoord() &&
965
0
                    cellMap->GetNumCellsOriginatingInCol(col) > 0) {
966
0
967
0
                    NS_ASSERTION(col_iSize == 0 &&
968
0
                                 colFrame->GetPrefCoord() == 0,
969
0
                                 "Since we're in FLEX_FLEX_LARGE_ZERO case, "
970
0
                                 "all auto-inline-size cols should have zero "
971
0
                                 "pref inline-size.");
972
0
                    float c = float(space) / float(basis.c);
973
0
                    col_iSize += NSToCoordRound(c);
974
0
                    --basis.c;
975
0
                }
976
0
                break;
977
0
            case FLEX_FIXED_LARGE:
978
0
                if (pct == 0.0f) {
979
0
                    NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
980
0
                                 "wrong inline-size assigned");
981
0
                    NS_ASSERTION(colFrame->GetHasSpecifiedCoord() ||
982
0
                                 colFrame->GetPrefCoord() == 0,
983
0
                                 "wrong case");
984
0
                    if (col_iSize != 0) {
985
0
                        float c = float(space) / float(basis.c);
986
0
                        basis.c -= col_iSize;
987
0
                        col_iSize += NSToCoordRound(float(col_iSize) * c);
988
0
                    }
989
0
                }
990
0
                break;
991
0
            case FLEX_PCT_LARGE:
992
0
                NS_ASSERTION(pct != 0.0f || colFrame->GetPrefCoord() == 0,
993
0
                             "wrong case");
994
0
                if (pct != 0.0f) {
995
0
                    float c = float(space) / basis.f;
996
0
                    col_iSize += NSToCoordRound(pct * c);
997
0
                    basis.f -= pct;
998
0
                }
999
0
                break;
1000
0
            case FLEX_ALL_LARGE:
1001
0
                {
1002
0
                    float c = float(space) / float(basis.c);
1003
0
                    col_iSize += NSToCoordRound(c);
1004
0
                    --basis.c;
1005
0
                }
1006
0
                break;
1007
0
        }
1008
0
1009
0
        // Only subtract from space if it's a real number.
1010
0
        if (space != nscoord_MAX) {
1011
0
            NS_ASSERTION(col_iSize != nscoord_MAX,
1012
0
                 "How is col_iSize nscoord_MAX if space isn't?");
1013
0
            NS_ASSERTION(col_iSize_before_adjust != nscoord_MAX,
1014
0
                 "How is col_iSize_before_adjust nscoord_MAX if space isn't?");
1015
0
            space -= col_iSize - col_iSize_before_adjust;
1016
0
        }
1017
0
1018
0
        NS_ASSERTION(col_iSize >= colFrame->GetMinCoord(),
1019
0
                     "assigned inline-size smaller than min");
1020
0
1021
0
        // Apply the new isize
1022
0
        switch (aISizeType) {
1023
0
            case BTLS_MIN_ISIZE:
1024
0
                {
1025
0
                    // Note: AddSpanCoords requires both a min and pref isize.
1026
0
                    // For the pref isize, we'll just pass in our computed
1027
0
                    // min isize, because the real pref isize will be at least
1028
0
                    // as big
1029
0
                    colFrame->AddSpanCoords(col_iSize, col_iSize,
1030
0
                                            aSpanHasSpecifiedISize);
1031
0
                }
1032
0
                break;
1033
0
            case BTLS_PREF_ISIZE:
1034
0
                {
1035
0
                    // Note: AddSpanCoords requires both a min and pref isize.
1036
0
                    // For the min isize, we'll just pass in 0, because
1037
0
                    // the real min isize will be at least 0
1038
0
                    colFrame->AddSpanCoords(0, col_iSize,
1039
0
                                            aSpanHasSpecifiedISize);
1040
0
                }
1041
0
                break;
1042
0
            case BTLS_FINAL_ISIZE:
1043
0
                {
1044
0
                    nscoord old_final = colFrame->GetFinalISize();
1045
0
                    colFrame->SetFinalISize(col_iSize);
1046
0
1047
0
                    if (old_final != col_iSize) {
1048
0
                        mTableFrame->DidResizeColumns();
1049
0
                    }
1050
0
                }
1051
0
                break;
1052
0
        }
1053
0
    }
1054
0
    NS_ASSERTION((space == 0 || space == nscoord_MAX) &&
1055
0
                 ((l2t == FLEX_PCT_LARGE)
1056
0
                    ? (-0.001f < basis.f && basis.f < 0.001f)
1057
0
                    : (basis.c == 0 || basis.c == nscoord_MAX)),
1058
0
                 "didn't subtract all that we added");
1059
0
}