LCOV - code coverage report
Current view: top level - layout/tables - BasicTableLayoutStrategy.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 457 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aTableFrame)
      32             :   : nsITableLayoutStrategy(nsITableLayoutStrategy::Auto)
      33           0 :   , mTableFrame(aTableFrame)
      34             : {
      35           0 :     MarkIntrinsicISizesDirty();
      36           0 : }
      37             : 
      38             : /* virtual */
      39           0 : BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
      40             : {
      41           0 : }
      42             : 
      43             : /* virtual */ nscoord
      44           0 : BasicTableLayoutStrategy::GetMinISize(gfxContext* aRenderingContext)
      45             : {
      46           0 :     DISPLAY_MIN_WIDTH(mTableFrame, mMinISize);
      47           0 :     if (mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
      48           0 :         ComputeIntrinsicISizes(aRenderingContext);
      49             :     }
      50           0 :     return mMinISize;
      51             : }
      52             : 
      53             : /* virtual */ nscoord
      54           0 : BasicTableLayoutStrategy::GetPrefISize(gfxContext* aRenderingContext,
      55             :                                        bool aComputingSize)
      56             : {
      57           0 :     DISPLAY_PREF_WIDTH(mTableFrame, mPrefISize);
      58           0 :     NS_ASSERTION((mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
      59             :                  (mPrefISizePctExpand == NS_INTRINSIC_WIDTH_UNKNOWN),
      60             :                  "dirtyness out of sync");
      61           0 :     if (mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
      62           0 :         ComputeIntrinsicISizes(aRenderingContext);
      63             :     }
      64           0 :     return aComputingSize ? mPrefISizePctExpand : mPrefISize;
      65             : }
      66             : 
      67             : struct CellISizeInfo {
      68           0 :     CellISizeInfo(nscoord aMinCoord, nscoord aPrefCoord,
      69             :                   float aPrefPercent, bool aHasSpecifiedISize)
      70           0 :         : hasSpecifiedISize(aHasSpecifiedISize)
      71             :         , minCoord(aMinCoord)
      72             :         , prefCoord(aPrefCoord)
      73           0 :         , prefPercent(aPrefPercent)
      74             :     {
      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           0 : GetISizeInfo(gfxContext *aRenderingContext,
      87             :              nsIFrame *aFrame, WritingMode aWM, bool aIsCell)
      88             : {
      89             :     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             :         // If aFrame is a container for font size inflation, then shrink
      96             :         // wrapping inside of it should not apply font size inflation.
      97           0 :         AutoMaybeDisableFontInflation an(aFrame);
      98             : 
      99           0 :         minCoord = aFrame->GetMinISize(aRenderingContext);
     100           0 :         prefCoord = aFrame->GetPrefISize(aRenderingContext);
     101             :         // Until almost the end of this function, minCoord and prefCoord
     102             :         // represent the box-sizing based isize values (which mean they
     103             :         // should include inline padding and border width when
     104             :         // box-sizing is set to border-box).
     105             :         // Note that this function returns border-box isize, we add the
     106             :         // outer edges near the end of this function.
     107             : 
     108             :         // XXX Should we ignore percentage padding?
     109             :         nsIFrame::IntrinsicISizeOffsetData offsets =
     110           0 :             aFrame->IntrinsicISizeOffsets();
     111             : 
     112             :         // In quirks mode, table cell isize should be content-box,
     113             :         // but bsize should be border box.
     114             :         // Because of this historic anomaly, we do not use quirk.css.
     115             :         // (We can't specify one value of box-sizing for isize and another
     116             :         // for bsize).
     117             :         // For this reason, we also do not use box-sizing for just one of
     118             :         // them, as this may be confusing.
     119           0 :         if (isQuirks || stylePos->mBoxSizing == StyleBoxSizing::Content) {
     120           0 :             boxSizingToBorderEdge = offsets.hPadding + offsets.hBorder;
     121             :         }
     122             :         else {
     123             :             // StyleBoxSizing::Border and standards-mode
     124           0 :             minCoord += offsets.hPadding + offsets.hBorder;
     125           0 :             prefCoord += offsets.hPadding + offsets.hBorder;
     126             :         }
     127             :     } else {
     128           0 :         minCoord = 0;
     129           0 :         prefCoord = 0;
     130             :     }
     131           0 :     float prefPercent = 0.0f;
     132           0 :     bool hasSpecifiedISize = false;
     133             : 
     134           0 :     const nsStyleCoord& iSize = stylePos->ISize(aWM);
     135           0 :     nsStyleUnit unit = iSize.GetUnit();
     136             :     // NOTE: We're ignoring calc() units with percentages here, for lack of a
     137             :     // sensible idea for what to do with them.  This means calc() with
     138             :     // percentages is basically handled like 'auto' for table cells and
     139             :     // columns.
     140           0 :     if (iSize.ConvertsToLength()) {
     141           0 :         hasSpecifiedISize = true;
     142             :         // Note: since ComputeISizeValue was designed to return content-box
     143             :         // isize, it will (in some cases) subtract the box-sizing edges.
     144             :         // We prevent this unwanted behavior by calling it with
     145             :         // aContentEdgeToBoxSizing and aBoxSizingToMarginEdge set to 0.
     146           0 :         nscoord c = aFrame->ComputeISizeValue(aRenderingContext, 0, 0, 0, iSize);
     147             :         // Quirk: A cell with "nowrap" set and a coord value for the
     148             :         // isize which is bigger than the intrinsic minimum isize uses
     149             :         // that coord value as the minimum isize.
     150             :         // This is kept up-to-date with dynamic changes to nowrap by code in
     151             :         // nsTableCellFrame::AttributeChanged
     152           0 :         if (aIsCell && c > minCoord && isQuirks &&
     153           0 :             aFrame->GetContent()->HasAttr(kNameSpaceID_None,
     154             :                                           nsGkAtoms::nowrap)) {
     155           0 :             minCoord = c;
     156             :         }
     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             :             case NS_STYLE_WIDTH_MAX_CONTENT:
     163             :                 // 'inline-size' only affects pref isize, not min
     164             :                 // isize, so don't change anything
     165           0 :                 break;
     166             :             case NS_STYLE_WIDTH_MIN_CONTENT:
     167           0 :                 prefCoord = minCoord;
     168           0 :                 break;
     169             :             case NS_STYLE_WIDTH_FIT_CONTENT:
     170             :             case NS_STYLE_WIDTH_AVAILABLE:
     171             :                 // act just like 'inline-size: auto'
     172           0 :                 break;
     173             :             default:
     174           0 :                 NS_NOTREACHED("unexpected enumerated value");
     175             :         }
     176             :     }
     177             : 
     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             :             // for 'max-inline-size', '-moz-fit-content' is like
     184             :             // '-moz-max-content'
     185             :             maxISize.SetIntValue(NS_STYLE_WIDTH_MAX_CONTENT,
     186           0 :                                  eStyleUnit_Enumerated);
     187             :         }
     188             :     }
     189           0 :     unit = maxISize.GetUnit();
     190             :     // XXX To really implement 'max-inline-size' well, we'd need to store
     191             :     // 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             :         }
     202             :     }
     203             :     // treat calc() with percentages on max-inline-size just like 'none'.
     204             : 
     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             :             // for 'min-inline-size', '-moz-fit-content' is like
     211             :             // '-moz-min-content'
     212             :             minISize.SetIntValue(NS_STYLE_WIDTH_MIN_CONTENT,
     213           0 :                                  eStyleUnit_Enumerated);
     214             :         }
     215             :     }
     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             :         }
     227             :     }
     228             :     // treat calc() with percentages on min-inline-size just like '0'.
     229             : 
     230             :     // XXX Should col frame have border/padding considered?
     231           0 :     if (aIsCell) {
     232           0 :         minCoord += boxSizingToBorderEdge;
     233           0 :         prefCoord = NSCoordSaturatingAdd(prefCoord, boxSizingToBorderEdge);
     234             :     }
     235             : 
     236           0 :     return CellISizeInfo(minCoord, prefCoord, prefPercent, hasSpecifiedISize);
     237             : }
     238             : 
     239             : static inline CellISizeInfo
     240           0 : GetCellISizeInfo(gfxContext *aRenderingContext,
     241             :                  nsTableCellFrame *aCellFrame, WritingMode aWM)
     242             : {
     243           0 :     return GetISizeInfo(aRenderingContext, aCellFrame, aWM, true);
     244             : }
     245             : 
     246             : static inline CellISizeInfo
     247           0 : GetColISizeInfo(gfxContext *aRenderingContext,
     248             :                 nsIFrame *aFrame, WritingMode aWM)
     249             : {
     250           0 :     return GetISizeInfo(aRenderingContext, aFrame, aWM, false);
     251             : }
     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           0 : BasicTableLayoutStrategy::ComputeColumnIntrinsicISizes(gfxContext* aRenderingContext)
     262             : {
     263           0 :     nsTableFrame *tableFrame = mTableFrame;
     264           0 :     nsTableCellMap *cellMap = tableFrame->GetCellMap();
     265           0 :     WritingMode wm = tableFrame->GetWritingMode();
     266             : 
     267           0 :     mozilla::AutoStackArena arena;
     268           0 :     SpanningCellSorter spanningCells;
     269             : 
     270             :     // Loop over the columns to consider the columns and cells *without*
     271             :     // a colspan.
     272             :     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             :         }
     279           0 :         colFrame->ResetIntrinsics();
     280           0 :         colFrame->ResetSpanIntrinsics();
     281             : 
     282             :         // Consider the isizes on the column.
     283             :         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             : 
     289             :         // Consider the isizes on the column-group.  Note that we follow
     290             :         // what the HTML spec says here, and make the isize apply to
     291             :         // each column in the group, not the group as a whole.
     292             : 
     293             :         // 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             :                        "expected a column-group");
     298             :           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             :         }
     304             : 
     305             :         // Consider the contents of and the isizes on the cells without
     306             :         // colspans.
     307           0 :         nsCellMapColumnIterator columnIter(cellMap, col);
     308             :         int32_t row, colSpan;
     309             :         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             :             }
     315             : 
     316             :             CellISizeInfo info = GetCellISizeInfo(aRenderingContext,
     317           0 :                                                   cellFrame, wm);
     318             : 
     319           0 :             colFrame->AddCoords(info.minCoord, info.prefCoord,
     320           0 :                                 info.hasSpecifiedISize);
     321           0 :             colFrame->AddPrefPercent(info.prefPercent);
     322             :         }
     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             :     // Consider the cells with a colspan that we saved in the loop above
     336             :     // into the spanning cell sorter.  We consider these cells by seeing
     337             :     // if they require adding to the isizes resulting only from cells
     338             :     // with a smaller colspan, and therefore we must process them sorted
     339             :     // in increasing order by colspan.  For each colspan group, we
     340             :     // accumulate new values to accumulate in the column frame's Span*
     341             :     // members.
     342             :     //
     343             :     // Considering things only relative to the isizes resulting from
     344             :     // cells with smaller colspans (rather than incrementally including
     345             :     // the results from spanning cells, or doing spanning and
     346             :     // non-spanning cells in a single pass) means that layout remains
     347             :     // row-order-invariant and (except for percentage isizes that add to
     348             :     // more than 100%) column-order invariant.
     349             :     //
     350             :     // Starting with smaller colspans makes it more likely that we
     351             :     // satisfy all the constraints given and don't distribute space to
     352             :     // columns where we don't need it.
     353             :     SpanningCellSorter::Item *item;
     354             :     int32_t colSpan;
     355           0 :     while ((item = spanningCells.GetNext(&colSpan))) {
     356           0 :         NS_ASSERTION(colSpan > 1,
     357             :                      "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             :                          "bogus result from spanning cell sorter");
     364             : 
     365           0 :             nsTableCellFrame *cellFrame = cellData->GetCellFrame();
     366           0 :             NS_ASSERTION(cellFrame, "bogus result from spanning cell sorter");
     367             : 
     368             :             CellISizeInfo info =
     369           0 :                 GetCellISizeInfo(aRenderingContext, cellFrame, wm);
     370             : 
     371           0 :             if (info.prefPercent > 0.0f) {
     372           0 :                 DistributePctISizeToColumns(info.prefPercent,
     373           0 :                                             col, colSpan);
     374             :             }
     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             : 
     381             :         // Combine the results of the span analysis into the main results,
     382             :         // for each increment of colspan.
     383             : 
     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             :             }
     390             : 
     391           0 :             colFrame->AccumulateSpanIntrinsics();
     392           0 :             colFrame->ResetSpanIntrinsics();
     393             : 
     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             :     }
     402             : 
     403             :     // Prevent percentages from adding to more than 100% by (to be
     404             :     // compatible with other browsers) treating any percentages that would
     405             :     // increase the total percentage to more than 100% as the number that
     406             :     // would increase it to only 100% (which is 0% if we've already hit
     407             :     // 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             :         }
     415             : 
     416           0 :         colFrame->AdjustPrefPercent(&pct_used);
     417             :     }
     418             : 
     419             : #ifdef DEBUG_TABLE_STRATEGY
     420             :     printf("ComputeColumnIntrinsicISizes spanning\n");
     421             :     mTableFrame->Dump(false, true, false);
     422             : #endif
     423           0 : }
     424             : 
     425             : void
     426           0 : BasicTableLayoutStrategy::ComputeIntrinsicISizes(gfxContext* aRenderingContext)
     427             : {
     428           0 :     ComputeColumnIntrinsicISizes(aRenderingContext);
     429             : 
     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             :     // add a total of (colcount + 1) lots of cellSpacingX for columns where a
     435             :     // cell originates
     436           0 :     nscoord add = mTableFrame->GetColSpacing(colCount);
     437             : 
     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             :         }
     444           0 :         if (mTableFrame->ColumnHasCellSpacingBefore(col)) {
     445           0 :             add += mTableFrame->GetColSpacing(col - 1);
     446             :         }
     447           0 :         min += colFrame->GetMinCoord();
     448           0 :         pref = NSCoordSaturatingAdd(pref, colFrame->GetPrefCoord());
     449             : 
     450             :         // Percentages are of the table, so we have to reverse them for
     451             :         // intrinsic isizes.
     452           0 :         float p = colFrame->GetPrefPercent();
     453           0 :         if (p > 0.0f) {
     454           0 :             nscoord colPref = colFrame->GetPrefCoord();
     455             :             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             :             }
     461           0 :             pct_total += p;
     462             :         } else {
     463           0 :             nonpct_pref_total = NSCoordSaturatingAdd(nonpct_pref_total,
     464           0 :                                                      colFrame->GetPrefCoord());
     465             :         }
     466             :     }
     467             : 
     468           0 :     nscoord pref_pct_expand = pref;
     469             : 
     470             :     // Account for small percentages expanding the preferred isize of
     471             :     // *other* columns.
     472           0 :     if (max_small_pct_pref > pref_pct_expand) {
     473           0 :         pref_pct_expand = max_small_pct_pref;
     474             :     }
     475             : 
     476             :     // Account for large percentages expanding the preferred isize of
     477             :     // themselves.  There's no need to iterate over the columns multiple
     478             :     // times, since when there is such a need, the small percentage
     479             :     // effect is bigger anyway.  (I think!)
     480           0 :     NS_ASSERTION(0.0f <= pct_total && pct_total <= 1.0f,
     481             :                  "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             :             // XXX Or should I use some smaller value?  (Test this using
     486             :             // nested tables!)
     487             :         }
     488             :     } else {
     489             :         nscoord large_pct_pref =
     490           0 :             (nonpct_pref_total == nscoord_MAX ?
     491             :              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             :     }
     496             : 
     497             :     // 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             :     }
     503             : 
     504           0 :     mMinISize = min;
     505           0 :     mPrefISize = pref;
     506           0 :     mPrefISizePctExpand = pref_pct_expand;
     507           0 : }
     508             : 
     509             : /* virtual */ void
     510           0 : BasicTableLayoutStrategy::MarkIntrinsicISizesDirty()
     511             : {
     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           0 : BasicTableLayoutStrategy::ComputeColumnISizes(const ReflowInput& aReflowInput)
     520             : {
     521           0 :     nscoord iSize = aReflowInput.ComputedISize();
     522             : 
     523           0 :     if (mLastCalcISize == iSize) {
     524           0 :         return;
     525             :     }
     526           0 :     mLastCalcISize = iSize;
     527             : 
     528           0 :     NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
     529             :                  (mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN),
     530             :                  "dirtyness out of sync");
     531           0 :     NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
     532             :                  (mPrefISizePctExpand == NS_INTRINSIC_WIDTH_UNKNOWN),
     533             :                  "dirtyness out of sync");
     534             :     // XXX Is this needed?
     535           0 :     if (mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
     536           0 :         ComputeIntrinsicISizes(aReflowInput.mRenderingContext);
     537             :     }
     538             : 
     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             : 
     544           0 :     DistributeISizeToColumns(iSize, 0, colCount, BTLS_FINAL_ISIZE, false);
     545             : 
     546             : #ifdef DEBUG_TABLE_STRATEGY
     547             :     printf("ComputeColumnISizes final\n");
     548             :     mTableFrame->Dump(false, true, false);
     549             : #endif
     550             : }
     551             : 
     552             : void
     553           0 : BasicTableLayoutStrategy::DistributePctISizeToColumns(float aSpanPrefPct,
     554             :                                                       int32_t aFirstCol,
     555             :                                                       int32_t aColCount)
     556             : {
     557             :     // 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             :     // and to reduce aSpanPrefPct by columns that already have % isize
     561             : 
     562             :     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             :         }
     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             :             }
     577             :         } else {
     578           0 :             aSpanPrefPct -= scolPct;
     579             :         }
     580             :     }
     581             : 
     582           0 :     if (aSpanPrefPct <= 0.0f || nonPctColCount == 0) {
     583             :         // There's no %-isize on the colspan left over to distribute,
     584             :         // or there are no columns to which we could distribute %-isize
     585           0 :         return;
     586             :     }
     587             : 
     588             :     // Second loop, to distribute what remains of aSpanPrefPct
     589             :     // 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             :         }
     598             : 
     599           0 :         if (scolFrame->GetPrefPercent() == 0.0f) {
     600           0 :             NS_ASSERTION((!spanHasNonPctPref ||
     601             :                           nonPctTotalPrefISize != 0) &&
     602             :                          nonPctColCount != 0,
     603             :                          "should not be zero if we haven't allocated "
     604             :                          "all pref percent");
     605             : 
     606             :             float allocatedPct; // % isize to be given to this column
     607           0 :             if (spanHasNonPctPref) {
     608             :                 // Group so we're multiplying by 1.0f when we need
     609             :                 // 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             :                 // distribute equally when all pref isizes are 0
     615           0 :                 allocatedPct = aSpanPrefPct / float(nonPctColCount);
     616             :             } else {
     617           0 :                 allocatedPct = 0.0f;
     618             :             }
     619             :             // Allocate the percent
     620           0 :             scolFrame->AddSpanPrefPercent(allocatedPct);
     621             : 
     622             :             // To avoid accumulating rounding error from division,
     623             :             // 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             :             }
     629             : 
     630           0 :             if (!aSpanPrefPct) {
     631             :                 // No more span-percent-isize to distribute --> we're done.
     632           0 :                 NS_ASSERTION(spanHasNonPctPref ?
     633             :                              nonPctTotalPrefISize == 0 :
     634             :                              nonPctColCount == 0,
     635             :                              "No more pct inline-size to distribute, "
     636             :                              "but there are still cols that need some.");
     637           0 :                 return;
     638             :             }
     639             :         }
     640             :     }
     641             : }
     642             : 
     643             : void
     644           0 : BasicTableLayoutStrategy::DistributeISizeToColumns(nscoord aISize,
     645             :                                                    int32_t aFirstCol,
     646             :                                                    int32_t aColCount,
     647             :                                                    BtlsISizeType aISizeType,
     648             :                                                    bool aSpanHasSpecifiedISize)
     649             : {
     650           0 :     NS_ASSERTION(aISizeType != BTLS_FINAL_ISIZE ||
     651             :                  (aFirstCol == 0 &&
     652             :                   aColCount == mTableFrame->GetCellMap()->GetColCount()),
     653             :             "Computing final column isizes, but didn't get full column range");
     654             : 
     655           0 :     nscoord subtract = 0;
     656             :     // aISize initially includes border-spacing for the boundaries in between
     657             :     // each of the columns. We start at aFirstCol + 1 because the first
     658             :     // 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             :             // border-spacing isn't part of the basis for percentages.
     662           0 :             subtract += mTableFrame->GetColSpacing(col - 1);
     663             :         }
     664             :     }
     665           0 :     if (aISizeType == BTLS_FINAL_ISIZE) {
     666             :         // If we're computing final col-isize, then aISize initially includes
     667             :         // border spacing on the table's far istart + far iend edge, too.  Need
     668             :         // to subtract those out, too.
     669           0 :         subtract += (mTableFrame->GetColSpacing(-1) +
     670           0 :                      mTableFrame->GetColSpacing(aColCount));
     671             :     }
     672           0 :     aISize = NSCoordSaturatingSubtract(aISize, subtract, nscoord_MAX);
     673             : 
     674             :     /*
     675             :      * The goal of this function is to distribute |aISize| between the
     676             :      * columns by making an appropriate AddSpanCoords or SetFinalISize
     677             :      * call for each column.  (We call AddSpanCoords if we're
     678             :      * distributing a column-spanning cell's minimum or preferred isize
     679             :      * to its spanned columns.  We call SetFinalISize if we're
     680             :      * distributing a table's final isize to its columns.)
     681             :      *
     682             :      * The idea is to either assign one of the following sets of isizes
     683             :      * or a weighted average of two adjacent sets of isizes.  It is not
     684             :      * possible to assign values smaller than the smallest set of
     685             :      * isizes.  However, see below for handling the case of assigning
     686             :      * values larger than the largest set of isizes.  From smallest to
     687             :      * largest, these are:
     688             :      *
     689             :      * 1. [guess_min] Assign all columns their min isize.
     690             :      *
     691             :      * 2. [guess_min_pct] Assign all columns with percentage isizes
     692             :      * their percentage isize, and all other columns their min isize.
     693             :      *
     694             :      * 3. [guess_min_spec] Assign all columns with percentage isizes
     695             :      * their percentage isize, all columns with specified coordinate
     696             :      * isizes their pref isize (since it doesn't matter whether it's the
     697             :      * largest contributor to the pref isize that was the specified
     698             :      * contributor), and all other columns their min isize.
     699             :      *
     700             :      * 4. [guess_pref] Assign all columns with percentage isizes their
     701             :      * specified isize, and all other columns their pref isize.
     702             :      *
     703             :      * If |aISize| is *larger* than what we would assign in (4), then we
     704             :      * expand the columns:
     705             :      *
     706             :      *   a. if any columns without a specified coordinate isize or
     707             :      *   percent isize have nonzero pref isize, in proportion to pref
     708             :      *   isize [total_flex_pref]
     709             :      *
     710             :      *   b. otherwise, if any columns without a specified coordinate
     711             :      *   isize or percent isize, but with cells originating in them,
     712             :      *   have zero pref isize, equally between these
     713             :      *   [numNonSpecZeroISizeCols]
     714             :      *
     715             :      *   c. otherwise, if any columns without percent isize have nonzero
     716             :      *   pref isize, in proportion to pref isize [total_fixed_pref]
     717             :      *
     718             :      *   d. otherwise, if any columns have nonzero percentage isizes, in
     719             :      *   proportion to the percentage isizes [total_pct]
     720             :      *
     721             :      *   e. otherwise, equally.
     722             :      */
     723             : 
     724             :     // Loop #1 over the columns, to figure out the four values above so
     725             :     // we know which case we're dealing with.
     726             : 
     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             : 
     737             :     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             :         }
     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             :             }
     754           0 :             guess_min_pct += val;
     755           0 :             guess_pref = NSCoordSaturatingAdd(guess_pref, val);
     756             :         } else {
     757           0 :             nscoord pref_iSize = colFrame->GetPrefCoord();
     758           0 :             if (pref_iSize == nscoord_MAX) {
     759           0 :                 ++numInfiniteISizeCols;
     760             :             }
     761           0 :             guess_pref = NSCoordSaturatingAdd(guess_pref, pref_iSize);
     762           0 :             guess_min_pct += min_iSize;
     763           0 :             if (colFrame->GetHasSpecifiedCoord()) {
     764             :                 // we'll add on the rest of guess_min_spec outside the
     765             :                 // loop
     766             :                 nscoord delta = NSCoordSaturatingSubtract(pref_iSize,
     767           0 :                                                           min_iSize, 0);
     768           0 :                 guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, delta);
     769             :                 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             :                 }
     775             :             } else {
     776             :                 total_flex_pref = NSCoordSaturatingAdd(total_flex_pref,
     777           0 :                                                        pref_iSize);
     778             :             }
     779             :         }
     780             :     }
     781           0 :     guess_min_spec = NSCoordSaturatingAdd(guess_min_spec, guess_min_pct);
     782             : 
     783             :     // Determine what we're flexing:
     784             :     enum Loop2Type {
     785             :         FLEX_PCT_SMALL, // between (1) and (2) above
     786             :         FLEX_FIXED_SMALL, // between (2) and (3) above
     787             :         FLEX_FLEX_SMALL, // between (3) and (4) above
     788             :         FLEX_FLEX_LARGE, // greater than (4) above, case (a)
     789             :         FLEX_FLEX_LARGE_ZERO, // greater than (4) above, case (b)
     790             :         FLEX_FIXED_LARGE, // greater than (4) above, case (c)
     791             :         FLEX_PCT_LARGE, // greater than (4) above, case (d)
     792             :         FLEX_ALL_LARGE // greater than (4) above, case (e)
     793             :     };
     794             : 
     795             :     Loop2Type l2t;
     796             :     // These are constants (over columns) for each case's math.  We use
     797             :     // a pair of nscoords rather than a float so that we can subtract
     798             :     // each column's allocation so we avoid accumulating rounding error.
     799             :     nscoord space; // the amount of extra isize to allocate
     800             :     union {
     801             :         nscoord c;
     802             :         float f;
     803             :     } 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             :             // Return early -- we don't have any extra space to distribute.
     807           0 :             return;
     808             :         }
     809           0 :         NS_ASSERTION(!(aISizeType == BTLS_FINAL_ISIZE && aISize < guess_min),
     810             :                      "Table inline-size is less than the "
     811             :                      "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             :                                                 nscoord_MAX);
     821             :         } 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             :                                                 nscoord_MAX);
     826             :         }
     827             :     } 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             :         } else {
     842           0 :             l2t = FLEX_ALL_LARGE;
     843           0 :             basis.c = aColCount;
     844             :         }
     845             :     }
     846             : 
     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             :         }
     863             :         nscoord col_iSize;
     864             : 
     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             :             }
     872             :         } else {
     873           0 :             col_iSize = colFrame->GetPrefCoord();
     874             :         }
     875             : 
     876           0 :         nscoord col_iSize_before_adjust = col_iSize;
     877             : 
     878           0 :         switch (l2t) {
     879             :             case FLEX_PCT_SMALL:
     880           0 :                 col_iSize = col_iSize_before_adjust = colFrame->GetMinCoord();
     881           0 :                 if (pct != 0.0f) {
     882             :                     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             :                     }
     889             :                 }
     890           0 :                 break;
     891             :             case FLEX_FIXED_SMALL:
     892           0 :                 if (pct == 0.0f) {
     893           0 :                     NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
     894             :                                  "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             :                         }
     905             :                     } else
     906           0 :                         col_iSize = col_iSize_before_adjust =
     907           0 :                             colFrame->GetMinCoord();
     908             :                 }
     909           0 :                 break;
     910             :             case FLEX_FLEX_SMALL:
     911           0 :                 if (pct == 0.0f &&
     912           0 :                     !colFrame->GetHasSpecifiedCoord()) {
     913           0 :                     NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
     914             :                                  "wrong inline-size assigned");
     915           0 :                     nscoord col_min = colFrame->GetMinCoord();
     916             :                     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             :                         // If we have infinite-isize cols, then the standard
     922             :                         // adjustment to col_iSize using 'c' won't work,
     923             :                         // because basis.c and pref_minus_min are both
     924             :                         // nscoord_MAX and will cancel each other out in the
     925             :                         // col_iSize adjustment (making us assign all the
     926             :                         // space to the first inf-isize col).  To correct for
     927             :                         // this, we'll also divide by numInfiniteISizeCols to
     928             :                         // 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             :                             } else {
     934           0 :                                 c = 0.0f;
     935             :                             }
     936             :                         }
     937           0 :                         basis.c = NSCoordSaturatingSubtract(basis.c,
     938             :                                                             pref_minus_min,
     939             :                                                             nscoord_MAX);
     940           0 :                         col_iSize += NSToCoordRound(
     941           0 :                             float(pref_minus_min) * c);
     942             :                     }
     943             :                 }
     944           0 :                 break;
     945             :             case FLEX_FLEX_LARGE:
     946           0 :                 if (pct == 0.0f &&
     947           0 :                     !colFrame->GetHasSpecifiedCoord()) {
     948           0 :                     NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
     949             :                                  "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             :                         } 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             :                         }
     959             :                     }
     960             :                 }
     961           0 :                 break;
     962             :             case FLEX_FLEX_LARGE_ZERO:
     963           0 :                 if (pct == 0.0f &&
     964           0 :                     !colFrame->GetHasSpecifiedCoord() &&
     965           0 :                     cellMap->GetNumCellsOriginatingInCol(col) > 0) {
     966             : 
     967           0 :                     NS_ASSERTION(col_iSize == 0 &&
     968             :                                  colFrame->GetPrefCoord() == 0,
     969             :                                  "Since we're in FLEX_FLEX_LARGE_ZERO case, "
     970             :                                  "all auto-inline-size cols should have zero "
     971             :                                  "pref inline-size.");
     972           0 :                     float c = float(space) / float(basis.c);
     973           0 :                     col_iSize += NSToCoordRound(c);
     974           0 :                     --basis.c;
     975             :                 }
     976           0 :                 break;
     977             :             case FLEX_FIXED_LARGE:
     978           0 :                 if (pct == 0.0f) {
     979           0 :                     NS_ASSERTION(col_iSize == colFrame->GetPrefCoord(),
     980             :                                  "wrong inline-size assigned");
     981           0 :                     NS_ASSERTION(colFrame->GetHasSpecifiedCoord() ||
     982             :                                  colFrame->GetPrefCoord() == 0,
     983             :                                  "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             :                     }
     989             :                 }
     990           0 :                 break;
     991             :             case FLEX_PCT_LARGE:
     992           0 :                 NS_ASSERTION(pct != 0.0f || colFrame->GetPrefCoord() == 0,
     993             :                              "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             :                 }
     999           0 :                 break;
    1000             :             case FLEX_ALL_LARGE:
    1001             :                 {
    1002           0 :                     float c = float(space) / float(basis.c);
    1003           0 :                     col_iSize += NSToCoordRound(c);
    1004           0 :                     --basis.c;
    1005             :                 }
    1006           0 :                 break;
    1007             :         }
    1008             : 
    1009             :         // 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             :                  "How is col_iSize nscoord_MAX if space isn't?");
    1013           0 :             NS_ASSERTION(col_iSize_before_adjust != nscoord_MAX,
    1014             :                  "How is col_iSize_before_adjust nscoord_MAX if space isn't?");
    1015           0 :             space -= col_iSize - col_iSize_before_adjust;
    1016             :         }
    1017             : 
    1018           0 :         NS_ASSERTION(col_iSize >= colFrame->GetMinCoord(),
    1019             :                      "assigned inline-size smaller than min");
    1020             : 
    1021             :         // Apply the new isize
    1022           0 :         switch (aISizeType) {
    1023             :             case BTLS_MIN_ISIZE:
    1024             :                 {
    1025             :                     // Note: AddSpanCoords requires both a min and pref isize.
    1026             :                     // For the pref isize, we'll just pass in our computed
    1027             :                     // min isize, because the real pref isize will be at least
    1028             :                     // as big
    1029           0 :                     colFrame->AddSpanCoords(col_iSize, col_iSize,
    1030           0 :                                             aSpanHasSpecifiedISize);
    1031             :                 }
    1032           0 :                 break;
    1033             :             case BTLS_PREF_ISIZE:
    1034             :                 {
    1035             :                     // Note: AddSpanCoords requires both a min and pref isize.
    1036             :                     // For the min isize, we'll just pass in 0, because
    1037             :                     // the real min isize will be at least 0
    1038           0 :                     colFrame->AddSpanCoords(0, col_iSize,
    1039           0 :                                             aSpanHasSpecifiedISize);
    1040             :                 }
    1041           0 :                 break;
    1042             :             case BTLS_FINAL_ISIZE:
    1043             :                 {
    1044           0 :                     nscoord old_final = colFrame->GetFinalISize();
    1045           0 :                     colFrame->SetFinalISize(col_iSize);
    1046             : 
    1047           0 :                     if (old_final != col_iSize) {
    1048           0 :                         mTableFrame->DidResizeColumns();
    1049             :                     }
    1050             :                 }
    1051           0 :                 break;
    1052             :         }
    1053             :     }
    1054           0 :     NS_ASSERTION((space == 0 || space == nscoord_MAX) &&
    1055             :                  ((l2t == FLEX_PCT_LARGE)
    1056             :                     ? (-0.001f < basis.f && basis.f < 0.001f)
    1057             :                     : (basis.c == 0 || basis.c == nscoord_MAX)),
    1058             :                  "didn't subtract all that we added");
    1059             : }

Generated by: LCOV version 1.13