Backing out fix for bug 392785 as per roc + mconnor.
authordmose@mozilla.org
Tue, 04 Dec 2007 15:32:08 -0800
changeset 8698 94fd02c2215c74e96a7c3b8f255c125d2e28e6b5
parent 8697 c46442f690438b44de0ec653992b0a487a42d0c7
child 8699 8e9e1de456ed17b2d31f5a000985a4f7d7f89bc9
push idunknown
push userunknown
push dateunknown
bugs392785
milestone1.9b2pre
Backing out fix for bug 392785 as per roc + mconnor.
gfx/public/nsIDeviceContext.h
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/nsPresContext.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsHTMLContainerFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsLineLayout.h
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/style/nsStyleStruct.cpp
layout/xul/base/src/nsTextBoxFrame.cpp
--- a/gfx/public/nsIDeviceContext.h
+++ b/gfx/public/nsIDeviceContext.h
@@ -163,20 +163,20 @@ typedef void * nsNativeDeviceContext;
 #ifdef NS_PRINT_PREVIEW
 const PRUint8 kUseAltDCFor_NONE            = 0x00; // Do not use the AltDC for anything
 const PRUint8 kUseAltDCFor_FONTMETRICS     = 0x01; // Use it for only getting the font metrics
 const PRUint8 kUseAltDCFor_CREATERC_REFLOW = 0x02; // Use when creating RenderingContexts for Reflow
 const PRUint8 kUseAltDCFor_CREATERC_PAINT  = 0x04; // Use when creating RenderingContexts for Painting
 const PRUint8 kUseAltDCFor_SURFACE_DIM     = 0x08; // Use it for getting the Surface Dimensions
 #endif
 
-// 92a1e76c-adbd-441e-aae6-243d6004e0ee
+// 4dd372b6-ef19-4995-a7ac-ba3efd3f656f
 #define NS_IDEVICE_CONTEXT_IID   \
