Bug 647421 -moz-text-decoration-color and -moz-text-decoration-style should be reset by text-decoration r=dbaron, sr=bzbarsky
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 23 Apr 2011 14:16:41 +0900
changeset 68461 135b8bba35afc71bf411a713fb826f22986156d1
parent 68460 6c66c546fb048c90ff0af1672da62b553372d707
child 68462 0cd3666fd5c9f771114d4ccc1dec2682de6f2fbf
push idunknown
push userunknown
push dateunknown
reviewersdbaron, bzbarsky
bugs647421
milestone6.0a1
Bug 647421 -moz-text-decoration-color and -moz-text-decoration-style should be reset by text-decoration r=dbaron, sr=bzbarsky
content/html/content/src/nsHTMLFontElement.cpp
content/smil/nsSMILCSSProperty.cpp
dom/interfaces/css/nsIDOMCSS2Properties.idl
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/nsStyleConsts.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsHTMLContainerFrame.cpp
layout/generic/nsHTMLContainerFrame.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/reftests/text-decoration/decoration-color-quirks-ref.html
layout/reftests/text-decoration/decoration-color-quirks.html
layout/reftests/text-decoration/decoration-color-standards-ref.html
layout/reftests/text-decoration/decoration-color-standards.html
layout/reftests/text-decoration/decoration-style-quirks-ref.html
layout/reftests/text-decoration/decoration-style-quirks.html
layout/reftests/text-decoration/decoration-style-standards-ref.html
layout/reftests/text-decoration/decoration-style-standards.html
layout/style/Declaration.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/xul/base/src/nsTextBoxFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
--- a/content/html/content/src/nsHTMLFontElement.cpp
+++ b/content/html/content/src/nsHTMLFontElement.cpp
@@ -236,23 +236,23 @@ MapAttributesIntoRule(const nsMappedAttr
       nscolor color;
       if (value && value->GetColorValue(color)) {
         colorValue->SetColorValue(color);
       }
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TextReset)) {
     // Make <a><font color="red">text</font></a> give the text a red underline
-    // in quirks mode.  The NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL flag only
+    // in quirks mode.  The NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL flag only
     // affects quirks mode rendering.
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
     nscolor color;
     if (value && value->GetColorValue(color)) {
-      nsCSSValue* decoration = aData->ValueForTextDecoration();
-      PRInt32 newValue = NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL;
+      nsCSSValue* decoration = aData->ValueForTextDecorationLine();
+      PRInt32 newValue = NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
       if (decoration->GetUnit() == eCSSUnit_Enumerated) {
         newValue |= decoration->GetIntValue();
       }
       decoration->SetIntValue(newValue, eCSSUnit_Enumerated);
     }
   }
 
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
--- a/content/smil/nsSMILCSSProperty.cpp
+++ b/content/smil/nsSMILCSSProperty.cpp
@@ -268,17 +268,19 @@ nsSMILCSSProperty::IsPropertyAnimatable(
     case eCSSProperty_stroke_dasharray:
     case eCSSProperty_stroke_dashoffset:
     case eCSSProperty_stroke_linecap:
     case eCSSProperty_stroke_linejoin:
     case eCSSProperty_stroke_miterlimit:
     case eCSSProperty_stroke_opacity:
     case eCSSProperty_stroke_width:
     case eCSSProperty_text_anchor:
+    case eCSSProperty_text_blink:
     case eCSSProperty_text_decoration:
+    case eCSSProperty_text_decoration_line:
     case eCSSProperty_text_rendering:
     case eCSSProperty_visibility:
     case eCSSProperty_word_spacing:
       return PR_TRUE;
 
     // EXPLICITLY NON-ANIMATABLE PROPERTIES:
     // (Some of these aren't supported at all in Gecko -- I've commented those
     // ones out. If/when we add support for them, uncomment their line here)
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -45,17 +45,17 @@
  * The nsIDOMCSS2Properties interface is a datatype for additional
  * reflection of data already provided in nsIDOMCSSStyleDeclaration in
  * the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
-[scriptable, uuid(f28df617-ac8b-48e0-8094-c4642ab43940)]
+[scriptable, uuid(35c15ba1-932d-4a95-8f08-ddcdd50c041a)]
 interface nsIDOMCSS2Properties : nsISupports
 {
            attribute DOMString        background;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundAttachment;
                                         // raises(DOMException) on setting
 
@@ -672,19 +672,25 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting 
 
            attribute DOMString        MozWindowShadow;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundSize;
                                         // raises(DOMException) on setting
 
+           attribute DOMString        MozTextBlink;
+                                        // raises(DOMException) on setting
+
            attribute DOMString        MozTextDecorationColor;
                                         // raises(DOMException) on setting
 
+           attribute DOMString        MozTextDecorationLine;
+                                        // raises(DOMException) on setting
+
            attribute DOMString        MozTextDecorationStyle;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozTransitionProperty;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozTransitionDuration;
                                         // raises(DOMException) on setting
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -3409,20 +3409,19 @@ nsCSSRendering::PaintDecorationLine(gfxC
   NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none");
 
   gfxRect rect =
     GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
                                   aDecoration, aStyle, aDescentLimit);
   if (rect.IsEmpty())
     return;
 
-  if (aDecoration != NS_STYLE_TEXT_DECORATION_UNDERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_OVERLINE &&
-      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_THROUGH)
-  {
+  if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
+      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
+      aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
     NS_ERROR("Invalid decoration value!");
     return;
   }
 
   gfxFloat lineHeight = NS_MAX(NS_round(aLineSize.height), 1.0);
   PRBool contextIsSaved = PR_FALSE;
 
   gfxFloat oldLineWidth;
@@ -3698,34 +3697,34 @@ nsCSSRendering::GetTextDecorationRectInt
         r.height = NS_MAX(suggestedMaxRectHeight, lineHeight * 2.0);
       }
     }
   }
 
   gfxFloat baseline = NS_floor(aPt.y + aAscent + 0.5);
   gfxFloat offset = 0.0;
   switch (aDecoration) {
-    case NS_STYLE_TEXT_DECORATION_UNDERLINE:
+    case NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE:
       offset = aOffset;
       if (canLiftUnderline) {
         if (descentLimit < -offset + r.Height()) {
           // If we can ignore the offset and the decoration line is overflowing,
           // we should align the bottom edge of the decoration line rect if it's
           // possible.  Otherwise, we should lift up the top edge of the rect as
           // far as possible.
           gfxFloat offsetBottomAligned = -descentLimit + r.Height();
           gfxFloat offsetTopAligned = 0.0;
           offset = NS_MIN(offsetBottomAligned, offsetTopAligned);
         }
       }
       break;
-    case NS_STYLE_TEXT_DECORATION_OVERLINE:
+    case NS_STYLE_TEXT_DECORATION_LINE_OVERLINE:
       offset = aOffset - lineHeight + r.Height();
       break;
-    case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: {
+    case NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH: {
       gfxFloat extra = NS_floor(r.Height() / 2.0 + 0.5);
       extra = NS_MAX(extra, lineHeight);
       offset = aOffset - lineHeight + extra;
       break;
     }
     default:
       NS_ERROR("Invalid decoration value!");
   }
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -296,19 +296,19 @@ struct nsCSSRendering {
    *     @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 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.
+   *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
    *     @param aStyle            the style of the decoration line such as
    *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
    *     @param aDescentLimit     If aDescentLimit is zero or larger and the
    *                              underline overflows from the descent space,
    *                              the underline should be lifted up as far as
    *                              possible.  Note that this does not mean the
    *                              underline never overflows from this
    *                              limitation.  Because if the underline is
@@ -336,19 +336,19 @@ struct nsCSSRendering {
    *     @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.
+   *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
    *     @param aStyle            the style of the decoration line such as
    *                              NS_STYLE_TEXT_DECORATION_STYLE_*.
    *     @param aDescentLimit     If aDescentLimit is zero or larger and the
    *                              underline overflows from the descent space,
    *                              the underline should be lifted up as far as
    *                              possible.  Note that this does not mean the
    *                              underline never overflows from this
    *                              limitation.  Because if the underline is
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -628,27 +628,30 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_TEXT_ALIGN_MOZ_RIGHT             8
 #define NS_STYLE_TEXT_ALIGN_MOZ_LEFT              9
 // NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT is only used in data structs; it
 // is never present in stylesheets or computed data.
 #define NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT 10
 // Note: make sure that the largest NS_STYLE_TEXT_ALIGN_* value is smaller than
 // the smallest NS_STYLE_VERTICAL_ALIGN_* value below!
 
+// See nsStyleText
+#define NS_STYLE_TEXT_BLINK_NONE                0
+#define NS_STYLE_TEXT_BLINK_BLINK               1
+
 // See nsStyleText, nsStyleFont
-#define NS_STYLE_TEXT_DECORATION_NONE           0
-#define NS_STYLE_TEXT_DECORATION_UNDERLINE      NS_FONT_DECORATION_UNDERLINE
-#define NS_STYLE_TEXT_DECORATION_OVERLINE       NS_FONT_DECORATION_OVERLINE
-#define NS_STYLE_TEXT_DECORATION_LINE_THROUGH   NS_FONT_DECORATION_LINE_THROUGH
-#define NS_STYLE_TEXT_DECORATION_BLINK          0x08
-#define NS_STYLE_TEXT_DECORATION_PREF_ANCHORS   0x10
+#define NS_STYLE_TEXT_DECORATION_LINE_NONE         0
+#define NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE    NS_FONT_DECORATION_UNDERLINE
+#define NS_STYLE_TEXT_DECORATION_LINE_OVERLINE     NS_FONT_DECORATION_OVERLINE
+#define NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH NS_FONT_DECORATION_LINE_THROUGH
+#define NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS 0x10
 // OVERRIDE_ALL does not occur in stylesheets; it only comes from HTML
 // attribute mapping (and thus appears in computed data)
-#define NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL   0x20
-#define NS_STYLE_TEXT_DECORATION_LINES_MASK     (NS_STYLE_TEXT_DECORATION_UNDERLINE | NS_STYLE_TEXT_DECORATION_OVERLINE | NS_STYLE_TEXT_DECORATION_LINE_THROUGH)
+#define NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL 0x20
+#define NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK   (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE | NS_STYLE_TEXT_DECORATION_LINE_OVERLINE | NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH)
 
 // See nsStyleText
 #define NS_STYLE_TEXT_DECORATION_STYLE_NONE     0 // not in CSS spec, mapped to -moz-none
 #define NS_STYLE_TEXT_DECORATION_STYLE_DOTTED   1
 #define NS_STYLE_TEXT_DECORATION_STYLE_DASHED   2
 #define NS_STYLE_TEXT_DECORATION_STYLE_SOLID    3
 #define NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE   4
 #define NS_STYLE_TEXT_DECORATION_STYLE_WAVY     5
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -854,18 +854,19 @@ nsBlockFrame::GetPrefWidth(nsRenderingCo
   mPrefWidth = data.prevLines;
   return mPrefWidth;
 }
 
 nsRect
 nsBlockFrame::ComputeTightBounds(gfxContext* aContext) const
 {
   // be conservative
-  if (GetStyleContext()->HasTextDecorations())
+  if (GetStyleContext()->HasTextDecorationLines()) {
     return GetVisualOverflowRect();
+  }
   return ComputeSimpleTightBounds(aContext);
 }
 
 static PRBool
 AvailableSpaceShrunk(const nsRect& aOldAvailableSpace,
                      const nsRect& aNewAvailableSpace)
 {
   if (aNewAvailableSpace.width == 0) {
--- a/layout/generic/nsHTMLContainerFrame.cpp
+++ b/layout/generic/nsHTMLContainerFrame.cpp
@@ -125,22 +125,22 @@ nsDisplayTextDecoration::Paint(nsDisplay
     tmp -= letterFrame->GetUsedBorderAndPadding().top;
     ascent = letterFrame->PresContext()->AppUnitsToGfxUnits(tmp);
   } else {
     ascent = metrics.maxAscent;
   }
 
   nsPoint pt = ToReferenceFrame();
   nsHTMLContainerFrame* f = static_cast<nsHTMLContainerFrame*>(mFrame);
-  if (mDecoration == NS_STYLE_TEXT_DECORATION_UNDERLINE) {
+  if (mDecoration == NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
     gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
     f->PaintTextDecorationLine(aCtx->ThebesContext(), pt, mLine, mColor,
                                mStyle, underlineOffset, ascent,
                                metrics.underlineSize, mDecoration);
-  } else if (mDecoration == NS_STYLE_TEXT_DECORATION_OVERLINE) {
+  } else if (mDecoration == NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
     f->PaintTextDecorationLine(aCtx->ThebesContext(), pt, mLine, mColor,
                                mStyle, metrics.maxAscent, ascent,
                                metrics.underlineSize, mDecoration);
   } else {
     f->PaintTextDecorationLine(aCtx->ThebesContext(), pt, mLine, mColor,
                                mStyle, metrics.strikeoutOffset,
                                ascent, metrics.strikeoutSize, mDecoration);
   }
@@ -235,33 +235,34 @@ nsDisplayTextShadow::Paint(nsDisplayList
   NS_ABORT_IF_FALSE(shadowList,
                     "Why did we make a display list item if we have no shadows?");
 
   // Get the rects for each text decoration line, so we know how big we
   // can make each shadow's surface
   nsRect underlineRect;
   nsRect overlineRect;
   nsRect lineThroughRect;
-  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
+  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
     gfxSize size(lineWidth, metrics.underlineSize);
     underlineRect = nsCSSRendering::GetTextDecorationRect(presContext, size,
                        ascent, underlineOffset,
-                       NS_STYLE_TEXT_DECORATION_UNDERLINE, mUnderlineStyle);
+                       NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+                       mUnderlineStyle);
   }
-  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_OVERLINE) {
+  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
     gfxSize size(lineWidth, metrics.underlineSize);
     overlineRect = nsCSSRendering::GetTextDecorationRect(presContext, size,
                        ascent, metrics.maxAscent,
-                       NS_STYLE_TEXT_DECORATION_OVERLINE, mOverlineStyle);
+                       NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, mOverlineStyle);
   }
-  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
+  if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
     gfxSize size(lineWidth, metrics.strikeoutSize);
     lineThroughRect = nsCSSRendering::GetTextDecorationRect(presContext, size,
                        ascent, metrics.strikeoutOffset,
-                       NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
+                       NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
                        mStrikeThroughStyle);
   }
 
   for (PRUint32 i = shadowList->Length(); i > 0; --i) {
     nsCSSShadowItem* shadow = shadowList->ShadowAt(i - 1);
 
     nscolor shadowColor =
       shadow->mHasColor ? shadow->mColor : mFrame->GetStyleColor()->mColor;
@@ -271,54 +272,56 @@ nsDisplayTextShadow::Paint(nsDisplayList
     nsPoint linePt;
     if (mLine) {
       linePt = nsPoint(start + pt.x, mLine->mBounds.y + pt.y);
     } else {
       linePt = mFrame->GetContentRect().TopLeft() - mFrame->GetPosition() + pt;
     }
 
     nsRect shadowRect(0, 0, 0, 0);
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
       shadowRect.UnionRect(shadowRect, underlineRect + linePt);
     }
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_OVERLINE) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
       shadowRect.UnionRect(shadowRect, overlineRect + linePt);
     }
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
       shadowRect.UnionRect(shadowRect, lineThroughRect + linePt);
     }
 
     gfxContextAutoSaveRestore save(thebesCtx);
     thebesCtx->NewPath();
     thebesCtx->SetColor(gfxRGBA(shadowColor));
 
     // Create our shadow surface, then paint the text decorations onto it
     nsContextBoxBlur contextBoxBlur;
     gfxContext* shadowCtx = contextBoxBlur.Init(shadowRect, 0, shadow->mRadius,
                                                 presContext->AppUnitsPerDevPixel(),
                                                 thebesCtx, mVisibleRect, nsnull);
     if (!shadowCtx) {
       continue;
     }
 
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
       f->PaintTextDecorationLine(shadowCtx, pt, mLine, shadowColor,
                                  mUnderlineStyle, underlineOffset, ascent,
-                                 metrics.underlineSize, NS_STYLE_TEXT_DECORATION_UNDERLINE);
+                                 metrics.underlineSize,
+                                 NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE);
     }
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_OVERLINE) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
       f->PaintTextDecorationLine(shadowCtx, pt, mLine, shadowColor,
                                  mOverlineStyle, metrics.maxAscent, ascent,
-                                 metrics.underlineSize, NS_STYLE_TEXT_DECORATION_OVERLINE);
+                                 metrics.underlineSize,
+                                 NS_STYLE_TEXT_DECORATION_LINE_OVERLINE);
     }
