Bug 523304 - expose text-underline-color and text-line-through-color text attributes, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Sun, 11 Mar 2012 00:35:02 +0900
changeset 91597 c29f828d1ce456d8764ad305d4a80636723d67db
parent 91596 ba7da6256b234effb34a471e9df5995e804d5146
child 91598 5e6429f6f66d4a1ed51bc4add36014ba9564c60a
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs523304
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 523304 - expose text-underline-color and text-line-through-color text attributes, r=tbsaunde
accessible/src/base/StyleInfo.cpp
accessible/src/base/StyleInfo.h
accessible/src/base/TextAttrs.cpp
accessible/src/base/TextAttrs.h
accessible/tests/mochitest/attributes/test_text.html
content/base/src/nsGkAtomList.h
--- a/accessible/src/base/StyleInfo.cpp
+++ b/accessible/src/base/StyleInfo.cpp
@@ -126,8 +126,17 @@ StyleInfo::FormatColor(const nscolor& aV
 
 void
 StyleInfo::FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue)
 {
   nsCSSKeyword keyword =
     nsCSSProps::ValueToKeywordEnum(aValue, nsCSSProps::kFontStyleKTable);
   AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue);
 }
+
+void
+StyleInfo::FormatTextDecorationStyle(PRUint8 aValue, nsAString& aFormattedValue)
+{
+  nsCSSKeyword keyword =
+    nsCSSProps::ValueToKeywordEnum(aValue,
+                                   nsCSSProps::kTextDecorationStyleKTable);
+  AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue);
+}
--- a/accessible/src/base/StyleInfo.h
+++ b/accessible/src/base/StyleInfo.h
@@ -57,16 +57,17 @@ public:
   void TextIndent(nsAString& aValue);
   void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); }
   void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); }
   void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
   void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
 
   static void FormatColor(const nscolor& aValue, nsString& aFormattedValue);
   static void FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue);
+  static void FormatTextDecorationStyle(PRUint8 aValue, nsAString& aFormattedValue);
 
 private:
   StyleInfo() MOZ_DELETE;
   StyleInfo(const StyleInfo&) MOZ_DELETE;
   StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
 
   void Margin(css::Side aSide, nsAString& aValue);
 