-{ 0x92a1e76c, 0xadbd, 0x441e, \
- { 0xaa, 0xe6, 0x24, 0x3d, 0x60, 0x4, 0xe0, 0xee } }
+{ 0x4dd372b6, 0xef19, 0x4995, \
+ { 0xa7, 0xac, 0xba, 0x3e, 0xfd, 0x3f, 0x65, 0x6f } }
 
 //a cross platform way of specifying a native palette handle
 typedef void * nsPalette;
 
   //structure used to return information about a device's palette capabilities
   struct nsPaletteInfo {
      PRPackedBool  isPaletteDevice;
      PRUint16      sizePalette;  // number of entries in the palette
@@ -290,24 +290,17 @@ public:
 
   /**
    * Gets the number of app units in one device pixel; this number is usually
    * a factor of AppUnitsPerCSSPixel(), although that is not guaranteed.
    */
   PRInt32 AppUnitsPerDevPixel() const { return mAppUnitsPerDevPixel; }
 
   /**
-   * Convert device pixels which is used for gfx/thebes to nearest (rounded)
-   * app units
-   */
-  nscoord GfxUnitsToAppUnits(gfxFloat aGfxUnits) const
-  { return nscoord(NS_round(aGfxUnits * AppUnitsPerDevPixel())); }
-
-  /**
-   * Convert app units to device pixels which is used for gfx/thebes.
+   * Convert app units to device pixels which is used in gfx/thebes.
    */
   gfxFloat AppUnitsToGfxUnits(nscoord aAppUnits) const
   { return gfxFloat(aAppUnits) / AppUnitsPerDevPixel(); }
 
   /**
    * Gets the number of app units in one inch; this is the device's DPI
    * times AppUnitsPerDevPixel().
    */
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -4347,162 +4347,126 @@ nsCSSRendering::DrawTableBorderSegment(n
 
 void
 nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
                                     const nscolor aColor,
                                     const gfxPoint& aPt,
                                     const gfxSize& aLineSize,
                                     const gfxFloat aAscent,
                                     const gfxFloat aOffset,
+                                    const gfxFloat aPreferredHeight,
                                     const PRUint8 aDecoration,
                                     const PRUint8 aStyle,
                                     const PRBool aIsRTL)
 {
-  gfxRect rect =
-    GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
-                                  aDecoration, aStyle);
-  if (rect.IsEmpty())
+  if (aLineSize.width <= 0 || aLineSize.height <= 0 ||
+      aStyle == NS_STYLE_BORDER_STYLE_NONE)
     return;
 
-  gfxFloat lineHeight = PR_MAX(NS_round(aLineSize.height), 1.0);
   PRBool contextIsSaved = PR_FALSE;
+  gfxFloat totalHeight = aLineSize.height;
   switch (aStyle) {
     case NS_STYLE_BORDER_STYLE_SOLID:
-    case NS_STYLE_BORDER_STYLE_DOUBLE:
       break;
     case NS_STYLE_BORDER_STYLE_DASHED: {
       aGfxContext->Save();
       contextIsSaved = PR_TRUE;
-      gfxFloat dashWidth = lineHeight * DOT_LENGTH * DASH_LENGTH;
+      gfxFloat dashWidth = aLineSize.height * DOT_LENGTH * DASH_LENGTH;
       gfxFloat dash[2] = { dashWidth, dashWidth };
       aGfxContext->SetLineCap(gfxContext::LINE_CAP_BUTT);
       aGfxContext->SetDash(dash, 2, 0.0);
       break;
     }
     case NS_STYLE_BORDER_STYLE_DOTTED: {
       aGfxContext->Save();
       contextIsSaved = PR_TRUE;
-      gfxFloat dashWidth = lineHeight * DOT_LENGTH;
+      gfxFloat dashWidth = aLineSize.height * DOT_LENGTH;
       gfxFloat dash[2];
-      if (lineHeight > 2.0) {
+      if (aLineSize.height > 2.0) {
         dash[0] = 0.0;
         dash[1] = dashWidth * 2.0;
         aGfxContext->SetLineCap(gfxContext::LINE_CAP_ROUND);
       } else {
         dash[0] = dashWidth;
         dash[1] = dashWidth;
       }
       aGfxContext->SetDash(dash, 2, 0.0);
       break;
     }
+    case NS_STYLE_BORDER_STYLE_DOUBLE:
+      totalHeight *= 3.0;
+      break;
     default:
       NS_ERROR("Invalid style value!");
       return;
   }
 
+  gfxFloat offset = aOffset;
+  switch (aDecoration) {
+    case NS_STYLE_TEXT_DECORATION_UNDERLINE:
+      break;
+    case NS_STYLE_TEXT_DECORATION_OVERLINE:
+      // The offset includes the preferred size, we should remove it
+      offset += aPreferredHeight;
+      // the bottom of the decoration line should be aligned to the top of the
+      // text.
+      offset -= totalHeight;
+      break;
+    case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: {
+      // The offset includes the preferred size, we should remove it
+      offset += aPreferredHeight;
+      // the middle of the decoration line should be aligned to the middle of
+      // the original strike out offset.
+      offset -= PR_MAX(aPreferredHeight, (totalHeight / 2.0));
+      break;
+    }
+    default:
+      NS_ERROR("Invalid decoration value!");
+      if (contextIsSaved)
+        aGfxContext->Restore();
+      return;
+  }
+
+  // round to device pixels for suppressing the AA.
+  gfxFloat x = NS_round(aPt.x);
+  gfxFloat y = NS_round(aPt.y + aAscent) - NS_round(offset);
+  gfxFloat width = NS_round(aLineSize.width);
+  gfxFloat height = NS_round(aLineSize.height);
   // The y position should be set to the middle of the line.
-  rect.pos.y += lineHeight / 2;
+  y += height / 2;
 
   aGfxContext->SetColor(gfxRGBA(aColor));
-  aGfxContext->SetLineWidth(lineHeight);
+  aGfxContext->SetLineWidth(height);
   switch (aStyle) {
     case NS_STYLE_BORDER_STYLE_SOLID:
       aGfxContext->NewPath();
-      aGfxContext->MoveTo(rect.TopLeft());
-      aGfxContext->LineTo(rect.TopRight());
+      aGfxContext->MoveTo(gfxPoint(x, y));
+      aGfxContext->LineTo(gfxPoint(x + width, y));
       aGfxContext->Stroke();
       break;
     case NS_STYLE_BORDER_STYLE_DOUBLE:
       aGfxContext->NewPath();
-      aGfxContext->MoveTo(rect.TopLeft());
-      aGfxContext->LineTo(rect.TopRight());
-      rect.size.height -= lineHeight;
-      aGfxContext->MoveTo(rect.BottomLeft());
-      aGfxContext->LineTo(rect.BottomRight());
+      aGfxContext->MoveTo(gfxPoint(x, y));
+      aGfxContext->LineTo(gfxPoint(x + width, y));
+      aGfxContext->MoveTo(gfxPoint(x, y + height * 2.0));
+      aGfxContext->LineTo(gfxPoint(x + width, y + height * 2.0));
       aGfxContext->Stroke();
       break;
     case NS_STYLE_BORDER_STYLE_DOTTED:
     case NS_STYLE_BORDER_STYLE_DASHED:
       aGfxContext->NewPath();
       if (aIsRTL) {
-        aGfxContext->MoveTo(rect.TopRight());
-        aGfxContext->LineTo(rect.TopLeft());
+        aGfxContext->MoveTo(gfxPoint(x + width, y));
+        aGfxContext->LineTo(gfxPoint(x, y));
       } else {
-        aGfxContext->MoveTo(rect.TopLeft());
-        aGfxContext->LineTo(rect.TopRight());
+        aGfxContext->MoveTo(gfxPoint(x, y));
+        aGfxContext->LineTo(gfxPoint(x + width, y));
       }
       aGfxContext->Stroke();
       aGfxContext->Restore();
       contextIsSaved = PR_FALSE;
       break;
     default:
       NS_ERROR("Invalid style value!");
       break;
   }
   NS_ASSERTION(!contextIsSaved, "The gfxContext has been saved, but not restored!");
 }
-
-nsRect
-nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
-                                      const gfxSize& aLineSize,
-                                      const gfxFloat aAscent,
-                                      const gfxFloat aOffset,
-                                      const PRUint8 aDecoration,
-                                      const PRUint8 aStyle)
-{
-  NS_ASSERTION(aPresContext, "aPresContext is null");
-
-  gfxRect rect =
-    GetTextDecorationRectInternal(gfxPoint(0, 0), aLineSize, aAscent, aOffset,
-                                  aDecoration, aStyle);
-  // The rect values are already rounded to nearest device pixels.
-  nsRect r;
-  r.x = aPresContext->GfxUnitsToAppUnits(rect.X());
-  r.y = aPresContext->GfxUnitsToAppUnits(rect.Y());
-  r.width = aPresContext->GfxUnitsToAppUnits(rect.Width());
-  r.height = aPresContext->GfxUnitsToAppUnits(rect.Height());
-  return r;
-}
-
-gfxRect
-nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
-                                              const gfxSize& aLineSize,
-                                              const gfxFloat aAscent,
-                                              const gfxFloat aOffset,
-                                              const PRUint8 aDecoration,
-                                              const PRUint8 aStyle)
-{
-  gfxRect r;
-  r.pos.x = NS_round(aPt.x);
-  r.size.width = NS_round(aLineSize.width);
-
-  gfxFloat basesize = NS_round(aLineSize.height);
-  basesize = PR_MAX(basesize, 1.0);
-  r.size.height = basesize;
-  if (aStyle == NS_STYLE_BORDER_STYLE_DOUBLE) {
-    gfxFloat gap = NS_round(basesize / 2.0);
-    gap = PR_MAX(gap, 1.0);
-    r.size.height = basesize * 2.0 + gap;
-  } else {
-    r.size.height = basesize;
-  }
-
-  gfxFloat baseline = NS_round(aPt.y + aAscent);
-  gfxFloat offset = 0;
-  switch (aDecoration) {
-    case NS_STYLE_TEXT_DECORATION_UNDERLINE:
-      offset = NS_round(aOffset);
-      break;
-    case NS_STYLE_TEXT_DECORATION_OVERLINE:
-      offset = NS_round(aOffset - basesize + r.Height());
-      break;
-    case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: {
-      gfxFloat extra = NS_round(r.Height() / 2.0);
-      extra = PR_MAX(extra, basesize);
-      offset = NS_round(aOffset - basesize + extra);
-      break;
-    }
-    default:
-      NS_ERROR("Invalid decoration value!");
-  }
-  r.pos.y = baseline - NS_round(offset);
-  return r;
-}
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -36,17 +36,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* utility functions for drawing borders and backgrounds */
 
 #ifndef nsCSSRendering_h___
 #define nsCSSRendering_h___
 
 #include "nsIRenderingContext.h"
