Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes
FixedTableLayoutStrategy Class Reference

Implementation of HTML4 "table-layout=fixed" table layout. More...

#include <FixedTableLayoutStrategy.h>

Inheritance diagram for FixedTableLayoutStrategy:
Inheritance graph
[legend]
Collaboration diagram for FixedTableLayoutStrategy:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 FixedTableLayoutStrategy (nsTableFrame *aFrame)
 Public constructor.
virtual ~FixedTableLayoutStrategy ()
 destructor
virtual PRBool BalanceColumnWidths (const nsHTMLReflowState &aReflowState)
 Called during resize reflow to determine the new column widths.
virtual nscoord CalcPctAdjTableWidth (const nsHTMLReflowState &aReflowState, nscoord aAvailWidth)
 Calculate the basis for percent width calculations of the table elements.
virtual PRBool Initialize (const nsHTMLReflowState &aReflowState)
 call every time any table thing changes that might effect the width of any column in the table (content, structure, or style)
void Dump (PRInt32 aIndent)

Protected Member Functions

virtual PRBool AssignNonPctColumnWidths (nscoord aComputedWidth, const nsHTMLReflowState &aReflowState)
 assign widths for each column.
void ComputeNonPctColspanWidths (const nsHTMLReflowState &aReflowState, PRBool aConsiderPct, float aPixelToTwips, PRBool *aHasPctCol)
 Calculate the adjusted widths (min, desired, fixed, or pct) for a cell spanning multiple columns.
PRBool ComputeNonPctColspanWidths (PRInt32 aWidthIndex, const nsTableCellFrame *aCellFrame, PRInt32 aCellWidth, PRInt32 aColIndex, PRInt32 aColSpan, PRInt32 &aLimitType, float aPixelToTwips)
 main helper for above.
nscoord AssignPctColumnWidths (const nsHTMLReflowState &aReflowState, nscoord aBasis, PRBool aTableIsAutoWidth, float aPixelToTwips)
 Determine percentage col widths for each col frame.
void ReduceOverSpecifiedPctCols (nscoord aExcess)
 Reduce the percent columns by the amount specified in aExcess as the percent width's can accumulate to be over 100%.
void CalculateTotals (PRInt32 *aTotalCounts, PRInt32 *aTotalWidths, PRInt32 *aDupedWidths, PRInt32 &a0ProportionalCount)
 calculate totals by width type.
void AllocateFully (nscoord &aTotalAllocated, PRInt32 *aAllocTypes, PRInt32 aWidthType)
 Allocate aWidthType values to the corresponding columns.
void AllocateConstrained (PRInt32 aAvailWidth, PRInt32 aWidthType, PRBool aStartAtMin, PRInt32 *aAllocTypes, float aPixelToTwips)
 Allocate aWidthType values to the corresponding columns up to the aAvailWidth.
void AllocateUnconstrained (PRInt32 aAllocAmount, PRInt32 *aAllocTypes, PRBool aExcludePct, PRBool aExcludeFix, PRBool aExcludePro, PRBool aExclude0Pro, float aPixelToTwips)
 Give the remaining space and exclude the selected columns.
void ContinuingFrameCheck ()
 Check in debug mode whether the routine is called on a continuing frame.

Protected Attributes

nsTableFramemTableFrame
PRInt32 mCols
nscoord mCellSpacingTotal
float mMinToDesProportionRatio
PRPackedBool mIsNavQuirksMode

Detailed Description

Implementation of HTML4 "table-layout=fixed" table layout.

The input to this class is the resolved styles for both the table columns and the cells in row0. The output from this class is to set the column widths in mTableFrame.

Definition at line 58 of file FixedTableLayoutStrategy.h.


Constructor & Destructor Documentation

Public constructor.

Parameters:
aFramethe table frame for which this delegate will do layout

Definition at line 44 of file FixedTableLayoutStrategy.cpp.

  : BasicTableLayoutStrategy(aFrame)
{
}

destructor

Definition at line 49 of file FixedTableLayoutStrategy.cpp.

{
}

Member Function Documentation

void BasicTableLayoutStrategy::AllocateConstrained ( PRInt32  aAvailWidth,
PRInt32  aWidthType,
PRBool  aStartAtMin,
PRInt32 aAllocTypes,
float  aPixelToTwips 
) [protected, inherited]

Allocate aWidthType values to the corresponding columns up to the aAvailWidth.

Parameters:
aAvailWidth- width that can distributed to the selected columns
aWidthType- width type selecting the columns for width allocation
aStartAtMin- allocation should start at min. content width
aAllocTypes- width type that has determined col width
aPixelToTwips- the number of twips in a pixel.

Definition at line 1828 of file BasicTableLayoutStrategy.cpp.