-    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
+    if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
       f->PaintTextDecorationLine(shadowCtx, pt, mLine, shadowColor,
                                  mStrikeThroughStyle, metrics.strikeoutOffset,
                                  ascent, metrics.strikeoutSize,
-                                 NS_STYLE_TEXT_DECORATION_LINE_THROUGH);
+                                 NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
     }
 
     contextBoxBlur.DoPaint();
   }
 }
 
 nsRect
 nsDisplayTextShadow::GetBounds(nsDisplayListBuilder* aBuilder)
@@ -345,53 +348,56 @@ nsHTMLContainerFrame::DisplayTextDecorat
   if (fm->GetThebesFontGroup()->ShouldSkipDrawing())
     return NS_OK;
 
   // Do standards mode painting of 'text-decoration's: under+overline
   // behind children, line-through in front.  For Quirks mode, see
   // nsTextFrame::PaintTextDecorations.  (See bug 1777.)
   nscolor underColor, overColor, strikeColor;
   PRUint8 underStyle, overStyle, strikeStyle;
-  PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE;
+  PRUint8 decorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
   GetTextDecorations(PresContext(), aLine != nsnull, decorations, underColor, 
                      overColor, strikeColor, underStyle, overStyle,
                      strikeStyle);
 
-  if (decorations == NS_STYLE_TEXT_DECORATION_NONE) {
+  if (decorations == NS_STYLE_TEXT_DECORATION_LINE_NONE) {
     return NS_OK;
   }
 
   // The text-shadow spec says that any text decorations must also have a
   // shadow applied to them. So draw the shadows as part of the display
   // list, underneath the text and all decorations.
   if (GetStyleText()->mTextShadow) {
     rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
       nsDisplayTextShadow(aBuilder, this, decorations, underStyle, overStyle,
                           strikeStyle, aLine));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if ((decorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) &&
+  if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
       underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
-      nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_UNDERLINE,
+      nsDisplayTextDecoration(aBuilder, this,
+                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
                               underColor, underStyle, aLine));
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  if ((decorations & NS_STYLE_TEXT_DECORATION_OVERLINE) &&
+  if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
       overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
-      nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_OVERLINE,
+      nsDisplayTextDecoration(aBuilder, this,
+                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE,
                               overColor, overStyle, aLine));
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) &&
+  if ((decorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
       strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     rv = aAboveTextDecorations->AppendNewToTop(new (aBuilder)
-      nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
+      nsDisplayTextDecoration(aBuilder, this,
+                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
                               strikeColor, strikeStyle, aLine));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
 nsresult
 nsHTMLContainerFrame::DisplayTextDecorationsAndChildren(
@@ -468,71 +474,71 @@ nsHTMLContainerFrame::GetTextDecorations
                                          PRUint8& aDecorations,
                                          nscolor& aUnderColor, 
                                          nscolor& aOverColor, 
                                          nscolor& aStrikeColor,
                                          PRUint8& aUnderStyle,
                                          PRUint8& aOverStyle,
                                          PRUint8& aStrikeStyle)
 {
-  aDecorations = NS_STYLE_TEXT_DECORATION_NONE;
-  if (!mStyleContext->HasTextDecorations()) {
+  aDecorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
+  if (!mStyleContext->HasTextDecorationLines()) {
     // This is a necessary, but not sufficient, condition for text
     // decorations.
     return; 
   }
 
   if (!aIsBlock) {
     const nsStyleTextReset* styleTextReset = this->GetStyleTextReset();
-    aDecorations = styleTextReset->mTextDecoration &
-                   NS_STYLE_TEXT_DECORATION_LINES_MASK;
+    aDecorations = styleTextReset->mTextDecorationLine &
+                   NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
     if (aDecorations) {
       nscolor color =
         this->GetVisitedDependentColor(eCSSProperty_text_decoration_color);
       aUnderColor = aOverColor = aStrikeColor = color;
       aUnderStyle = aOverStyle = aStrikeStyle =
         styleTextReset->GetDecorationStyle();
     }
   }
   else {
     // We want to ignore a text-decoration from an ancestor frame that
     // is redundant with one from a descendant frame.  This isn't just
     // an optimization; the descendant frame's color specification
     // must win.  At any point in the loop below, this variable
     // indicates which decorations we are still paying attention to;
     // it starts set to all possible decorations.
-    PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINES_MASK;
+    PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
 
     // walk tree
     for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
       const nsStyleTextReset* styleTextReset = frame->GetStyleTextReset();
-      PRUint8 decors = styleTextReset->mTextDecoration & decorMask;
+      PRUint8 decors = styleTextReset->mTextDecorationLine & decorMask;
       if (decors) {
         // A *new* text-decoration is found.
         nscolor color = frame->GetVisitedDependentColor(
                                  eCSSProperty_text_decoration_color);
         PRUint8 style = styleTextReset->GetDecorationStyle();
 
-        if (NS_STYLE_TEXT_DECORATION_UNDERLINE & decors) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decors) {
           aUnderColor = color;
           aUnderStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
-          aDecorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
+          aDecorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
         }
-        if (NS_STYLE_TEXT_DECORATION_OVERLINE & decors) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & decors) {
           aOverColor = color;
           aOverStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE;
-          aDecorations |= NS_STYLE_TEXT_DECORATION_OVERLINE;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
+          aDecorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
         }
-        if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & decors) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & decors) {
           aStrikeColor = color;
           aStrikeStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
-          aDecorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
+          aDecorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
         }
       }
       // If all possible decorations have now been specified, no
       // further ancestor frames can affect the rendering.
       if (!decorMask) {
         break;
       }
 
@@ -560,17 +566,17 @@ nsHTMLContainerFrame::GetTextDecorations
         break;
       }
     }
   }
   
   if (aDecorations) {
     // If this frame contains no text, we're required to ignore this property
     if (!HasTextFrameDescendantOrInFlow(this)) {
-      aDecorations = NS_STYLE_TEXT_DECORATION_NONE;
+      aDecorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
     }
   }
 }
 
 static PRBool 
 HasTextFrameDescendant(nsIFrame* aParent)
 {
   for (nsIFrame* kid = aParent->GetFirstChild(nsnull); kid;
--- a/layout/generic/nsHTMLContainerFrame.h
+++ b/layout/generic/nsHTMLContainerFrame.h
@@ -136,17 +136,17 @@ protected:
    *  @param aOverStyle    The style of overline if the appropriate bit
    *                         in aDecoration is set. It is undefined otherwise.
    *                         The style is one of
    *                         NS_STYLE_TEXT_DECORATION_STYLE_* consts.
    *  @param aStrikeStyle  The style of strike-through if the appropriate bit
    *                         in aDecoration is set. It is undefined otherwise.
    *                         The style is one of
    *                         NS_STYLE_TEXT_DECORATION_STYLE_* consts.
-   *  NOTE: This function assigns NS_STYLE_TEXT_DECORATION_NONE to
+   *  NOTE: This function assigns NS_STYLE_TEXT_DECORATION_LINE_NONE to
    *        aDecorations for text-less frames.  See bug 20163 for
    *        details.
    *  NOTE: The results of color and style for each lines were not initialized
    *        if the line wasn't included in aDecorations.
    */
   void GetTextDecorations(nsPresContext* aPresContext, 
                           PRBool aIsBlock,
                           PRUint8& aDecorations, 
@@ -167,20 +167,20 @@ protected:
    *                                NS_STYLE_TEXT_DECORATION_STYLE_* consts.
    *    @param aAscent            ascent of the font from which the
    *                                text-decoration was derived. 
    *    @param aOffset            distance *above* baseline where the
    *                                text-decoration should be drawn,
    *                                i.e. negative offsets draws *below*
    *                                the baseline.
    *    @param aSize              the thickness of the line
-   *    @param aDecoration        which line will be painted
-   *                                i.e., NS_STYLE_TEXT_DECORATION_UNDERLINE or
-   *                                      NS_STYLE_TEXT_DECORATION_OVERLINE or
-   *                                      NS_STYLE_TEXT_DECORATION_LINE_THROUGH.
+   *    @param aDecoration        which line will be painted i.e.,
+   *                              NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_OVERLINE or
+   *                              NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH.
    */
   virtual void PaintTextDecorationLine(gfxContext* aCtx,
                                        const nsPoint& aPt,
                                        nsLineBox* aLine,
                                        nscolor aColor,
                                        PRUint8 aStyle,
                                        gfxFloat aOffset,
                                        gfxFloat aAscent,
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -1873,18 +1873,17 @@ nsHTMLReflowState::InitConstraints(nsPre
       if (isBlock && !IsSideCaption(frame, mStyleDisplay))
         CalculateBlockSideMargins(availableWidth, mComputedWidth);
     }
   }
   // Check for blinking text and permission to display it
   mFlags.mBlinks = (parentReflowState && parentReflowState->mFlags.mBlinks);
   if (!mFlags.mBlinks && BlinkIsAllowed()) {
     const nsStyleTextReset* st = frame->GetStyleTextReset();
-    mFlags.mBlinks = 
-      ((st->mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) != 0);
+    mFlags.mBlinks = (st->mTextBlink != NS_STYLE_TEXT_BLINK_NONE);
   }
 }
 
 static void
 UpdateProp(FrameProperties& aProps,
            const FramePropertyDescriptor* aProperty,
            PRBool aNeeded,
            nsMargin& aNewValue)
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -225,18 +225,19 @@ nsInlineFrame::ComputeSize(nsRenderingCo
   // Inlines and text don't compute size before reflow.
   return nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
 }
 
 nsRect
 nsInlineFrame::ComputeTightBounds(gfxContext* aContext) const
 {
   // be conservative
-  if (GetStyleContext()->HasTextDecorations())
+  if (GetStyleContext()->HasTextDecorationLines()) {
     return GetVisualOverflowRect();
+  }
   return ComputeSimpleTightBounds(aContext);
 }
 
 void
 nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
                                             nsIFrame* aFrame,
                                             PRBool aReparentSiblings)
 {
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -446,25 +446,25 @@ protected:
       mOverColor(NS_RGB(0, 0, 0)), mUnderColor(NS_RGB(0, 0, 0)),
       mStrikeColor(NS_RGB(0, 0, 0))
     { }
 
     PRBool HasDecorationlines() {
       return HasUnderline() || HasOverline() || HasStrikeout();
     }
     PRBool HasUnderline() {
-      return (mDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) &&
+      return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
              mUnderStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
     }
     PRBool HasOverline() {
-      return (mDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE) &&
+      return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
              mOverStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
     }
     PRBool HasStrikeout() {
-      return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) &&
+      return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
              mStrikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
     }
   };
   TextDecorations GetTextDecorations(nsPresContext* aPresContext);
 
   // Set non empty rect to aRect, it should be overflow rect or frame rect.
   // If the result rect is larger than the given rect, this returns PR_TRUE.
   PRBool CombineSelectionUnderlineRect(nsPresContext* aPresContext,
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -4237,70 +4237,69 @@ nsTextFrame::GetTextDecorations(nsPresCo
     return decorations;
 
   PRBool useOverride = PR_FALSE;
   nscolor overrideColor;
 
   // A mask of all possible decorations.
   // FIXME: Per spec, we still need to draw all relevant decorations
   // from ancestors, not just the nearest one from each.
-  PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_UNDERLINE | 
-                      NS_STYLE_TEXT_DECORATION_OVERLINE |
-                      NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
+  PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
 
   PRBool isChild; // ignored
   for (nsIFrame* f = this; decorMask && f;
        NS_SUCCEEDED(f->GetParentStyleContextFrame(aPresContext, &f, &isChild))
          || (f = nsnull)) {
     nsStyleContext* context = f->GetStyleContext();
-    if (!context->HasTextDecorations()) {
+    if (!context->HasTextDecorationLines()) {
       break;
     }
     const nsStyleTextReset* styleText = context->GetStyleTextReset();
     if (!useOverride && 
-        (NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL & styleText->mTextDecoration)) {
+        (NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL &
+           styleText->mTextDecorationLine)) {
       // 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->GetVisitedDependentColor(
                                  eCSSProperty_text_decoration_color);
     }
 
     // FIXME: see above (remove this check)
-    PRUint8 useDecorations = decorMask & styleText->mTextDecoration;
+    PRUint8 useDecorations = decorMask & styleText->mTextDecorationLine;
     if (useDecorations) {// a decoration defined here
       nscolor color = context->GetVisitedDependentColor(
                                  eCSSProperty_text_decoration_color);
 
       // FIXME: We also need to record the thickness and position
       // metrics appropriate to this element (at least in standards
       // mode).  This will require adjusting the visual overflow region
       // of this frame and maybe its ancestors.  The positions should
       // probably be relative to the line's baseline (when text
       // decorations are specified on inlines we should look for their
       // containing line; otherwise use the element's font); when
       // drawing it should always be relative to the line baseline.
       // This way we move the decorations for relative positioning.
-      if (NS_STYLE_TEXT_DECORATION_UNDERLINE & useDecorations) {
+      if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & useDecorations) {
         decorations.mUnderColor = useOverride ? overrideColor : color;
         decorations.mUnderStyle = styleText->GetDecorationStyle();
-        decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
+        decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
+        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
       }
-      if (NS_STYLE_TEXT_DECORATION_OVERLINE & useDecorations) {
+      if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & useDecorations) {
         decorations.mOverColor = useOverride ? overrideColor : color;
         decorations.mOverStyle = styleText->GetDecorationStyle();
-        decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_OVERLINE;
+        decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
+        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
       }
-      if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & useDecorations) {
+      if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & useDecorations) {
         decorations.mStrikeColor = useOverride ? overrideColor : color;
         decorations.mStrikeStyle = styleText->GetDecorationStyle();
-        decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
-        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
+        decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
+        decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
       }
     }
 
     // In all modes, if we're on an inline-block or inline-table (or
     // inline-stack, inline-box, inline-grid), we're done.
     const nsStyleDisplay *disp = context->GetStyleDisplay();
     if (disp->mDisplay != NS_STYLE_DISPLAY_INLINE &&
         disp->IsInlineOutside()) {
@@ -4382,33 +4381,33 @@ nsTextFrame::PaintTextDecorations(gfxCon
   gfxFloat ascent = gfxFloat(mAscent) / app;
 
   nscolor lineColor;
   if (decorations.HasOverline()) {
     lineColor = aOverrideColor ? *aOverrideColor : decorations.mOverColor;
     size.height = fontMetrics.underlineSize;
     nsCSSRendering::PaintDecorationLine(
       aCtx, lineColor, pt, size, ascent, fontMetrics.maxAscent,
-      NS_STYLE_TEXT_DECORATION_OVERLINE, decorations.mOverStyle);
+      NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorations.mOverStyle);
   }
   if (decorations.HasUnderline()) {
     lineColor = aOverrideColor ? *aOverrideColor : decorations.mUnderColor;
     size.height = fontMetrics.underlineSize;
     gfxFloat offset = aProvider.GetFontGroup()->GetUnderlineOffset();
     nsCSSRendering::PaintDecorationLine(
       aCtx, lineColor, pt, size, ascent, offset,
-      NS_STYLE_TEXT_DECORATION_UNDERLINE, decorations.mUnderStyle);
+      NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorations.mUnderStyle);
   }
   if (decorations.HasStrikeout()) {
     lineColor = aOverrideColor ? *aOverrideColor : decorations.mStrikeColor;
     size.height = fontMetrics.strikeoutSize;
     gfxFloat offset = fontMetrics.strikeoutOffset;
     nsCSSRendering::PaintDecorationLine(
       aCtx, lineColor, pt, size, ascent, offset,
-      NS_STYLE_TEXT_DECORATION_LINE_THROUGH, decorations.mStrikeStyle);
+      NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorations.mStrikeStyle);
   }
 }
 
 static gfxFloat
 ComputeDescentLimitForSelectionUnderline(nsPresContext* aPresContext,
                                          nsTextFrame* aFrame,
                                          const gfxFont::Metrics& aFontMetrics)
 {
@@ -4544,17 +4543,17 @@ static void DrawSelectionDecorations(gfx
       break;
     default:
       NS_WARNING("Requested selection decorations when there aren't any");
       return;
   }
   size.height *= relativeSize;
   nsCSSRendering::PaintDecorationLine(
     aContext, color, pt, size, aAscent, aFontMetrics.underlineOffset,
-    NS_STYLE_TEXT_DECORATION_UNDERLINE, style, descentLimit);
+    NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, style, descentLimit);
 }
 
 /**
  * This function encapsulates all knowledge of how selections affect foreground
  * and background colors.
  * @return true if the selection affects colors, false otherwise
  * @param aForeground the foreground color to use
  * @param aBackground the background color to use, or RGBA(0,0,0,0) if no
@@ -5335,19 +5334,18 @@ nsTextFrame::CombineSelectionUnderlineRe
     nsRect decorationArea;
     gfxSize size(aPresContext->AppUnitsToGfxUnits(aRect.width),
                  ComputeSelectionUnderlineHeight(aPresContext,
                                                  metrics, sd->mType));
     relativeSize = NS_MAX(relativeSize, 1.0f);
     size.height *= relativeSize;
     decorationArea =
       nsCSSRendering::GetTextDecorationRect(aPresContext, size,
-                                            ascent, underlineOffset,
-                                            NS_STYLE_TEXT_DECORATION_UNDERLINE,
-                                            style, descentLimit);
+        ascent, underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+        style, descentLimit);
     aRect.UnionRect(aRect, decorationArea);
   }
   DestroySelectionDetails(details);
 
   return !aRect.IsEmpty() && !givenRect.Contains(aRect);
 }
 
 void
@@ -6310,17 +6308,17 @@ RoundOut(const gfxRect& aRect)
   r.width = NSToCoordCeil(aRect.XMost()) - r.x;
   r.height = NSToCoordCeil(aRect.YMost()) - r.y;
   return r;
 }
 
 nsRect
 nsTextFrame::ComputeTightBounds(gfxContext* aContext) const
 {
-  if ((GetStyleContext()->HasTextDecorations() &&
+  if ((GetStyleContext()->HasTextDecorationLines() &&
        eCompatibility_NavQuirks == PresContext()->CompatibilityMode()) ||
       (GetStateBits() & TEXT_HYPHEN_BREAK)) {
     // This is conservative, but OK.
     return GetVisualOverflowRect();
   }
 
   gfxSkipCharsIterator iter = const_cast<nsTextFrame*>(this)->EnsureTextRun();
   if (!mTextRun)
--- a/layout/reftests/text-decoration/decoration-color-quirks-ref.html
+++ b/layout/reftests/text-decoration/decoration-color-quirks-ref.html
@@ -58,8 +58,13 @@
   This is blue paragraph and decoration color is specified as green,
   <span style="font-size:2em;
                color: red;
                text-decoration: underline line-through overline;
                -moz-text-decoration-color: green;">
     here is red text with green decoration lines</span>,
   and here is blue text without decoration lines.
 </p>
+<p style="color: blue;
+          text-decoration: underline line-through overline;">
+  Here has blue decoration lines even though its color is specified as red
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-color-quirks.html
+++ b/layout/reftests/text-decoration/decoration-color-quirks.html
@@ -66,8 +66,14 @@
   This is blue paragraph and decoration color is specified as green,
   <span style="font-size:2em;
                color: red;
                text-decoration: underline line-through overline;
                -moz-text-decoration-color: inherit;">
     here is red text with green decoration lines</span>,
   and here is blue text without decoration lines.
 </p>
+<p style="color: blue;
+          -moz-text-decoration-color: red;
+          text-decoration: underline line-through overline;">
+  Here has blue decoration lines even though its color is specified as red
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-color-standards-ref.html
+++ b/layout/reftests/text-decoration/decoration-color-standards-ref.html
@@ -60,8 +60,13 @@
   This is blue paragraph and decoration color is specified as green,
   <span style="font-size:2em;
                color: red;
                text-decoration: underline line-through overline;
                -moz-text-decoration-color: green;">
     here is red text with green decoration lines</span>,
   and here is blue text without decoration lines.
 </p>
+<p style="color: blue;
+          text-decoration: underline line-through overline;">
+  Here has blue decoration lines even though its color is specified as red
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-color-standards.html
+++ b/layout/reftests/text-decoration/decoration-color-standards.html
@@ -65,8 +65,14 @@
   This is blue paragraph and decoration color is specified as green,
   <span style="font-size:2em;
                color: red;
                text-decoration: underline line-through overline;
                -moz-text-decoration-color: inherit;">
     here is red text with green decoration lines</span>,
   and here is blue text without decoration lines.
 </p>
+<p style="color: blue;
+          -moz-text-decoration-color: red;
+          text-decoration: underline line-through overline;">
+  Here has blue decoration lines even though its color is specified as red
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-style-quirks-ref.html
+++ b/layout/reftests/text-decoration/decoration-style-quirks-ref.html
@@ -38,8 +38,12 @@
     here is specified as dashed decoration lines but should be
     ignored</span><span style="text-decoration: underline line-through overline;
                                -moz-text-decoration-style: double;">,
     and here has double decoration lines.</span>
 </p>
 <p>
   Here is specified the decoration style as -moz-none.
 </p>
+<p style="text-decoration: underline line-through overline;">
+  Here has solid decoration lines even if its style is specified as dotted
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-style-quirks.html
+++ b/layout/reftests/text-decoration/decoration-style-quirks.html
@@ -30,8 +30,13 @@
                -moz-text-decoration-style: dashed;">
     here is specified as dashed decoration lines but should be ignored</span>,
   and here has double decoration lines.
 </p>
 <p style="text-decoration: underline line-through overline;
           -moz-text-decoration-style: -moz-none;">
   Here is specified the decoration style as -moz-none.
 </p>
+<p style="-moz-text-decoration-style: dotted;
+          text-decoration: underline line-through overline;">
+  Here has solid decoration lines even if its style is specified as dotted
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-style-standards-ref.html
+++ b/layout/reftests/text-decoration/decoration-style-standards-ref.html
@@ -23,8 +23,12 @@
   <span style="font-size: 2em;
                text-decoration: none;">
      here is specified as dashed decoration lines but should be ignored</span>,
   and here has double decoration lines.
 </p>
 <p>
   Here is specified the decoration style as -moz-none.
 </p>
+<p style="text-decoration: underline line-through overline;">
+  Here has solid decoration lines even if its style is specified as dotted
+  before text-decoration.
+</p>
--- a/layout/reftests/text-decoration/decoration-style-standards.html
+++ b/layout/reftests/text-decoration/decoration-style-standards.html
@@ -22,8 +22,13 @@
                -moz-text-decoration-style: dashed;">
     here is specified as dashed decoration lines but should be ignored</span>,
   and here has double decoration lines.
 </p>
 <p style="text-decoration: underline line-through overline;
           -moz-text-decoration-style: -moz-none;">
   Here is specified the decoration style as -moz-none.
 </p>
+<p style="-moz-text-decoration-style: dotted;
+          text-decoration: underline line-through overline;">
+  Here has solid decoration lines even if its style is specified as dotted
+  before text-decoration.
+</p>
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -575,16 +575,66 @@ Declaration::GetValue(nsCSSProperty aPro
       const nsCSSValue &xValue =
         *data->ValueFor(eCSSProperty_overflow_x);
       const nsCSSValue &yValue =
         *data->ValueFor(eCSSProperty_overflow_y);
       if (xValue == yValue)
         xValue.AppendToString(eCSSProperty_overflow_x, aValue);
       break;
     }
+    case eCSSProperty_text_decoration: {
+      // If text-decoration-color or text-decoration-style isn't initial value,
+      // we cannot serialize the text-decoration shorthand value.
+      const nsCSSValue &decorationColor =
+        *data->ValueFor(eCSSProperty_text_decoration_color);
+      const nsCSSValue &decorationStyle =
+        *data->ValueFor(eCSSProperty_text_decoration_style);
+
+      NS_ABORT_IF_FALSE(decorationStyle.GetUnit() == eCSSUnit_Enumerated,
+                        nsPrintfCString(32, "bad text-decoration-style unit %d",
+                                        decorationStyle.GetUnit()).get());
+
+      if (decorationColor.GetUnit() != eCSSUnit_Enumerated ||
+          decorationColor.GetIntValue() != NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR ||
+          decorationStyle.GetIntValue() !=
+            NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
+        return;
+      }
+
+      const nsCSSValue &textBlink =
+        *data->ValueFor(eCSSProperty_text_blink);
+      const nsCSSValue &decorationLine =
+        *data->ValueFor(eCSSProperty_text_decoration_line);
+
+      NS_ABORT_IF_FALSE(textBlink.GetUnit() == eCSSUnit_Enumerated,
+                        nsPrintfCString(32, "bad text-blink unit %d",
+                                        textBlink.GetUnit()).get());
+      NS_ABORT_IF_FALSE(decorationLine.GetUnit() == eCSSUnit_Enumerated,
+                        nsPrintfCString(32, "bad text-decoration-line unit %d",
+                                        decorationLine.GetUnit()).get());
+
+      PRBool blinkNone = (textBlink.GetIntValue() == NS_STYLE_TEXT_BLINK_NONE);
+      PRBool lineNone =
+        (decorationLine.GetIntValue() == NS_STYLE_TEXT_DECORATION_LINE_NONE);
+
+      if (blinkNone && lineNone) {
+        AppendValueToString(eCSSProperty_text_decoration_line, aValue);
+      } else {
+        if (!blinkNone) {
+          AppendValueToString(eCSSProperty_text_blink, aValue);
+        }
+        if (!lineNone) {
+          if (!aValue.IsEmpty()) {
+            aValue.Append(PRUnichar(' '));
+          }
+          AppendValueToString(eCSSProperty_text_decoration_line, aValue);
+        }
+      }
+      break;
+    }
     case eCSSProperty_transition: {
       const nsCSSValue &transProp =
         *data->ValueFor(eCSSProperty_transition_property);
       const nsCSSValue &transDuration =
         *data->ValueFor(eCSSProperty_transition_duration);
       const nsCSSValue &transTiming =
         *data->ValueFor(eCSSProperty_transition_timing_function);
       const nsCSSValue &transDelay =
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -517,17 +517,18 @@ protected:
   PRBool ParseMargin();
   PRBool ParseMarks(nsCSSValue& aValue);
   PRBool ParseMozTransform();
   PRBool ParseOutline();
   PRBool ParseOverflow();
   PRBool ParsePadding();
   PRBool ParseQuotes();
   PRBool ParseSize();
-  PRBool ParseTextDecoration(nsCSSValue& aValue);
+  PRBool ParseTextDecoration();
+  PRBool ParseTextDecorationLine(nsCSSValue& aValue);
 
   PRBool ParseShadowItem(nsCSSValue& aValue, PRBool aIsBoxShadow);
   PRBool ParseShadowList(nsCSSProperty aProperty);
   PRBool ParseTransitionProperty();
   PRBool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
   PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent,
                                                      char aStop,
                                                      PRBool aCheckRange);
@@ -5561,16 +5562,18 @@ CSSParserImpl::ParsePropertyByFunction(n
                                        NS_BOXPROP_SOURCE_PHYSICAL);
   case eCSSProperty_padding_start:
     return ParseDirectionalBoxProperty(eCSSProperty_padding_start,
                                        NS_BOXPROP_SOURCE_LOGICAL);
   case eCSSProperty_quotes:
     return ParseQuotes();
   case eCSSProperty_size:
     return ParseSize();
+  case eCSSProperty_text_decoration:
+    return ParseTextDecoration();
   case eCSSProperty__moz_transform:
     return ParseMozTransform();
   case eCSSProperty__moz_transform_origin:
     return ParseMozTransformOrigin();
   case eCSSProperty_transition:
     return ParseTransition();
 #ifdef MOZ_CSS_ANIMATIONS
   case eCSSProperty_animation:
@@ -5620,18 +5623,18 @@ CSSParserImpl::ParseSingleValueProperty(
   if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_VALUE_PARSER_FUNCTION)) {
     switch (aPropID) {
       case eCSSProperty_font_family:
         return ParseFamily(aValue);
       case eCSSProperty_font_weight:
         return ParseFontWeight(aValue);
       case eCSSProperty_marks:
         return ParseMarks(aValue);
-      case eCSSProperty_text_decoration:
-        return ParseTextDecoration(aValue);
+      case eCSSProperty_text_decoration_line:
+        return ParseTextDecorationLine(aValue);
       default:
         NS_ABORT_IF_FALSE(PR_FALSE, "should not reach here");
         return PR_FALSE;
     }
   }
 
   PRUint32 variant = nsCSSProps::ParserVariant(aPropID);
   if (variant == 0) {
@@ -7939,29 +7942,118 @@ CSSParserImpl::ParseSize()
     nsCSSValue pair;
     pair.SetPairValue(width, height);
     AppendValue(eCSSProperty_size, pair);
   }
   return PR_TRUE;
 }
 
 PRBool
-CSSParserImpl::ParseTextDecoration(nsCSSValue& aValue)
-{
-  if (ParseVariant(aValue, VARIANT_HK, nsCSSProps::kTextDecorationKTable)) {
+CSSParserImpl::ParseTextDecoration()
+{
+  enum {
+    eDecorationNone         = 0x00,
+    eDecorationUnderline    = 0x01,
+    eDecorationOverline     = 0x02,
+    eDecorationLineThrough  = 0x04,
+    eDecorationBlink        = 0x08,
+    eDecorationPrefAnchors  = 0x10
+  };
+
+  PR_STATIC_ASSERT(eDecorationUnderline ==
+                   NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE);
+  PR_STATIC_ASSERT(eDecorationOverline ==
+                   NS_STYLE_TEXT_DECORATION_LINE_OVERLINE);
+  PR_STATIC_ASSERT(eDecorationLineThrough ==
+                   NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
+  PR_STATIC_ASSERT(eDecorationPrefAnchors ==
+                   NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS);
+
+  static const PRInt32 kTextDecorationKTable[] = {
+    eCSSKeyword_none,                   eDecorationNone,
+    eCSSKeyword_underline,              eDecorationUnderline,
+    eCSSKeyword_overline,               eDecorationOverline,
+    eCSSKeyword_line_through,           eDecorationLineThrough,
+    eCSSKeyword_blink,                  eDecorationBlink,
+    eCSSKeyword__moz_anchor_decoration, eDecorationPrefAnchors,
+    eCSSKeyword_UNKNOWN,-1
+  };
+
+  nsCSSValue value;
+  if (!ParseVariant(value, VARIANT_HK, kTextDecorationKTable)) {
+    return PR_FALSE;
+  }
+
+  nsCSSValue blink, line, style, color;
+  switch (value.GetUnit()) {
+    case eCSSUnit_Enumerated: {
+      // We shouldn't accept decoration line style and color via
+      // text-decoration.
+      color.SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR,
+                        eCSSUnit_Enumerated);
+      style.SetIntValue(NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
+                        eCSSUnit_Enumerated);
+
+      PRInt32 intValue = value.GetIntValue();
+      if (intValue == eDecorationNone) {
+        blink.SetIntValue(NS_STYLE_TEXT_BLINK_NONE, eCSSUnit_Enumerated);
+        line.SetIntValue(NS_STYLE_TEXT_DECORATION_LINE_NONE,
+                         eCSSUnit_Enumerated);
+        break;
+      }
+
+      // look for more keywords
+      nsCSSValue keyword;
+      PRInt32 index;
+      for (index = 0; index < 3; index++) {
+        if (!ParseEnum(keyword, kTextDecorationKTable)) {
+          break;
+        }
+        PRInt32 newValue = keyword.GetIntValue();
+        if (newValue == eDecorationNone || newValue & intValue) {
+          // 'none' keyword in conjuction with others is not allowed, and
+          // duplicate keyword is not allowed.
+          return PR_FALSE;
+        }
+        intValue |= newValue;
+      }
+
+      blink.SetIntValue((intValue & eDecorationBlink) != 0 ?
+                          NS_STYLE_TEXT_BLINK_BLINK : NS_STYLE_TEXT_BLINK_NONE,
+                        eCSSUnit_Enumerated);
+      line.SetIntValue((intValue & ~eDecorationBlink), eCSSUnit_Enumerated);
+      break;
+    }
+    default:
+      blink = line = color = style = value;
+      break;
+  }
+
+  AppendValue(eCSSProperty_text_blink, blink);
+  AppendValue(eCSSProperty_text_decoration_line, line);
+  AppendValue(eCSSProperty_text_decoration_color, color);
+  AppendValue(eCSSProperty_text_decoration_style, style);
+
+  return PR_TRUE;
+}
+
+PRBool
+CSSParserImpl::ParseTextDecorationLine(nsCSSValue& aValue)
+{
+  if (ParseVariant(aValue, VARIANT_HK, nsCSSProps::kTextDecorationLineKTable)) {
     if (eCSSUnit_Enumerated == aValue.GetUnit()) {
       PRInt32 intValue = aValue.GetIntValue();
-      if (intValue != NS_STYLE_TEXT_DECORATION_NONE) {
+      if (intValue != NS_STYLE_TEXT_DECORATION_LINE_NONE) {
         // look for more keywords
         nsCSSValue  keyword;
         PRInt32 index;
-        for (index = 0; index < 3; index++) {
-          if (ParseEnum(keyword, nsCSSProps::kTextDecorationKTable)) {
+        for (index = 0; index < 2; index++) {
+          if (ParseEnum(keyword, nsCSSProps::kTextDecorationLineKTable)) {
             PRInt32 newValue = keyword.GetIntValue();
-            if (newValue == NS_STYLE_TEXT_DECORATION_NONE ||
+            if (newValue == NS_STYLE_TEXT_DECORATION_LINE_NONE ||
                 newValue & intValue) {
               // 'none' keyword in conjuction with others is not allowed, and
               // duplicate keyword is not allowed.
               return PR_FALSE;
             }
             intValue |= newValue;
           }
           else {
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2125,39 +2125,54 @@ CSS_PROP_TEXT(
     TextAlign,
     CSS_PROPERTY_PARSE_VALUE,
     // When we support aligning on a string, we can parse text-align
     // as a string....
     VARIANT_HK /* | VARIANT_STRING */,
     kTextAlignKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