-#include "nsStyleConsts.h"
 #include "gfxContext.h"
 struct nsPoint;
 class nsStyleContext;
 class nsPresContext;
 
 class nsCSSRendering {
 public:
   /**
@@ -197,81 +196,53 @@ public:
    * aMapColor - color to evaluate
    * aIsPrinter - Is this a printing device
    * return - the transformed color
    */
   static nscolor TransformColor(nscolor  aMapColor,PRBool aNoBackGround);
 
   /**
    * Function for painting the decoration lines for the text.
-   * NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
-   *       not app units.
+   * NOTE: aPt, aLineSize, aAscent, aOffset and aPreferredHeight are non-rounded
+   *       device pixels, not app units.
    *   input:
    *     @param aGfxContext
    *     @param aColor            the color of the decoration line
    *     @param aPt               the top/left edge of the text
    *     @param aLineSize         the width and the height of the decoration
    *                              line
    *     @param aAscent           the ascent of the text
    *     @param aOffset           the offset of the decoration line from
    *                              the baseline of the text (if the value is
    *                              positive, the line is lifted up)
+   *     @param aPreferredHeight  the preferred size of the decoration line by
+   *                              the font of the text
    *     @param aDecoration       which line will be painted. The value can be
    *                              NS_STYLE_TEXT_DECORATION_UNDERLINE or
    *                              NS_STYLE_TEXT_DECORATION_OVERLINE or
    *                              NS_STYLE_TEXT_DECORATION_LINE_THROUGH.
    *     @param aStyle            the style of the decoration line. The value
    *                              can be NS_STYLE_BORDER_STYLE_SOLID or
    *                              NS_STYLE_BORDER_STYLE_DOTTED or
    *                              NS_STYLE_BORDER_STYLE_DASHED or
-   *                              NS_STYLE_BORDER_STYLE_DOUBLE.
+   *                              NS_STYLE_BORDER_STYLE_DOUBLE or
+   *                              NS_STYLE_BORDER_STYLE_NONE.
    *     @param aIsRTL            when the text is RTL, it is true.
    */
   static void PaintDecorationLine(gfxContext* aGfxContext,
                                   const nscolor aColor,
                                   const gfxPoint& aPt,
                                   const gfxSize& aLineSize,
                                   const gfxFloat aAscent,
                                   const gfxFloat aOffset,
+                                  const gfxFloat aPreferredSize,
                                   const PRUint8 aDecoration,
                                   const PRUint8 aStyle,
                                   const PRBool aIsRTL);
 
-  /**
-   * Function for getting the decoration line rect for the text.
-   * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels,
-   *       not app units.
-   *   input:
-   *     @param aPresContext
-   *     @param aLineSize         the width and the height of the decoration
-   *                              line
-   *     @param aAscent           the ascent of the text
-   *     @param aOffset           the offset of the decoration line from
-   *                              the baseline of the text (if the value is
-   *                              positive, the line is lifted up)
-   *     @param aDecoration       which line will be painted. The value can be
-   *                              NS_STYLE_TEXT_DECORATION_UNDERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_OVERLINE or
-   *                              NS_STYLE_TEXT_DECORATION_LINE_THROUGH.
-   *     @param aStyle            the style of the decoration line. The value
-   *                              can be NS_STYLE_BORDER_STYLE_SOLID or
-   *                              NS_STYLE_BORDER_STYLE_DOTTED or
-   *                              NS_STYLE_BORDER_STYLE_DASHED or
-   *                              NS_STYLE_BORDER_STYLE_DOUBLE.
-   *   output:
-   *     @return                  the decoration line rect for the input,
-   *                              the each values are app units.
-   */
-  static nsRect GetTextDecorationRect(nsPresContext* aPresContext,
-                                      const gfxSize& aLineSize,
-                                      const gfxFloat aAscent,
-                                      const gfxFloat aOffset,
-                                      const PRUint8 aDecoration,
-                                      const PRUint8 aStyle);
-
 protected:
 
   static void PaintBackgroundColor(nsPresContext* aPresContext,
                                    nsIRenderingContext& aRenderingContext,
                                    nsIFrame* aForFrame,
                                    const nsRect& aBgClipArea,
                                    const nsStyleBackground& aColor,
                                    const nsStyleBorder& aBorder,
@@ -295,18 +266,12 @@ protected:
                         nscoord aX1, nscoord aY1, nscoord aX2, nscoord aY2,
                         nsRect* aGap);
 
   static void FillPolygon (nsIRenderingContext& aContext, 
                            const nsPoint aPoints[],
                            PRInt32 aNumPoints,
                            nsRect* aGap);
 
-  static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt,
-                                               const gfxSize& aLineSize,
-                                               const gfxFloat aAscent,
-                                               const gfxFloat aOffset,
-                                               const PRUint8 aDecoration,
-                                               const PRUint8 aStyle);
 };
 
 
 #endif /* nsCSSRendering_h___ */
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -504,20 +504,16 @@ public:
   nscoord DevPixelsToAppUnits(PRInt32 aPixels) const
   { return NSIntPixelsToAppUnits(aPixels,
                                  mDeviceContext->AppUnitsPerDevPixel()); }
 
   PRInt32 AppUnitsToDevPixels(nscoord aAppUnits) const
   { return NSAppUnitsToIntPixels(aAppUnits,
                                  mDeviceContext->AppUnitsPerDevPixel()); }
 
-  // If there is a remainder, it is rounded to nearest app units.
-  nscoord GfxUnitsToAppUnits(gfxFloat aGfxUnits) const
-  { return mDeviceContext->GfxUnitsToAppUnits(aGfxUnits); }
-
   gfxFloat AppUnitsToGfxUnits(nscoord aAppUnits) const
   { return mDeviceContext->AppUnitsToGfxUnits(aAppUnits); }
 
   nscoord TwipsToAppUnits(PRInt32 aTwips) const
   { return NSToCoordRound(NS_TWIPS_TO_INCHES(aTwips) *
                           mDeviceContext->AppUnitsPerInch()); }
 
   PRInt32 AppUnitsToTwips(nscoord aTwips) const
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -3998,26 +3998,16 @@ nsBlockFrame::PlaceLine(nsBlockReflowSta
         bidiUtils->ReorderFrames(aLine->mFirstChild, aLine->GetChildCount());
       } // bidiUtils
     } // not visual mode
   } // bidi enabled
 #endif // IBMBIDI
 
   nsRect combinedArea;
   aLineLayout.RelativePositionFrames(combinedArea);  // XXXldb This returned width as -15, 2001-06-12, Bugzilla
