LCOV - code coverage report
Current view: directory - layout/tables - BasicTableLayoutStrategy.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 432 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

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

Generated by: LCOV version 1.7