{
  if ((0 == aAvailWidth) || (aWidthType < 0) || (aWidthType >= NUM_WIDTHS)) {
    NS_ASSERTION(PR_TRUE, "invalid args to AllocateConstrained");
    return;
  }

  PRInt32 numCols = mTableFrame->GetColCount();
  PRInt32 numConstrainedCols = 0;
  nscoord sumMaxConstraints  = 0;
  nscoord sumMinConstraints  = 0;
  PRInt32 colX;
  // find out how many constrained cols there are
  for (colX = 0; colX < numCols; colX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    numConstrainedCols++;
  }

  // allocate storage for the constrained cols. Only they get adjusted.
  ColInfo** colInfo = new ColInfo*[numConstrainedCols];
  if (!colInfo) return;
  memset(colInfo, 0, numConstrainedCols * sizeof(ColInfo *));

  PRInt32 maxMinDiff = 0;
  PRInt32 constrColX = 0;
  // set the col info entries for each constrained col
  for (colX = 0; colX < numCols; colX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    nscoord minWidth = mTableFrame->GetColumnWidth(colX);
    nscoord maxWidth = GetColWidth(colFrame, aWidthType);
    // proportional and desired widths are handled together
    PRBool haveProWidth = PR_FALSE;
    if (DES_CON == aWidthType) {
      // Take into acount MIN_adj width as it has been included in totals before
      maxWidth = PR_MAX(maxWidth, colFrame->GetWidth(MIN_ADJ));
      nscoord proWidth = colFrame->GetWidth(MIN_PRO);
      if (proWidth >= 0) {
        haveProWidth = PR_TRUE;
        maxWidth = proWidth;
      }
    }

    if (maxWidth <= 0) continue;

    sumMaxConstraints += maxWidth;
    sumMinConstraints += minWidth;

    maxWidth = PR_MAX(maxWidth, minWidth);
    maxMinDiff += maxWidth - minWidth;
    nscoord startWidth = (aStartAtMin) ? minWidth : maxWidth;
    colInfo[constrColX] = new ColInfo(colFrame, colX, minWidth, startWidth, maxWidth);
    if (!colInfo[constrColX]) {
      AC_Wrapup(mTableFrame, numConstrainedCols, colInfo, PR_TRUE);
      return;
    }
    aAllocTypes[colX] = (haveProWidth) ? MIN_PRO : aWidthType;
    constrColX++;
  }

  if (constrColX < numConstrainedCols) {
    // some of the constrainted cols might have been 0 and skipped
    numConstrainedCols = constrColX;
  }

  PRInt32 i;
  if (aStartAtMin) { // allocate extra space 
    nscoord availWidth = aAvailWidth; 
    for (i = 0; i < numConstrainedCols; i++) {
      // the weight here is a relative metric for determining when cols reach their max constraint. 
      // A col with a larger weight will reach its max before one with a smaller value.
      nscoord delta = colInfo[i]->mMaxWidth - colInfo[i]->mWidth;
      colInfo[i]->mWeight = (delta <= 0) 
        ? 1000000 // cols which have already reached their max get a large value
        : ((float)colInfo[i]->mMaxWidth) / ((float)delta);
    }
      
    // sort the cols based on the weight so that in one pass cols with higher 
    // weights will get their max earlier than ones with lower weights
    // This is an innefficient bubble sort, but unless there are an unlikely 
    // large number of cols, it is not an issue.
    AC_Sort(colInfo, numConstrainedCols);
   
    // compute the proportion to be added to each column, don't go beyond the col's
    // max. This algorithm assumes that the Weight works as stated above
    AC_Increase(numConstrainedCols, colInfo, sumMaxConstraints - sumMinConstraints, 
                availWidth, aPixelToTwips);
  }
  else { // reduce each col width 
    nscoord reduceWidth = maxMinDiff - aAvailWidth;
    if (reduceWidth < 0) {
      NS_ASSERTION(PR_TRUE, "AllocateConstrained called incorrectly");
      AC_Wrapup(mTableFrame, numConstrainedCols, colInfo);
      return;
    }
    for (i = 0; i < numConstrainedCols; i++) {
      // the weight here is a relative metric for determining when cols reach their min. 
      // A col with a larger weight will reach its min before one with a smaller value.
      nscoord delta = colInfo[i]->mWidth - colInfo[i]->mMinWidth;
      colInfo[i]->mWeight = (delta <= 0) 
        ? 1000000 // cols which have already reached their min get a large value
        : ((float)colInfo[i]->mWidth) / ((float)delta);
    }
      
    // sort the cols based on the Weight 
    AC_Sort(colInfo, numConstrainedCols);
   
    // compute the proportion to be subtracted from each column, don't go beyond 
    // the col's min. This algorithm assumes that the Weight works as stated above
    AC_Decrease(numConstrainedCols, colInfo, sumMaxConstraints, reduceWidth, aPixelToTwips);
  }
  AC_Wrapup(mTableFrame, numConstrainedCols, colInfo);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::AllocateFully ( nscoord aTotalAllocated,
PRInt32 aAllocTypes,
PRInt32  aWidthType 
) [protected, inherited]

Allocate aWidthType values to the corresponding columns.

Parameters:
aTotalAllocated- width that has been allocated in this routine
aAllocTypes- width type that has determined col width
aWidthType- width type selecting the columns for full width allocation

Definition at line 411 of file BasicTableLayoutStrategy.cpp.

{
  PRInt32 numCols = mTableFrame->GetColCount(); 
  for (PRInt32 colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
    nscoord newWidth = GetColWidth(colFrame, aWidthType);
    // proportional and desired widths are handled together
    PRBool haveProWidth = PR_FALSE;
    if (DES_CON == aWidthType) {
      nscoord proWidth = colFrame->GetWidth(MIN_PRO);
      if (proWidth >= 0) {
        haveProWidth = PR_TRUE;
        newWidth = proWidth;
      }
    }

    if (WIDTH_NOT_SET == newWidth) continue;
   
    if (newWidth > oldWidth) {
      mTableFrame->SetColumnWidth(colX, newWidth);
      aTotalAllocated += newWidth - oldWidth;
    }
    aAllocTypes[colX] = (haveProWidth) ? MIN_PRO : aWidthType;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::AllocateUnconstrained ( PRInt32  aAllocAmount,
PRInt32 aAllocTypes,
PRBool  aExcludePct,
PRBool  aExcludeFix,
PRBool  aExcludePro,
PRBool  aExclude0Pro,
float  aPixelToTwips 
) [protected, inherited]

Give the remaining space and exclude the selected columns.

Parameters:
aAllocAmount- space that can be distributed
aAllocTypes- width type that has determined col width
aExcludePct- dont give space to percent columns
aExcludeFix- dont give space to fixed width columns
aExcludePro- dont give space to proportional columns
aExclude0Pro- dont give space to proportional columns with 0*
aPixelToTwips- the number of twips in a pixel.

Definition at line 447 of file BasicTableLayoutStrategy.cpp.

{
  // set up allocTypes to exclude anything but auto cols if possible
  PRInt32 colX;
  PRInt32 numCols = mTableFrame->GetColCount();
  for (colX = 0; colX < numCols; colX++) {
    if (aExcludePct && (PCT == aAllocTypes[colX])) {
      aAllocTypes[colX] = FINISHED;
    }
    else if (aExcludeFix && ((FIX == aAllocTypes[colX]) || (FIX_ADJ == aAllocTypes[colX]))) {
      aAllocTypes[colX] = FINISHED;
    }
    else if (MIN_PRO == aAllocTypes[colX]) {
      if (aExcludePro) {
        aAllocTypes[colX] = FINISHED;
      }
      else {
        if (aExclude0Pro) {
          nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
          if (!colFrame) continue;
          if (colFrame->GetConstraint() == e0ProportionConstraint) {
            aAllocTypes[colX] = FINISHED;
          }
        }
      }
    }
  }
    
  nscoord divisor          = 0;
  PRInt32 numColsAllocated = 0; 
  PRInt32 totalAllocated   = 0;
  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue; 
    PRBool skipColumn = aExclude0Pro && (e0ProportionConstraint == colFrame->GetConstraint());
    if (FINISHED != aAllocTypes[colX] && !skipColumn ) {
      divisor += mTableFrame->GetColumnWidth(colX);
      numColsAllocated++;
    }
  }
  if (!numColsAllocated) {
    // redistribute the space to all columns and prevent a division by zero
    numColsAllocated = numCols;
  }
  for (colX = 0; colX < numCols; colX++) { 
    if (FINISHED != aAllocTypes[colX]) {
      if (aExclude0Pro) {
        nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
        if (!colFrame) continue;
        if (e0ProportionConstraint == colFrame->GetConstraint()) {
          continue;
        }
      }
      nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
      float percent = (divisor == 0) 
        ? (1.0f / ((float)numColsAllocated))
        : ((float)oldWidth) / ((float)divisor);
      nscoord addition = nsTableFrame::RoundToPixel(NSToCoordRound(((float)aAllocAmount) * percent), aPixelToTwips);
      if (addition > (aAllocAmount - totalAllocated)) {
        addition = nsTableFrame::RoundToPixel(aAllocAmount - totalAllocated, aPixelToTwips);
        mTableFrame->SetColumnWidth(colX, oldWidth + addition);
        break;
      }
      mTableFrame->SetColumnWidth(colX, oldWidth + addition);
      totalAllocated += addition;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool FixedTableLayoutStrategy::AssignNonPctColumnWidths ( nscoord  aComputedWidth,
const nsHTMLReflowState aReflowState 
) [protected, virtual]

assign widths for each column.

if the column has a fixed coord width, use it. if the column includes col spanning cells, then distribute the fixed space between cells proportionately. Computes the minimum and maximum table widths. Set column width information in each column frame and in the table frame.

Returns:
PR_TRUE has a pct cell or col, PR_FALSE otherwise

Reimplemented from BasicTableLayoutStrategy.

Definition at line 67 of file FixedTableLayoutStrategy.cpp.

{
  // NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
  const nsStylePosition* tablePosition = mTableFrame->GetStylePosition();
  PRBool tableIsFixedWidth = eStyleUnit_Coord   == tablePosition->mWidth.GetUnit() ||
                             eStyleUnit_Percent == tablePosition->mWidth.GetUnit();

  PRInt32 numCols = mTableFrame->GetColCount();
  PRInt32 colX;
  float pixelToTwips = mTableFrame->GetPresContext()->ScaledPixelsToTwips();
  // availWidth is used as the basis for percentage width columns. It is aComputedWidth
  // minus table border, padding, & cellspacing
  nscoord spacingX = mTableFrame->GetCellSpacingX();
  mCellSpacingTotal = spacingX;
  for (colX = 0; colX < numCols; colX++){
    if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) {
      mCellSpacingTotal += spacingX;
    }
  }
  nscoord availWidth = (NS_UNCONSTRAINEDSIZE == aComputedWidth) 
    ? NS_UNCONSTRAINEDSIZE
    : aComputedWidth - aReflowState.mComputedBorderPadding.left - 
      aReflowState.mComputedBorderPadding.right - 
      mCellSpacingTotal;
  
  PRInt32 specifiedCols = 0;  // the number of columns whose width is given
  nscoord totalColWidth = 0;  // the sum of the widths of the columns 

  nscoord* colWidths = new nscoord[numCols];
  if (!colWidths) return PR_FALSE;
  memset(colWidths, WIDTH_NOT_SET, numCols*sizeof(nscoord));

  nscoord* propInfo = new nscoord[numCols];
  if (!propInfo) {
    delete [] colWidths;
    return PR_FALSE;
  }

  memset(propInfo, 0, numCols*sizeof(nscoord));
  nscoord propTotal = 0;
  nscoord percTotal = 0;
  // for every column, determine its specified width
  for (colX = 0; colX < numCols; colX++) { 
    // Get column information
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
    if (!colFrame) {
      NS_ASSERTION(PR_FALSE, "bad col frame");
      return PR_FALSE;
    }

    // Get the columns's style
    const nsStylePosition* colPosition = colFrame->GetStylePosition();

    // get the fixed width if available
    if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) { 
      colWidths[colX] = colPosition->mWidth.GetCoordValue();
      colFrame->SetWidth(MIN_CON, colWidths[colX]);
    } // get the percentage width
    else if ((eStyleUnit_Percent == colPosition->mWidth.GetUnit()) &&
             (aComputedWidth != NS_UNCONSTRAINEDSIZE)) { 
      // Only apply percentages if we're constrained.
      float percent = colPosition->mWidth.GetPercentValue();
      colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(percent * (float)availWidth), pixelToTwips); 
      colFrame->SetWidth(PCT, colWidths[colX]);
      percTotal+=colWidths[colX];
    }
    else if (eStyleUnit_Proportional == colPosition->mWidth.GetUnit() &&
      colPosition->mWidth.GetIntValue() > 0) {
      propInfo[colX] = colPosition->mWidth.GetIntValue();
      propTotal += propInfo[colX];
    }
    else { // get width from the cell

      nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
      if (nsnull != cellFrame) {
        // Get the cell's style
        const nsStylePosition* cellPosition = cellFrame->GetStylePosition();

        nscoord cellWidth = 0;
        PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(*cellFrame);
        // Get fixed cell width if available
        if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
          // need to add border and padding into fixed width
          nsMargin borderPadding = nsTableFrame::GetBorderPadding(nsSize(aReflowState.mComputedWidth, 0),
                                                                  pixelToTwips, cellFrame);
          cellWidth = cellPosition->mWidth.GetCoordValue() + borderPadding.left + borderPadding.right;
          colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(((float) cellWidth) / ((float) colSpan)),
                                                                      pixelToTwips);
          colFrame->SetWidth(MIN_CON, colWidths[colX]);
        }
        else if ((eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) &&
                 (aComputedWidth != NS_UNCONSTRAINEDSIZE)) {
          float percent = cellPosition->mWidth.GetPercentValue();
          // need to add border and padding into percent width
          nsMargin borderPadding = nsTableFrame::GetBorderPadding(nsSize(aReflowState.mComputedWidth, 0),
                                                                  pixelToTwips, cellFrame);
          cellWidth = NSToCoordRound(percent * (float) availWidth) + borderPadding.left + borderPadding.right;
          colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(((float) cellWidth) / ((float) colSpan)),
                                                                      pixelToTwips); 
          colFrame->SetWidth(PCT, colWidths[colX]);
          percTotal += colWidths[colX];
        }
      }
    }
    if (colWidths[colX] >= 0) {
      totalColWidth += colWidths[colX];
      specifiedCols++;
    }
  }
 
  nscoord lastColAllocated = -1;
  nscoord remainingWidth = availWidth - totalColWidth;
  if(availWidth == NS_UNCONSTRAINEDSIZE)
    remainingWidth = 0; 
  if (remainingWidth >= 500000) {
    // let's put a cap on the width so that it doesn't become insane.
    remainingWidth = 100;
  }

  if (0 < remainingWidth) {
    if (propTotal > 0) {
      nscoord amountToAllocate = 0;
      for (colX = 0; colX < numCols; colX++) {
        if (propInfo[colX] > 0) {
          // We're proportional
          float percent = ((float)propInfo[colX])/((float)propTotal);
          amountToAllocate += NSToCoordRound(percent * (float)remainingWidth);
          colWidths[colX] = (amountToAllocate > 0) ?
            nsTableFrame::RoundToPixel(amountToAllocate, pixelToTwips,
                                       eRoundUpIfHalfOrMore) : 0;
          totalColWidth += colWidths[colX];
          amountToAllocate -= colWidths[colX];
          lastColAllocated = colX;
        }
      }  
    }
    else if (tableIsFixedWidth) {
      if (numCols > specifiedCols) {
        // allocate the extra space to the columns which have no width specified
        nscoord colAlloc =
          NSToCoordRound(((float)remainingWidth) /
                         (((float)numCols) - ((float)specifiedCols)));
        nscoord amountToAllocate = 0;
        for (colX = 0; colX < numCols; colX++) {
          if (-1 == colWidths[colX]) {
            amountToAllocate += colAlloc;
            colWidths[colX] = (amountToAllocate > 0) ?
              nsTableFrame::RoundToPixel(amountToAllocate,
                                         pixelToTwips,
                                         eRoundUpIfHalfOrMore) : 0;
            totalColWidth += colWidths[colX];
            amountToAllocate -= colWidths[colX];
            lastColAllocated = colX;
          }
        }
      }
      else { // allocate the extra space to the columns which have width specified
        float divisor = (float)totalColWidth;
        nscoord amountToAllocate = 0;
        for (colX = 0; colX < numCols; colX++) {
          if (colWidths[colX] > 0) {
            amountToAllocate += NSToCoordRound(remainingWidth * colWidths[colX] / divisor);
            nscoord colAlloc = (amountToAllocate > 0) ?
              nsTableFrame::RoundToPixel(amountToAllocate, pixelToTwips,
                                         eRoundUpIfHalfOrMore) : 0;
            colWidths[colX] += colAlloc;
            totalColWidth += colAlloc;
            amountToAllocate -= colAlloc;
            lastColAllocated = colX;
          }
        }
      }  
    }
  }

  nscoord overAllocation = ((availWidth >= 0) && (availWidth != NS_UNCONSTRAINEDSIZE))  
    ? totalColWidth - availWidth : 0;
  // set the column widths
  for (colX = 0; colX < numCols; colX++) {
    if (colWidths[colX] < 0) 
      colWidths[colX] = 0;
    // if there was too much allocated due to rounding, remove it from the last col
    if ((colX == lastColAllocated) && (overAllocation != 0)) {
      nscoord thisRemoval = nsTableFrame::RoundToPixel(overAllocation, pixelToTwips);
      colWidths[colX] -= thisRemoval;
      totalColWidth -= thisRemoval;
      
      totalColWidth -= colWidths[colX] - PR_MAX(0, colWidths[colX]);
      colWidths[colX] = PR_MAX(0, colWidths[colX]);
    }
  }
  overAllocation = ((availWidth >= 0) && (availWidth != NS_UNCONSTRAINEDSIZE))  
    ? totalColWidth - availWidth : 0;
  if(overAllocation > 0){
    // reduce over specified percent col
    nscoord amountToRemove = 0;
    for (colX = 0; colX < numCols; colX++) {
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
      if(( colFrame->GetWidth(PCT) > 0) && ( percTotal > 0)){
        amountToRemove += NSToCoordRound(overAllocation* colWidths[colX] / (float) percTotal);
        nscoord thisRemoval = (amountToRemove > 0) ?
          nsTableFrame::RoundToPixel(amountToRemove, pixelToTwips,
                                     eRoundUpIfHalfOrMore) : 0;
        colWidths[colX] -= thisRemoval;
        amountToRemove -= thisRemoval;
        totalColWidth -= thisRemoval;
        
        totalColWidth -= colWidths[colX] - PR_MAX(0, colWidths[colX]);
        colWidths[colX] = PR_MAX(0, colWidths[colX]);
        colFrame->SetWidth(PCT, colWidths[colX]);
      }
    }
  }
  for (colX = 0; colX < numCols; colX++) {
    mTableFrame->SetColumnWidth(colX, colWidths[colX]);
  }

  // clean up
  if (nsnull != colWidths) {
    delete [] colWidths;
  }

  if (nsnull != propInfo) {
    delete [] propInfo;
  }
  
  return PR_TRUE;
}

