Backed out changeset 68362ba98c23
authorL. David Baron <dbaron@dbaron.org>
Tue, 17 Jun 2008 16:10:17 -0700
changeset 15404 59120ca470902ebc3d7d084657ba10910e803d85
parent 15398 68362ba98c239bb08cf23255e28c37e96ccd3a79
child 15405 5017b968c5d3b6d93126645252facd3f84313af4
push id193
push userdbaron@mozilla.com
push dateTue, 17 Jun 2008 23:13:24 +0000
treeherdermozilla-central@7b6aaf10b6db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a1pre
backs out68362ba98c239bb08cf23255e28c37e96ccd3a79
Backed out changeset 68362ba98c23
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsFrame.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleCoord.cpp
layout/style/nsStyleCoord.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/tables/BasicTableLayoutStrategy.cpp
layout/tables/FixedTableLayoutStrategy.cpp
layout/xul/base/src/nsBox.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1488,16 +1488,35 @@ static nscoord AddPercents(nsLayoutUtils
     if (aPercent >= 1.0f)
       result = nscoord_MAX;
     else
       result = NSToCoordRound(float(result) / (1.0f - aPercent));
   }
   return result;
 }
 
+/* static */ PRBool
+nsLayoutUtils::GetAbsoluteCoord(const nsStyleCoord& aStyle,
+                                nsIRenderingContext* aRenderingContext,
+                                nsStyleContext* aStyleContext,
+                                nscoord& aResult)
+{
+  nsStyleUnit unit = aStyle.GetUnit();
+  if (eStyleUnit_Coord == unit) {
+    aResult = aStyle.GetCoordValue();
+    return PR_TRUE;
+  }
+  if (eStyleUnit_Chars == unit) {
+    aResult = nsLayoutUtils::CharsToCoord(aStyle, aRenderingContext,
+                                          aStyleContext);
+    return PR_TRUE;
+  }
+  return PR_FALSE;
+}
+
 static PRBool
 GetPercentHeight(const nsStyleCoord& aStyle,
                  nsIRenderingContext* aRenderingContext,
                  nsIFrame* aFrame,
                  nscoord& aResult)
 {
   if (eStyleUnit_Percent != aStyle.GetUnit())
     return PR_FALSE;
@@ -2627,16 +2646,36 @@ void
 nsLayoutUtils::SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC) 
 {
   const nsStyleFont* font = aSC->GetStyleFont();
   const nsStyleVisibility* visibility = aSC->GetStyleVisibility();
 
   aRC->SetFont(font->mFont, visibility->mLangGroup);
 }
 