-CSS_PROP_TEXTRESET(
+CSS_PROP_SHORTHAND(
     text-decoration,
     text_decoration,
     TextDecoration,
+    CSS_PROPERTY_PARSE_FUNCTION)
+CSS_PROP_TEXTRESET(
+    -moz-text-blink,
+    text_blink,
+    CSS_PROP_DOMPROP_PREFIXED(TextBlink),
     CSS_PROPERTY_PARSE_VALUE |
-        CSS_PROPERTY_VALUE_PARSER_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
-    0,
-    kTextDecorationKTable,
-    offsetof(nsStyleTextReset, mTextDecoration),
+    VARIANT_HK,
+    kTextBlinkKTable,
+    offsetof(nsStyleTextReset, mTextBlink),
     eStyleAnimType_EnumU8)
 CSS_PROP_TEXTRESET(
     -moz-text-decoration-color,
     text_decoration_color,
     CSS_PROP_DOMPROP_PREFIXED(TextDecorationColor),
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED,
     VARIANT_HCK,
     kBorderColorKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_TEXTRESET(
+    -moz-text-decoration-line,
+    text_decoration_line,
+    CSS_PROP_DOMPROP_PREFIXED(TextDecorationLine),
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_VALUE_PARSER_FUNCTION |
+        CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
+    0,
+    kTextDecorationLineKTable,
+    offsetof(nsStyleTextReset, mTextDecorationLine),
+    eStyleAnimType_EnumU8)
+CSS_PROP_TEXTRESET(
     -moz-text-decoration-style,
     text_decoration_style,
     CSS_PROP_DOMPROP_PREFIXED(TextDecorationStyle),
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE,
     VARIANT_HK,
     kTextDecorationStyleKTable,
     CSS_PROP_NO_OFFSET,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1179,23 +1179,28 @@ const PRInt32 nsCSSProps::kTextAlignKTab
   eCSSKeyword__moz_center, NS_STYLE_TEXT_ALIGN_MOZ_CENTER,
   eCSSKeyword__moz_right, NS_STYLE_TEXT_ALIGN_MOZ_RIGHT,
   eCSSKeyword__moz_left, NS_STYLE_TEXT_ALIGN_MOZ_LEFT,
   eCSSKeyword_start, NS_STYLE_TEXT_ALIGN_DEFAULT,
   eCSSKeyword_end, NS_STYLE_TEXT_ALIGN_END,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const PRInt32 nsCSSProps::kTextDecorationKTable[] = {
-  eCSSKeyword_none, NS_STYLE_TEXT_DECORATION_NONE,
-  eCSSKeyword_underline, NS_STYLE_TEXT_DECORATION_UNDERLINE,
-  eCSSKeyword_overline, NS_STYLE_TEXT_DECORATION_OVERLINE,
-  eCSSKeyword_line_through, NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
-  eCSSKeyword_blink, NS_STYLE_TEXT_DECORATION_BLINK,
-  eCSSKeyword__moz_anchor_decoration, NS_STYLE_TEXT_DECORATION_PREF_ANCHORS,
+const PRInt32 nsCSSProps::kTextBlinkKTable[] = {
+  eCSSKeyword_none, NS_STYLE_TEXT_BLINK_NONE,
+  eCSSKeyword_blink, NS_STYLE_TEXT_BLINK_BLINK,
+  eCSSKeyword_UNKNOWN,-1
+};
+
+const PRInt32 nsCSSProps::kTextDecorationLineKTable[] = {
+  eCSSKeyword_none, NS_STYLE_TEXT_DECORATION_LINE_NONE,
+  eCSSKeyword_underline, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+  eCSSKeyword_overline, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE,
+  eCSSKeyword_line_through, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
+  eCSSKeyword__moz_anchor_decoration, NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS,
   eCSSKeyword_UNKNOWN,-1
 };
 
 const PRInt32 nsCSSProps::kTextDecorationStyleKTable[] = {
   eCSSKeyword__moz_none, NS_STYLE_TEXT_DECORATION_STYLE_NONE,
   eCSSKeyword_solid, NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
   eCSSKeyword_double, NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
   eCSSKeyword_dotted, NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
@@ -1999,16 +2004,24 @@ static const nsCSSProperty gPaddingStart
 static const nsCSSProperty gPaddingEndSubpropTable[] = {
   // nsCSSParser::ParseDirectionalBoxProperty depends on this order
   eCSSProperty_padding_end_value,
   eCSSProperty_padding_right_ltr_source,
   eCSSProperty_padding_left_rtl_source,
   eCSSProperty_UNKNOWN
 };
 
+static const nsCSSProperty gTextDecorationSubpropTable[] = {
+  eCSSProperty_text_blink,
+  eCSSProperty_text_decoration_color,
+  eCSSProperty_text_decoration_line,
+  eCSSProperty_text_decoration_style,
+  eCSSProperty_UNKNOWN
+};
+
 static const nsCSSProperty gTransitionSubpropTable[] = {
   eCSSProperty_transition_property,
   eCSSProperty_transition_duration,
   eCSSProperty_transition_timing_function,
   eCSSProperty_transition_delay,
   eCSSProperty_UNKNOWN
 };
 
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -403,17 +403,18 @@ public:
   static const PRInt32 kSpeakKTable[];
   static const PRInt32 kSpeakHeaderKTable[];
   static const PRInt32 kSpeakNumeralKTable[];
   static const PRInt32 kSpeakPunctuationKTable[];
   static const PRInt32 kSpeechRateKTable[];
   static const PRInt32 kStackSizingKTable[];
   static const PRInt32 kTableLayoutKTable[];
   static const PRInt32 kTextAlignKTable[];
-  static const PRInt32 kTextDecorationKTable[];
+  static const PRInt32 kTextBlinkKTable[];
+  static const PRInt32 kTextDecorationLineKTable[];
   static const PRInt32 kTextDecorationStyleKTable[];
   static const PRInt32 kTextTransformKTable[];
   static const PRInt32 kTransitionTimingFunctionKTable[];
   static const PRInt32 kUnicodeBidiKTable[];
   static const PRInt32 kUserFocusKTable[];
   static const PRInt32 kUserInputKTable[];
   static const PRInt32 kUserModifyKTable[];
   static const PRInt32 kUserSelectKTable[];
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -785,29 +785,29 @@ nsCSSValue::AppendToString(nsCSSProperty
     NS_ABORT_IF_FALSE(GetUnit() == eCSSUnit_Calc, "unexpected unit");
     CSSValueSerializeCalcOps ops(aProperty, aResult);
     css::SerializeCalc(*this, ops);
   }
   else if (eCSSUnit_Integer == unit) {
     aResult.AppendInt(GetIntValue(), 10);
   }
   else if (eCSSUnit_Enumerated == unit) {
-    if (eCSSProperty_text_decoration == aProperty) {
+    if (eCSSProperty_text_decoration_line == aProperty) {
       PRInt32 intValue = GetIntValue();
-      if (NS_STYLE_TEXT_DECORATION_NONE == intValue) {
+      if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
         AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
                            aResult);
       } else {
         // Ignore the "override all" internal value.
         // (It doesn't have a string representation.)
-        intValue &= ~NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL;
+        intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
         nsStyleUtil::AppendBitmaskCSSValue(
           aProperty, intValue,
-          NS_STYLE_TEXT_DECORATION_UNDERLINE,
-          NS_STYLE_TEXT_DECORATION_PREF_ANCHORS,
+          NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+          NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS,
           aResult);
       }
     }
     else if (eCSSProperty_marks == aProperty) {
       PRInt32 intValue = GetIntValue();
       if (intValue == NS_STYLE_PAGE_MARKS_NONE) {
         AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
                            aResult);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2257,35 +2257,57 @@ nsComputedDOMStyle::DoGetTextAlign()
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleText()->mTextAlign,
                                    nsCSSProps::kTextAlignKTable));
   return val;
 }
 
 nsIDOMCSSValue*
+nsComputedDOMStyle::DoGetMozTextBlink()
+{
+  nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
+
+  val->SetIdent(
+    nsCSSProps::ValueToKeywordEnum(GetStyleTextReset()->mTextBlink,
+                                   nsCSSProps::kTextBlinkKTable));
+
+  return val;
+}
+
+nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetTextDecoration()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
-  PRInt32 intValue = GetStyleTextReset()->mTextDecoration;
-
-  if (NS_STYLE_TEXT_DECORATION_NONE == intValue) {
+  PRUint8 line = GetStyleTextReset()->mTextDecorationLine;
+  // Clear the -moz-anchor-decoration bit and the OVERRIDE_ALL bits -- we
+  // don't want these to appear in the computed style.
+  line &= ~(NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS |
+            NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL);
+  PRUint8 blink = GetStyleTextReset()->mTextBlink;
+
+  if (blink == NS_STYLE_TEXT_BLINK_NONE &&
+      line == NS_STYLE_TEXT_DECORATION_LINE_NONE) {
     val->SetIdent(eCSSKeyword_none);
   } else {
-    nsAutoString decorationString;
-    // Clear the -moz-anchor-decoration bit and the OVERRIDE_ALL bits -- we
-    // don't want these to appear in the computed style.
-    intValue &= ~(NS_STYLE_TEXT_DECORATION_PREF_ANCHORS |
-                  NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL);
-    nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration, intValue,
-                                       NS_STYLE_TEXT_DECORATION_UNDERLINE,
-                                       NS_STYLE_TEXT_DECORATION_BLINK,
-                                       decorationString);
-    val->SetString(decorationString);
+    nsAutoString str;
+    if (line != NS_STYLE_TEXT_DECORATION_LINE_NONE) {
+      nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration_line,
+        line, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+        NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, str);
+    }
+    if (blink != NS_STYLE_TEXT_BLINK_NONE) {
+      if (!str.IsEmpty()) {
+        str.Append(PRUnichar(' '));
+      }
+      nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_blink, blink,
+        NS_STYLE_TEXT_BLINK_BLINK, NS_STYLE_TEXT_BLINK_BLINK, str);
+    }
+    val->SetString(str);
   }
 
   return val;
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetMozTextDecorationColor()
 {
@@ -2299,16 +2321,40 @@ nsComputedDOMStyle::DoGetMozTextDecorati
   }
 
   SetToRGBAColor(val, color);
 
   return val;
 }
 
 nsIDOMCSSValue*
+nsComputedDOMStyle::DoGetMozTextDecorationLine()
+{
+  nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
+
+  PRInt32 intValue = GetStyleTextReset()->mTextDecorationLine;
+
+  if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
+    val->SetIdent(eCSSKeyword_none);
+  } else {
+    nsAutoString decorationLineString;
+    // Clear the -moz-anchor-decoration bit and the OVERRIDE_ALL bits -- we
+    // don't want these to appear in the computed style.
+    intValue &= ~(NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS |
+                  NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL);
+    nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration_line,
+      intValue, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
+      NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorationLineString);
+    val->SetString(decorationLineString);
+  }
+
+  return val;
+}
+
+nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetMozTextDecorationStyle()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleTextReset()->GetDecorationStyle(),
                                    nsCSSProps::kTextDecorationStyleKTable));
 