Here is the call graph for this function:

nscoord BasicTableLayoutStrategy::AssignPctColumnWidths ( const nsHTMLReflowState aReflowState,
nscoord  aBasis,
PRBool  aTableIsAutoWidth,
float  aPixelToTwips 
) [protected, inherited]

Determine percentage col widths for each col frame.

Parameters:
aReflowState- the reflow state of the table
aBasis- the basis for percent width as computed by CalcPctAdjTableWidth
aTableIsAutoWidth- true if no width specification for the table is available
aPixelToTwips- the number of twips in a pixel.
Returns:
- the adjusted basis including table border, padding and cell spacing

Definition at line 1361 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::ePctCols, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  mTableFrame->SetHasCellSpanningPctCol(PR_FALSE); // this gets refigured below
  PRInt32 numRows = mTableFrame->GetRowCount();
  PRInt32 numCols = mTableFrame->GetColCount(); // consider cols at end without orig cells 
  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  nscoord spacingX = mTableFrame->GetCellSpacingX();
  PRInt32 colX, rowX; 

  NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aAvailWidth, "AssignPctColumnWidths has unconstrained avail width");  
  // For an auto table, determine the potentially new percent adjusted width based 
  // on percent cells/cols. This probably should only be a NavQuirks thing, since
  // a percentage based cell or column on an auto table should force the column to auto
  nscoord basis = (aTableIsAutoWidth) 
                  ? CalcPctAdjTableWidth(aReflowState, aAvailWidth)
                  : aAvailWidth;

  // adjust the basis to exclude table border, padding and cell spacing
  nsMargin borderPadding = mTableFrame->GetContentAreaOffset(&aReflowState);
  basis -= borderPadding.left + borderPadding.right + mCellSpacingTotal;

  nscoord colPctTotal = 0;

  struct nsSpannedEle {
    nsSpannedEle *next, *prev;
    PRInt32 col, colSpan;
    nsTableCellFrame *cellFrame;
  };

  nsSpannedEle *spanList = 0;
  nsSpannedEle *spanTail = 0;
  PLArenaPool   spanArena;
  
  PL_INIT_ARENA_POOL(&spanArena, "AssignPctColumnWidths", 512);
  // Determine the percentage contribution for cols and for cells with colspan = 1
  // Iterate backwards, similarly to the reasoning in AssignNonPctColumnWidths
  for (colX = numCols - 1; colX >= 0; colX--) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord maxColPctWidth = WIDTH_NOT_SET;
    float maxColPct = 0.0f;

    nsTableCellFrame* percentContributor = nsnull;
    // Scan the cells in the col that have colspan = 1; assign PER widths
    for (rowX = 0; rowX < numRows; rowX++) {
      PRBool originates;
      PRInt32 colSpan;
      nsTableCellFrame* cellFrame = mTableFrame->GetCellInfoAt(rowX, colX, &originates, &colSpan);
      // skip cells that don't originate at (rowX, colX)
      if (!cellFrame || !originates) { 
        continue;
      }

      // colspans are handled in the next pass, but we record them here so we dont have to
      // search for the again.  row spans do not need to be handled.
      if(colSpan>1) {
        nsSpannedEle *spanned;
        ARENA_ALLOCATE(spanned, &spanArena, 1, nsSpannedEle);
        if(spanned) {
          spanned->col = colX;
          spanned->colSpan = colSpan;
          spanned->cellFrame = cellFrame;
          spanned->next = spanList;
          spanned->prev = nsnull;
          if(spanList) {
            spanList->prev = spanned;
          } else {
            spanTail = spanned;
          }
          spanList = spanned;
        }
        continue;
      }
      // see if the cell has a style percent width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
        float percent = cellPosition->mWidth.GetPercentValue();
        if (percent > maxColPct) {
          maxColPct = percent;
          maxColPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * maxColPct ), aPixelToTwips);
          percentContributor = cellFrame;
          if (!mIsNavQuirksMode) { 
            // need to add border and padding
            nsMargin cellBorderPadding = nsTableFrame::GetBorderPadding(nsSize(basis, 0), aPixelToTwips, cellFrame);
            maxColPctWidth += cellBorderPadding.left + cellBorderPadding.right;
          }
        }
      }
    }
    if (WIDTH_NOT_SET == maxColPctWidth) {
      // see if the col has a style percent width specified
      nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
      if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
        maxColPct = colStyleWidth.GetPercentValue();
        maxColPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * maxColPct ), aPixelToTwips);
      }
    }
    // conflicting pct/fixed widths are recorded. Nav 4.x may be changing the
    // fixed width value if it exceeds the pct value and not recording the pct
    // value. This is not being done and IE5 doesn't do it either.
    if (maxColPctWidth > 0) {
      maxColPctWidth = PR_MAX(maxColPctWidth, colFrame->GetWidth(MIN_CON));
      colFrame->SetWidth(PCT, maxColPctWidth);
      colPctTotal += NSToCoordRound(100.0f * (float)maxColPct);
    }
  }

  // if the percent total went over 100%, adjustments need to be made to right most cols
  if (colPctTotal > 100) {
    ReduceOverSpecifiedPctCols(nsTableFrame::RoundToPixel(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis), aPixelToTwips));
    colPctTotal = 100;
  }

  // check to see if a cell spans a percentage col. This will cause the MIN_ADJ,
  // FIX_ADJ, and DES_ADJ values to be recomputed 
  PRBool done = PR_FALSE;
  nsSpannedEle *spannedCell;
  for(spannedCell=spanList; !done && spannedCell; spannedCell=spannedCell->next)
  {
    colX = spannedCell->col;
    PRInt32 colSpan = spannedCell->colSpan;
    // determine if the cell spans cols which have a pct value
    for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
      if (!colFrame) continue;
      if (colFrame->GetWidth(PCT) > 0) {
        mTableFrame->SetHasCellSpanningPctCol(PR_TRUE);
        // recompute the MIN_ADJ, FIX_ADJ, and DES_ADJ values
        ComputeNonPctColspanWidths(aReflowState, PR_TRUE, aPixelToTwips, nsnull);
        done = PR_TRUE;
        break;
      }
    }
  }

  // For each col, consider the cells originating in it with colspans > 1.
  // Adjust the cols that each cell spans if necessary.
  // if more than one  colspan originate in one column, resort the access to 
  // the rows so that the inner colspans are handled first

  CellInfo* cellInfo = nsnull;

  if(spanTail)
    ARENA_ALLOCATE(cellInfo, &spanArena, numRows, CellInfo);

  if(cellInfo) for(spannedCell=spanTail; spannedCell;) {
    PRInt32 spannedRows = 0;
    colX = spannedCell->col;
    do {
      cellInfo[spannedRows].cellFrame = spannedCell->cellFrame;
      cellInfo[spannedRows].colSpan   = spannedCell->colSpan;
      ++spannedRows;
    } while((spannedCell=spannedCell->prev) && (spannedCell->col==colX));
    if(spannedRows>1) {
      NS_QuickSort(cellInfo, spannedRows, sizeof(cellInfo[0]), RowSortCB, 0);
    }

    for (PRInt32 i = 0; i < spannedRows; i++) {
      const CellInfo *inf = &cellInfo[i];
      const nsTableCellFrame* cellFrame = inf->cellFrame;

      const PRInt32 colSpan = PR_MIN(inf->colSpan, numEffCols - colX);
      nscoord cellPctWidth = WIDTH_NOT_SET;
      // see if the cell has a style percentage width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      float cellPct = 0.0f;
      if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
        cellPct = cellPosition->mWidth.GetPercentValue();
        if (colSpan == numEffCols)
          cellPct = 1.0f; // overwrite spurious percent colspan width's - bug 46944
        cellPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * cellPct ), aPixelToTwips);
        if (!mIsNavQuirksMode) { 
          // need to add border and padding 
          nsMargin cellBorderPadding = nsTableFrame::GetBorderPadding(nsSize(basis, 0), aPixelToTwips, cellFrame);
          cellPctWidth += cellBorderPadding.left + cellBorderPadding.right;
        }
      }
      if (cellPctWidth > 0) {
        nscoord spanCellSpacing = 0;
        nscoord spanTotal = 0;
        nscoord spanTotalNoPctAdj = 0;
        nscoord colPctWidthTotal = 0; // accumulate the PCT width 
        nscoord colPctAdjTotal = 0;   // accumulate the PCT_ADJ width or  the max of PCT_ADJ and PCT width if a 
                                      // PCT width is specified
        PRBool canSkipPctAdj = PR_FALSE;
        // accumulate the spanTotal as the max of MIN, DES, FIX, PCT
        PRInt32 spanX;
        for (spanX = 0; spanX < colSpan; spanX++) {
          nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
          if (!colFrame) continue;
          nscoord colPctWidth = colFrame->GetWidth(PCT);
          if (colPctWidth > 0) { // skip pct cols
            colPctWidthTotal += colPctWidth;
            colPctAdjTotal += PR_MAX(colFrame->GetWidth(PCT_ADJ), colPctWidth);
            continue;
          }
          colPctAdjTotal += PR_MAX(colFrame->GetWidth(PCT_ADJ), 0);
          nscoord colWidth = PR_MAX(colFrame->GetMinWidth(), colFrame->GetFixWidth());
          colWidth = PR_MAX(colWidth, colFrame->GetDesWidth()); // XXX check this
          //colWidth = PR_MAX(colWidth, colFrame->GetPctWidth());
          spanTotal += colWidth;
          if (colFrame->GetWidth(PCT_ADJ) <= 0) { // if we have a cell that is neither PCT or PCT_ADJ we have
                                                  // other places where we can drop the width
            canSkipPctAdj = PR_TRUE; 
            spanTotalNoPctAdj += colWidth;
          }
          if ((spanX > 0) && (mTableFrame->GetNumCellsOriginatingInCol(colX + spanX) > 0)) {
            spanCellSpacing += spacingX;
          }
        }
        cellPctWidth += spanCellSpacing; // add it back in since it was subtracted from aBasisIn
        if (cellPctWidth <= 0) {
          continue;
        }
        spanTotal = canSkipPctAdj ? spanTotalNoPctAdj: spanTotal; // if we can skip the PCT_ADJ ignore theire width
      
        colPctWidthTotal = canSkipPctAdj ? colPctAdjTotal: colPctWidthTotal; 
        
        if ((PR_MAX(colPctWidthTotal, colPctAdjTotal)+ spanCellSpacing) < cellPctWidth) { 
          // we have something to distribute ...
          // record the percent contributions for the spanned cols
          PRInt32 usedColumns = colSpan;
          for (spanX = colSpan-1; spanX >= 0; spanX--) {
            nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
            if (!colFrame) continue;
            if ((colFrame->GetWidth(PCT) > 0) || (canSkipPctAdj && (colFrame->GetWidth(PCT_ADJ) > 0))) {
              // dont use pct cols or if we can skip the pct adj event do not take the PCT_ADJ cols
              usedColumns--;
              continue;
            } // count the pieces 
            if (usedColumns == 0)
              usedColumns = 1; // avoid division by 0 later
            nscoord minWidth = colFrame->GetMinWidth();
            nscoord colWidth = PR_MAX(minWidth, colFrame->GetFixWidth());
            colWidth = PR_MAX(colWidth, colFrame->GetDesWidth()); // XXX check this
            float avail = (float)PR_MAX(cellPctWidth - colPctWidthTotal, 0);
            float colPctAdj = (0 == spanTotal) 
                              ? avail / ((float) usedColumns) / ((float)basis)
                              : (avail / (float)basis) * (((float)colWidth) / (float)spanTotal);
            if (colPctAdj > 0) {
              nscoord colPctAdjWidth = colFrame->GetWidth(PCT_ADJ);
              nscoord newColPctAdjWidth = nsTableFrame::RoundToPixel(NSToCoordRound(colPctAdj * (float)basis), aPixelToTwips);
              if (newColPctAdjWidth > colPctAdjWidth) {
                newColPctAdjWidth = PR_MAX(newColPctAdjWidth, minWidth); 
                if (newColPctAdjWidth > colFrame->GetWidth(PCT)) {
                  colFrame->SetWidth(PCT_ADJ, newColPctAdjWidth);
                  if(0 != basis) { // I am paranoid
                    colPctTotal += NSToCoordRound(100.0f *(newColPctAdjWidth-colPctAdjWidth) / (float)basis); 
                    // accumulate the new distributed percents
                  }
                }
              }
              else {
                usedColumns--;
                colPctWidthTotal += colPctAdjWidth; // accumulate the already distributed percents
              }
            }
          }
        }
      }
    } // end for (index ..
  } // end for (colX ..

  // We are done with our spanlist, get rid of it now
  PL_FinishArenaPool(&spanArena);

  // if the percent total went over 100%, adjustments need to be made to right most cols
  if (colPctTotal > 100) {
    ReduceOverSpecifiedPctCols(nsTableFrame::RoundToPixel(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis), aPixelToTwips));
  }

  // adjust the basis to include table border, padding and cell spacing
  basis += borderPadding.left + borderPadding.right + mCellSpacingTotal;
  return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, basis); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called during resize reflow to determine the new column widths.