--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -68,19 +68,17 @@ struct nsCSSTextAttrMapItem
 /**
  * The map of CSS properties to text attributes.
  */
 const char* const kAnyValue = nsnull;
 const char* const kCopyValue = nsnull;
 
 static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
 {
-  // CSS name            CSS value        Attribute name                                Attribute value
-  { "text-decoration",   "line-through",  &nsGkAtoms::textLineThroughStyle,  "solid" },
-  { "text-decoration",   "underline",     &nsGkAtoms::textUnderlineStyle,    "solid" },
+  // CSS name            CSS value        Attribute name                     Attribute value
   { "vertical-align",    kAnyValue,       &nsGkAtoms::textPosition,          kCopyValue }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextAttrsMgr
 ////////////////////////////////////////////////////////////////////////////////
 
 void
@@ -136,32 +134,24 @@ TextAttrsMgr::GetAttributes(nsIPersisten
   nsIContent *offsetNode = nsnull, *offsetElm = nsnull;
   nsIFrame *frame = nsnull;
   if (mOffsetAcc) {
     offsetNode = mOffsetAcc->GetContent();
     offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
     frame = offsetElm->GetPrimaryFrame();
   }
 
-  nsTArray<TextAttr*> textAttrArray(10);
+  nsTArray<TextAttr*> textAttrArray(9);
 
   // "language" text attribute
   LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
   textAttrArray.AppendElement(&langTextAttr);
 
-  // "text-line-through-style" text attribute
-  CSSTextAttr lineThroughTextAttr(0, hyperTextElm, offsetElm);
-  textAttrArray.AppendElement(&lineThroughTextAttr);
-
-  // "text-underline-style" text attribute
-  CSSTextAttr underlineTextAttr(1, hyperTextElm, offsetElm);
-  textAttrArray.AppendElement(&underlineTextAttr);
-
   // "text-position" text attribute
-  CSSTextAttr posTextAttr(2, hyperTextElm, offsetElm);
+  CSSTextAttr posTextAttr(0, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(&posTextAttr);
 
   // "background-color" text attribute
   BGColorTextAttr bgColorTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(&bgColorTextAttr);
 
   // "color" text attribute
   ColorTextAttr colorTextAttr(rootFrame, frame);
@@ -178,16 +168,20 @@ TextAttrsMgr::GetAttributes(nsIPersisten
   // "font-style" text attribute
   FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(&fontStyleTextAttr);
 
   // "font-weight" text attribute
   FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(&fontWeightTextAttr);
 
+  // "text-underline(line-through)-style(color)" text attributes
+  TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
+  textAttrArray.AppendElement(&textDecorTextAttr);
+
   // Expose text attributes if applicable.
   if (aAttributes) {
     PRUint32 len = textAttrArray.Length();
     for (PRUint32 idx = 0; idx < len; idx++)
       textAttrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
   }
 
   // Expose text attributes range where they are applied if applicable.
@@ -664,8 +658,87 @@ TextAttrsMgr::FontWeightTextAttr::
   // may not be the weight of the font face used to render the characters.
   // On Mac, font->GetStyle()->weight will just give the same number as
   // getComputedStyle(). fontEntry->Weight() will give the weight of the font
   // face used.
   gfxFontEntry *fontEntry = font->GetFontEntry();
   return fontEntry->Weight();
 #endif
 }
+
+
+////////////////////////////////////////////////////////////////////////////////
+// TextDecorTextAttr
+////////////////////////////////////////////////////////////////////////////////
+
+TextAttrsMgr::TextDecorValue::
+  TextDecorValue(nsIFrame* aFrame)
+{
+  const nsStyleTextReset* textReset = aFrame->GetStyleTextReset();
+  mStyle = textReset->GetDecorationStyle();
+
+  bool isForegroundColor = false;
+  textReset->GetDecorationColor(mColor, isForegroundColor);
+  if (isForegroundColor)
+    mColor = aFrame->GetStyleColor()->mColor;
+
+  mLine = textReset->mTextDecorationLine &
+    (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
+     NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
+}
+
+TextAttrsMgr::TextDecorTextAttr::
+  TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
+  TTextAttr<TextDecorValue>(!aFrame)
+{
+  mRootNativeValue = TextDecorValue(aRootFrame);
+  mIsRootDefined = mRootNativeValue.IsDefined();
+
+  if (aFrame) {
+    mNativeValue = TextDecorValue(aFrame);
+    mIsDefined = mNativeValue.IsDefined();
+  }
+}
+
+bool
+TextAttrsMgr::TextDecorTextAttr::
+  GetValueFor(nsIContent* aContent, TextDecorValue* aValue)
+{
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  if (frame) {
+    *aValue = TextDecorValue(frame);
+    return aValue->IsDefined();
+  }
+
+  return false;
+}
+
+void
+TextAttrsMgr::TextDecorTextAttr::
+  ExposeValue(nsIPersistentProperties* aAttributes, const TextDecorValue& aValue)
+{
+  if (aValue.IsUnderline()) {
+    nsAutoString formattedStyle;
+    StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
+    nsAccUtils::SetAccAttr(aAttributes,
+                           nsGkAtoms::textUnderlineStyle,
+                           formattedStyle);
+
+    nsAutoString formattedColor;
+    StyleInfo::FormatColor(aValue.Color(), formattedColor);
+    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textUnderlineColor,
+                           formattedColor);
+    return;
+  }
+
+  if (aValue.IsLineThrough()) {
+    nsAutoString formattedStyle;
+    StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
+    nsAccUtils::SetAccAttr(aAttributes,
+                           nsGkAtoms::textLineThroughStyle,
+                           formattedStyle);
+
+    nsAutoString formattedColor;
+    StyleInfo::FormatColor(aValue.Color(), formattedColor);
+    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
+                           formattedColor);
+  }
+}
--- a/accessible/src/base/TextAttrs.h
+++ b/accessible/src/base/TextAttrs.h
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTextAttrs_h_
 #define nsTextAttrs_h_
 
 #include "nsIContent.h"
 #include "nsIFrame.h"
 #include "nsIPersistentProperties2.h"
+#include "nsStyleConsts.h"
 
 class nsHyperTextAccessible;
 
 namespace mozilla {
 namespace a11y {
 
 /**
  * Used to expose text attributes for the hyper text accessible (see
@@ -377,14 +378,66 @@ protected:
     // TTextAttr
     virtual bool GetValueFor(nsIContent* aElm, PRInt32* aValue);
     virtual void ExposeValue(nsIPersistentProperties* aAttributes,
                              const PRInt32& aValue);
 
   private:
     PRInt32 GetFontWeight(nsIFrame* aFrame);
   };
+
+
+  /**
+   * TextDecorTextAttr class is used for the work with
+   * "text-line-through-style", "text-line-through-color",
+   * "text-underline-style" and "text-underline-color" text attributes.
+   */
+
+  class TextDecorValue
+  {
+  public:
+    TextDecorValue() { }
+    TextDecorValue(nsIFrame* aFrame);
+
+    nscolor Color() const { return mColor; }
+    PRUint8 Style() const { return mStyle; }
+
+    bool IsDefined() const
+      { return IsUnderline() || IsLineThrough(); }
+    bool IsUnderline() const
+      { return mLine & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; }
+    bool IsLineThrough() const
+      { return mLine & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH; }
+
+    bool operator ==(const TextDecorValue& aValue)
+    {
+      return mColor == aValue.mColor && mLine == aValue.mLine &&
+        mStyle == aValue.mStyle;
+    }
+    bool operator !=(const TextDecorValue& aValue)
+      { return !(*this == aValue); }
+
+  private:
+    nscolor mColor;
+    PRUint8 mLine;
+    PRUint8 mStyle;
+  };
+
+  class TextDecorTextAttr : public TTextAttr<TextDecorValue>
+  {
+  public:
+    TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
+    virtual ~TextDecorTextAttr() { }
+
+  protected:
+
+    // TextAttr
+    virtual bool GetValueFor(nsIContent* aElm, TextDecorValue* aValue);
+    virtual void ExposeValue(nsIPersistentProperties* aAttributes,
+                             const TextDecorValue& aValue);
+  };
+
 }; // TextAttrMgr
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/tests/mochitest/attributes/test_text.html
+++ b/accessible/tests/mochitest/attributes/test_text.html
@@ -264,23 +264,29 @@
       tempElem = tempElem.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = { "font-family": kMonospaceFontFamily };
       testTextAttrs(ID, 70, attrs, defAttrs, 69, 83);
 
       attrs = {};
       testTextAttrs(ID, 84, attrs, defAttrs, 83, 91);
 
-      attrs = { "text-underline-style": "solid" };
+      attrs = {
+        "text-underline-style": "solid",
+        "text-underline-color": gComputedStyle.color
+      };
       testTextAttrs(ID, 92, attrs, defAttrs, 91, 101);
 
       attrs = {};
       testTextAttrs(ID, 102, attrs, defAttrs, 101, 109);
 
-      attrs = { "text-line-through-style": "solid" };
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": gComputedStyle.color
+      };
       testTextAttrs(ID, 110, attrs, defAttrs, 109, 122);
 
       attrs = {};
       testTextAttrs(ID, 123, attrs, defAttrs, 122, 130);
 
       //////////////////////////////////////////////////////////////////////////
       // area10, different single style spans in non-styled paragraph
       ID = "area10";
@@ -318,23 +324,29 @@
       tempElem = tempElem.nextSibling.nextSibling;
       gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
       attrs = { "font-family": kMonospaceFontFamily };
       testTextAttrs(ID, 71, attrs, defAttrs, 70, 84);
 
       attrs = {};
       testTextAttrs(ID, 85, attrs, defAttrs, 84, 92);
 
-      attrs = { "text-underline-style": "solid" };
+      attrs = {
+        "text-underline-style": "solid",
+        "text-underline-color": gComputedStyle.color
+      };
       testTextAttrs(ID, 93, attrs, defAttrs, 92, 102);
 
       attrs = {};
       testTextAttrs(ID, 103, attrs, defAttrs, 102, 110);
 
-      attrs = { "text-line-through-style": "solid" };
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": gComputedStyle.color
+      };
       testTextAttrs(ID, 111, attrs, defAttrs, 110, 123);
 
       attrs = {};
       testTextAttrs(ID, 124, attrs, defAttrs, 123, 131);
 
       //////////////////////////////////////////////////////////////////////////
       // area11, "font-weight" tests
       ID = "area11";
@@ -432,35 +444,82 @@
       testTextAttrs(ID, 22, attrs, defAttrs, 22, 27);
 
       attrs = { "font-family": kCursiveFontFamily };
       testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
 
       attrs = { };
       testTextAttrs(ID, 31, attrs, defAttrs, 31, 45);
 
+      //////////////////////////////////////////////////////////////////////////
+      // area17, "text-decoration" tests
+      ID = "area17";
+      defAttrs = buildDefaultTextAttrs(ID, "12pt");
+      testDefaultTextAttrs(ID, defAttrs);
+
+      attrs = {
+        "text-underline-style": "solid",
+        "text-underline-color": "rgb(0, 0, 0)",
+      };
+      testTextAttrs(ID, 0, attrs, defAttrs, 0, 10);
+
+      attrs = {
+        "text-underline-style": "solid",
+        "text-underline-color": "rgb(0, 0, 255)",
+      };
+      testTextAttrs(ID, 10, attrs, defAttrs, 10, 15);
+
+      attrs = {
+        "text-underline-style": "dotted",
+        "text-underline-color": "rgb(0, 0, 0)",
+      };
+      testTextAttrs(ID, 15, attrs, defAttrs, 15, 22);
+
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": "rgb(0, 0, 0)",
+      };
+      testTextAttrs(ID, 22, attrs, defAttrs, 22, 34);
+
+      attrs = {
+        "text-line-through-style": "solid",
+        "text-line-through-color": "rgb(0, 0, 255)",
+      };
+      testTextAttrs(ID, 34, attrs, defAttrs, 34, 39);
+
+      attrs = {
+        "text-line-through-style": "wavy",
+        "text-line-through-color": "rgb(0, 0, 0)",
+      };
+      testTextAttrs(ID, 39, attrs, defAttrs, 39, 44);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body style="font-size: 12pt">
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
      title="Implement text attributes">
     Mozilla Bug 345759