@@ -4342,17 +4388,19 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY(stroke_dashoffset,             StrokeDashoffset),
     COMPUTED_STYLE_MAP_ENTRY(stroke_linecap,                StrokeLinecap),
     COMPUTED_STYLE_MAP_ENTRY(stroke_linejoin,               StrokeLinejoin),
     COMPUTED_STYLE_MAP_ENTRY(stroke_miterlimit,             StrokeMiterlimit),
     COMPUTED_STYLE_MAP_ENTRY(stroke_opacity,                StrokeOpacity),
     COMPUTED_STYLE_MAP_ENTRY(stroke_width,                  StrokeWidth),
     COMPUTED_STYLE_MAP_ENTRY(text_anchor,                   TextAnchor),
     COMPUTED_STYLE_MAP_ENTRY(text_rendering,                TextRendering),
+    COMPUTED_STYLE_MAP_ENTRY(text_blink,                    MozTextBlink),
     COMPUTED_STYLE_MAP_ENTRY(text_decoration_color,         MozTextDecorationColor),
+    COMPUTED_STYLE_MAP_ENTRY(text_decoration_line,          MozTextDecorationLine),
     COMPUTED_STYLE_MAP_ENTRY(text_decoration_style,         MozTextDecorationStyle)
 
   };
 
   *aLength = NS_ARRAY_LENGTH(map);
 
   return map;
 }
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -303,18 +303,20 @@ private:
   nsIDOMCSSValue* DoGetListStyleImage();
   nsIDOMCSSValue* DoGetListStylePosition();
   nsIDOMCSSValue* DoGetListStyleType();
   nsIDOMCSSValue* DoGetImageRegion();
 
   /* Text Properties */
   nsIDOMCSSValue* DoGetLineHeight();
   nsIDOMCSSValue* DoGetTextAlign();