Parameters:
aReflowState- the reflow state for mTableFrame

Reimplemented from BasicTableLayoutStrategy.

Definition at line 53 of file FixedTableLayoutStrategy.cpp.

{
  return PR_TRUE;
}
virtual nscoord FixedTableLayoutStrategy::CalcPctAdjTableWidth ( const nsHTMLReflowState aReflowState,
nscoord  aAvailWidth 
) [inline, virtual]

Calculate the basis for percent width calculations of the table elements.

Parameters:
aReflowState- the reflow state of the table
aAvailWidth- the available width for the table
Returns:
- the basis for percent calculations

Reimplemented from BasicTableLayoutStrategy.

Definition at line 81 of file FixedTableLayoutStrategy.h.

                                                                             {return 0;};
void BasicTableLayoutStrategy::CalculateTotals ( PRInt32 aTotalCounts,
PRInt32 aTotalWidths,
PRInt32 aDupedWidths,
PRInt32 a0ProportionalCount 
) [protected, inherited]

calculate totals by width type.

The logic here is kept in synch with that in CanAllocate

Parameters:
aTotalCounts- array with counts for each width type that has determined the aTotalWidths sum
aTotalWidths- array with accumulated widths for each width type
aDupedWidths- (duplicatd) are widths that will be allocated in BalanceColumnWidths before aTotalsWidths
a0ProportionalCount- number of columns with col="0*" constraint