-  </a><br>
+  </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
      title="font-family text attribute should expose actual font used">
     Mozilla Bug 473576
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=523304"
+     title="expose text-underline-color and text-line-through-color text attributes">
+    Mozilla Bug 523304
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="area1" style="font-size: smaller">Normal <b>Bold</b> Normal</p>
   <p id="area2" style="font-size: 120%">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p>
   <p id="area3" style="background-color: blue;">
@@ -541,10 +600,20 @@
 
   <p id="area16" style="font-family: sans-serif;">
     <span style="font-family: monospace;">text</span>text
     <span style="font-family: serif;">text</span>text
     <span style="font-family: BodoniThatDoesntExist;">text</span>text
     <span style="font-family: Comic Sans MS, cursive;">text</span>text
     <span style="font-family: sans-serif, fantasy;">text</span>text
   </p>
+
+  <p id="area17">
+    <span style="-moz-text-decoration-line: underline;">underline
+    </span><span style="text-decoration: underline; -moz-text-decoration-color: blue;">blue
+    </span><span style="text-decoration: underline; -moz-text-decoration-style: dotted;">dotted
+    </span><span style="-moz-text-decoration-line: line-through;">linethrough
+    </span><span style="text-decoration: line-through; -moz-text-decoration-color: blue;">blue
+    </span><span style="text-decoration: line-through; -moz-text-decoration-style: wavy;">wavy
+    </span>
+  </p>
 </body>
 </html>
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1999,18 +1999,20 @@ GK_ATOM(mixed, "mixed")
 GK_ATOM(multiline, "multiline")
 GK_ATOM(password, "password")
 GK_ATOM(posinset, "posinset") 
 GK_ATOM(select1, "select1")
 GK_ATOM(setsize, "setsize")
 GK_ATOM(tableCellIndex, "table-cell-index")
 GK_ATOM(textAlign, "text-align")
 GK_ATOM(textIndent, "text-indent")
+GK_ATOM(textLineThroughColor, "text-line-through-color")
 GK_ATOM(textLineThroughStyle, "text-line-through-style")
 GK_ATOM(textPosition, "text-position")
+GK_ATOM(textUnderlineColor, "text-underline-color")
 GK_ATOM(textUnderlineStyle, "text-underline-style")
 GK_ATOM(toolbarname, "toolbarname")
 GK_ATOM(toolbarseparator, "toolbarseparator")
 GK_ATOM(toolbarspacer, "toolbarspacer")
 GK_ATOM(toolbarspring, "toolbarspring")
 GK_ATOM(_undefined, "undefined")
 GK_ATOM(xmlroles, "xml-roles")
 #endif