+  nsIDOMCSSValue* DoGetMozTextBlink();
   nsIDOMCSSValue* DoGetTextDecoration();
   nsIDOMCSSValue* DoGetMozTextDecorationColor();
+  nsIDOMCSSValue* DoGetMozTextDecorationLine();
   nsIDOMCSSValue* DoGetMozTextDecorationStyle();
   nsIDOMCSSValue* DoGetTextIndent();
   nsIDOMCSSValue* DoGetTextTransform();
   nsIDOMCSSValue* DoGetTextShadow();
   nsIDOMCSSValue* DoGetLetterSpacing();
   nsIDOMCSSValue* DoGetWordSpacing();
   nsIDOMCSSValue* DoGetWhiteSpace();
   nsIDOMCSSValue* DoGetWordWrap();
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -3366,36 +3366,42 @@ nsRuleNode::ComputeTextResetData(void* a
                 SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC,
                 aContext, mPresContext, canStoreInRuleTree)) {
     if (eCSSUnit_Initial == verticalAlignValue->GetUnit()) {
       text->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE,
                                        eStyleUnit_Enumerated);
     }
   }
 
-  // text-decoration: enum (bit field), inherit, initial
-  const nsCSSValue* decorationValue = aRuleData->ValueForTextDecoration();
-  if (eCSSUnit_Enumerated == decorationValue->GetUnit()) {
-    PRInt32 td = decorationValue->GetIntValue();
-    text->mTextDecoration = td;
-    if (td & NS_STYLE_TEXT_DECORATION_PREF_ANCHORS) {
+  // text-blink: enum, inherit, initial
+  SetDiscrete(*aRuleData->ValueForTextBlink(), text->mTextBlink,
+              canStoreInRuleTree, SETDSC_ENUMERATED, parentText->mTextBlink,
+              NS_STYLE_TEXT_BLINK_NONE, 0, 0, 0, 0);
+
+  // text-decoration-line: enum (bit field), inherit, initial
+  const nsCSSValue* decorationLineValue =
+    aRuleData->ValueForTextDecorationLine();
+  if (eCSSUnit_Enumerated == decorationLineValue->GetUnit()) {
+    PRInt32 td = decorationLineValue->GetIntValue();
+    text->mTextDecorationLine = td;
+    if (td & NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS) {
       PRBool underlineLinks =
         mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
       if (underlineLinks) {
-        text->mTextDecoration |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
+        text->mTextDecorationLine |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
       }
       else {
-        text->mTextDecoration &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
+        text->mTextDecorationLine &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
       }
     }
-  } else if (eCSSUnit_Inherit == decorationValue->GetUnit()) {
+  } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) {
     canStoreInRuleTree = PR_FALSE;
-    text->mTextDecoration = parentText->mTextDecoration;
-  } else if (eCSSUnit_Initial == decorationValue->GetUnit()) {
-    text->mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE;
+    text->mTextDecorationLine = parentText->mTextDecorationLine;
+  } else if (eCSSUnit_Initial == decorationLineValue->GetUnit()) {
+    text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
   }
 
   // text-decoration-color: color, string, enum, inherit, initial
   const nsCSSValue* decorationColorValue =
     aRuleData->ValueForTextDecorationColor();
   nscolor decorationColor;
   if (eCSSUnit_Inherit == decorationColorValue->GetUnit()) {
     canStoreInRuleTree = PR_FALSE;
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -324,24 +324,26 @@ nsStyleContext::SetStyle(nsStyleStructID
   *dataSlot = aStruct;
 }
 
 void
 nsStyleContext::ApplyStyleFixups(nsPresContext* aPresContext)
 {
   // See if we have any text decorations.
   // First see if our parent has text decorations.  If our parent does, then we inherit the bit.
-  if (mParent && mParent->HasTextDecorations())
-    mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
-  else {
+  if (mParent && mParent->HasTextDecorationLines()) {
+    mBits |= NS_STYLE_HAS_TEXT_DECORATION_LINES;
+  } else {
     // We might have defined a decoration.
     const nsStyleTextReset* text = GetStyleTextReset();
-    if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
-        text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
-      mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
+    PRUint8 decorationLine = text->mTextDecorationLine;
+    if (decorationLine != NS_STYLE_TEXT_DECORATION_LINE_NONE &&
+        decorationLine != NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL) {
+      mBits |= NS_STYLE_HAS_TEXT_DECORATION_LINES;
+    }
   }
 
   if ((mParent && mParent->HasPseudoElementData()) || mPseudoTag) {
     mBits |= NS_STYLE_HAS_PSEUDO_ELEMENT_DATA;
   }
 
   // Correct tables.
   const nsStyleDisplay* disp = GetStyleDisplay();
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -123,19 +123,19 @@ public:
   //    non-null, GetStyleIfVisited()->GetRuleNode() == aRulesIfVisited
   //  * RelevantLinkVisited() == aRelevantLinkVisited
   already_AddRefed<nsStyleContext>
   FindChildWithRules(const nsIAtom* aPseudoTag, nsRuleNode* aRules,
                      nsRuleNode* aRulesIfVisited,
                      PRBool aRelevantLinkVisited);
 
   // Does this style context or any of its ancestors have text
-  // decorations?
-  PRBool HasTextDecorations() const
-    { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATIONS); }
+  // decoration lines?
+  PRBool HasTextDecorationLines() const
+    { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); }
 
   // Does this style context represent the style for a pseudo-element or
   // inherit data from such a style context?  Whether this returns true
   // is equivalent to whether it or any of its ancestors returns
   // non-null for GetPseudo.
   PRBool HasPseudoElementData() const
     { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2596,17 +2596,18 @@ nsChangeHint nsStyleQuotes::MaxDifferenc
 // --------------------
 // nsStyleTextReset
 //
 
 nsStyleTextReset::nsStyleTextReset(void) 
 { 
   MOZ_COUNT_CTOR(nsStyleTextReset);
   mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
-  mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE;
+  mTextBlink = NS_STYLE_TEXT_BLINK_NONE;
+  mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
   mTextDecorationColor = NS_RGB(0,0,0);
   mTextDecorationStyle =
     NS_STYLE_TEXT_DECORATION_STYLE_SOLID | BORDER_COLOR_FOREGROUND;
   mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
 }
 
 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource) 
 { 
@@ -2618,25 +2619,25 @@ nsStyleTextReset::~nsStyleTextReset(void
 {
   MOZ_COUNT_DTOR(nsStyleTextReset);
 }
 
 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
 {
   if (mVerticalAlign == aOther.mVerticalAlign
       && mUnicodeBidi == aOther.mUnicodeBidi) {
+    // Reflow for blink changes
+    if (mTextBlink != aOther.mTextBlink) {
+      return NS_STYLE_HINT_REFLOW;
+    }
+
     PRUint8 lineStyle = GetDecorationStyle();
     PRUint8 otherLineStyle = aOther.GetDecorationStyle();
-    if (mTextDecoration != aOther.mTextDecoration ||
+    if (mTextDecorationLine != aOther.mTextDecorationLine ||
         lineStyle != otherLineStyle) {
-      // Reflow for blink changes
-      if ((mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) !=
-            (aOther.mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK)) {
-        return NS_STYLE_HINT_REFLOW;
-      }
       // Reflow for decoration line style changes only to or from double or
       // wave because that may cause overflow area changes
       if (lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
           lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY ||
           otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
           otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
         return NS_STYLE_HINT_REFLOW;
       }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -76,18 +76,18 @@ struct nsCSSValueList;
 // Includes nsStyleStructID.
 #include "nsStyleStructFwd.h"
 
 // Bits for each struct.
 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
 #define NS_STYLE_INHERIT_MASK             0x00ffffff
 
 // Additional bits for nsStyleContext's mBits:
-// See nsStyleContext::HasTextDecorations
-#define NS_STYLE_HAS_TEXT_DECORATIONS     0x01000000
+// See nsStyleContext::HasTextDecorationLines
+#define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x01000000
 // See nsStyleContext::HasPseudoElementData.
 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA  0x02000000
 // See nsStyleContext::RelevantLinkIsVisited
 #define NS_STYLE_RELEVANT_LINK_VISITED    0x04000000
 // See nsStyleContext::IsStyleIfVisited
 #define NS_STYLE_IS_STYLE_IF_VISITED      0x08000000
 // See nsStyleContext::GetPseudoEnum
 #define NS_STYLE_CONTEXT_TYPE_MASK        0xf0000000
@@ -1205,17 +1205,18 @@ struct nsStyleTextReset {
   nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static PRBool ForceCompare() { return PR_FALSE; }
 
   nsStyleCoord  mVerticalAlign;         // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
 
-  PRUint8 mTextDecoration;              // [reset] see nsStyleConsts.h
+  PRUint8 mTextBlink;                   // [reset] see nsStyleConsts.h
+  PRUint8 mTextDecorationLine;          // [reset] see nsStyleConsts.h
   PRUint8 mUnicodeBidi;                 // [reset] see nsStyleConsts.h
 protected:
   PRUint8 mTextDecorationStyle;         // [reset] see nsStyleConsts.h
 
   nscolor mTextDecorationColor;         // [reset] the colors to use for a decoration lines, not used at currentColor
 };
 
 struct nsStyleText {
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2427,33 +2427,51 @@ var gCSSProperties = {
 		domProp: "textAlign",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		// don't know whether left and right are same as start
 		initial_values: [ "start" ],
 		other_values: [ "center", "justify", "end" ],
 		invalid_values: []
 	},
+	"-moz-text-blink": {
+		domProp: "MozTextBlink",
+		inherited: false,
+		type: CSS_TYPE_LONGHAND,
+		initial_values: [ "none" ],
+		other_values: [ "blink" ],
+		invalid_values: [ "underline", "overline", "line-through", "none underline", "underline blink", "blink underline" ]
+	},
 	"text-decoration": {
 		domProp: "textDecoration",
 		inherited: false,
-		type: CSS_TYPE_LONGHAND,
+		type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
+		subproperties: [ "-moz-text-blink", "-moz-text-decoration-color", "-moz-text-decoration-line", "-moz-text-decoration-style" ],
 		initial_values: [ "none" ],
-		other_values: [ "underline", "overline", "line-through", "blink line-through underline", "underline overline line-through blink", "-moz-anchor-decoration", "blink -moz-anchor-decoration" ],
-		invalid_values: [ "underline none", "none underline", "line-through blink line-through" ]
+		other_values: [ "underline", "overline", "line-through", "blink", "blink line-through underline", "underline overline line-through blink", "-moz-anchor-decoration", "blink -moz-anchor-decoration" ],
+		invalid_values: [ "none none", "underline none", "none underline", "blink none", "none blink", "line-through blink line-through", "underline overline line-through blink none", "underline overline line-throuh blink blink",
+		                  "underline red solid", "underline #ff0000", "solid underline", "red underline", "#ff0000 underline" ]
 	},
 	"-moz-text-decoration-color": {
 		domProp: "MozTextDecorationColor",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		prerequisites: { "color": "black" },
 		initial_values: [ "currentColor", "-moz-use-text-color" ],
 		other_values: [ "green", "rgba(255,128,0,0.5)", "transparent" ],
 		invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000" ]
 	},
+	"-moz-text-decoration-line": {
+		domProp: "MozTextDecorationLine",
+		inherited: false,
+		type: CSS_TYPE_LONGHAND,
+		initial_values: [ "none" ],
+		other_values: [ "underline", "overline", "line-through", "line-through underline", "underline overline line-through", "-moz-anchor-decoration", "-moz-anchor-decoration" ],
+		invalid_values: [ "none none", "underline none", "none underline", "line-through blink line-through", "underline overline line-through blink none", "underline overline line-throuh blink blink" ]
+	},
 	"-moz-text-decoration-style": {
 		domProp: "MozTextDecorationStyle",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "solid" ],
 		other_values: [ "double", "dotted", "dashed", "wavy", "-moz-none" ],
 		invalid_values: [ "none", "groove", "ridge", "inset", "outset", "solid dashed", "wave" ]
 	},
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -421,64 +421,68 @@ nsTextBoxFrame::DrawText(nsRenderingCont
     // paint the title
     nscolor overColor;
     nscolor underColor;
     nscolor strikeColor;
     PRUint8 overStyle;
     PRUint8 underStyle;
     PRUint8 strikeStyle;
     nsStyleContext* context = mStyleContext;
-  
-    PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE; // Begin with no decorations
-    PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_UNDERLINE | NS_STYLE_TEXT_DECORATION_OVERLINE |
-                        NS_STYLE_TEXT_DECORATION_LINE_THROUGH; // A mask of all possible decorations.
-    PRBool hasDecorations = context->HasTextDecorations();
+
+    // Begin with no decorations
+    PRUint8 decorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
+    // A mask of all possible decorations.
+    PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
+    PRBool hasDecorationLines = context->HasTextDecorationLines();
 
     do {  // find decoration colors
       const nsStyleTextReset* styleText = context->GetStyleTextReset();
       
-      if (decorMask & styleText->mTextDecoration) {  // a decoration defined here
+      if (decorMask & styleText->mTextDecorationLine) {  // a decoration defined here
         nscolor color;
         if (aOverrideColor) {
           color = *aOverrideColor;
         } else {
           PRBool isForeground;
           styleText->GetDecorationColor(color, isForeground);
           if (isForeground) {
             color = context->GetVisitedDependentColor(eCSSProperty_color);
           }
         }
         PRUint8 style = styleText->GetDecorationStyle();
 
-        if (NS_STYLE_TEXT_DECORATION_UNDERLINE & decorMask & styleText->mTextDecoration) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decorMask &
+              styleText->mTextDecorationLine) {
           underColor = color;
           underStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
-          decorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
+          decorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
         }
-        if (NS_STYLE_TEXT_DECORATION_OVERLINE & decorMask & styleText->mTextDecoration) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & decorMask &
+              styleText->mTextDecorationLine) {
           overColor = color;
           overStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE;
-          decorations |= NS_STYLE_TEXT_DECORATION_OVERLINE;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
+          decorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
         }
-        if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & decorMask & styleText->mTextDecoration) {
+        if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & decorMask &
+              styleText->mTextDecorationLine) {
           strikeColor = color;
           strikeStyle = style;
-          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
-          decorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH;
+          decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
+          decorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
         }
       }
       if (0 != decorMask) {
         context = context->GetParent();
         if (context) {
-          hasDecorations = context->HasTextDecorations();
+          hasDecorationLines = context->HasTextDecorationLines();
         }
       }
-    } while (context && hasDecorations && (0 != decorMask));
+    } while (context && hasDecorationLines && (0 != decorMask));
 
     nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
 
     nscoord offset;
     nscoord size;
     nscoord ascent = fontMet->MaxAscent();
 
@@ -500,24 +504,24 @@ nsTextBoxFrame::DrawText(nsRenderingCont
       fontMet->GetUnderline(offset, size);
       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
       if ((decorations & NS_FONT_DECORATION_UNDERLINE) &&
           underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
         nsCSSRendering::PaintDecorationLine(ctx, underColor,
                           pt, gfxSize(width, sizePixel),
                           ascentPixel, offsetPixel,
-                          NS_STYLE_TEXT_DECORATION_UNDERLINE, underStyle);
+                          NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle);
       }
       if ((decorations & NS_FONT_DECORATION_OVERLINE) &&
           overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
         nsCSSRendering::PaintDecorationLine(ctx, overColor,
                           pt, gfxSize(width, sizePixel),
                           ascentPixel, ascentPixel,
-                          NS_STYLE_TEXT_DECORATION_OVERLINE, overStyle);
+                          NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle);
       }
     }
 
     nsRefPtr<nsRenderingContext> refContext =
         PresContext()->PresShell()->GetReferenceRenderingContext();
 
     aRenderingContext.SetFont(fontMet);
     refContext->SetFont(fontMet);
@@ -588,17 +592,18 @@ nsTextBoxFrame::DrawText(nsRenderingCont
     // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
     if ((decorations & NS_FONT_DECORATION_LINE_THROUGH) &&
         strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
       fontMet->GetStrikeout(offset, size);
       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
       nsCSSRendering::PaintDecorationLine(ctx, strikeColor,
                         pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel,
-                        NS_STYLE_TEXT_DECORATION_LINE_THROUGH, strikeStyle);
+                        NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
+                        strikeStyle);
     }
 }
 
 void nsTextBoxFrame::PaintOneShadow(gfxContext*      aCtx,
                                     const nsRect&    aTextRect,
                                     nsCSSShadowItem* aShadowDetails,
                                     const nscolor&   aForegroundColor,
                                     const nsRect&    aDirtyRect) {
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -3597,17 +3597,17 @@ nsTreeBodyFrame::PaintText(PRInt32      
   textRect.Deflate(bp);
   if (isRTL)
     textRect.x = rightEdge - textRect.width;
 
   // Set our color.
   aRenderingContext.SetColor(textContext->GetStyleColor()->mColor);
 
   // Draw decorations.
-  PRUint8 decorations = textContext->GetStyleTextReset()->mTextDecoration;
+  PRUint8 decorations = textContext->GetStyleTextReset()->mTextDecorationLine;
 
   nscoord offset;
   nscoord size;
   if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) {
     fontMet->GetUnderline(offset, size);
     if (decorations & NS_FONT_DECORATION_OVERLINE)
       aRenderingContext.FillRect(textRect.x, textRect.y, textRect.width, size);
     if (decorations & NS_FONT_DECORATION_UNDERLINE)