+nscoord
+nsLayoutUtils::CharsToCoord(const nsStyleCoord& aStyle,
+                            nsIRenderingContext* aRenderingContext,
+                            nsStyleContext* aStyleContext)
+{
+  NS_ASSERTION(aStyle.GetUnit() == eStyleUnit_Chars,
+               "Shouldn't have called this");
+
+  nsCOMPtr<nsIFontMetrics> metrics;
+  aRenderingContext->GetMetricsFor(aStyleContext->GetStyleFont()->mFont,
+                                   *getter_AddRefs(metrics));
+  nsCOMPtr<nsIThebesFontMetrics> tfm(do_QueryInterface(metrics));
+  gfxFloat zeroWidth =
+    tfm->GetThebesFontGroup()->GetFontAt(0)->GetMetrics().zeroOrAveCharWidth;
+
+  return NSToCoordRound(aValue.GetFloatValue() *
+                        NS_ceil(aPresContext->AppUnitsPerDevPixel() *
+                                zeroWidth));
+}
+
 static PRBool NonZeroStyleCoord(const nsStyleCoord& aCoord)
 {
   switch (aCoord.GetUnit()) {
   case eStyleUnit_Percent:
     return aCoord.GetPercentValue() > 0;
   case eStyleUnit_Coord:
     return aCoord.GetCoordValue() > 0;
   default:
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -584,43 +584,34 @@ public:
 
   /**
    * Return the value of aStyle as an nscoord if it can be determined without
    * reference to ancestors or children (e.g. is not a percentage width)
    * @param aStyle the style coord
    * @param aRenderingContext the rendering context to use for font measurement
    * @param aFrame the frame whose style context should be used for font information
    * @param aResult the nscoord value of the style coord
-   * @return TRUE if the unit is eStyleUnit_Coord
+   * @return TRUE if the unit is eStyleUnit_Coord or eStyleUnit_Chars
    */
   static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle,
                                  nsIRenderingContext* aRenderingContext,
                                  nsIFrame* aFrame,
                                  nscoord& aResult)
   {
     return GetAbsoluteCoord(aStyle, aRenderingContext,
                             aFrame->GetStyleContext(), aResult);
   }
 
   /**
    * Same as above but doesn't need a frame
    */
   static PRBool GetAbsoluteCoord(const nsStyleCoord& aStyle,
                                  nsIRenderingContext* aRenderingContext,
                                  nsStyleContext* aStyleContext,
-                                 nscoord& aResult)
-  {
-    nsStyleUnit unit = aStyle.GetUnit();
-    if (eStyleUnit_Coord == unit) {
-      aResult = aStyle.GetCoordValue();
-      return PR_TRUE;
-    }
-    return PR_FALSE;
-  }
-
+                                 nscoord& aResult);
   /**
    * Get the contribution of aFrame to its containing block's intrinsic
    * width.  This considers the child's intrinsic width, its 'width',
    * 'min-width', and 'max-width' properties, and its padding, border,
    * and margin.
    */
   enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH };
   static nscoord IntrinsicForContainer(nsIRenderingContext* aRenderingContext,
@@ -766,16 +757,27 @@ public:
                             const nsRect* aSourceRect = nsnull);
 
   /**
    * Set the font on aRC based on the style in aSC
    */
   static void SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC);
 
   /**
+   * Convert an eStyleUnit_Chars nsStyleCoord to an nscoord.
+   *
+   * @param aStyle the style coord
+   * @param aRenderingContext the rendering context to use for font measurement
+   * @param aStyleContext the style context to use for font infomation
+   */
+  static nscoord CharsToCoord(const nsStyleCoord& aStyle,
+                              nsIRenderingContext* aRenderingContext,
+                              nsStyleContext* aStyleContext);
+
+  /**
    * Determine if any style coordinate is nonzero
    *   @param aCoord the style sides
    *   @return PR_TRUE unless all the coordinates are 0%, 0 or null.
    */
   static PRBool HasNonZeroSide(const nsStyleSides& aSides);
 
   /**
    * Determine if a widget is likely to require transparency or translucency.
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -205,34 +205,36 @@ nsAbsoluteContainingBlock::Reflow(nsCont
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
     NS_FRAME_SET_OVERFLOW_INCOMPLETE(reflowStatus);
 
   NS_MergeReflowStatusInto(&aReflowStatus, reflowStatus);
   return NS_OK;
 }
 
 static inline PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord;
+  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Chars;
 }
 static inline PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord;
+  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Chars;
 }
 static inline PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_None || aUnit == eStyleUnit_Coord;
+  return aUnit == eStyleUnit_None || aUnit == eStyleUnit_Coord ||
+         aUnit == eStyleUnit_Chars;
 }
 static inline PRBool IsFixedOffset(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord;
+  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Chars;
 }
 static inline PRBool IsFixedHeight(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord;
+  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Chars;
 }
 
 static inline PRBool IsFixedWidth(const nsStyleCoord& aCoord)
 {
   return aCoord.GetUnit() == eStyleUnit_Coord ||
+         aCoord.GetUnit() == eStyleUnit_Chars ||
          (aCoord.GetUnit() == eStyleUnit_Enumerated &&
           (aCoord.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
            aCoord.GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT));
 }
 
 static inline PRBool IsFixedMaxWidth(const nsStyleCoord& aCoord)
 {
   return aCoord.GetUnit() == eStyleUnit_None ||
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2958,16 +2958,21 @@ AddCoord(const nsStyleCoord& aStyle,
 {
   switch (aStyle.GetUnit()) {
     case eStyleUnit_Coord:
       *aCoord += aStyle.GetCoordValue();
       break;
     case eStyleUnit_Percent:
       *aPercent += aStyle.GetPercentValue();
       break;
+    case eStyleUnit_Chars: {
+      *aCoord += nsLayoutUtils::CharsToCoord(aStyle, aRenderingContext,
+                                             aFrame->GetStyleContext());
+      break;
+    }
     default:
       break;
   }
 }
 
 /* virtual */ nsIFrame::IntrinsicWidthOffsetData
 nsFrame::IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext)
 {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2766,16 +2766,17 @@ nsComputedDOMStyle::GetRelativeOffset(PR
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   const nsStylePosition* positionData = GetStylePosition();
   PRInt32 sign = 1;
   nsStyleCoord coord = positionData->mOffset.Get(aSide);
 
   NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
                coord.GetUnit() == eStyleUnit_Percent ||
+               coord.GetUnit() == eStyleUnit_Chars ||
                coord.GetUnit() == eStyleUnit_Auto,
                "Unexpected unit");
   
   if (coord.GetUnit() == eStyleUnit_Auto) {
     coord = positionData->mOffset.Get(NS_OPPOSITE_SIDE(aSide));
     sign = -1;
   }
   PercentageBaseGetter baseGetter;
@@ -3052,16 +3053,34 @@ nsComputedDOMStyle::SetValueToCoord(nsRO
       break;
       
     case eStyleUnit_Enumerated:
       NS_ASSERTION(aTable, "Must have table to handle this case");
       aValue->SetIdent(nsCSSProps::ValueToKeyword(aCoord.GetIntValue(),
                                                   aTable));
       break;
       
+    case eStyleUnit_Chars: {
+      // Get a rendering context
+      nsCOMPtr<nsIRenderingContext> cx;
+      nsIFrame* frame = mPresShell->FrameManager()->GetRootFrame();
+      if (frame) {
+        mPresShell->CreateRenderingContext(frame, getter_AddRefs(cx));
+      }
+      if (cx) {
+        nscoord val =
+          nsLayoutUtils::CharsToCoord(aCoord, cx, mStyleContextHolder);
+        aValue->SetAppUnits(PR_MAX(aMinAppUnits, PR_MIN(val, aMaxAppUnits)));
+      } else {
+        // Oh, well.  Give up.
+        aValue->SetAppUnits(0);
+      }
+      break;
+    }
+
     case eStyleUnit_None:
       aValue->SetIdent(nsGkAtoms::none);
       break;
       
     default:
       NS_ERROR("Can't handle this unit");
       break;
   }
@@ -3071,16 +3090,31 @@ nscoord
 nsComputedDOMStyle::StyleCoordToNSCoord(const nsStyleCoord& aCoord,
                                         PercentageBaseGetter aPercentageBaseGetter,
                                         nscoord aDefaultValue)
 {
   NS_PRECONDITION(aPercentageBaseGetter, "Must have a percentage base getter");
   switch (aCoord.GetUnit()) {
     case eStyleUnit_Coord:
       return aCoord.GetCoordValue();
+    case eStyleUnit_Chars:
+      {
+        // Get a rendering context
+        nsCOMPtr<nsIRenderingContext> cx;
+        nsIFrame* frame = mPresShell->FrameManager()->GetRootFrame();
+        if (frame) {
+          mPresShell->CreateRenderingContext(frame, getter_AddRefs(cx));
+        }
+        if (!cx) {
+          // Return the default value, I guess
+          break;
+        }
+
+        return nsLayoutUtils::CharsToCoord(aCoord, cx, mStyleContextHolder);
+      }
     case eStyleUnit_Percent:
       {
         nscoord percentageBase;
         if ((this->*aPercentageBaseGetter)(percentageBase)) {
           return nscoord(aCoord.GetPercentValue() * percentageBase);
         }
       }
       // Fall through to returning aDefaultValue if we have no percentage base.
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -228,17 +228,18 @@ static nscoord CalcLengthWith(const nsCS
     aStyleFont = aStyleContext->GetStyleFont();
   }
   if (aFontSize == -1) {
     // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
     // prefs into account?
     aFontSize = aStyleFont->mFont.size;
   }
   switch (unit) {
-    case eCSSUnit_EM: {
+    case eCSSUnit_EM:
+    case eCSSUnit_Char: {
       return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize));
       // XXX scale against font metrics height instead?
     }
     case eCSSUnit_EN: {
       return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
     }
     case eCSSUnit_XHeight: {
       nsFont font = aStyleFont->mFont;
@@ -248,27 +249,16 @@ static nscoord CalcLengthWith(const nsCS
       fm->GetXHeight(xHeight);
       return NSToCoordRound(aValue.GetFloatValue() * float(xHeight));
     }
     case eCSSUnit_CapHeight: {
       NS_NOTYETIMPLEMENTED("cap height unit");
       nscoord capHeight = ((aFontSize / 3) * 2); // XXX HACK!
       return NSToCoordRound(aValue.GetFloatValue() * float(capHeight));
     }
-    case eCSSUnit_Char: {
-      nsFont font = aStyleFont->mFont;
-      font.size = aFontSize;
-      nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
-      nsCOMPtr<nsIThebesFontMetrics> tfm(do_QueryInterface(fm));
-      gfxFloat zeroWidth = tfm->GetThebesFontGroup()->GetFontAt(0)->GetMetrics().zeroOrAveCharWidth;
-
-      return NSToCoordRound(aValue.GetFloatValue() *
-                            NS_ceil(aPresContext->AppUnitsPerDevPixel() *
-                                    zeroWidth));
-    }
     default:
       NS_NOTREACHED("unexpected unit");
       break;
   }
   return 0;
 }
 
 static nscoord CalcLength(const nsCSSValue& aValue,
@@ -316,16 +306,20 @@ static PRBool SetCoord(const nsCSSValue&
                        PRInt32 aMask, nsStyleContext* aStyleContext,
                        nsPresContext* aPresContext, PRBool& aInherited)
 {
   PRBool  result = PR_TRUE;
   if (aValue.GetUnit() == eCSSUnit_Null) {
     result = PR_FALSE;
   }
   else if (((aMask & SETCOORD_LENGTH) != 0) && 
+           (aValue.GetUnit() == eCSSUnit_Char)) {
+    aCoord.SetIntValue(NSToIntFloor(aValue.GetFloatValue()), eStyleUnit_Chars);
+  } 
+  else if (((aMask & SETCOORD_LENGTH) != 0) && 
            aValue.IsLengthUnit()) {
     aCoord.SetCoordValue(CalcLength(aValue, aStyleContext, aPresContext, aInherited));
   }
   else if (((aMask & SETCOORD_PERCENT) != 0) && 
            (aValue.GetUnit() == eCSSUnit_Percent)) {
     aCoord.SetPercentValue(aValue.GetPercentValue());
   } 
   else if (((aMask & SETCOORD_INTEGER) != 0) && 
@@ -3724,18 +3718,25 @@ nsRuleNode::ComputeBorderData(void* aSta
                      value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
                      "Unexpected enum value");
         border->SetBorderWidth(side,
                                (mPresContext->GetBorderWidthTable())[value.GetIntValue()]);
       }
       // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
       else if (SetCoord(value, coord, nsStyleCoord(), SETCOORD_LENGTH,
                         aContext, mPresContext, inherited)) {
-        NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
-        border->SetBorderWidth(side, coord.GetCoordValue());
+        if (coord.GetUnit() == eStyleUnit_Coord) {
+          border->SetBorderWidth(side, coord.GetCoordValue());
+        }
+#ifdef DEBUG
+        else {
+          NS_ASSERTION(coord.GetUnit() == eStyleUnit_Chars, "unexpected unit");
+          NS_WARNING("Border set in chars; we don't handle that");
+        }
+#endif        
       }
       else if (eCSSUnit_Inherit == value.GetUnit()) {
         inherited = PR_TRUE;
         border->SetBorderWidth(side, parentBorder->GetBorderWidth(side));
       }
       else if (eCSSUnit_Initial == value.GetUnit()) {
         border->SetBorderWidth(side,
           (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -124,18 +124,20 @@ void nsStyleCoord::SetCoordValue(nscoord
 {
   mUnit = eStyleUnit_Coord;
   mValue.mInt = aValue;
 }
 
 void nsStyleCoord::SetIntValue(PRInt32 aValue, nsStyleUnit aUnit)
 {
   NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
+               (aUnit == eStyleUnit_Chars) ||
                (aUnit == eStyleUnit_Integer), "not an int value");
   if ((aUnit == eStyleUnit_Enumerated) ||
+      (aUnit == eStyleUnit_Chars) ||
       (aUnit == eStyleUnit_Integer)) {
     mUnit = aUnit;
     mValue.mInt = aValue;
   }
   else {
     Reset();
   }
 }
@@ -189,16 +191,17 @@ void nsStyleCoord::AppendToString(nsStri
     case eStyleUnit_Coord:        aBuffer.AppendLiteral("tw");       break;
     case eStyleUnit_Percent:      aBuffer.AppendLiteral("%");        break;
     case eStyleUnit_Factor:       aBuffer.AppendLiteral("f");        break;
     case eStyleUnit_Normal:       aBuffer.AppendLiteral("Normal");   break;
     case eStyleUnit_Auto:         aBuffer.AppendLiteral("Auto");     break;
     case eStyleUnit_None:         aBuffer.AppendLiteral("None");     break;
     case eStyleUnit_Enumerated:   aBuffer.AppendLiteral("enum");     break;
     case eStyleUnit_Integer:      aBuffer.AppendLiteral("int");      break;
+    case eStyleUnit_Chars:        aBuffer.AppendLiteral("chars");    break;
   }
   aBuffer.Append(PRUnichar(' '));
 }
 
 void nsStyleCoord::ToString(nsString& aBuffer) const
 {
   aBuffer.Truncate();
   AppendToString(aBuffer);
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -50,17 +50,18 @@ enum nsStyleUnit {
   eStyleUnit_Null         = 0,      // (no value) value is not specified
   eStyleUnit_Normal       = 1,      // (no value)
   eStyleUnit_Auto         = 2,      // (no value)
   eStyleUnit_None         = 3,      // (no value)
   eStyleUnit_Percent      = 10,     // (float) 1.0 == 100%
   eStyleUnit_Factor       = 11,     // (float) a multiplier
   eStyleUnit_Coord        = 20,     // (nscoord) value is twips
   eStyleUnit_Integer      = 30,     // (int) value is simple integer
-  eStyleUnit_Enumerated   = 32      // (int) value has enumerated meaning
+  eStyleUnit_Enumerated   = 32,     // (int) value has enumerated meaning
+  eStyleUnit_Chars        = 33      // (int) value is number of characters
 };
 
 typedef union {
   PRInt32     mInt;   // nscoord is a PRInt32 for now
   float       mFloat;
 } nsStyleUnion;
 
 /**
@@ -191,18 +192,20 @@ inline PRInt32 nsStyleCoord::GetCoordVal
     return mValue.mInt;
   }
   return 0;
 }
 
 inline PRInt32 nsStyleCoord::GetIntValue(void) const
 {
   NS_ASSERTION((mUnit == eStyleUnit_Enumerated) ||
+               (mUnit == eStyleUnit_Chars) ||
                (mUnit == eStyleUnit_Integer), "not an int value");
   if ((mUnit == eStyleUnit_Enumerated) ||
+      (mUnit == eStyleUnit_Chars) ||
       (mUnit == eStyleUnit_Integer)) {
     return mValue.mInt;
   }
   return 0;
 }
 
 inline float nsStyleCoord::GetPercentValue(void) const
 {
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -226,16 +226,20 @@ static nscoord CalcCoord(const nsStyleCo
     case eStyleUnit_Enumerated:
       if (nsnull != aEnumTable) {
         PRInt32 value = aCoord.GetIntValue();
         if ((0 <= value) && (value < aNumEnums)) {
           return aEnumTable[aCoord.GetIntValue()];
         }
       }
       break;
+    case eStyleUnit_Chars:
+      // XXX we need a frame and a rendering context to calculate this, bug 281972, bug 282126.
+      NS_NOTYETIMPLEMENTED("CalcCoord: eStyleUnit_Chars");
+      return 0;
     default:
       NS_ERROR("bad unit type");
       break;
   }
   return 0;
 }
 
 nsStyleMargin::nsStyleMargin() {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -521,17 +521,17 @@ struct nsStyleOutline {
 
   PRBool GetOutlineOffset(nscoord& aOffset) const
   {
     if (mOutlineOffset.GetUnit() == eStyleUnit_Coord) {
       nscoord offset = mOutlineOffset.GetCoordValue();
       aOffset = NS_ROUND_OFFSET_TO_PIXELS(offset, mTwipsPerPixel);
       return PR_TRUE;
     } else {
-      NS_ERROR("GetOutlineOffset: bad unit type");
+      NS_NOTYETIMPLEMENTED("GetOutlineOffset: eStyleUnit_Chars");
       aOffset = 0;
       return PR_FALSE;
     }
   }
 
   PRBool GetOutlineWidth(nscoord& aWidth) const
   {
     if (mHasCachedOutline) {
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -116,17 +116,17 @@ GetWidthInfo(nsIRenderingContext *aRende
         prefCoord = 0;
     }
     float prefPercent = 0.0f;
     PRBool hasSpecifiedWidth = PR_FALSE;
 
     // XXXldb Should we consider -moz-box-sizing?
 
     nsStyleUnit unit = aStylePos->mWidth.GetUnit();
-    if (unit == eStyleUnit_Coord) {
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars) {
         hasSpecifiedWidth = PR_TRUE;
         nscoord w = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
                       aFrame, 0, 0, 0, aStylePos->mWidth);
         // Quirk: A cell with "nowrap" set and a coord value for the
         // width which is bigger than the intrinsic minimum width uses
         // that coord value as the minimum width.
         // This is kept up-to-date with dynamic chnages to nowrap by code in
         // nsTableCellFrame::AttributeChanged
@@ -166,17 +166,18 @@ GetWidthInfo(nsIRenderingContext *aRende
             // for 'max-width', '-moz-fit-content' is like
             // '-moz-max-content'
             maxWidth.SetIntValue(NS_STYLE_WIDTH_MAX_CONTENT,
                                  eStyleUnit_Enumerated);
     }
     unit = maxWidth.GetUnit();
     // XXX To really implement 'max-width' well, we'd need to store
     // it separately on the columns.
-    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Enumerated) {
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars ||
+        unit == eStyleUnit_Enumerated) {
         nscoord w =
             nsLayoutUtils::ComputeWidthValue(aRenderingContext, aFrame,
                                              0, 0, 0, maxWidth);
         if (w < minCoord)
             minCoord = w;
         if (w < prefCoord)
             prefCoord = w;
     } else if (unit == eStyleUnit_Percent) {
@@ -191,17 +192,18 @@ GetWidthInfo(nsIRenderingContext *aRende
             minWidth.SetCoordValue(0);
         else if (minWidth.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT)
             // for 'min-width', '-moz-fit-content' is like
             // '-moz-min-content'
             minWidth.SetIntValue(NS_STYLE_WIDTH_MIN_CONTENT,
                                  eStyleUnit_Enumerated);
     }
     unit = minWidth.GetUnit();
-    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Enumerated) {
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars ||
+        unit == eStyleUnit_Enumerated) {
         nscoord w =
             nsLayoutUtils::ComputeWidthValue(aRenderingContext, aFrame,
                                              0, 0, 0, minWidth);
         if (w > minCoord)
             minCoord = w;
         if (w > prefCoord)
             prefCoord = w;
     } else if (unit == eStyleUnit_Percent) {
--- a/layout/tables/FixedTableLayoutStrategy.cpp
+++ b/layout/tables/FixedTableLayoutStrategy.cpp
@@ -93,17 +93,18 @@ FixedTableLayoutStrategy::GetMinWidth(ns
     for (PRInt32 col = 0; col < colCount; ++col) {
         nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
         if (!colFrame) {
             NS_ERROR("column frames out of sync with cell map");
             continue;
         }
         const nsStyleCoord *styleWidth =
             &colFrame->GetStylePosition()->mWidth;
-        if (styleWidth->GetUnit() == eStyleUnit_Coord) {
+        if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+            styleWidth->GetUnit() == eStyleUnit_Chars) {
             result += nsLayoutUtils::ComputeWidthValue(aRenderingContext,
                         colFrame, 0, 0, 0, *styleWidth);
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             // do nothing
         } else {
             NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
                          styleWidth->GetUnit() == eStyleUnit_Enumerated,
                          "bad width");
@@ -112,16 +113,17 @@ FixedTableLayoutStrategy::GetMinWidth(ns
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
             if (cellFrame) {
                 styleWidth = &cellFrame->GetStylePosition()->mWidth;
                 if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+                    styleWidth->GetUnit() == eStyleUnit_Chars ||
                     (styleWidth->GetUnit() == eStyleUnit_Enumerated &&
                      (styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
                       styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
                     nscoord cellWidth = nsLayoutUtils::IntrinsicForContainer(
                         aRenderingContext, cellFrame, nsLayoutUtils::MIN_WIDTH);
                     if (colSpan > 1) {
                         // If a column-spanning cell is in the first
                         // row, split up the space evenly.  (XXX This
@@ -209,17 +211,18 @@ FixedTableLayoutStrategy::ComputeColumnW
         if (!colFrame) {
             NS_ERROR("column frames out of sync with cell map");
             continue;
         }
         colFrame->ResetPrefPercent();
         const nsStyleCoord *styleWidth =
             &colFrame->GetStylePosition()->mWidth;
         nscoord colWidth;
-        if (styleWidth->GetUnit() == eStyleUnit_Coord) {
+        if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+            styleWidth->GetUnit() == eStyleUnit_Chars) {
             colWidth = nsLayoutUtils::ComputeWidthValue(
                          aReflowState.rendContext,
                          colFrame, 0, 0, 0, *styleWidth);
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             float pct = styleWidth->GetPercentValue();
             colWidth = NSToCoordFloor(pct * float(tableWidth));
             colFrame->AddPrefPercent(pct);
             pctTotal += pct;
@@ -232,16 +235,17 @@ FixedTableLayoutStrategy::ComputeColumnW
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
             if (cellFrame) {
                 styleWidth = &cellFrame->GetStylePosition()->mWidth;
                 if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+                    styleWidth->GetUnit() == eStyleUnit_Chars ||
                     (styleWidth->GetUnit() == eStyleUnit_Enumerated &&
                      (styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
                       styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
                     // XXX This should use real percentage padding
                     // Note that the difference between MIN_WIDTH and
                     // PREF_WIDTH shouldn't matter for any of these
                     // values of styleWidth; use MIN_WIDTH for symmetry
                     // with GetMinWidth above, just in case there is a
--- a/layout/xul/base/src/nsBox.cpp
+++ b/layout/xul/base/src/nsBox.cpp
@@ -678,16 +678,17 @@ nsIBox::AddCSSPrefSize(nsBoxLayoutState&
     // (Handling the eStyleUnit_Enumerated types requires
     // GetPrefSize/GetMinSize methods that don't consider
     // (min-/max-/)(width/height) properties.
 
     if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
         aSize.height = position->mHeight.GetCoordValue();     
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
     
     nsIContent* content = aBox->GetContent();
     // ignore 'height' and 'width' attributes if the actual element is not XUL
     // For example, we might be magic XUL frames whose primary content is an HTML
     // <select>
     if (content && content->IsNodeOfType(nsINode::eXUL)) {
         nsAutoString value;
         PRInt32 error;
@@ -776,16 +777,17 @@ nsIBox::AddCSSMinSize(nsBoxLayoutState& 
            heightSet = PR_TRUE;
         }
     } else if (position->mMinHeight.GetUnit() == eStyleUnit_Percent) {
         float min = position->mMinHeight.GetPercentValue();
         NS_ASSERTION(min == 0.0f, "Non-zero percentage values not currently supported");
         aSize.height = 0;
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
 
     nsIContent* content = aBox->GetContent();
     if (content) {
         nsAutoString value;
         PRInt32 error;
 
         content->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value);
         if (!value.IsEmpty())
@@ -834,16 +836,17 @@ nsIBox::AddCSSMaxSize(nsBoxLayoutState& 
     // GetPrefSize/GetMinSize methods that don't consider
     // (min-/max-/)(width/height) properties.
 
     if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) {
         nscoord max = position->mMaxHeight.GetCoordValue();
         aSize.height = max;
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
 
     nsIContent* content = aBox->GetContent();
     if (content) {
         nsAutoString value;
         PRInt32 error;
 
         content->GetAttr(kNameSpaceID_None, nsGkAtoms::maxwidth, value);
         if (!value.IsEmpty()) {