Make computed style handle "normal" for line-height by computing an actualnumeric height. Bug 371041, r+sr=dbaron
authorbzbarsky@mit.edu
Fri, 04 May 2007 22:30:10 -0700
changeset 1102 bead47d904e7aabd721b4674ad342f41a7c3714a
parent 1101 581de97184e3dc98fdc69bb1de14875f9d4cb693
child 1103 dc9c4f4d52e079fb7c8d4e54e96b52fca466501f
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs371041
milestone1.9a5pre
Make computed style handle "normal" for line-height by computing an actualnumeric height. Bug 371041, r+sr=dbaron
layout/forms/nsTextControlFrame.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsBlockReflowState.cpp
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/generic/nsLineLayout.cpp
layout/reftests/bugs/371041-1-ref.html
layout/reftests/bugs/371041-1.html
layout/reftests/bugs/reftest.list
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -1277,19 +1277,17 @@ nsTextControlFrame::CalcIntrinsicSize(ns
   nscoord charMaxAdvance  = 0;
 
   nsCOMPtr<nsIFontMetrics> fontMet;
   nsresult rv =
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
   NS_ENSURE_SUCCESS(rv, rv);
   aRenderingContext->SetFont(fontMet);
 
-  nsPresContext* presContext = PresContext();
-  lineHeight = nsHTMLReflowState::CalcLineHeight(presContext,
-                                                 aRenderingContext,
+  lineHeight = nsHTMLReflowState::CalcLineHeight(aRenderingContext,
                                                  this);
   fontMet->GetAveCharWidth(charWidth);
   fontMet->GetMaxAdvance(charMaxAdvance);
 
   // Set the width equal to the width in characters
   PRInt32 cols = GetCols();
   aIntrinsicSize.width = cols * charWidth;
 
@@ -1308,17 +1306,17 @@ nsTextControlFrame::CalcIntrinsicSize(ns
     } else {
       internalPadding += t - rest;
     }
     // Now add the extra padding on (so that small input sizes work well)
     aIntrinsicSize.width += internalPadding;
   } else {
     // This is to account for the anonymous <br> having a 1 twip width
     // in Full Standards mode, see BRFrame::Reflow and bug 228752.
-    if (presContext->CompatibilityMode() == eCompatibility_FullStandards) {
+    if (PresContext()->CompatibilityMode() == eCompatibility_FullStandards) {
       aIntrinsicSize.width += 1;
     }
   }
 
   // Increment width with cols * letter-spacing.
   {
     const nsStyleCoord& lsCoord = GetStyleText()->mLetterSpacing;
     if (eStyleUnit_Coord == lsCoord.GetUnit()) {
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -147,19 +147,17 @@ BRFrame::Reflow(nsPresContext* aPresCont
       SetFontFromStyle(aReflowState.rendContext, mStyleContext);
       nsCOMPtr<nsIFontMetrics> fm;
       aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
       if (fm) {
         nscoord ascent, descent;
         fm->GetMaxAscent(ascent);
         fm->GetMaxDescent(descent);
         nscoord logicalHeight =
-          aReflowState.CalcLineHeight(aPresContext,
-                                       aReflowState.rendContext,
-                                       this);
+          aReflowState.CalcLineHeight(aReflowState.rendContext, this);
         nscoord leading = logicalHeight - ascent - descent;
         aMetrics.height = logicalHeight;
         aMetrics.ascent = ascent + (leading/2);
       }
       else {
         aMetrics.ascent = aMetrics.height = 0;
       }
 
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -131,18 +131,17 @@ nsBlockReflowState::nsBlockReflowState(c
   }
 
   mY = borderPadding.top;
   mBand.Init(mSpaceManager, mContentArea);
 
   mPrevChild = nsnull;
   mCurrentLine = aFrame->end_lines();
 
-  mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
-                                                     aReflowState.rendContext,
+  mMinLineHeight = nsHTMLReflowState::CalcLineHeight(aReflowState.rendContext,
                                                      aReflowState.frame);
 }
 
 void
 nsBlockReflowState::SetupOverflowPlaceholdersProperty()
 {
   if (mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE ||
       !mOverflowPlaceholders.IsEmpty()) {
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1927,22 +1927,24 @@ GetNormalLineHeight(nsIFontMetrics* aFon
     normalLineHeight = emHeight + internalLeading;
   }
 #else
   aFontMetrics->GetNormalLineHeight(normalLineHeight);
 #endif // FONT_LEADING_APIS_V2
   return normalLineHeight;
 }
 
+// Need only one of aRenderingContext and aDeviceContext
 static nscoord
-ComputeLineHeight(nsPresContext* aPresContext,
-                  nsIRenderingContext* aRenderingContext,
+ComputeLineHeight(nsIRenderingContext* aRenderingContext,
+                  nsIDeviceContext* aDeviceContext,
                   nsStyleContext* aStyleContext)
 {
-  NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
+  NS_PRECONDITION(aRenderingContext || aDeviceContext,
+                  "Need to have a way of getting a device context");
 
   nscoord lineHeight;
 
   const nsStyleFont* font = aStyleContext->GetStyleFont();
   const nsStyleCoord& lhCoord = aStyleContext->GetStyleText()->mLineHeight;
   
   nsStyleUnit unit = lhCoord.GetUnit();
 
@@ -1952,43 +1954,59 @@ ComputeLineHeight(nsPresContext* aPresCo
   } else if (unit == eStyleUnit_Factor) {
     // For factor units the computed value of the line-height property 
     // is found by multiplying the factor by the font's computed size
     // (adjusted for min-size prefs and text zoom).
     float factor = lhCoord.GetFactorValue();
     lineHeight = NSToCoordRound(factor * font->mFont.size);
   } else {
     NS_ASSERTION(eStyleUnit_Normal == unit, "bad unit");
-    nsCOMPtr<nsIDeviceContext> deviceContext;
-    aRenderingContext->GetDeviceContext(*getter_AddRefs(deviceContext));
+    nsCOMPtr<nsIDeviceContext> deviceContext = aDeviceContext;
+    if (NS_UNLIKELY(!deviceContext)) {
+      aRenderingContext->GetDeviceContext(*getter_AddRefs(deviceContext));
+    }
     const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
     nsCOMPtr<nsIFontMetrics> fm;
     deviceContext->GetMetricsFor(font->mFont, vis->mLangGroup,
                                  *getter_AddRefs(fm));
     lineHeight = GetNormalLineHeight(fm);
   }
   return lineHeight;
 }
 
 nscoord
-nsHTMLReflowState::CalcLineHeight(nsPresContext* aPresContext,
-                                  nsIRenderingContext* aRenderingContext,
+nsHTMLReflowState::CalcLineHeight(nsIRenderingContext* aRenderingContext,
                                   nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame && aFrame->GetStyleContext(),
                "Bogus data passed in to CalcLineHeight");
 
-  nscoord lineHeight = ComputeLineHeight(aPresContext, aRenderingContext,
+  nscoord lineHeight = ComputeLineHeight(aRenderingContext, nsnull,
                                          aFrame->GetStyleContext());
 
   NS_ASSERTION(lineHeight >= 0, "ComputeLineHeight screwed up");
 
   return lineHeight;
 }
 
+nscoord
+nsHTMLReflowState::CalcLineHeight(nsStyleContext* aStyleContext,
+                                  nsIDeviceContext* aDeviceContext)
+{
+  NS_PRECONDITION(aStyleContext, "Must have a style context");
+  NS_PRECONDITION(aDeviceContext, "Must have a device context");
+  
+  nscoord lineHeight = ComputeLineHeight(nsnull, aDeviceContext,
+                                         aStyleContext);
+
+  NS_ASSERTION(lineHeight >= 0, "ComputeLineHeight screwed up");
+
+  return lineHeight;
+}
+
 /* static */
 void
 nsCSSOffsetState::DestroyMarginFunc(void*    aFrame,
                                     nsIAtom* aPropertyName,
                                     void*    aPropertyValue,
                                     void*    aDtorData)
 {
   delete NS_STATIC_CAST(nsMargin*, aPropertyValue);
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -401,22 +401,25 @@ public:
    * Find the containing block of aFrame.  This may return null if
    * there isn't one (but that should really only happen for root
    * frames).
    */
   static nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame);
 
   /**
    * Calculate the raw line-height property for the given frame. The return
-   * value, if line-height was applied and is valid will be >= 0. Otherwise,
-   * the return value will be <0 which is illegal (CSS2 spec: section 10.8.1).
+   * value will be >= 0.
    */
-  static nscoord CalcLineHeight(nsPresContext* aPresContext,
-                                nsIRenderingContext* aRenderingContext,
+  static nscoord CalcLineHeight(nsIRenderingContext* aRenderingContext,
                                 nsIFrame* aFrame);
+  /**
+   * Same as above, but doesn't need quite as much info.
+   */
+  static nscoord CalcLineHeight(nsStyleContext* aStyleContext,
+                                nsIDeviceContext* aDeviceContext);
 
   void InitFrameType();
 
   void ComputeContainingBlockRectangle(nsPresContext*          aPresContext,
                                        const nsHTMLReflowState* aContainingBlockRS,
                                        nscoord&                 aContainingBlockWidth,
                                        nscoord&                 aContainingBlockHeight);
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1743,18 +1743,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
            mTopEdge, mMinLineHeight,
            zeroEffectiveSpanBox ? "yes" : "no");
 #endif
   }
   else {
     // Compute the logical height for this span. The logical height
     // is based on the line-height value, not the font-size. Also
     // compute the top leading.
-    nscoord logicalHeight =
-      nsHTMLReflowState::CalcLineHeight(mPresContext, rc, spanFrame);
+    nscoord logicalHeight = nsHTMLReflowState::CalcLineHeight(rc, spanFrame);
     nscoord contentHeight = spanFramePFD->mBounds.height -
       spanFramePFD->mBorderPadding.top - spanFramePFD->mBorderPadding.bottom;
 
     // Special-case for a ::first-letter frame, set the line height to
     // the frame height if the user has left line-height == normal 
     if (spanFramePFD->GetFlag(PFD_ISLETTERFRAME) && !spanPrevInFlow &&
         spanFrame->GetStyleText()->mLineHeight.GetUnit() == eStyleUnit_Normal) {
       logicalHeight = spanFramePFD->mBounds.height;
@@ -1974,18 +1973,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
         revisedBaselineY = baselineY - coordOffset;
         pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
         pfd->mVerticalAlign = VALIGN_OTHER;
         break;
 
       case eStyleUnit_Percent:
         // Similar to a length value (eStyleUnit_Coord) except that the
         // percentage is a function of the elements line-height value.
-        elementLineHeight =
-          nsHTMLReflowState::CalcLineHeight(mPresContext, rc, frame);
+        elementLineHeight = nsHTMLReflowState::CalcLineHeight(rc, frame);
         percentOffset = nscoord(
           textStyle->mVerticalAlign.GetPercentValue() * elementLineHeight
           );
         revisedBaselineY = baselineY - percentOffset;
         pfd->mBounds.y = revisedBaselineY - pfd->mAscent;
         pfd->mVerticalAlign = VALIGN_OTHER;
         break;
     }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/371041-1-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+  span { visibility: hidden }
+  div { font-size: 20px; background: blue; margin: 10px; }
+</style>
+</head>
+<body>
+<div><span>TEST</span></div>
+<div style="line-height: 5px;"><span>TEST</span></div>
+<div style="line-height: 40px;"><span>TEST</span></div>
+<div><span>TEST</span></div>
+<div style="line-height: 30px;"><span>TEST</span></div>
+<div style="line-height: 10px;"><span>TEST</span></div>
+
+<div><span>TEST</span></div>
+<div style="line-height: 5px;"><span>TEST</span></div>
+<div style="line-height: 40px;"><span>TEST</span></div>
+<div><span>TEST</span></div>
+<div style="line-height: 30px;"><span>TEST</span></div>
+<div style="line-height: 10px;"><span>TEST</span></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/371041-1.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+  div.source { display: none; font-size: 20px }
+  div.source2 { font-size: 20px ; height: 0; margin: 0; visibility: hidden; }
+  div { background: blue; margin: 10px }
+</style>
+</head>
+<body>
+<!-- Put all the source divs after the test divs so the test divs can margin-collapse like the reference -->
+
+<div id="test1"></div>
+<div id="test2"></div>
+<div id="test3"></div>
+<div id="test4"></div>
+<div id="test5"></div>
+<div id="test6"></div>
+
+<div id="test7"></div>
+<div id="test8"></div>
+<div id="test9"></div>
+<div id="test10"></div>
+<div id="test11"></div>
+<div id="test12"></div>
+
+<div id="source1" class="source">TEST</div>
+<div id="source2" class="source" style="line-height: 5px">TEST</div>
+<div id="source3" class="source" style="line-height: 2em">TEST</div>
+<div id="source4" class="source" style="line-height: normal">TEST</div>
+<div id="source5" class="source" style="line-height: 150%">TEST</div>
+<div id="source6" class="source" style="line-height: 0.5">TEST</div>
+
+<div id="source7" class="source2">TEST</div>
+<div id="source8" class="source2" style="line-height: 5px">TEST</div>
+<div id="source9" class="source2" style="line-height: 2em">TEST</div>
+<div id="source10" class="source2" style="line-height: normal">TEST</div>
+<div id="source11" class="source2" style="line-height: 150%">TEST</div>
+<div id="source12" class="source2" style="line-height: 0.5">TEST</div>
+
+<script>
+  var d = document;
+  for (var i = 1; i <= 12; ++i) {
+    d.getElementById("test" + i).style.height =
+      d.defaultView.getComputedStyle(d.getElementById("source" + i),
+                                     "").lineHeight;
+  }
+</script>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -204,16 +204,17 @@ fails == 368020-4.html 368020-4-ref.html
 fails == 368504-1.html 368504-1-ref.html # bug 368504
 == 368622-1.html 368622-1-ref.html
 == 368622-1.html 368622-1-ref.html
 == 370422-1.html 370422-1-ref.html
 == 370586-1.xhtml 370586-1-ref.xhtml
 == 370629-1.html 370629-1-ref.html
 == 370629-2.html 370629-2-ref.html
 == 370692-1.xhtml 370692-1-ref.xhtml
+== 371041-1.html 371041-1-ref.html
 == 371925-1a.html 371925-1-ref.html
 == 371925-1b.html 371925-1-ref.html
 == 372553-1.html 372553-1-ref.html
 == 373381-1.html 373381-1-ref.html
 fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 372037-1.html 372037-1-ref.html # bug 377118
 == 375508-1.html 375508-1-ref.html
 == 373433-1.html 373433-1-ref.html
 == 372062-1.html 372062-1-ref.html
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -109,17 +109,18 @@ static nsIFrame*
 GetContainingBlockFor(nsIFrame* aFrame) {
   if (!aFrame) {
     return nsnull;
   }
   return nsHTMLReflowState::GetContainingBlockFor(aFrame);
 }
 
 nsComputedDOMStyle::nsComputedDOMStyle()
-  : mInner(this), mDocumentWeak(nsnull), mFrame(nsnull), mAppUnitsPerInch(0)
+  : mInner(this), mDocumentWeak(nsnull), mFrame(nsnull), mPresShell(nsnull),
+    mAppUnitsPerInch(0)
 {
 }
 
 
 nsComputedDOMStyle::~nsComputedDOMStyle()
 {
 }
 
@@ -303,27 +304,43 @@ nsComputedDOMStyle::GetPropertyCSSValue(
   NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE);
 
   // Flush _before_ getting the presshell, since that could create a new
   // presshell.  Also note that we want to flush the style on the document
   // we're computing style in, not on the document mContent is in -- the two
   // may be different.
   document->FlushPendingNotifications(Flush_Style);
 
-  nsIPresShell* presShell = document->GetPrimaryShell();
-  NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
-
-  mFrame = presShell->GetPrimaryFrameFor(mContent);
+  mPresShell = document->GetPrimaryShell();
+  NS_ENSURE_TRUE(mPresShell && mPresShell->GetPresContext(),
+                 NS_ERROR_NOT_AVAILABLE);
+
+  mFrame = mPresShell->GetPrimaryFrameFor(mContent);
   if (!mFrame || mPseudo) {
     // Need to resolve a style context
     mStyleContextHolder =
       nsInspectorCSSUtils::GetStyleContextForContent(mContent,
                                                      mPseudo,
-                                                     presShell);
+                                                     mPresShell);
     NS_ENSURE_TRUE(mStyleContextHolder, NS_ERROR_OUT_OF_MEMORY);
+  } else {
+    nsIAtom* type = mFrame->GetType();
+    nsIFrame* frame = mFrame;
+    if (type == nsGkAtoms::tableOuterFrame) {
+      // If the frame is an outer table frame then we should get the style
+      // from the inner table frame.
+      frame = frame->GetFirstChild(nsnull);
+      NS_ASSERTION(frame, "Outer table must have an inner");
+      NS_ASSERTION(!frame->GetNextSibling(),
+                   "Outer table frames should have just one child, the inner "
+                   "table");
+    }
+
+    mStyleContextHolder = frame->GetStyleContext();
+    NS_ASSERTION(mStyleContextHolder, "Frame without style context?");
   }
 
   nsresult rv = NS_OK;
 
   nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName);
 
   PRUint32 i = 0;
   PRUint32 length = 0;
@@ -343,16 +360,17 @@ nsComputedDOMStyle::GetPropertyCSSValue(
   }
 #endif
 
   if (NS_FAILED(rv)) {
     *aReturn = nsnull;
   }
 
   mFrame = nsnull;
+  mPresShell = nsnull;
 
   // Release the current style context for it should be re-resolved
   // whenever a frame is not available.
   mStyleContextHolder = nsnull;
 
   return rv;
 }
 
@@ -1471,21 +1489,18 @@ nsComputedDOMStyle::GetImageRegion(nsIDO
 
 nsresult
 nsComputedDOMStyle::GetLineHeight(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   nscoord lineHeight;
-  if (GetLineHeightCoord(lineHeight)) {
-    val->SetAppUnits(lineHeight);
-  } else {
-    SetValueToCoord(val, GetStyleText()->mLineHeight);
-  }
+  GetLineHeightCoord(lineHeight);
+  val->SetAppUnits(lineHeight);
 
   return CallQueryInterface(val, aValue);
 }
 
 nsresult
 nsComputedDOMStyle::GetVerticalAlign(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
@@ -2485,39 +2500,16 @@ nsComputedDOMStyle::FlushPendingReflows(
 {
   // Flush all pending notifications so that our frames are up to date
   nsCOMPtr<nsIDocument> document = mContent->GetDocument();
   if (document) {
     document->FlushPendingNotifications(Flush_Layout);
   }
 }
 
-const nsStyleStruct*
-nsComputedDOMStyle::GetStyleData(nsStyleStructID aSID)
-{
-  if (mFrame && !mPseudo) {
-    nsIAtom* type = mFrame->GetType();
-    nsIFrame* frame = mFrame;
-    if (type == nsGkAtoms::tableOuterFrame) {
-      // If the frame is an outer table frame then we should get the style
-      // from the inner table frame.
-      frame = frame->GetFirstChild(nsnull);
-      NS_ASSERTION(frame, "Outer table must have an inner");
-      NS_ASSERTION(!frame->GetNextSibling(),
-                   "Outer table frames should have just one child, the inner table");
-    }
-    return frame->GetStyleData(aSID);
-  }
-  
-  NS_ASSERTION(mStyleContextHolder,
-               "GetPropertyCSSValue should have resolved a style context");
-
-  return mStyleContextHolder->GetStyleData(aSID);
-}
-
 nsresult
 nsComputedDOMStyle::GetPaddingWidthFor(PRUint8 aSide, nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   if (!mFrame) {
     nsStyleCoord c;
@@ -2529,33 +2521,28 @@ nsComputedDOMStyle::GetPaddingWidthFor(P
   }
 
   return CallQueryInterface(val, aValue);
 }
 
 PRBool
 nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord)
 {
-  const nsStyleText* text = GetStyleText();
-  const nsStyleFont *font = GetStyleFont();
-  switch (text->mLineHeight.GetUnit()) {
-    case eStyleUnit_Coord:
-      aCoord = text->mLineHeight.GetCoordValue();
-      return PR_TRUE;
-    case eStyleUnit_Percent:
-      aCoord = nscoord(text->mLineHeight.GetPercentValue() * font->mSize);
-      return PR_TRUE;
-    case eStyleUnit_Factor:
-      aCoord = nscoord(text->mLineHeight.GetFactorValue() * font->mSize);
-      return PR_TRUE;
-    default:
-      break;
-  }
-
-  return PR_FALSE;
+  aCoord = nsHTMLReflowState::CalcLineHeight(mStyleContextHolder,
+                                             mPresShell->GetPresContext()->
+                                               DeviceContext());
+  // CalcLineHeight uses font->mFont.size, but we want to use
+  // font->mSize as the font size.  Adjust for that.  Also adjust for
+  // the text zoom, if any.
+  const nsStyleFont* font = GetStyleFont();
+  aCoord = NSToCoordRound((float(aCoord) *
+                           (float(font->mSize) / float(font->mFont.size))) /
+                          mPresShell->GetPresContext()->TextZoom());
+  
+  return PR_TRUE;
 }
 
 nsresult
 nsComputedDOMStyle::GetBorderColorsFor(PRUint8 aSide, nsIDOMCSSValue** aValue)
 {
   const nsStyleBorder *border = GetStyleBorder();
 
   if (border->mBorderColors) {
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -74,25 +74,21 @@ public:
 
   static void Shutdown();
 
 private:
   void FlushPendingReflows();
   
 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_)                  \
   const nsStyle##name_ * GetStyle##name_() {                            \
-    return NS_STATIC_CAST(const nsStyle##name_ *,                       \
-                          GetStyleData(eStyleStruct_##name_));          \
+    return mStyleContextHolder->GetStyle##name_();                      \
   }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
-  // This never returns null
-  const nsStyleStruct* GetStyleData(nsStyleStructID aSID);
-
   nsresult GetOffsetWidthFor(PRUint8 aSide, nsIDOMCSSValue** aValue);
 
   nsresult GetAbsoluteOffset(PRUint8 aSide, nsIDOMCSSValue** aValue);
 
   nsresult GetRelativeOffset(PRUint8 aSide, nsIDOMCSSValue** aValue);
 
   nsresult GetStaticOffset(PRUint8 aSide, nsIDOMCSSValue** aValue);
 
@@ -330,25 +326,31 @@ private:
 
   // We don't really have a good immutable representation of "presentation".
   // Given the way GetComputedStyle is currently used, we should just grab the
   // 0th presshell, if any, from the document.
   nsWeakPtr mDocumentWeak;
   nsCOMPtr<nsIContent> mContent;
 
   /*
-   * When a frame is unavailable, strong reference to the
-   * style context while we're accessing the data from it.
+   * Strong reference to the style context while we're accessing the data from
+   * it.  This can be either a style context we resolved ourselves or a style
+   * context we got from our frame.
    */
   nsRefPtr<nsStyleContext> mStyleContextHolder;
   nsCOMPtr<nsIAtom> mPseudo;
 
   /*
    * While computing style data, the primary frame for mContent.  Null
    * otherwise.
    */
   nsIFrame* mFrame;
+  /*
+   * While computing style data, the presshell we're working with.  Null
+   * otherwise.
+   */
+  nsIPresShell* mPresShell;
 
   PRInt32 mAppUnitsPerInch; /* For unit conversions */
 };
 
 #endif /* nsComputedDOMStyle_h__ */