Definition at line 1649 of file BasicTableLayoutStrategy.cpp.

{
  //mTableFrame->Dump(PR_TRUE, PR_FALSE);
  for (PRInt32 widthX = 0; widthX < NUM_WIDTHS; widthX++) {
    aTotalCounts[widthX]      = 0;
    aTotalWidths[widthX]      = 0;
    aDupedWidths[widthX]      = 0;
  }
  a0ProportionalCount = 0;

  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  PRInt32 colX;

  for (colX = 0; colX < numEffCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord minCol = colFrame->GetMinWidth();
    aTotalCounts[MIN_CON]++;
    aTotalWidths[MIN_CON] += minCol;

    if (e0ProportionConstraint == colFrame->GetConstraint()) {
      a0ProportionalCount++;
    }

    nscoord pct    = colFrame->GetPctWidth();
    nscoord fix    = colFrame->GetWidth(FIX);
    nscoord fixAdj = colFrame->GetWidth(FIX_ADJ);
    // if there is a pct width then no others are considered
    if (pct > 0) {
      aTotalCounts[PCT]++;
      aTotalWidths[PCT] += PR_MAX(pct, minCol);
      aDupedWidths[PCT] += minCol;
    }
    else if ((fix > 0) || (fixAdj > 0)) {
      if (fix > 0) {
        aTotalCounts[FIX]++;
        aTotalWidths[FIX] += PR_MAX(fix, minCol);
        aDupedWidths[FIX] += minCol;
      }
      if (fixAdj > 0) {
        if (fixAdj > fix) {
          aTotalCounts[FIX_ADJ]++;
          aTotalWidths[FIX_ADJ] += PR_MAX(fixAdj, minCol);
          if (fix > 0) {
            aDupedWidths[FIX_ADJ] += fix;
          }
          else { // there was no fix
            aDupedWidths[FIX_ADJ] += minCol;
          }
        }
      }
    }
    else if ((eProportionConstraint == colFrame->GetConstraint()) ||
             (e0ProportionConstraint == colFrame->GetConstraint())) {
      aTotalCounts[MIN_PRO]++;
      aTotalWidths[MIN_PRO] += PR_MAX(colFrame->GetWidth(MIN_PRO), minCol);
      aDupedWidths[MIN_PRO] += minCol;
    }
    else {
      // desired alone is lowest priority
      aTotalCounts[DES_CON]++;
      aTotalWidths[DES_CON] += PR_MAX(colFrame->GetDesWidth(), minCol);
      aDupedWidths[DES_CON] += minCol;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::ComputeNonPctColspanWidths ( const nsHTMLReflowState aReflowState,
PRBool  aConsiderPct,
float  aPixelToTwips,
PRBool aHasPctCol 
) [protected, inherited]

Calculate the adjusted widths (min, desired, fixed, or pct) for a cell spanning multiple columns.

Parameters:
aReflowState- the reflow state of the table
aConsiderPct- if true, consider columns that have pct widths and are spanned by the cell
aPixelToTwips-the number of twips in a pixel.
aHasPctCol- if not null, then set *aHasPctCol to true if there is a pct cell or col

Definition at line 587 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctColspans, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  PRInt32 numCols = mTableFrame->GetColCount();
  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  // zero out prior ADJ values 

  PRInt32 colX;
  for (colX = numCols - 1; colX >= 0; colX--) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    colFrame->SetWidth(MIN_ADJ, WIDTH_NOT_SET);
    colFrame->SetWidth(FIX_ADJ, WIDTH_NOT_SET);
    colFrame->SetWidth(DES_ADJ, WIDTH_NOT_SET);
  }

  // For each col, consider the cells originating in it with colspans > 1.
  // Adjust the cols that each cell spans if necessary. Iterate backwards 
  // so that nested and/or overlaping col spans handle the inner ones first, 
  // ensuring more accurated calculations.
  // if more than one  colspan originate in one column, resort the access to 
  // the rows so that the inner colspans are handled first
  PRInt32 numRows = mTableFrame->GetRowCount();

  CellInfo* cellInfo = new CellInfo[numRows];

  if(!cellInfo) {
    return;
  }

  for (colX = numEffCols - 1; colX >= 0; colX--) { // loop only over effective columns
    PRInt32 spannedRows = GetSortedFrames(mTableFrame, colX, numRows, cellInfo);

    for (PRInt32 i = 0; i < spannedRows; i++) {
      const CellInfo *inf = &cellInfo[i];
      const nsTableCellFrame* cellFrame = inf->cellFrame;

      const PRInt32 colSpan = PR_MIN(inf->colSpan, numEffCols - colX);
      // set MIN_ADJ, DES_ADJ, FIX_ADJ
      for (PRInt32 widthX = 0; widthX < NUM_MAJOR_WIDTHS; widthX++) {
        nscoord cellWidth = 0;
        if (MIN_CON == widthX) {
          cellWidth = cellFrame->GetPass1MaxElementWidth();
        }
        else if (DES_CON == widthX) {
          cellWidth = cellFrame->GetMaximumWidth();
        }
        else { // FIX width
          // see if the cell has a style width specified
          const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
          if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
            // need to add borde and padding into fixed width
            nsMargin borderPadding = nsTableFrame::GetBorderPadding(nsSize(aReflowState.mComputedWidth, 0),
                                                                    aPixelToTwips, cellFrame);
            cellWidth = cellPosition->mWidth.GetCoordValue() + borderPadding.left + borderPadding.right;
            cellWidth = PR_MAX(cellWidth, cellFrame->GetPass1MaxElementWidth());
          }
        }

        if (0 >= cellWidth) continue;

        // first allocate pct cells up to their value if aConsiderPct, then
        // allocate fixed cells up to their value, then allocate auto cells 
        // up to their value, then allocate auto cells proportionally.
        PRInt32 limit = (aConsiderPct) ? LIMIT_PCT : LIMIT_FIX;
        if (MIN_CON != widthX) { // FIX and DES only need to allocate NONE
          limit = LIMIT_NONE;
        }
        while (limit <= LIMIT_NONE) {
          if (ComputeNonPctColspanWidths(widthX, cellFrame, cellWidth, colX, colSpan, 
                                         limit, aPixelToTwips)) {
            break;
          }
          limit++;
        }
      }
      // determine if there is a pct col if we are requested to do so
      if (aHasPctCol && !*aHasPctCol) {
        *aHasPctCol = HasPctValue(cellFrame);
      }
    }
  }
  delete [] cellInfo;
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctColspans, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool BasicTableLayoutStrategy::ComputeNonPctColspanWidths ( PRInt32  aWidthIndex,
const nsTableCellFrame aCellFrame,
PRInt32  aCellWidth,
PRInt32  aColIndex,
PRInt32  aColSpan,
PRInt32 aLimitType,
float  aPixelToTwips 
) [protected, inherited]

main helper for above.

For min width calculations, it can get called up to 3 times, 1st to let constrained pct cols reach their limit, 2nd to let fix cols reach their limit and 3rd to spread any remainder among auto cols. If there are no auto cols then only constrained cols are considered.

Parameters:
aWidthIndex- the width to calculate (see nsTableColFrame.h for enums)
aCellFrame- the frame of the cell with a colspan
aCellWidth- the width of the cell with a colspan
aColIndex- the column index of the cell in the table
aColSpan- the colspan of the cell
aLimitType- the type of limit (ie. pct, fix, none).
aPixelToTwips-the number of twips in a pixel.
Returns:
- true if all of aCellWidth was allocated, false otherwise

Definition at line 714 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_STRATEGY
  DumpColWidths(*mTableFrame, "enter ComputeNonPctColspanWidths", aCellFrame, aColIndex, aWidthIndex, aLimitType);
#endif  
  PRBool result = PR_TRUE;

  nscoord spanCellSpacing   = 0; // total cell spacing cells being spanned
  nscoord minTotal          = 0; // the sum of min widths of spanned cells. 
  nscoord autoMinTotal      = 0; // the sum of min widths of spanned auto cells. 
  nscoord fixMinTotal       = 0; // the sum of min widths of spanned fix cells. 
  nscoord pctMinTotal       = 0; // the sum of min widths of spanned pct cells. 
  nscoord pctTotal          = 0; // the sum of pct widths of spanned cells. 
  nscoord fixTotal          = 0; // the sum of fix widths of spanned cells
  nscoord autoDesTotal      = 0; // the sum of desired widths of spanned cells which are auto
  nscoord pctLimitTotal     = 0; // the sum of pct widths not exceeding aCellWidth
  nscoord fixLimitTotal     = 0; // the sum of fix widths not exceeding aCellWidth
  nscoord desLimitTotal     = 0; // the sum of des widths not exceeding aCellWidth
  PRInt32 numAutoCols       = 0;

  nscoord spacingX = mTableFrame->GetCellSpacingX();
  PRInt32 spanX;
  // accumulate the various divisors to be used later
  for (spanX = 0; spanX < aColSpan; spanX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); 
    if (!colFrame) continue;
    nscoord minWidth = PR_MAX(colFrame->GetMinWidth(), 0);
    nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
    nscoord fixWidth = PR_MAX(colFrame->GetFixWidth(), 0);
    nscoord desWidth = PR_MAX(colFrame->GetDesWidth(), minWidth);

    minTotal += minWidth;

    if (pctWidth > 0) {
      pctTotal += pctWidth;
      pctMinTotal += minWidth;
    }
    else if (fixWidth > 0) {
      fixTotal += fixWidth;
      fixMinTotal += minWidth;
    }
    if (colFrame->GetWidth(PCT) + colFrame->GetWidth(FIX) <= 0) {
      autoDesTotal += desWidth;
      autoMinTotal += minWidth;
      numAutoCols++;
    }
    if ((spanX > 0) && (mTableFrame->GetNumCellsOriginatingInCol(aColIndex + spanX) > 0)) {
      spanCellSpacing += spacingX;
    }
  }
  nscoord availWidth = aCellWidth - spanCellSpacing;
  if (MIN_CON == aWidthIndex) {
    // MIN widths (unlike the others) are added to existing values, so subtract out the min total
    availWidth -= minTotal;

    pctLimitTotal = ((pctTotal - pctMinTotal) < availWidth) ? pctTotal - pctMinTotal : availWidth;
    fixLimitTotal = ((fixTotal - fixMinTotal) < availWidth) ? fixTotal - fixMinTotal : availWidth;
    desLimitTotal = ((autoDesTotal - autoMinTotal) < availWidth) ? autoDesTotal - autoMinTotal : availWidth;
  }
  else { // FIX or DES_CON with LIMIT_NONE
    if (FIX == aWidthIndex) {
      if (autoDesTotal > 0) {
        availWidth -= pctTotal + fixTotal;
      }
      else if (fixTotal > 0) {
        availWidth -= pctTotal;
      }
    }
    else if (DES_CON == aWidthIndex) {
      availWidth -= pctTotal + fixTotal; 
    }
  }

  // Below are some optimizations which can skip steps.
  if (LIMIT_PCT == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no pct cols, limit fix cols
    if (0 == pctTotal) {
      aLimitType = LIMIT_FIX;
    }
  }
  if (LIMIT_FIX == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no fix cols, limit des
    if (0 == fixTotal) {
      aLimitType = LIMIT_DES;
    }
  }
  if (LIMIT_DES == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no auto cols, limit none
    if (0 == autoDesTotal) {
      aLimitType = LIMIT_NONE;
    }
  }

  // there are some cases where allocating up to aCellWidth will not be satisfied
  switch (aLimitType) {
  case LIMIT_PCT:
    if (pctLimitTotal < availWidth) {
      // the pct cols won't satisfy the request alone
      availWidth = pctLimitTotal;
      result = PR_FALSE;
    }
    break;
  case LIMIT_FIX:
    if (fixLimitTotal < availWidth) {
      // the fix cols won't satisfy the request alone
      availWidth = fixLimitTotal;
      result = PR_FALSE;
    }
    break;
  case LIMIT_DES:
    if (desLimitTotal < availWidth) {
      // the auto cols won't satisfy the request alone
      availWidth = desLimitTotal;
      result = PR_FALSE;
    }
    break;
  default: // LIMIT_NONE
    break;
  }

  if (availWidth > 0) {
    nscoord usedWidth = 0;
    // get the correct numerator in a similar fashion to getting the divisor
    for (spanX = 0; spanX < aColSpan; spanX++) {
      if (usedWidth >= availWidth) break;
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); 
      if (!colFrame) continue;
      nscoord minWidth = colFrame->GetMinWidth();
      nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
      nscoord fixWidth = PR_MAX(colFrame->GetFixWidth(), 0);
      nscoord desWidth = PR_MAX(colFrame->GetDesWidth(), minWidth);

      nscoord colWidth = PR_MAX(colFrame->GetWidth(aWidthIndex), 
                                colFrame->GetWidth(aWidthIndex + NUM_MAJOR_WIDTHS));
      colWidth = PR_MAX(colWidth, minWidth);

      nscoord numeratorPct     = 0;
      nscoord numeratorFix     = 0;
      nscoord numeratorAutoDes = 0;

      if (pctWidth > 0) {
        numeratorPct = pctWidth;
      }
      else if (fixWidth > 0) {
        numeratorFix = fixWidth;
      }
      if (colFrame->GetWidth(PCT) + colFrame->GetWidth(FIX) <= 0) {
        numeratorAutoDes = desWidth;
      }

      nscoord divisor = 0;
      nscoord numerator = 0;

      // let pct cols reach their target 
      if (LIMIT_PCT == aLimitType) {
        if (pctLimitTotal > 0) {
          divisor   = pctTotal - pctMinTotal;
          numerator = PR_MAX(numeratorPct - minWidth, 0);
        }
      }
      // let fix cols reach their target 
      else if (LIMIT_FIX == aLimitType) {
        if (fixLimitTotal > 0) {
          divisor   = fixTotal - fixMinTotal;
          numerator = PR_MAX(numeratorFix - minWidth, 0);
        }
      }
      // let auto cols reach their target 
      else if (LIMIT_DES == aLimitType) {
        if (desLimitTotal > 0) {
          if (autoDesTotal > 0) { // there were auto cols
            divisor   = autoDesTotal - autoMinTotal;
            numerator = PR_MAX(numeratorAutoDes - minWidth, 0);
          }
          else if (fixTotal > 0) {  // there were fix cols but no auto
            divisor   = fixTotal - fixMinTotal;
            numerator = PR_MAX(numeratorFix - minWidth, 0);
          }
          else if (pctTotal > 0) {  // there were only pct cols
            divisor   = pctTotal - pctMinTotal;
            numerator = PR_MAX(numeratorPct - minWidth, 0);
          }
          else continue;
        }
      }
      else if (LIMIT_NONE == aLimitType) { 
        if ((MIN_CON == aWidthIndex) && (0 == minTotal)) {
          // divide evenly among the spanned cols
          divisor = aColSpan;
          numerator = 1;
        }
        else {
          if (autoDesTotal > 0) { // there were auto cols
            divisor   = autoDesTotal;
            numerator = numeratorAutoDes;
          }
          else if (fixTotal > 0) {  // there were fix cols but no auto
            divisor   = fixTotal;
            numerator = numeratorFix;
          }
          else if (pctTotal > 0) {  // there were only pct cols
            divisor   = pctTotal;
            numerator = numeratorPct;
          }
          else continue;

        }
      }
      // calculate the adj col width
      nscoord newColAdjWidth = (0 >= divisor) 
        ? NSToCoordRound( ((float)availWidth) / ((float)aColSpan) )
        : NSToCoordRound( (((float)numerator) / ((float)divisor)) * availWidth);
      newColAdjWidth = nsTableFrame::RoundToPixel(newColAdjWidth, aPixelToTwips);
      // don't let the new allocation exceed the avail total
      newColAdjWidth = PR_MIN(newColAdjWidth, availWidth - usedWidth);
      // put the remainder of the avail total in the last spanned col
      if (spanX == aColSpan - 1) {
        newColAdjWidth = availWidth - usedWidth;
      }
      usedWidth += newColAdjWidth;
      // MIN_CON gets added to what is there, the others don't
      if (MIN_CON == aWidthIndex) {
        newColAdjWidth += colWidth;
      }
      if (newColAdjWidth > colWidth) { 
        if (FIX == aWidthIndex) {
          // a colspan cannot fix a column below what a cell desires on its own
          nscoord desCon = colFrame->GetWidth(DES_CON); // do not consider DES_ADJ
          if (desCon > newColAdjWidth) {
            newColAdjWidth = desCon;
          }
        }
        colFrame->SetWidth(aWidthIndex + NUM_MAJOR_WIDTHS, newColAdjWidth);
      }
      else {        
        if((newColAdjWidth > 0) && (FIX == aWidthIndex)) {
          if(colFrame->GetWidth(FIX) < 0) {
            nscoord desCon = colFrame->GetWidth(DES_CON);
            if (desCon > newColAdjWidth) {
              newColAdjWidth = desCon;
            }
          }
          if(colFrame->GetWidth(FIX_ADJ) < newColAdjWidth) {
            colFrame->SetWidth(FIX_ADJ, PR_MAX(colWidth,newColAdjWidth));
          }
        }
      }
    }
  }