-  if (aState.mPresContext->CompatibilityMode() != eCompatibility_NavQuirks) {
-    PRUint8 decorations;
-    nscolor underColor, overColor, strikeColor;
-    GetTextDecorations(aState.mPresContext, PR_TRUE, decorations,
-                       underColor, overColor, strikeColor);
-    if (decorations) {
-      nsLineLayout::CombineTextDecorations(aState.mPresContext, decorations,
-                                           this, combinedArea);
-    }
-  }
   aLine->SetCombinedArea(combinedArea);
   if (addedBullet) {
     aLineLayout.RemoveBulletFrame(mBullet);
   }
 
   // Inline lines do not have margins themselves; however they are
   // impacted by prior block margins. If this line ends up having some
   // height then we zero out the previous bottom margin value that was
@@ -5882,16 +5872,17 @@ nsBlockFrame::PaintTextDecorationLine(ns
     gfxPoint pt(PresContext()->AppUnitsToGfxUnits(start + aPt.x),
                 PresContext()->AppUnitsToGfxUnits(aLine->mBounds.y + aPt.y));
     gfxSize size(PresContext()->AppUnitsToGfxUnits(width),
                  PresContext()->AppUnitsToGfxUnits(aSize));
     nsCSSRendering::PaintDecorationLine(
       ctx, aColor, pt, size,
       PresContext()->AppUnitsToGfxUnits(aLine->GetAscent()),
       PresContext()->AppUnitsToGfxUnits(aOffset),
+      PresContext()->AppUnitsToGfxUnits(aSize),
       aDecoration, NS_STYLE_BORDER_STYLE_SOLID, isRTL);
   }
 }
 
 #ifdef DEBUG
 static void DebugOutputDrawLine(PRInt32 aDepth, nsLineBox* aLine, PRBool aDrawn) {
   if (nsBlockFrame::gNoisyDamageRepair) {
     nsFrame::IndentBy(stdout, aDepth+1);
--- a/layout/generic/nsHTMLContainerFrame.cpp
+++ b/layout/generic/nsHTMLContainerFrame.cpp
@@ -80,17 +80,16 @@ public:
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayTextDecoration() {
     MOZ_COUNT_DTOR(nsDisplayTextDecoration);
   }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
      const nsRect& aDirtyRect);
-  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
   NS_DISPLAY_DECL_NAME("TextDecoration")
 private:
   nsLineBox*            mLine;
   nscolor               mColor;
   PRUint8               mDecoration;
 };
 
 void
@@ -118,22 +117,16 @@ nsDisplayTextDecoration::Paint(nsDisplay
     }
   } else {
     fm->GetStrikeout(offset, size);
     f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor,
                                offset, ascent, size, mDecoration);
   }
 }
 
-nsRect
-nsDisplayTextDecoration::GetBounds(nsDisplayListBuilder* aBuilder)
-{
-  return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
-}
-
 nsresult
 nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
                                              nsDisplayList* aBelowTextDecorations,
                                              nsDisplayList* aAboveTextDecorations,
                                              nsLineBox* aLine)
 {
   if (eCompatibility_NavQuirks == PresContext()->CompatibilityMode())
     return NS_OK;
@@ -190,17 +183,17 @@ nsHTMLContainerFrame::BuildDisplayList(n
                                        const nsDisplayListSet& aLists) {
   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return DisplayTextDecorationsAndChildren(aBuilder, aDirtyRect, aLists);
 }
 
 static PRBool 
-HasTextFrameDescendantOrInFlow(nsIFrame* aFrame);
+HasTextFrameDescendantOrInFlow(nsPresContext* aPresContext, nsIFrame* aFrame);
 
 /*virtual*/ void
 nsHTMLContainerFrame::PaintTextDecorationLine(
                    nsIRenderingContext& aRenderingContext, 
                    nsPoint aPt,
                    nsLineBox* aLine,
                    nscolor aColor, 
                    nscoord aOffset, 
@@ -223,16 +216,17 @@ nsHTMLContainerFrame::PaintTextDecoratio
     aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
   gfxPoint pt(PresContext()->AppUnitsToGfxUnits(bp.left + aPt.x),
               PresContext()->AppUnitsToGfxUnits(bp.top + aPt.y));
   gfxSize size(PresContext()->AppUnitsToGfxUnits(innerWidth),
                PresContext()->AppUnitsToGfxUnits(aSize));
   nsCSSRendering::PaintDecorationLine(
     ctx, aColor, pt, size, PresContext()->AppUnitsToGfxUnits(aAscent),
     PresContext()->AppUnitsToGfxUnits(aOffset),
+    PresContext()->AppUnitsToGfxUnits(aSize),
     aDecoration, NS_STYLE_BORDER_STYLE_SOLID, isRTL);
 }
 
 void
 nsHTMLContainerFrame::GetTextDecorations(nsPresContext* aPresContext, 
                                          PRBool aIsBlock,
                                          PRUint8& aDecorations,
                                          nscolor& aUnderColor, 
@@ -298,48 +292,48 @@ nsHTMLContainerFrame::GetTextDecorations
           aDecorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
         }
       }
     }
   }
   
   if (aDecorations) {
     // If this frame contains no text, we're required to ignore this property
-    if (!HasTextFrameDescendantOrInFlow(this)) {
+    if (!HasTextFrameDescendantOrInFlow(aPresContext, this)) {
       aDecorations = NS_STYLE_TEXT_DECORATION_NONE;
     }
   }
 }
 
 static PRBool 
