LCOV - app.info - layout/tables/BasicTableLayoutStrategy.cpp

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-04-21 | 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