#ifdef DEBUG_TABLE_STRATEGY
  DumpColWidths(*mTableFrame, "exit ComputeNonPctColspanWidths", aCellFrame, aColIndex, aWidthIndex, aLimitType);
#endif
  return result;
}

Here is the call graph for this function:

Check in debug mode whether the routine is called on a continuing frame.

Definition at line 171 of file BasicTableLayoutStrategy.cpp.

{
  NS_ASSERTION(!mTableFrame->GetPrevInFlow(),
               "never ever call me on a continuing frame!");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::Dump ( PRInt32  aIndent) [inherited]
PRBool BasicTableLayoutStrategy::Initialize ( const nsHTMLReflowState aReflowState) [virtual, inherited]

call every time any table thing changes that might effect the width of any column in the table (content, structure, or style)

Parameters:
aReflowState- the reflow state for mTableFrame

Implements nsITableLayoutStrategy.

Definition at line 127 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eInit, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  ContinuingFrameCheck();

  PRBool result = PR_TRUE;

  // re-init instance variables
  mCellSpacingTotal = 0;
  mCols             = mTableFrame->GetEffectiveCOLSAttribute();

  mTableFrame->SetHasPctCol(PR_FALSE);

  nscoord boxWidth = mTableFrame->CalcBorderBoxWidth(aReflowState);
  PRBool hasPctCol = AssignNonPctColumnWidths(boxWidth, aReflowState);

  mTableFrame->SetHasPctCol(hasPctCol);

  // calc the min, desired, preferred widths from what we know so far
  nscoord minWidth, prefWidth;
  mTableFrame->CalcMinAndPreferredWidths(aReflowState, PR_FALSE, minWidth, prefWidth);
  if (hasPctCol && mTableFrame->IsAutoWidth()) {
    prefWidth = CalcPctAdjTableWidth(aReflowState, boxWidth);
  }
  // calc the desired width, considering if there is a specified width. 
  // don't use nsTableFrame::CalcDesiredWidth because it is based on table column widths.
  nscoord desWidth = (mTableFrame->IsAutoWidth()) ? PR_MIN(prefWidth, aReflowState.availableWidth)
                                                  : prefWidth;
  desWidth = PR_MAX(desWidth, minWidth);

  mTableFrame->SetMinWidth(minWidth);
  mTableFrame->SetDesiredWidth(desWidth);
  mTableFrame->SetPreferredWidth(prefWidth);

  mTableFrame->SetNeedStrategyInit(PR_FALSE);

#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eInit, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
  return result;
}