-HasTextFrameDescendant(nsIFrame* aParent)
+HasTextFrameDescendant(nsPresContext* aPresContext, nsIFrame* aParent)
 {
   for (nsIFrame* kid = aParent->GetFirstChild(nsnull); kid;
        kid = kid->GetNextSibling())
   {
     if (kid->GetType() == nsGkAtoms::textFrame) {
       // This is only a candidate. We need to determine if this text
       // frame is empty, as in containing only (non-pre) whitespace.
       // See bug 20163.
       if (!kid->IsEmpty()) {
         return PR_TRUE;
       }
     }
-    if (HasTextFrameDescendant(kid)) {
+    if (HasTextFrameDescendant(aPresContext, kid)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 static PRBool 
-HasTextFrameDescendantOrInFlow(nsIFrame* aFrame)
+HasTextFrameDescendantOrInFlow(nsPresContext* aPresContext, nsIFrame* aFrame)
 {
   for (nsIFrame *f = aFrame->GetFirstInFlow(); f; f = f->GetNextInFlow()) {
-    if (HasTextFrameDescendant(f))
+    if (HasTextFrameDescendant(aPresContext, f))
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 /**
  * Create a next-in-flow for aFrame. Will return the newly created
  * frame in aNextInFlowResult <b>if and only if</b> a new frame is
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -563,34 +563,35 @@ nsInlineFrame::ReflowFrames(nsPresContex
     // 4.4 (you will have to read between the lines to really see
     // it).
     //
     // The height of our box is the sum of our font size plus the top
     // and bottom border and padding. The height of children do not
     // affect our height.
     fm->GetMaxAscent(aMetrics.ascent);
     fm->GetHeight(aMetrics.height);
-    // Include the text-decoration lines to the height for readable.
+    // Include the text-decoration lines to the height.
+    // Currently, only underline is overflowable.
     nscoord offset, size;
     fm->GetUnderline(offset, size);
     nscoord ascentAndUnderline =
       aPresContext->RoundAppUnitsToNearestDevPixels(aMetrics.ascent - offset) +
       aPresContext->RoundAppUnitsToNearestDevPixels(size);
     if (ascentAndUnderline > aMetrics.height)
       aMetrics.height = ascentAndUnderline;
   } else {
     NS_WARNING("Cannot get font metrics - defaulting sizes to 0");
     aMetrics.ascent = aMetrics.height = 0;
   }
   aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
   aMetrics.height += aReflowState.mComputedBorderPadding.top +
     aReflowState.mComputedBorderPadding.bottom;
 
   // For now our overflow area is zero. The real value will be
-  // computed in |nsLineLayout::RelativePositionFrames|.
+  // computed during vertical alignment of the line we are on.
   aMetrics.mOverflowArea.SetRect(0, 0, 0, 0);
 
 #ifdef NOISY_FINAL_SIZE
   ListTag(stdout);
   printf(": metrics=%d,%d ascent=%d\n",
          aMetrics.width, aMetrics.height, aMetrics.ascent);
 #endif
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -61,17 +61,16 @@
 #include "nsPlaceholderFrame.h"
 #include "nsIDocument.h"
 #include "nsIHTMLDocument.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "nsBidiUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsTextFrame.h"
-#include "nsCSSRendering.h"
 
 #ifdef DEBUG
 #undef  NOISY_HORIZONTAL_ALIGN
 #undef  NOISY_VERTICAL_ALIGN
 #undef  REALLY_NOISY_VERTICAL_ALIGN
 #undef  NOISY_REFLOW
 #undef  REALLY_NOISY_REFLOW
 #undef  NOISY_PUSHING
@@ -2620,18 +2619,16 @@ nsLineLayout::RelativePositionFrames(Per
     combinedAreaResult.x = psd->mLeftEdge;
     // If this turns out to be negative, the rect will be treated as empty.
     // Which is just fine.
     combinedAreaResult.width = psd->mX - combinedAreaResult.x;
     combinedAreaResult.y = mTopEdge;
     combinedAreaResult.height = mFinalLineHeight;
   }
 
-  PRBool isStandardsMode =
-    mPresContext->CompatibilityMode() != eCompatibility_NavQuirks;
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     nsPoint origin = nsPoint(pfd->mBounds.x, pfd->mBounds.y);
     nsIFrame* frame = pfd->mFrame;
 
     // Adjust the origin of the frame
     if (pfd->GetFlag(PFD_RELATIVEPOS)) {
       // right and bottom are handled by
       // nsHTMLReflowState::ComputeRelativeOffsets
@@ -2650,25 +2647,16 @@ nsLineLayout::RelativePositionFrames(Per
                                                  NS_FRAME_NO_SIZE_VIEW);
 
     // Note: the combined area of a child is in its coordinate
     // system. We adjust the childs combined area into our coordinate
     // system before computing the aggregated value by adding in
     // <b>x</b> and <b>y</b> which were computed above.
     nsRect r;
     if (pfd->mSpan) {
-      if (isStandardsMode) {
-        // Combine the text decoration area for inline elements of standards
-        // mode
-        PRUint8 decorations = frame->GetStyleTextReset()->mTextDecoration;
-        if (decorations) {
-          nsLineLayout::CombineTextDecorations(mPresContext, decorations,
-                          frame, pfd->mSpan->mFrame->mCombinedArea);
-        }
-      }
       // Compute a new combined area for the child span before
       // aggregating it into our combined area.
       RelativePositionFrames(pfd->mSpan, r);
     } else {
       r = pfd->mCombinedArea;
       if (pfd->GetFlag(PFD_ISTEXTFRAME)) {
         if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW)) {
           nsTextFrame* f = static_cast<nsTextFrame*>(frame);
@@ -2702,65 +2690,8 @@ nsLineLayout::RelativePositionFrames(Per
   // NS_FRAME_OUTSIDE_CHILDREN bit..
   if (psd->mFrame) {
     PerFrameData* spanPFD = psd->mFrame;
     nsIFrame* frame = spanPFD->mFrame;
     frame->FinishAndStoreOverflow(&combinedAreaResult, frame->GetSize());
   }
   aCombinedArea = combinedAreaResult;
 }
-
-void
-nsLineLayout::CombineTextDecorations(nsPresContext* aPresContext,
-                                     PRUint8 aDecorations,
-                                     nsIFrame* aFrame,
-                                     nsRect& aCombinedArea,
-                                     nscoord aAscentOverride,
-                                     float aUnderlineSizeRatio)
-{
-  if (!(aDecorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
-                        NS_STYLE_TEXT_DECORATION_OVERLINE |
-                        NS_STYLE_TEXT_DECORATION_LINE_THROUGH)))
-    return;
-
-  nsCOMPtr<nsIFontMetrics> fm;
-  nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
-  if (aAscentOverride == 0)
-    fm->GetMaxAscent(aAscentOverride);
-  gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(aAscentOverride);
-  nsRect decorationArea;
-  if (aDecorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
-                      NS_STYLE_TEXT_DECORATION_OVERLINE)) {
-    nscoord offsetCoord, sizeCoord;
-    fm->GetUnderline(offsetCoord, sizeCoord);
-    gfxSize size(aPresContext->AppUnitsToGfxUnits(aCombinedArea.width),
-                 aPresContext->AppUnitsToGfxUnits(sizeCoord));
-    if (aDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE) {
-      decorationArea =
-        nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
-                          ascent, NS_STYLE_TEXT_DECORATION_OVERLINE,
-                          NS_STYLE_BORDER_STYLE_SOLID);
-      aCombinedArea.UnionRect(aCombinedArea, decorationArea);
-    }
-    if (aDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
-      aUnderlineSizeRatio = PR_MAX(aUnderlineSizeRatio, 1.0);
-      size.height *= aUnderlineSizeRatio;
-      gfxFloat offset = aPresContext->AppUnitsToGfxUnits(offsetCoord);
-      decorationArea =
-        nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
-                          offset, NS_STYLE_TEXT_DECORATION_UNDERLINE,
-                          NS_STYLE_BORDER_STYLE_SOLID);
-      aCombinedArea.UnionRect(aCombinedArea, decorationArea);
-    }
-  }
-  if (aDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
-    nscoord offsetCoord, sizeCoord;
-    fm->GetStrikeout(offsetCoord, sizeCoord);
-    gfxSize size(aPresContext->AppUnitsToGfxUnits(aCombinedArea.width),
-                 aPresContext->AppUnitsToGfxUnits(sizeCoord));
-    gfxFloat offset = aPresContext->AppUnitsToGfxUnits(offsetCoord);
-    decorationArea =
-      nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
-                        offset, NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
-                        NS_STYLE_BORDER_STYLE_SOLID);
-    aCombinedArea.UnionRect(aCombinedArea, decorationArea);
-  }
-}
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -127,22 +127,16 @@ public:
 
   /**
    * Handle all the relative positioning in the line, compute the
    * combined area (== overflow area) for the line, and handle view
    * sizing/positioning and the setting of NS_FRAME_OUTSIDE_CHILDREN.
    */
   void RelativePositionFrames(nsRect& aCombinedArea);
 
-  static void CombineTextDecorations(nsPresContext* aPresContext,
-                                     PRUint8 aDecorations,
-                                     nsIFrame* aFrame,
-                                     nsRect& aCombinedArea,
-                                     nscoord aAscentOverride = 0,
-                                     float aUnderlineSizeRatio = 1.0f);
   //----------------------------------------
 
   // Supporting methods and data for flags
 protected:
 #define LL_FIRSTLETTERSTYLEOK          0x00000008
 #define LL_ISTOPOFPAGE                 0x00000010
 #define LL_UPDATEDBAND                 0x00000020
 #define LL_IMPACTEDBYFLOATS            0x00000040
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -354,43 +354,11 @@ protected:
 
   SelectionDetails* GetSelectionDetails();
   
   void AdjustSelectionPointsForBidi(SelectionDetails *sdptr,
                                     PRInt32 textLength,
                                     PRBool isRTLChars,
                                     PRBool isOddLevel,
                                     PRBool isBidiSystem);
-
-  void UnionTextDecorationOverflow(nsPresContext* aPresContext,
-                                   const gfxTextRun::Metrics& aTextMetrics,
-                                   nsRect* aOverflowRect);
-
-  struct TextDecorations {
-    PRUint8 mDecorations;
-    nscolor mOverColor;
-    nscolor mUnderColor;
-    nscolor mStrikeColor;
-
-    TextDecorations() :
-      mDecorations(0), mOverColor(NS_RGB(0, 0, 0)),
-      mUnderColor(NS_RGB(0, 0, 0)), mStrikeColor(NS_RGB(0, 0, 0))
-    { }
-
-    PRBool HasDecorationlines() {
-      return !!(mDecorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
-                                NS_STYLE_TEXT_DECORATION_OVERLINE |
-                                NS_STYLE_TEXT_DECORATION_LINE_THROUGH));
-    }
-    PRBool HasUnderline() {
-      return !!(mDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE);
-    }
-    PRBool HasOverline() {
-      return !!(mDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE);
-    }
-    PRBool HasStrikeout() {
-      return !!(mDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH);
-    }
-  };
-  TextDecorations GetTextDecorations(nsPresContext* aPresContext);
 };
 
 #endif
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -3556,135 +3556,110 @@ FillClippedRect(gfxContext* aCtx, nsPres
   aCtx->NewPath();
   // pixel-snap
   aCtx->Rectangle(gfxRect(r.X() / app, r.Y() / app,
                           r.Width() / app, r.Height() / app), PR_TRUE);
   aCtx->SetColor(gfxRGBA(aColor));
   aCtx->Fill();
 }
 
-nsTextFrame::TextDecorations
-nsTextFrame::GetTextDecorations(nsPresContext* aPresContext)
-{
-  TextDecorations decorations;
-
+void 
+nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
+                                  const gfxPoint& aFramePt,
+                                  const gfxPoint& aTextBaselinePt,
+                                  nsTextPaintStyle& aTextPaintStyle,
+                                  PropertyProvider& aProvider)
+{
   // Quirks mode text decoration are rendered by children; see bug 1777
   // In non-quirks mode, nsHTMLContainer::Paint and nsBlockFrame::Paint
   // does the painting of text decorations.
-  if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode())
-    return decorations;
+  if (eCompatibility_NavQuirks != aTextPaintStyle.PresContext()->CompatibilityMode())
+    return;
 
   PRBool useOverride = PR_FALSE;
   nscolor overrideColor;
 
+  PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE;
   // A mask of all possible decorations.
   PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_UNDERLINE | 
                       NS_STYLE_TEXT_DECORATION_OVERLINE |
-                      NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
-
-  for (nsStyleContext* context = GetStyleContext();
-       decorMask && context && context->HasTextDecorations();
-       context = context->GetParent()) {
+                      NS_STYLE_TEXT_DECORATION_LINE_THROUGH;    
+  nscolor overColor, underColor, strikeColor;
+  nsStyleContext* context = GetStyleContext();
+  PRBool hasDecorations = context->HasTextDecorations();
+
+  while (hasDecorations) {
     const nsStyleTextReset* styleText = context->GetStyleTextReset();
     if (!useOverride && 
         (NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL & styleText->mTextDecoration)) {
       // This handles the <a href="blah.html"><font color="green">La 
       // la la</font></a> case. The link underline should be green.
       useOverride = PR_TRUE;
-      overrideColor = context->GetStyleColor()->mColor;
+      overrideColor = context->GetStyleColor()->mColor;          
     }
 
     PRUint8 useDecorations = decorMask & styleText->mTextDecoration;
     if (useDecorations) {// a decoration defined here
       nscolor color = context->GetStyleColor()->mColor;
   
       if (NS_STYLE_TEXT_DECORATION_UNDERLINE & useDecorations) {
-        decorations.mUnderColor = useOverride ? overrideColor : color;
+        underColor = useOverride ? overrideColor : color;
         decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
+        decorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
       }
       if (NS_STYLE_TEXT_DECORATION_OVERLINE & useDecorations) {
-        decorations.mOverColor = useOverride ? overrideColor : color;
+        overColor = useOverride ? overrideColor : color;
         decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_OVERLINE;
+        decorations |= NS_STYLE_TEXT_DECORATION_OVERLINE;
       }
       if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & useDecorations) {
-        decorations.mStrikeColor = useOverride ? overrideColor : color;
+        strikeColor = useOverride ? overrideColor : color;
         decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
+        decorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
       }
     }
-  }
-
-  return decorations;
-}
-
-void
-nsTextFrame::UnionTextDecorationOverflow(
-               nsPresContext* aPresContext,
-               const gfxTextRun::Metrics& aTextMetrics,
-               nsRect* aOverflowRect)
-{
-  NS_ASSERTION(mTextRun, "mTextRun is null");
-  nsRect rect;
-  TextDecorations decorations = GetTextDecorations(aPresContext);
-  float ratio = 1.0f;
-  // Note that we need to add underline area when this frame has selection for
-  // spellchecking and IME.
-  if (mState & NS_FRAME_SELECTED_CONTENT) {
-    nsILookAndFeel* look = aPresContext->LookAndFeel();
-    look->GetMetric(nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize,
-                    ratio);
-    decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
-  }
-  nsLineLayout::CombineTextDecorations(aPresContext, decorations.mDecorations,
-                  this, *aOverflowRect, nscoord(NS_round(aTextMetrics.mAscent)),
-                  ratio);
-}
-
-void 
-nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
-                                  const gfxPoint& aFramePt,
-                                  const gfxPoint& aTextBaselinePt,
-                                  nsTextPaintStyle& aTextPaintStyle,
-                                  PropertyProvider& aProvider)
-{
-  TextDecorations decorations =
-    GetTextDecorations(aTextPaintStyle.PresContext());
-  if (!decorations.HasDecorationlines())
+    if (0 == decorMask)
+      break;
+    context = context->GetParent();
+    if (!context)
+      break;
+    hasDecorations = context->HasTextDecorations();
+  }
+
+  if (!decorations)
     return;
 
   gfxFont::Metrics fontMetrics = GetFontMetrics(aProvider.GetFontGroup());
   gfxFloat app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
 
   // XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint?
   gfxPoint pt(aFramePt.x / app, (aTextBaselinePt.y - mAscent) / app);
   gfxSize size(GetRect().width / app, 0);
   gfxFloat ascent = gfxFloat(mAscent) / app;
 
-  if (decorations.HasOverline()) {
+  if (decorations & NS_FONT_DECORATION_OVERLINE) {
     size.height = fontMetrics.underlineSize;
     nsCSSRendering::PaintDecorationLine(
-      aCtx, decorations.mOverColor, pt, size, ascent, ascent,
+      aCtx, overColor, pt, size, ascent, ascent, size.height,
       NS_STYLE_TEXT_DECORATION_OVERLINE, NS_STYLE_BORDER_STYLE_SOLID,
       mTextRun->IsRightToLeft());
   }
-  if (decorations.HasUnderline()) {
+  if (decorations & NS_FONT_DECORATION_UNDERLINE) {
     size.height = fontMetrics.underlineSize;
     gfxFloat offset = fontMetrics.underlineOffset;
     nsCSSRendering::PaintDecorationLine(
-      aCtx, decorations.mUnderColor, pt, size, ascent, offset,
+      aCtx, underColor, pt, size, ascent, offset, size.height,
       NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID,
       mTextRun->IsRightToLeft());
   }
-  if (decorations.HasStrikeout()) {
+  if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
     size.height = fontMetrics.strikeoutSize;
     gfxFloat offset = fontMetrics.strikeoutOffset;
     nsCSSRendering::PaintDecorationLine(
-      aCtx, decorations.mStrikeColor, pt, size, ascent, offset,
+      aCtx, strikeColor, pt, size, ascent, offset, size.height,
       NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID,
       mTextRun->IsRightToLeft());
   }
 }
 
 // Make sure this stays in sync with DrawSelectionDecorations below
 static const SelectionType SelectionTypesWithDecorations =
   nsISelectionController::SELECTION_SPELLCHECK |
@@ -3702,17 +3677,17 @@ static void DrawIMEUnderline(gfxContext*
   PRUint8 style;
   if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize, &style))
     return;
 
   gfxFloat actualSize = relativeSize * aSize;
   gfxFloat width = PR_MAX(0, aWidth - 2.0 * aSize);
   gfxPoint pt(aPt.x + 1.0, aPt.y);
   nsCSSRendering::PaintDecorationLine(
-    aContext, color, pt, gfxSize(width, actualSize), aAscent, aOffset,
+    aContext, color, pt, gfxSize(width, actualSize), aAscent, aOffset, aSize,
     NS_STYLE_TEXT_DECORATION_UNDERLINE, style, aIsRTL);
 }
 
 /**
  * This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
  * drawing text decoration for selections.
  */
 static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
@@ -3720,17 +3695,17 @@ static void DrawSelectionDecorations(gfx
     gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics, PRBool aIsRTL)
 {
   gfxSize size(aWidth, aFontMetrics.underlineSize);
 
   switch (aType) {
     case nsISelectionController::SELECTION_SPELLCHECK: {
       nsCSSRendering::PaintDecorationLine(
         aContext, NS_RGB(255,0,0),
-        aPt, size, aAscent, aFontMetrics.underlineOffset,
+        aPt, size, aAscent, aFontMetrics.underlineOffset, size.height,
         NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_DOTTED,
         aIsRTL);
       break;
     }
 
     case nsISelectionController::SELECTION_IME_RAWINPUT:
       DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput,
                        aTextPaintStyle, aPt, aWidth, aAscent, size.height,
@@ -4348,43 +4323,28 @@ nsTextFrame::SetSelected(nsPresContext* 
       found = PR_TRUE;
     }
   }
   else {
     // null range means the whole thing
     found = PR_TRUE;
   }
 
- nsFrameState oldState = mState;
   if ( aSelected )
     AddStateBits(NS_FRAME_SELECTED_CONTENT);
   else
   { //we need to see if any other selection is available.
     SelectionDetails *details = GetSelectionDetails();
     if (!details) {
       RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
     } else {
       DestroySelectionDetails(details);
     }
   }
   if (found) {
-    // If the selection state is changed, we need to reflow to recompute
-    // the overflow area for underline of spellchecking or IME. However, if
-    // the non-selected text already has underline, we don't need to reflow.
-    // And also when the IME underline is thicker than normal underline.
-    nsILookAndFeel* look = aPresContext->LookAndFeel();
-    float ratio;
-    look->GetMetric(nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize,
-                    ratio);
-    if (oldState != mState &&
-        (ratio > 1.0 || !GetTextDecorations(aPresContext).HasUnderline())) {
-      PresContext()->PresShell()->FrameNeedsReflow(this,
-                                                   nsIPresShell::eStyleChange,
-                                                   NS_FRAME_IS_DIRTY);
-    }
     // Selection might change anything. Invalidate the overflow area.
     Invalidate(GetOverflowRect(), PR_FALSE);
   }
   if (aSpread == eSpreadDown)
   {
     nsIFrame* frame = GetPrevContinuation();
     while(frame){
       frame->SetSelected(aPresContext, aRange,aSelected,eSpreadNone);
@@ -5497,19 +5457,16 @@ nsTextFrame::Reflow(nsPresContext*      
   mAscent = aMetrics.ascent;
 
   // Handle text that runs outside its normal bounds.
   nsRect boundingBox =
     ConvertGfxRectOutward(textMetrics.mBoundingBox + gfxPoint(0, textMetrics.mAscent));
   aMetrics.mOverflowArea.UnionRect(boundingBox,
                                    nsRect(0, 0, aMetrics.width, aMetrics.height));
 
-  UnionTextDecorationOverflow(aPresContext, textMetrics,
-                              &aMetrics.mOverflowArea);
-
   /////////////////////////////////////////////////////////////////////
   // Clean up, update state
   /////////////////////////////////////////////////////////////////////
 
   // If all our characters are discarded or collapsed, then trimmable width
   // from the last textframe should be preserved. Otherwise the trimmable width
   // from this textframe overrides. (Currently in CSS trimmable width can be
   // at most one space so there's no way for trimmable width from a previous
@@ -5717,19 +5674,16 @@ nsTextFrame::RecomputeOverflowRect()
     mTextRun->MeasureText(provider.GetStart().GetSkippedOffset(),
                           ComputeTransformedLength(provider), PR_FALSE, nsnull,
                           &provider);
 
   nsRect boundingBox =
     ConvertGfxRectOutward(textMetrics.mBoundingBox + gfxPoint(0, textMetrics.mAscent));
   boundingBox.UnionRect(boundingBox,
                         nsRect(nsPoint(0,0), GetSize()));
-
-  UnionTextDecorationOverflow(PresContext(), textMetrics, &boundingBox);
-
   return boundingBox;
 }
 
 static PRUnichar TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun,
                                PRUint32 aSkippedOffset, PRUnichar aChar)
 {
   if (aChar == '\n' || aChar == '\r') {
     return aStyle->WhiteSpaceIsSignificant() ? aChar : ' ';
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1507,20 +1507,28 @@ nsStyleTextReset::nsStyleTextReset(const
 { 
   memcpy((nsStyleTextReset*)this, &aSource, sizeof(nsStyleTextReset));
 }
 
 nsStyleTextReset::~nsStyleTextReset(void) { }
 
 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
 {
-  if (mVerticalAlign == aOther.mVerticalAlign &&
-      mUnicodeBidi == aOther.mUnicodeBidi &&
-      mTextDecoration == aOther.mTextDecoration)
+  if (mVerticalAlign == aOther.mVerticalAlign
+      && mUnicodeBidi == aOther.mUnicodeBidi) {
+    if (mTextDecoration != aOther.mTextDecoration) {
+      // Reflow for blink changes, repaint for others
+      return
+        (mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ==
+        (aOther.mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ?
+          NS_STYLE_HINT_VISUAL : NS_STYLE_HINT_REFLOW;
+    }
+    
     return NS_STYLE_HINT_NONE;
+  }
   return NS_STYLE_HINT_REFLOW;
 }
 
 #ifdef DEBUG
 /* static */
 nsChangeHint nsStyleTextReset::MaxDifference()
 {
   return NS_STYLE_HINT_REFLOW;
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -460,36 +460,39 @@ nsTextBoxFrame::PaintTitle(nsIRenderingC
     if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) {
       fontMet->GetUnderline(offset, size);
       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
       if (decorations & NS_FONT_DECORATION_OVERLINE) {
         nsCSSRendering::PaintDecorationLine(ctx, overColor,
                                             pt, gfxSize(width, sizePixel),
                                             ascentPixel, ascentPixel,
+                                            sizePixel,
                                             NS_STYLE_TEXT_DECORATION_OVERLINE,
                                             NS_STYLE_BORDER_STYLE_SOLID,
                                             isRTL);
       }
       if (decorations & NS_FONT_DECORATION_UNDERLINE) {
         nsCSSRendering::PaintDecorationLine(ctx, underColor,
                                             pt, gfxSize(width, sizePixel),
                                             ascentPixel, offsetPixel,
+                                            sizePixel,
                                             NS_STYLE_TEXT_DECORATION_UNDERLINE,
                                             NS_STYLE_BORDER_STYLE_SOLID,
                                             isRTL);
       }
     }
     if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
       fontMet->GetStrikeout(offset, size);
       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
       nsCSSRendering::PaintDecorationLine(ctx, underColor,
                                           pt, gfxSize(width, sizePixel),
                                           ascentPixel, offsetPixel,
+                                          sizePixel,
                                           NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
                                           NS_STYLE_BORDER_STYLE_SOLID,
                                           isRTL);
     }
 
     aRenderingContext.SetFont(fontMet);
 
     CalculateUnderline(aRenderingContext);