Here is the call graph for this function:

Reduce the percent columns by the amount specified in aExcess as the percent width's can accumulate to be over 100%.

Parameters:
aExcess- reduction amount

Definition at line 1189 of file BasicTableLayoutStrategy.cpp.

{
  nscoord numCols = mTableFrame->GetColCount();
  for (PRInt32 colX = numCols - 1; (colX >= 0) && (aExcess > 0); colX--) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord pctWidth = colFrame->GetWidth(PCT);
    nscoord reduction = 0;
    if (pctWidth > 0) {
      reduction = (aExcess > pctWidth) ? pctWidth : aExcess;
      nscoord newPctWidth = (reduction == pctWidth) ? WIDTH_NOT_SET : pctWidth - reduction;
      colFrame->SetWidth(PCT, PR_MAX(newPctWidth, colFrame->GetMinWidth()));
    }
    else {
      nscoord pctAdjWidth = colFrame->GetWidth(PCT_ADJ);
      if (pctAdjWidth > 0) {
        reduction = (aExcess > pctAdjWidth) ? pctAdjWidth : aExcess;
        nscoord newPctAdjWidth = (reduction == pctAdjWidth) ? WIDTH_NOT_SET : pctAdjWidth - reduction;
        colFrame->SetWidth(PCT_ADJ, PR_MAX(newPctAdjWidth, colFrame->GetMinWidth()));
      }
    }
    aExcess -= reduction;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 229 of file BasicTableLayoutStrategy.h.

PRInt32 BasicTableLayoutStrategy::mCols [protected, inherited]

Definition at line 227 of file BasicTableLayoutStrategy.h.

Definition at line 231 of file BasicTableLayoutStrategy.h.

Definition at line 230 of file BasicTableLayoutStrategy.h.

Definition at line 226 of file BasicTableLayoutStrategy.h.


The documentation for this class was generated from the following files: