author | Marco Zehe <marco.zehe@googlemail.com> |
Thu, 12 Feb 2009 15:37:03 +0100 | |
changeset 24964 | 0e17dea79681363686f32cabf9a546c6969270e7 |
parent 24962 | e94509d21882f52c2d26cea0607e48d4a2248766 (current diff) |
parent 24963 | 4bb932755d5c4d2a79ce867b256e95cbb3118fcd (diff) |
child 24965 | 222841605203ef3e999a83ef60d772d46b19c0d7 |
push id | unknown |
push user | unknown |
push date | unknown |
milestone | 1.9.2a1pre |
accessible/src/base/nsTextAttrs.cpp | file | annotate | diff | comparison | revisions | |
accessible/src/base/nsTextAttrs.h | file | annotate | diff | comparison | revisions |
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -88,17 +88,17 @@ CPPSRCS = \ nsAccessibleRelation.cpp \ nsAccessibleTreeWalker.cpp \ nsBaseWidgetAccessible.cpp \ nsFormControlAccessible.cpp \ nsRootAccessible.cpp \ nsApplicationAccessible.cpp \ nsCaretAccessible.cpp \ nsTextAccessible.cpp \ - nsTextAttrs.cpp \ + nsTextUtils.cpp \ $(NULL) EXPORTS = \ nsRootAccessible.h \ nsAccessibleEventData.h \ nsAccessNode.h \ $(NULL)
--- a/accessible/src/base/nsAccessibilityAtomList.h +++ b/accessible/src/base/nsAccessibilityAtomList.h @@ -188,27 +188,20 @@ ACCESSIBILITY_ATOM(type, "type") ACCESSIBILITY_ATOM(value, "value") // Alphabetical list of object attributes ACCESSIBILITY_ATOM(display, "display") ACCESSIBILITY_ATOM(textAlign, "text-align") ACCESSIBILITY_ATOM(textIndent, "text-indent") // Alphabetical list of text attributes (AT API) -ACCESSIBILITY_ATOM(color, "color") ACCESSIBILITY_ATOM(backgroundColor, "background-color") -ACCESSIBILITY_ATOM(fontFamily, "font-family") -ACCESSIBILITY_ATOM(fontStyle, "font-style") -ACCESSIBILITY_ATOM(fontWeight, "font-weight") ACCESSIBILITY_ATOM(fontSize, "font-size") ACCESSIBILITY_ATOM(invalid, "invalid") ACCESSIBILITY_ATOM(language, "language") -ACCESSIBILITY_ATOM(textLineThroughStyle, "text-line-through-style") -ACCESSIBILITY_ATOM(textUnderlineStyle, "text-underline-style") -ACCESSIBILITY_ATOM(textPosition, "text-position") // ARIA (DHTML accessibility) attributes // Also add to nsARIAMap.cpp and nsARIAMap.h // ARIA role attribute ACCESSIBILITY_ATOM(role, "role") ACCESSIBILITY_ATOM(aria_activedescendant, "aria-activedescendant") ACCESSIBILITY_ATOM(aria_atomic, "aria-atomic") ACCESSIBILITY_ATOM(aria_autocomplete, "aria-autocomplete")
deleted file mode 100644 --- a/accessible/src/base/nsTextAttrs.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Alexander Surkov <surkov.alexander@gmail.com> (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsTextAttrs.h" - -#include "nsAccessNode.h" -#include "nsHyperTextAccessibleWrap.h" - -//////////////////////////////////////////////////////////////////////////////// -// Constants and structures - -/** - * Item of the gCSSTextAttrsMap map. - */ -struct nsCSSTextAttrMapItem -{ - const char* mCSSName; - const char* mCSSValue; - nsIAtom** mAttrName; - const char* mAttrValue; -}; - -/** - * 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 - { "color", kAnyValue, &nsAccessibilityAtoms::color, kCopyValue }, - { "font-family", kAnyValue, &nsAccessibilityAtoms::fontFamily, kCopyValue }, - { "font-style", kAnyValue, &nsAccessibilityAtoms::fontStyle, kCopyValue }, - { "font-weight", kAnyValue, &nsAccessibilityAtoms::fontWeight, kCopyValue }, - { "text-decoration", "line-through", &nsAccessibilityAtoms::textLineThroughStyle, "solid" }, - { "text-decoration", "underline", &nsAccessibilityAtoms::textUnderlineStyle, "solid" }, - { "vertical-align", kAnyValue, &nsAccessibilityAtoms::textPosition, kCopyValue } -}; - -//////////////////////////////////////////////////////////////////////////////// -// nsTextAttrs - -nsTextAttrsMgr::nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc, - nsIDOMNode *aHyperTextNode, - PRBool aIncludeDefAttrs, - nsIDOMNode *aOffsetNode) : - mHyperTextAcc(aHyperTextAcc), mHyperTextNode(aHyperTextNode), - mIncludeDefAttrs(aIncludeDefAttrs), mOffsetNode(aOffsetNode) -{ -} - -nsresult -nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, - PRInt32 *aStartHTOffset, - PRInt32 *aEndHTOffset) -{ - // 1. Hyper text accessible and its DOM node must be specified always. - // 2. Offset DOM node and result hyper text offsets must be specifed in - // the case of text attributes. - // 3. Offset DOM node and result hyper text offsets must not be specifed but - // include default text attributes flag and attributes list must be specified - // in the case of default text attributes. - NS_PRECONDITION(mHyperTextAcc && mHyperTextNode && - ((mOffsetNode && aStartHTOffset && aEndHTOffset) || - (!mOffsetNode && !aStartHTOffset && !aEndHTOffset && - mIncludeDefAttrs && aAttributes)), - "Wrong usage of nsTextAttrsMgr!"); - - nsCOMPtr<nsIDOMElement> hyperTextElm = - nsCoreUtils::GetDOMElementFor(mHyperTextNode); - nsCOMPtr<nsIDOMElement> offsetElm; - if (mOffsetNode) - offsetElm = nsCoreUtils::GetDOMElementFor(mOffsetNode); - - nsIFrame *rootFrame = nsCoreUtils::GetFrameFor(hyperTextElm); - nsIFrame *frame = nsnull; - if (offsetElm) - frame = nsCoreUtils::GetFrameFor(offsetElm); - - nsTPtrArray<nsITextAttr> textAttrArray(10); - - // "language" text attribute - nsLangTextAttr langTextAttr(mHyperTextAcc, mHyperTextNode, mOffsetNode); - textAttrArray.AppendElement(&langTextAttr); - - // "color" text attribute - nsCSSTextAttr colorTextAttr(0, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&colorTextAttr); - - // "font-family" text attribute - nsCSSTextAttr fontFamilyTextAttr(1, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&fontFamilyTextAttr); - - // "font-style" text attribute - nsCSSTextAttr fontStyleTextAttr(2, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&fontStyleTextAttr); - - // "font-weight" text attribute - nsCSSTextAttr fontWeightTextAttr(3, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&fontWeightTextAttr); - - // "text-line-through-style" text attribute - nsCSSTextAttr lineThroughTextAttr(4, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&lineThroughTextAttr); - - // "text-underline-style" text attribute - nsCSSTextAttr underlineTextAttr(5, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&underlineTextAttr); - - // "text-position" text attribute - nsCSSTextAttr posTextAttr(6, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&posTextAttr); - - // "background-color" text attribute - nsBGColorTextAttr bgColorTextAttr(rootFrame, frame); - textAttrArray.AppendElement(&bgColorTextAttr); - - // "font-size" text attribute - nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame); - textAttrArray.AppendElement(&fontSizeTextAttr); - - // Expose text attributes if applicable. - if (aAttributes) { - PRUint32 len = textAttrArray.Length(); - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = textAttrArray[idx]; - - nsAutoString value; - if (textAttr->GetValue(value, mIncludeDefAttrs)) - nsAccUtils::SetAccAttr(aAttributes, textAttr->GetName(), value); - } - } - - nsresult rv = NS_OK; - - // Expose text attributes range where they are applied if applicable. - if (mOffsetNode) - rv = GetRange(textAttrArray, aStartHTOffset, aEndHTOffset); - - textAttrArray.Clear(); - return rv; -} - -nsresult -nsTextAttrsMgr::GetRange(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset) -{ - nsCOMPtr<nsIDOMElement> rootElm = - nsCoreUtils::GetDOMElementFor(mHyperTextNode); - NS_ENSURE_STATE(rootElm); - - nsCOMPtr<nsIDOMNode> tmpNode(mOffsetNode); - nsCOMPtr<nsIDOMNode> currNode(mOffsetNode); - - PRUint32 len = aTextAttrArray.Length(); - - // Navigate backwards and forwards from current node to the root node to - // calculate range bounds for the text attribute. Navigation sequence is the - // following: - // 1. Navigate through the siblings. - // 2. If the traversed sibling has children then navigate from its leaf child - // to it through whole tree of the traversed sibling. - // 3. Get the parent and cycle algorithm until the root node. - - // Navigate backwards (find the start offset). - while (currNode && currNode != rootElm) { - nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(currNode)); - NS_ENSURE_STATE(currElm); - - if (currNode != mOffsetNode) { - PRBool stop = PR_FALSE; - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = aTextAttrArray[idx]; - if (!textAttr->Equal(currElm)) { - - PRInt32 startHTOffset = 0; - nsCOMPtr<nsIAccessible> startAcc; - nsresult rv = mHyperTextAcc-> - DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset, - getter_AddRefs(startAcc)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!startAcc) - startHTOffset = 0; - - if (startHTOffset > *aStartHTOffset) - *aStartHTOffset = startHTOffset; - - stop = PR_TRUE; - break; - } - } - if (stop) - break; - } - - currNode->GetPreviousSibling(getter_AddRefs(tmpNode)); - if (tmpNode) { - // Navigate through the subtree of traversed children to calculate - // left bound of the range. - FindStartOffsetInSubtree(aTextAttrArray, tmpNode, currNode, - aStartHTOffset); - } - - currNode->GetParentNode(getter_AddRefs(tmpNode)); - currNode.swap(tmpNode); - } - - // Navigate forwards (find the end offset). - PRBool moveIntoSubtree = PR_TRUE; - currNode = mOffsetNode; - - while (currNode && currNode != rootElm) { - nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(currNode)); - NS_ENSURE_STATE(currElm); - - // Stop new end offset searching if the given text attribute changes its - // value. - PRBool stop = PR_FALSE; - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = aTextAttrArray[idx]; - if (!textAttr->Equal(currElm)) { - - PRInt32 endHTOffset = 0; - nsresult rv = mHyperTextAcc-> - DOMPointToHypertextOffset(currNode, -1, &endHTOffset); - NS_ENSURE_SUCCESS(rv, rv); - - if (endHTOffset < *aEndHTOffset) - *aEndHTOffset = endHTOffset; - - stop = PR_TRUE; - break; - } - } - - if (stop) - break; - - if (moveIntoSubtree) { - // Navigate through subtree of traversed node. We use 'moveIntoSubtree' - // flag to avoid traversing the same subtree twice. - currNode->GetFirstChild(getter_AddRefs(tmpNode)); - if (tmpNode) - FindEndOffsetInSubtree(aTextAttrArray, tmpNode, aEndHTOffset); - } - - currNode->GetNextSibling(getter_AddRefs(tmpNode)); - moveIntoSubtree = PR_TRUE; - if (!tmpNode) { - currNode->GetParentNode(getter_AddRefs(tmpNode)); - moveIntoSubtree = PR_FALSE; - } - - currNode.swap(tmpNode); - } - - return NS_OK; -} - -PRBool -nsTextAttrsMgr::FindEndOffsetInSubtree(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - nsIDOMNode *aCurrNode, - PRInt32 *aHTOffset) -{ - if (!aCurrNode) - return PR_FALSE; - - nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(aCurrNode)); - NS_ENSURE_STATE(currElm); - - // If the given text attribute (pointed by nsTextAttr object) changes its - // value on the traversed element then fit the end of range. - PRUint32 len = aTextAttrArray.Length(); - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = aTextAttrArray[idx]; - if (!textAttr->Equal(currElm)) { - PRInt32 endHTOffset = 0; - nsresult rv = mHyperTextAcc-> - DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset); - NS_ENSURE_SUCCESS(rv, PR_FALSE); - - if (endHTOffset < *aHTOffset) - *aHTOffset = endHTOffset; - - return PR_TRUE; - } - } - - // Deeply traverse into the tree to fit the end of range. - nsCOMPtr<nsIDOMNode> nextNode; - aCurrNode->GetFirstChild(getter_AddRefs(nextNode)); - if (nextNode) { - PRBool res = FindEndOffsetInSubtree(aTextAttrArray, nextNode, aHTOffset); - if (res) - return res; - } - - aCurrNode->GetNextSibling(getter_AddRefs(nextNode)); - if (nextNode) { - if (FindEndOffsetInSubtree(aTextAttrArray, nextNode, aHTOffset)) - return PR_TRUE; - } - - return PR_FALSE; -} - -PRBool -nsTextAttrsMgr::FindStartOffsetInSubtree(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - nsIDOMNode *aCurrNode, - nsIDOMNode *aPrevNode, - PRInt32 *aHTOffset) -{ - if (!aCurrNode) - return PR_FALSE; - - // Find the closest element back to the traversed element. - nsCOMPtr<nsIDOMNode> nextNode; - aCurrNode->GetLastChild(getter_AddRefs(nextNode)); - if (nextNode) { - if (FindStartOffsetInSubtree(aTextAttrArray, nextNode, aPrevNode, aHTOffset)) - return PR_TRUE; - } - - nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(aCurrNode)); - NS_ENSURE_STATE(currElm); - - // If the given text attribute (pointed by nsTextAttr object) changes its - // value on the traversed element then fit the start of range. - PRUint32 len = aTextAttrArray.Length(); - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = aTextAttrArray[idx]; - if (!textAttr->Equal(currElm)) { - - PRInt32 startHTOffset = 0; - nsCOMPtr<nsIAccessible> startAcc; - nsresult rv = mHyperTextAcc-> - DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset, - getter_AddRefs(startAcc)); - NS_ENSURE_SUCCESS(rv, PR_FALSE); - - if (!startAcc) - startHTOffset = 0; - - if (startHTOffset > *aHTOffset) - *aHTOffset = startHTOffset; - - return PR_TRUE; - } - } - - // Moving backwards to find the start of range. - aCurrNode->GetPreviousSibling(getter_AddRefs(nextNode)); - if (nextNode) { - if (FindStartOffsetInSubtree(aTextAttrArray, nextNode, aCurrNode, aHTOffset)) - return PR_TRUE; - } - - return PR_FALSE; -} - -//////////////////////////////////////////////////////////////////////////////// -// nsLangTextAttr - -nsLangTextAttr::nsLangTextAttr(nsHyperTextAccessible *aRootAcc, - nsIDOMNode *aRootNode, nsIDOMNode *aNode) : - nsTextAttr(aNode == nsnull) -{ - mRootContent = do_QueryInterface(aRootNode); - - nsresult rv = aRootAcc->GetLanguage(mRootNativeValue); - mIsRootDefined = NS_SUCCEEDED(rv) && !mRootNativeValue.IsEmpty(); - - if (aNode) { - nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); - mIsDefined = GetLang(content, mNativeValue); - } -} - -PRBool -nsLangTextAttr::GetValueFor(nsIDOMElement *aElm, nsAutoString *aValue) -{ - nsCOMPtr<nsIContent> content = do_QueryInterface(aElm); - return GetLang(content, *aValue); -} - -void -nsLangTextAttr::Format(const nsAutoString& aValue, nsAString& aFormattedValue) -{ - aFormattedValue = aValue; -} - -PRBool -nsLangTextAttr::GetLang(nsIContent *aContent, nsAString& aLang) -{ - nsCoreUtils::GetLanguageFor(aContent, mRootContent, aLang); - return !aLang.IsEmpty(); -} - -//////////////////////////////////////////////////////////////////////////////// -// nsCSSTextAttr - -nsCSSTextAttr::nsCSSTextAttr(PRUint32 aIndex, nsIDOMElement *aRootElm, - nsIDOMElement *aElm) : - nsTextAttr(aElm == nsnull), mIndex(aIndex) -{ - mIsRootDefined = GetValueFor(aRootElm, &mRootNativeValue); - - if (aElm) - mIsDefined = GetValueFor(aElm, &mNativeValue); -} - -nsIAtom* -nsCSSTextAttr::GetName() -{ - return *gCSSTextAttrsMap[mIndex].mAttrName; -} - -PRBool -nsCSSTextAttr::GetValueFor(nsIDOMElement *aElm, nsAutoString *aValue) -{ - nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl; - nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm, - getter_AddRefs(currStyleDecl)); - if (!currStyleDecl) - return PR_FALSE; - - NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName); - - nsresult rv = currStyleDecl->GetPropertyValue(cssName, *aValue); - if (NS_FAILED(rv)) - return PR_TRUE; - - const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue; - if (cssValue != kAnyValue && !aValue->EqualsASCII(cssValue)) - return PR_FALSE; - - return PR_TRUE; -} - -void -nsCSSTextAttr::Format(const nsAutoString& aValue, nsAString& aFormattedValue) -{ - const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue; - if (attrValue != kCopyValue) - AppendASCIItoUTF16(attrValue, aFormattedValue); - else - aFormattedValue = aValue; -} - -//////////////////////////////////////////////////////////////////////////////// -// nsBackgroundTextAttr - -nsBGColorTextAttr::nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : - nsTextAttr(aFrame == nsnull), mRootFrame(aRootFrame) -{ - mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue); - if (aFrame) - mIsDefined = GetColor(aFrame, &mNativeValue); -} - -PRBool -nsBGColorTextAttr::GetValueFor(nsIDOMElement *aElm, nscolor *aValue) -{ - nsIFrame *frame = nsCoreUtils::GetFrameFor(aElm); - if (!frame) - return PR_FALSE; - - return GetColor(frame, aValue); -} - -void -nsBGColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue) -{ - // Combine the string like rgb(R, G, B) from nscolor. - nsAutoString value; - value.AppendLiteral("rgb("); - value.AppendInt(NS_GET_R(aValue)); - value.AppendLiteral(", "); - value.AppendInt(NS_GET_G(aValue)); - value.AppendLiteral(", "); - value.AppendInt(NS_GET_B(aValue)); - value.Append(')'); - - aFormattedValue = value; -} - -PRBool -nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor) -{ - const nsStyleBackground *styleBackground = aFrame->GetStyleBackground(); - - if (!styleBackground->IsTransparent()) { - *aColor = styleBackground->mBackgroundColor; - return PR_TRUE; - } - - nsIFrame *parentFrame = aFrame->GetParent(); - if (!parentFrame) { - *aColor = aFrame->PresContext()->DefaultBackgroundColor(); - return PR_TRUE; - } - - // Each frame of parents chain for the initially passed 'aFrame' has - // transparent background color. So background color isn't changed from - // 'mRootFrame' to initially passed 'aFrame'. - if (parentFrame == mRootFrame) - return PR_FALSE; - - return GetColor(parentFrame, aColor); -} - -//////////////////////////////////////////////////////////////////////////////// -// nsFontSizeTextAttr - -nsFontSizeTextAttr::nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : - nsTextAttr(aFrame == nsnull) -{ - mDC = aRootFrame->PresContext()->DeviceContext(); - - mRootNativeValue = GetFontSize(aRootFrame); - mIsRootDefined = PR_TRUE; - - if (aFrame) { - mNativeValue = GetFontSize(aFrame); - mIsDefined = PR_TRUE; - } -} - -PRBool -nsFontSizeTextAttr::GetValueFor(nsIDOMElement *aElm, nscoord *aValue) -{ - nsIFrame *frame = nsCoreUtils::GetFrameFor(aElm); - if (!frame) - return PR_FALSE; - - *aValue = GetFontSize(frame); - return PR_TRUE; -} - -void -nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) -{ - // Convert from nscoord to pt. - // - // Note: according to IA2, "The conversion doesn't have to be exact. - // The intent is to give the user a feel for the size of the text." - // - // ATK does not specify a unit and will likely follow IA2 here. - // - // XXX todo: consider sharing this code with layout module? (bug 474621) - float inches = static_cast<float>(aValue) / - static_cast<float>(mDC->AppUnitsPerInch()); - int pts = static_cast<int>(inches * 72 + .5); // 72 pts per inch - - nsAutoString value; - value.AppendInt(pts); - value.Append(NS_LITERAL_STRING("pt")); - aFormattedValue = value; -} - -nscoord -nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame) -{ - nsStyleFont* styleFont = - (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font)); - - return styleFont->mSize; -}
deleted file mode 100644 --- a/accessible/src/base/nsTextAttrs.h +++ /dev/null @@ -1,371 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Alexander Surkov <surkov.alexander@gmail.com> (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsTextAttrs_h_ -#define nsTextAttrs_h_ - -class nsHyperTextAccessible; - -#include "nsAccessibilityAtoms.h" - -#include "nsIDOMNode.h" -#include "nsIDOMElement.h" -#include "nsIDOMCSSStyleDeclaration.h" - -#include "nsIContent.h" -#include "nsIFrame.h" -#include "nsIPersistentProperties2.h" - -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsTPtrArray.h" - -class nsITextAttr; - -/** - * Used to expose text attributes for the hyper text accessible (see - * nsHyperTextAccessible class). It is indended for the work with 'language' and - * CSS based text attributes. - * - * @note "invalid: spelling" text attrbiute is implemented entirerly in - * nsHyperTextAccessible class. - */ -class nsTextAttrsMgr -{ -public: - /** - * Constructor. If instance of the class is intended to expose default text - * attributes then 'aIncludeDefAttrs' and 'oOffsetNode' argument must be - * skiped. - * - * @param aHyperTextAcc hyper text accessible text attributes are - * calculated for - * @param aHyperTextNode DOM node of the given hyper text accessbile - * @param aIncludeDefAttrs [optional] indicates whether default text - * attributes should be included into list of exposed - * text attributes. - * @param oOffsetNode [optional] DOM node represents hyper text offset - * inside hyper text accessible - */ - nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc, - nsIDOMNode *aHyperTextNode, - PRBool aIncludeDefAttrs = PR_TRUE, - nsIDOMNode *oOffsetNode = nsnull); - - /* - * Return text attributes and hyper text offsets where these attributes are - * applied. Offsets are calculated in the case of non default attributes. - * - * @note In the case of default attributes pointers on hyper text offsets - * must be skiped. - * - * @param aAttributes [in, out] text attributes list - * @param aStartHTOffset [out, optional] start hyper text offset - * @param aEndHTOffset [out, optional] end hyper text offset - */ - nsresult GetAttributes(nsIPersistentProperties *aAttributes, - PRInt32 *aStartHTOffset = nsnull, - PRInt32 *aEndHTOffset = nsnull); - -protected: - - /** - * Calculates range (start and end offsets) of text where the text attributes - * are stretched. New offsets may be smaller if one of text attributes changes - * its value before or after the given offsets. - * - * @param aTextAttrArray [in] text attributes array - * @param aStartHTOffset [in, out] the start offset - * @param aEndHTOffset [in, out] the end offset - */ - nsresult GetRange(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset); - - /* - * Find new end offset for text attributes navigating through the tree. New - * end offset may be smaller if one of text attributes changes its value - * before the given end offset. - * - * @param aTextAttrArray [in] text attributes array - * @param aCurrNode [in] the first node of the tree - * @param aHTOffset [in, out] the end offset - * @return true if the end offset has been changed - */ - PRBool FindEndOffsetInSubtree(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - nsIDOMNode *aCurrNode, PRInt32 *aHTOffset); - - /* - * Find the start offset for text attributes navigating through the tree. New - * start offset may be bigger if one of text attributes changes its value - * after the given start offset. - * - * @param aTextAttrArray [in] text attributes array - * @param aCurrNode [in] the node navigating through thee thee is - * started from - * @param aPrevNode [in] the previous node placed before the start node - * @param aHTOffset [in, out] the start offset - * @return true if the start offset has been changed - */ - PRBool FindStartOffsetInSubtree(const nsTPtrArray<nsITextAttr>& aTextAttrArray, - nsIDOMNode *aCurrNode, nsIDOMNode *aPrevNode, - PRInt32 *aHTOffset); - -private: - nsRefPtr<nsHyperTextAccessible> mHyperTextAcc; - nsCOMPtr<nsIDOMNode> mHyperTextNode; - - PRBool mIncludeDefAttrs; - nsCOMPtr<nsIDOMNode> mOffsetNode; -}; - - -//////////////////////////////////////////////////////////////////////////////// -// Private implementation details - -/** - * Interface class of text attribute class implementations. - */ -class nsITextAttr -{ -public: - /** - * Return the name of text attribute. - */ - virtual nsIAtom* GetName() = 0; - - /** - * Retrieve the value of text attribute in out param, return true if differs - * from the default value of text attribute or if include default attribute - * value flag is setted. - * - * @param aValue [in, out] the value of text attribute - * @param aIncludeDefAttrValue [in] include default attribute value flag - * @return true if text attribute value differs from - * default or include default attribute value - * flag is applied - */ - virtual PRBool GetValue(nsAString& aValue, PRBool aIncludeDefAttrValue) = 0; - - /** - * Return true if the text attribute value on the given element equals with - * predefined attribute value. - */ - virtual PRBool Equal(nsIDOMElement *aElm) = 0; -}; - - -/** - * Base class to work with text attributes. See derived classes below. - */ -template<class T> -class nsTextAttr : public nsITextAttr -{ -public: - nsTextAttr(PRBool aGetRootValue) : mGetRootValue(aGetRootValue) {} - - // nsITextAttr - virtual PRBool GetValue(nsAString& aValue, PRBool aIncludeDefAttrValue) - { - if (mGetRootValue) { - Format(mRootNativeValue, aValue); - return mIsRootDefined; - } - - PRBool isDefined = mIsDefined; - T* nativeValue = &mNativeValue; - - if (!isDefined) { - if (aIncludeDefAttrValue) { - isDefined = mIsRootDefined; - nativeValue = &mRootNativeValue; - } - } else if (!aIncludeDefAttrValue) { - isDefined = mRootNativeValue != mNativeValue; - } - - if (!isDefined) - return PR_FALSE; - - Format(*nativeValue, aValue); - return PR_TRUE; - } - - virtual PRBool Equal(nsIDOMElement *aElm) - { - T nativeValue; - PRBool isDefined = GetValueFor(aElm, &nativeValue); - - if (!mIsDefined && !isDefined) - return PR_TRUE; - - if (mIsDefined && isDefined) - return nativeValue == mNativeValue; - - if (mIsDefined) - return mNativeValue == mRootNativeValue; - - return nativeValue == mRootNativeValue; - } - -protected: - - // Return native value for the given DOM element. - virtual PRBool GetValueFor(nsIDOMElement *aElm, T *aValue) = 0; - - // Format native value to text attribute value. - virtual void Format(const T& aValue, nsAString& aFormattedValue) = 0; - - // Indicates if root value should be exposed. - PRBool mGetRootValue; - - // Native value and flag indicating if the value is defined (initialized in - // derived classes). Note, undefined native value means it is inherited - // from root. - T mNativeValue; - PRBool mIsDefined; - - // Native root value and flag indicating if the value is defined (initialized - // in derived classes). - T mRootNativeValue; - PRBool mIsRootDefined; -}; - - -/** - * Class is used for the work with 'language' text attribute in nsTextAttrsMgr - * class. - */ -class nsLangTextAttr : public nsTextAttr<nsAutoString> -{ -public: - nsLangTextAttr(nsHyperTextAccessible *aRootAcc, nsIDOMNode *aRootNode, - nsIDOMNode *aNode); - - // nsITextAttr - virtual nsIAtom *GetName() { return nsAccessibilityAtoms::language; } - -protected: - - // nsTextAttr - virtual PRBool GetValueFor(nsIDOMElement *aElm, nsAutoString *aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); - -private: - PRBool GetLang(nsIContent *aContent, nsAString& aLang); - nsCOMPtr<nsIContent> mRootContent; -}; - - -/** - * Class is used for the work with CSS based text attributes in nsTextAttrsMgr - * class. - */ -class nsCSSTextAttr : public nsTextAttr<nsAutoString> -{ -public: - nsCSSTextAttr(PRUint32 aIndex, nsIDOMElement *aRootElm, nsIDOMElement *aElm); - - // nsITextAttr - virtual nsIAtom *GetName(); - -protected: - - // nsTextAttr - virtual PRBool GetValueFor(nsIDOMElement *aElm, nsAutoString *aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); - -private: - PRInt32 mIndex; -}; - - -/** - * Class is used for the work with 'background-color' text attribute in - * nsTextAttrsMgr class. - */ -class nsBGColorTextAttr : public nsTextAttr<nscolor> -{ -public: - nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); - - // nsITextAttr - virtual nsIAtom *GetName() { return nsAccessibilityAtoms::backgroundColor; } - -protected: - // nsTextAttr - virtual PRBool GetValueFor(nsIDOMElement *aElm, nscolor *aValue); - virtual void Format(const nscolor& aValue, nsAString& aFormattedValue); - -private: - PRBool GetColor(nsIFrame *aFrame, nscolor *aColor); - nsIFrame *mRootFrame; -}; - - -/** - * Class is used for the work with "font-size" text attribute in nsTextAttrsMgr - * class. - */ -class nsFontSizeTextAttr : public nsTextAttr<nscoord> -{ -public: - nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); - - // nsITextAttr - virtual nsIAtom *GetName() { return nsAccessibilityAtoms::fontSize; } - -protected: - - // nsTextAttr - virtual PRBool GetValueFor(nsIDOMElement *aElm, nscoord *aValue); - virtual void Format(const nscoord& aValue, nsAString& aFormattedValue); - -private: - - /** - * Return font size for the given frame. - * - * @param aFrame [in] the given frame to query font-size - * @return font size - */ - nscoord GetFontSize(nsIFrame *aFrame); - - nsIDeviceContext *mDC; -}; - -#endif
new file mode 100644 --- /dev/null +++ b/accessible/src/base/nsTextUtils.cpp @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsTextUtils.h" + +#include "nsAccessNode.h" + +//////////////////////////////////////////////////////////////////////////////// +// nsLangTextAttr + +PRBool +nsLangTextAttr::Equal(nsIDOMElement *aElm) +{ + nsCOMPtr<nsIContent> content(do_QueryInterface(aElm)); + if (!content) + return PR_FALSE; + + nsAutoString lang; + nsCoreUtils::GetLanguageFor(content, mRootContent, lang); + + return lang == mLang; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsCSSTextAttr + +/** + * Item of the gCSSTextAttrsMap map. + */ +struct nsCSSTextAttrMapItem +{ + const char* mCSSName; + const char* mCSSValue; + const char* mAttrName; + const char* mAttrValue; +}; + +/** + * The map of CSS properties to text attributes. + */ + +const char* const kAnyValue = nsnull; +const char* const kCopyName = nsnull; +const char* const kCopyValue = nsnull; + +static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = { + // CSS name CSS value Attribute name Attribute value + { "color", kAnyValue, kCopyName, kCopyValue }, + { "font-family", kAnyValue, kCopyName, kCopyValue }, + { "font-style", kAnyValue, kCopyName, kCopyValue }, + { "font-weight", kAnyValue, kCopyName, kCopyValue }, + { "text-decoration", "line-through", "text-line-through-style", "solid" }, + { "text-decoration", "underline", "text-underline-style", "solid" }, + { "vertical-align", kAnyValue, "text-position", kCopyValue } +}; + +nsCSSTextAttr::nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm, + nsIDOMElement *aRootElm) : + mIndex(-1), mIncludeDefAttrValue(aIncludeDefAttrValue) +{ + nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm, + getter_AddRefs(mStyleDecl)); + + if (!mIncludeDefAttrValue) + nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aRootElm, + getter_AddRefs(mDefStyleDecl)); +} + +PRBool +nsCSSTextAttr::Equal(nsIDOMElement *aElm) +{ + if (!aElm || !mStyleDecl) + return PR_FALSE; + + nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl; + nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm, + getter_AddRefs(currStyleDecl)); + if (!currStyleDecl) + return PR_FALSE; + + NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName); + + nsAutoString currValue; + nsresult rv = currStyleDecl->GetPropertyValue(cssName, currValue); + if (NS_FAILED(rv)) + return PR_FALSE; + + nsAutoString value; + rv = mStyleDecl->GetPropertyValue(cssName, value); + return NS_SUCCEEDED(rv) && value == currValue; +} + +PRBool +nsCSSTextAttr::Iterate() +{ + return ++mIndex < static_cast<PRInt32>(NS_ARRAY_LENGTH(gCSSTextAttrsMap)); +} + +PRBool +nsCSSTextAttr::Get(nsACString& aName, nsAString& aValue) +{ + if (!mStyleDecl) + return PR_FALSE; + + NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName); + nsresult rv = mStyleDecl->GetPropertyValue(cssName, aValue); + if (NS_FAILED(rv)) + return PR_FALSE; + + // Don't expose text attribute if corresponding CSS value on the element + // equals to CSS value on the root element and we don't want to include + // default values. + if (!mIncludeDefAttrValue) { + if (!mDefStyleDecl) + return PR_FALSE; + + nsAutoString defValue; + mDefStyleDecl->GetPropertyValue(cssName, defValue); + if (defValue == aValue) + return PR_FALSE; + } + + // Don't expose text attribute if its required specific CSS value isn't + // matched with the CSS value we got. + const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue; + if (cssValue != kAnyValue && !aValue.EqualsASCII(cssValue)) + return PR_FALSE; + + // Get the name of text attribute. + if (gCSSTextAttrsMap[mIndex].mAttrName != kCopyName) + aName = gCSSTextAttrsMap[mIndex].mAttrName; + else + aName = gCSSTextAttrsMap[mIndex].mCSSName; + + // Get the value of text attribute. + const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue; + if (attrValue != kCopyValue) + AppendASCIItoUTF16(attrValue, aValue); + + return PR_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsBackgroundTextAttr + +nsBackgroundTextAttr::nsBackgroundTextAttr(nsIFrame *aFrame, + nsIFrame *aRootFrame) : + mFrame(aFrame), mRootFrame(aRootFrame) +{ +} + +PRBool +nsBackgroundTextAttr::Equal(nsIDOMElement *aElm) +{ + nsIFrame *frame = nsCoreUtils::GetFrameFor(aElm); + if (!frame) + return PR_FALSE; + + return GetColor(mFrame) == GetColor(frame); +} + +PRBool +nsBackgroundTextAttr::Get(nsAString& aValue) +{ + // Do not expose "background-color" text attribute if its value is matched + // with the default value. + nscolor color = GetColor(mFrame); + if (mRootFrame && color == GetColor(mRootFrame)) + return PR_FALSE; + + // Combine the string like rgb(R, G, B) from nscolor. + nsAutoString value; + value.AppendLiteral("rgb("); + value.AppendInt(NS_GET_R(color)); + value.AppendLiteral(", "); + value.AppendInt(NS_GET_G(color)); + value.AppendLiteral(", "); + value.AppendInt(NS_GET_B(color)); + value.Append(')'); + + aValue = value; + return PR_TRUE; +} + +nscolor +nsBackgroundTextAttr::GetColor(nsIFrame *aFrame) +{ + const nsStyleBackground *styleBackground = aFrame->GetStyleBackground(); + + if (!styleBackground->IsTransparent()) + return styleBackground->mBackgroundColor; + + nsIFrame *parentFrame = aFrame->GetParent(); + if (!parentFrame) + return aFrame->PresContext()->DefaultBackgroundColor(); + + // Each frame of parents chain for the initially passed 'aFrame' has + // transparent background color. So background color isn't changed from + // 'mRootFrame' to initially passed 'aFrame'. + if (parentFrame == mRootFrame) + return GetColor(mRootFrame); + + return GetColor(parentFrame); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsFontSizeTextAttr + +nsFontSizeTextAttr::nsFontSizeTextAttr(nsIFrame *aFrame, + nsIFrame *aRootFrame) : + mFrame(aFrame), mRootFrame(aRootFrame) +{ +} + +PRBool +nsFontSizeTextAttr::Equal(nsIDOMElement *aElm) +{ + nsIFrame *frame = nsCoreUtils::GetFrameFor(aElm); + if (!frame) + return PR_FALSE; + + return GetFontSize(mFrame) == GetFontSize(frame); +} + + +PRBool +nsFontSizeTextAttr::Get(nsAString& aValue) +{ + // Do not expose "font-size" text attribute if its value is the same + // as the default value. + nscoord fontsize = GetFontSize(mFrame); + if (mRootFrame && fontsize == GetFontSize(mRootFrame)) + return PR_FALSE; + + // Convert from nscoord to pt. + // + // Note: according to IA2, "The conversion doesn't have to be exact. + // The intent is to give the user a feel for the size of the text." + // + // ATK does not specify a unit and will likely follow IA2 here. + // + // XXX todo: consider sharing this code with layout module? (bug 474621) + nsIDeviceContext *dc = mFrame->PresContext()->DeviceContext(); + float inches = static_cast<float>(GetFontSize(mFrame)) / + static_cast<float>(dc->AppUnitsPerInch()); + int pts = inches * 72 + .5; // 72 pts per inch + + nsAutoString value; + value.AppendInt(pts); + value.Append(NS_LITERAL_STRING("pt")); + aValue = value; + + return PR_TRUE; +} + +nscoord +nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame) +{ + nsStyleFont* styleFont = + (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font)); + + return styleFont->mSize; +}
new file mode 100644 --- /dev/null +++ b/accessible/src/base/nsTextUtils.h @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTextUtils_h_ +#define nsTextUtils_h_ + +#include "nsIDOMElement.h" +#include "nsIDOMCSSStyleDeclaration.h" + +#include "nsIContent.h" +#include "nsIFrame.h" + +#include "nsCOMPtr.h" +#include "nsString.h" + +/** + * Base class to work with text attributes. See derived classes below. + */ +class nsTextAttr +{ +public: + /** + * Return true if the text attribute for the given element equals with + * predefined attribute. + */ + virtual PRBool Equal(nsIDOMElement *aElm) = 0; +}; + +/** + * Class is used for the work with 'lang' text attributes. Used in + * nsHyperTextAccessible. + */ +class nsLangTextAttr : public nsTextAttr +{ +public: + nsLangTextAttr(nsAString& aLang, nsIContent *aRootContent) : + mLang(aLang), mRootContent(aRootContent) { } + + virtual PRBool Equal(nsIDOMElement *aElm); + +private: + nsString mLang; + nsCOMPtr<nsIContent> mRootContent; +}; + +/** + * Class is used for the work with CSS based text attributes. Used in + * nsHyperTextAccessible. + */ +class nsCSSTextAttr : public nsTextAttr +{ +public: + nsCSSTextAttr(PRBool aIncludeDefAttrValue, nsIDOMElement *aElm, + nsIDOMElement *aRootElm); + + // nsTextAttr + virtual PRBool Equal(nsIDOMElement *aElm); + + // nsCSSTextAttr + /** + * Interates through attributes. + */ + PRBool Iterate(); + + /** + * Get name and value of attribute. + */ + PRBool Get(nsACString& aName, nsAString& aValue); + +private: + PRInt32 mIndex; + PRBool mIncludeDefAttrValue; + + nsCOMPtr<nsIDOMCSSStyleDeclaration> mStyleDecl; + nsCOMPtr<nsIDOMCSSStyleDeclaration> mDefStyleDecl; +}; + +/** + * Class is used for the work with "background-color" text attribute. It is + * used in nsHyperTextAccessible. + */ +class nsBackgroundTextAttr : public nsTextAttr +{ +public: + nsBackgroundTextAttr(nsIFrame *aFrame, nsIFrame *aRootFrame); + + // nsTextAttr + virtual PRBool Equal(nsIDOMElement *aElm); + + // nsBackgroundTextAttr + + /** + * Retrieve the "background-color" in out param, return true if differs from + * the default background-color. + * + * @param aValue [out] the background color in pts + * @return true if background color differs from default + */ + virtual PRBool Get(nsAString& aValue); + +private: + /** + * Return background color for the given frame. + * + * @note If background color for the given frame is transparent then walk + * trhough the frame parents chain until we'll got either a frame with + * not transparent background color or the given root frame. In the + * last case return background color for the root frame. + * + * @param aFrame [in] the given frame to calculate background-color + * @return background color + */ + nscolor GetColor(nsIFrame *aFrame); + + nsIFrame *mFrame; + nsIFrame *mRootFrame; +}; + +/** + * Class is used for the work with "font-size" text attribute. It is + * used in nsHyperTextAccessible. + */ +class nsFontSizeTextAttr : public nsTextAttr +{ +public: + nsFontSizeTextAttr(nsIFrame *aFrame, nsIFrame *aRootFrame); + + // nsTextAttr + virtual PRBool Equal(nsIDOMElement *aElm); + + // nsFontSizeTextAttr + + /** + * Retrieve the "font-size" in out param, return true if differs from + * the default font-size. + * + * @param aValue [out] the font size in pts + * @return true if font size differs from default + */ + virtual PRBool Get(nsAString& aValue); + +private: + /** + * Return font size for the given frame. + * + * @param aFrame [in] the given frame to query font-size + * @return font size + */ + nscoord GetFontSize(nsIFrame *aFrame); + + nsIFrame *mFrame; + nsIFrame *mRootFrame; +}; + +#endif
--- a/accessible/src/html/nsHyperTextAccessible.cpp +++ b/accessible/src/html/nsHyperTextAccessible.cpp @@ -36,17 +36,17 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsHyperTextAccessible.h" #include "nsAccessibilityAtoms.h" #include "nsAccessibilityService.h" #include "nsAccessibleTreeWalker.h" -#include "nsTextAttrs.h" +#include "nsTextUtils.h" #include "nsIClipboard.h" #include "nsContentCID.h" #include "nsIDOMAbstractView.h" #include "nsIDOMCharacterData.h" #include "nsIDOMDocument.h" #include "nsPIDOMWindow.h" #include "nsIDOMDocumentView.h" @@ -1169,18 +1169,27 @@ nsHyperTextAccessible::GetTextAttributes nsCOMPtr<nsIContent> content(do_QueryInterface(node)); if (content && content->IsNodeOfType(nsINode::eELEMENT)) node = do_QueryInterface(content->GetChildAt(nodeOffset)); if (!node) return NS_OK; - nsTextAttrsMgr textAttrsMgr(this, mDOMNode, aIncludeDefAttrs, node); - return textAttrsMgr.GetAttributes(*aAttributes, aStartOffset, aEndOffset); + // Set 'lang' text attribute. + rv = GetLangTextAttributes(aIncludeDefAttrs, node, + aStartOffset, aEndOffset, + aAttributes ? *aAttributes : nsnull); + NS_ENSURE_SUCCESS(rv, rv); + + // Set CSS based text attributes. + rv = GetCSSTextAttributes(aIncludeDefAttrs, node, + aStartOffset, aEndOffset, + aAttributes ? *aAttributes : nsnull); + return rv; } // nsIPersistentProperties // nsIAccessibleText::defaultTextAttributes NS_IMETHODIMP nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttributes) { NS_ENSURE_ARG_POINTER(aAttributes); @@ -1190,18 +1199,45 @@ nsHyperTextAccessible::GetDefaultTextAtt do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID); NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aAttributes = attributes); if (!mDOMNode) return NS_ERROR_FAILURE; - nsTextAttrsMgr textAttrsMgr(this, mDOMNode, PR_TRUE, nsnull); - return textAttrsMgr.GetAttributes(*aAttributes); + nsCOMPtr<nsIDOMElement> element = nsCoreUtils::GetDOMElementFor(mDOMNode); + + nsCSSTextAttr textAttr(PR_TRUE, element, nsnull); + while (textAttr.Iterate()) { + nsCAutoString name; + nsAutoString value, oldValue; + if (textAttr.Get(name, value)) + attributes->SetStringProperty(name, value, oldValue); + } + + nsIFrame *sourceFrame = nsCoreUtils::GetFrameFor(element); + NS_ENSURE_STATE(sourceFrame); + + // set font size + nsAutoString value; + nsFontSizeTextAttr fontSizeTextAttr(sourceFrame, nsnull); + fontSizeTextAttr.Get(value); + nsAccUtils::SetAccAttr(attributes, + nsAccessibilityAtoms::fontSize, value); + + value.Truncate(); + + // set font background color + nsBackgroundTextAttr backgroundTextAttr(sourceFrame, nsnull); + backgroundTextAttr.Get(value); + nsAccUtils::SetAccAttr(attributes, + nsAccessibilityAtoms::backgroundColor, value); + + return NS_OK; } nsresult nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes) { if (!mDOMNode) { return NS_ERROR_FAILURE; // Node already shut down } @@ -2279,8 +2315,280 @@ nsHyperTextAccessible::GetSpellTextAttri } return NS_OK; } } return NS_OK; } + +// nsHyperTextAccessible +nsresult +nsHyperTextAccessible::GetLangTextAttributes(PRBool aIncludeDefAttrs, + nsIDOMNode *aSourceNode, + PRInt32 *aStartHTOffset, + PRInt32 *aEndHTOffset, + nsIPersistentProperties *aAttributes) +{ + nsCOMPtr<nsIDOMElement> sourceElm(nsCoreUtils::GetDOMElementFor(aSourceNode)); + + nsCOMPtr<nsIContent> content(do_QueryInterface(sourceElm)); + nsCOMPtr<nsIContent> rootContent(do_QueryInterface(mDOMNode)); + + nsAutoString lang; + nsCoreUtils::GetLanguageFor(content, rootContent, lang); + + nsAutoString rootLang; + nsresult rv = GetLanguage(rootLang); + NS_ENSURE_SUCCESS(rv, rv); + + if (aAttributes) { + // Expose 'language' text attribute if the DOM 'lang' attribute is + // presented and it's different from the 'lang' attribute on the root + // element or we should include default values of text attribute. + const nsAString& resultLang = lang.IsEmpty() ? rootLang : lang; + if (!resultLang.IsEmpty() && (aIncludeDefAttrs || lang != rootLang)) + nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::language, + resultLang); + } + + nsLangTextAttr textAttr(lang, rootContent); + return GetRangeForTextAttr(aSourceNode, &textAttr, + aStartHTOffset, aEndHTOffset); +} + +// nsHyperTextAccessible +nsresult +nsHyperTextAccessible::GetCSSTextAttributes(PRBool aIncludeDefAttrs, + nsIDOMNode *aSourceNode, + PRInt32 *aStartHTOffset, + PRInt32 *aEndHTOffset, + nsIPersistentProperties *aAttributes) +{ + nsCOMPtr<nsIDOMElement> sourceElm(nsCoreUtils::GetDOMElementFor(aSourceNode)); + nsCOMPtr<nsIDOMElement> rootElm(nsCoreUtils::GetDOMElementFor(mDOMNode)); + + nsCSSTextAttr textAttr(aIncludeDefAttrs, sourceElm, rootElm); + while (textAttr.Iterate()) { + nsCAutoString name; + nsAutoString value, oldValue; + if (aAttributes && textAttr.Get(name, value)) + aAttributes->SetStringProperty(name, value, oldValue); + + nsresult rv = GetRangeForTextAttr(aSourceNode, &textAttr, + aStartHTOffset, aEndHTOffset); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsIFrame *sourceFrame = nsCoreUtils::GetFrameFor(sourceElm); + if (sourceFrame) { + nsIFrame *rootFrame = nsnull; + + if (!aIncludeDefAttrs) + rootFrame = nsCoreUtils::GetFrameFor(rootElm); + + nsFontSizeTextAttr fontSizeTextAttr(sourceFrame, rootFrame); + nsAutoString value; + if (fontSizeTextAttr.Get(value)) { + nsAccUtils::SetAccAttr(aAttributes, + nsAccessibilityAtoms::fontSize, value); + } + + nsBackgroundTextAttr backgroundTextAttr(sourceFrame, rootFrame); + value.Truncate(); + if (backgroundTextAttr.Get(value)) { + nsAccUtils::SetAccAttr(aAttributes, + nsAccessibilityAtoms::backgroundColor, value); + } + + nsresult rv = GetRangeForTextAttr(aSourceNode, &backgroundTextAttr, + aStartHTOffset, aEndHTOffset); + return rv; + } + + return NS_OK; +} + +// nsHyperTextAccessible +nsresult +nsHyperTextAccessible::GetRangeForTextAttr(nsIDOMNode *aNode, + nsTextAttr *aComparer, + PRInt32 *aStartHTOffset, + PRInt32 *aEndHTOffset) +{ + nsCOMPtr<nsIDOMElement> rootElm(nsCoreUtils::GetDOMElementFor(mDOMNode)); + NS_ENSURE_STATE(rootElm); + + nsCOMPtr<nsIDOMNode> tmpNode(aNode); + nsCOMPtr<nsIDOMNode> currNode(aNode); + + // Navigate backwards and forwards from current node to the root node to + // calculate range bounds for the text attribute. Navigation sequence is the + // following: + // 1. Navigate through the siblings. + // 2. If the traversed sibling has children then navigate from its leaf child + // to it through whole tree of the traversed sibling. + // 3. Get the parent and cycle algorithm until the root node. + + // Navigate backwards (find the start offset). + while (currNode && currNode != rootElm) { + nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(currNode)); + NS_ENSURE_STATE(currElm); + + if (currNode != aNode && !aComparer->Equal(currElm)) { + PRInt32 startHTOffset = 0; + nsCOMPtr<nsIAccessible> startAcc; + nsresult rv = DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset, + getter_AddRefs(startAcc)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!startAcc) + startHTOffset = 0; + + if (startHTOffset > *aStartHTOffset) + *aStartHTOffset = startHTOffset; + + break; + } + + currNode->GetPreviousSibling(getter_AddRefs(tmpNode)); + if (tmpNode) { + // Navigate through the subtree of traversed children to calculate + // left bound of the range. + FindStartOffsetInSubtree(tmpNode, currNode, aComparer, aStartHTOffset); + } + + currNode->GetParentNode(getter_AddRefs(tmpNode)); + currNode.swap(tmpNode); + } + + // Navigate forwards (find the end offset). + PRBool moveIntoSubtree = PR_TRUE; + currNode = aNode; + while (currNode && currNode != rootElm) { + nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(currNode)); + NS_ENSURE_STATE(currElm); + + // Stop new end offset searching if the given text attribute changes its + // value. + if (!aComparer->Equal(currElm)) { + PRInt32 endHTOffset = 0; + nsresult rv = DOMPointToHypertextOffset(currNode, -1, &endHTOffset); + NS_ENSURE_SUCCESS(rv, rv); + + if (endHTOffset < *aEndHTOffset) + *aEndHTOffset = endHTOffset; + + break; + } + + if (moveIntoSubtree) { + // Navigate through subtree of traversed node. We use 'moveIntoSubtree' + // flag to avoid traversing the same subtree twice. + currNode->GetFirstChild(getter_AddRefs(tmpNode)); + if (tmpNode) + FindEndOffsetInSubtree(tmpNode, aComparer, aEndHTOffset); + } + + currNode->GetNextSibling(getter_AddRefs(tmpNode)); + moveIntoSubtree = PR_TRUE; + if (!tmpNode) { + currNode->GetParentNode(getter_AddRefs(tmpNode)); + moveIntoSubtree = PR_FALSE; + } + + currNode.swap(tmpNode); + } + + return NS_OK; +} + + +PRBool +nsHyperTextAccessible::FindEndOffsetInSubtree(nsIDOMNode *aCurrNode, + nsTextAttr *aComparer, + PRInt32 *aHTOffset) +{ + if (!aCurrNode) + return PR_FALSE; + + nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(aCurrNode)); + NS_ENSURE_STATE(currElm); + + // If the given text attribute (pointed by nsTextAttr object) changes its + // value on the traversed element then fit the end of range. + if (!aComparer->Equal(currElm)) { + PRInt32 endHTOffset = 0; + nsresult rv = DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset); + NS_ENSURE_SUCCESS(rv, rv); + + if (endHTOffset < *aHTOffset) + *aHTOffset = endHTOffset; + + return PR_TRUE; + } + + // Deeply traverse into the tree to fit the end of range. + nsCOMPtr<nsIDOMNode> nextNode; + aCurrNode->GetFirstChild(getter_AddRefs(nextNode)); + if (nextNode) { + PRBool res = FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset); + if (res) + return res; + } + + aCurrNode->GetNextSibling(getter_AddRefs(nextNode)); + if (nextNode) { + if (FindEndOffsetInSubtree(nextNode, aComparer, aHTOffset)) + return PR_TRUE; + } + + return PR_FALSE; +} + +PRBool +nsHyperTextAccessible::FindStartOffsetInSubtree(nsIDOMNode *aCurrNode, + nsIDOMNode *aPrevNode, + nsTextAttr *aComparer, + PRInt32 *aHTOffset) +{ + if (!aCurrNode) + return PR_FALSE; + + // Find the closest element back to the traversed element. + nsCOMPtr<nsIDOMNode> nextNode; + aCurrNode->GetLastChild(getter_AddRefs(nextNode)); + if (nextNode) { + if (FindStartOffsetInSubtree(nextNode, aPrevNode, aComparer, aHTOffset)) + return PR_TRUE; + } + + nsCOMPtr<nsIDOMElement> currElm(nsCoreUtils::GetDOMElementFor(aCurrNode)); + NS_ENSURE_STATE(currElm); + + // If the given text attribute (pointed by nsTextAttr object) changes its + // value on the traversed element then fit the start of range. + if (!aComparer->Equal(currElm)) { + PRInt32 startHTOffset = 0; + nsCOMPtr<nsIAccessible> startAcc; + nsresult rv = DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset, + getter_AddRefs(startAcc)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!startAcc) + startHTOffset = 0; + + if (startHTOffset > *aHTOffset) + *aHTOffset = startHTOffset; + + return PR_TRUE; + } + + // Moving backwards to find the start of range. + aCurrNode->GetPreviousSibling(getter_AddRefs(nextNode)); + if (nextNode) { + if (FindStartOffsetInSubtree(nextNode, aCurrNode, aComparer, aHTOffset)) + return PR_TRUE; + } + + return PR_FALSE; +}
--- a/accessible/src/html/nsHyperTextAccessible.h +++ b/accessible/src/html/nsHyperTextAccessible.h @@ -40,17 +40,17 @@ #ifndef _nsHyperTextAccessible_H_ #define _nsHyperTextAccessible_H_ #include "nsAccessibleWrap.h" #include "nsIAccessibleText.h" #include "nsIAccessibleHyperText.h" #include "nsIAccessibleEditableText.h" #include "nsAccessibleEventData.h" -#include "nsTextAttrs.h" +#include "nsTextUtils.h" #include "nsFrameSelection.h" #include "nsISelectionController.h" enum EGetTextType { eGetBefore=-1, eGetAt=0, eGetAfter=1 }; // This character marks where in the text returned via nsIAccessibleText(), // that embedded object characters exist @@ -288,15 +288,97 @@ protected: * @param aStartOffset [in, out] the start offset * @param aEndOffset [in, out] the end offset * @param aAttributes [out, optional] result attributes */ nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsIPersistentProperties *aAttributes); + + /** + * Set 'lang' text attribute and return range offsets where attibute is + * stretched. The method is used by GetTextAttributes() method. + * + * @param aIncludeDefAttrs [in] points whether text attributes having default + * values of attributes should be included + * @param aSourceNode [in] the node we start to traverse from + * @param aStartOffset [in, out] the start offset + * @param aEndOffset [in, out] the end offset + * @param aAttributes [out, optional] result attributes + */ + nsresult GetLangTextAttributes(PRBool aIncludeDefAttrs, + nsIDOMNode *aSourceNode, + PRInt32 *aStartOffset, + PRInt32 *aEndOffset, + nsIPersistentProperties *aAttributes); + + /** + * Set CSS based text attribute and return range offsets where attibutes are + * stretched. The method is used by GetTextAttributes() method. + * + * @param aIncludeDefAttrs [in] points whether text attributes having default + * values of attributes should be included + * @param aSourceNode [in] the node we start to traverse from + * @param aStartOffset [in, out] the start offset + * @param aEndOffset [in, out] the end offset + * @param aAttributes [out, optional] result attributes + */ + nsresult GetCSSTextAttributes(PRBool aIncludeDefAttrs, + nsIDOMNode *aSourceNode, + PRInt32 *aStartOffset, + PRInt32 *aEndOffset, + nsIPersistentProperties *aAttributes); + + /** + * Calculates range (start and end offsets) of text where the text attribute + * (pointed by nsTextAttr object) is stretched. New offsets may be smaller if + * the given text attribute changes its value before or after the given + * offsets. + * + * @param aNode [in] the node we start to traverse from + * @param aComparer [in] object used to describe the text attribute + * @param aStartHTOffset [in, out] the start offset + * @param aEndHTOffset [in, out] the end offset + */ + nsresult GetRangeForTextAttr(nsIDOMNode *aNode, + nsTextAttr *aComparer, + PRInt32 *aStartHTOffset, + PRInt32 *aEndHTOffset); + + /** + * Find new end offset for text attributes navigating through the tree. New + * end offset may be smaller if the given text attribute (pointed by + * nsTextAttr object) changes its value before the given end offset. + * + * @param aCurrNode [in] the first node of the tree + * @param aComparer [in] object used to describe the text attribute + * @param aHTOffset [in, out] the end offset + * @return true if the end offset has been changed + */ + PRBool FindEndOffsetInSubtree(nsIDOMNode *aCurrNode, + nsTextAttr *aComparer, + PRInt32 *aHTOffset); + + /** + * Find the start offset for text attributes navigating through the tree. New + * start offset may be bigger if the given text attribute (pointed by + * nsTextAttr object) changes its value after the given start offset. + * + * @param aCurrNode [in] the node navigating through thee thee is started + * from + * @param aPrevNode [in] the previous node placed before the start node + * @param aComparer [in] object used to describe the text attribute + * @param aHTOffset [in, out] the start offset + * @return true if the start offset has been changed + */ + PRBool FindStartOffsetInSubtree(nsIDOMNode *aCurrNode, + nsIDOMNode *aPrevNode, + nsTextAttr *aComparer, + PRInt32 *aHTOffset); + }; NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible, NS_HYPERTEXTACCESSIBLE_IMPL_CID) #endif // _nsHyperTextAccessible_H_
--- a/accessible/tests/mochitest/attributes.js +++ b/accessible/tests/mochitest/attributes.js @@ -57,68 +57,51 @@ function testGroupAttrs(aAccOrElmOrID, a /** * Test text attributes. * * @param aID [in] the ID of DOM element having text * accessible * @param aOffset [in] the offset inside text accessible to fetch * text attributes * @param aAttrs [in] the map of expected text attributes - * (name/value pairs) exposed at the offset - * @param aDefAttrs [in] the map of expected text attributes - * (name/value pairs) exposed on hyper text - * accessible + * (name/value pairs) * @param aStartOffset [in] expected start offset where text attributes * are applied * @param aEndOffset [in] expected end offset where text attribute * are applied * @param aSkipUnexpectedAttrs [in] points the function doesn't fail if * unexpected attribute is encountered */ -function testTextAttrs(aID, aOffset, aAttrs, aDefAttrs, - aStartOffset, aEndOffset, aSkipUnexpectedAttrs) +function testTextAttrs(aID, aOffset, aAttrs, aStartOffset, aEndOffset, + aSkipUnexpectedAttrs) { var accessible = getAccessible(aID, [nsIAccessibleText]); if (!accessible) return; var startOffset = { value: -1 }; var endOffset = { value: -1 }; + var attrs = null; + try { + attrs = accessible.getTextAttributes(false, aOffset, + startOffset, endOffset); + } catch (e) { + } - // do not include attributes exposed on hyper text accessbile - var attrs = getTextAttributes(aID, accessible, false, aOffset, - startOffset, endOffset); - - if (!attrs) + if (!attrs) { + ok(false, "Can't get text attributes for " + aID); return; + } var errorMsg = " for " + aID + " at offset " + aOffset; is(startOffset.value, aStartOffset, "Wrong start offset" + errorMsg); is(endOffset.value, aEndOffset, "Wrong end offset" + errorMsg); compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs); - - // include attributes exposed on hyper text accessbile - var expectedAttrs = {}; - for (var name in aAttrs) - expectedAttrs[name] = aAttrs[name]; - - for (var name in aDefAttrs) { - if (!(name in expectedAttrs)) - expectedAttrs[name] = aDefAttrs[name]; - } - - attrs = getTextAttributes(aID, accessible, true, aOffset, - startOffset, endOffset); - - if (!attrs) - return; - - compareAttrs(errorMsg, attrs, expectedAttrs, aSkipUnexpectedAttrs); } /** * Test default text attributes. * * @param aID [in] the ID of DOM element having text * accessible * @param aDefAttrs [in] the map of expected text attributes @@ -145,35 +128,16 @@ function testDefaultTextAttrs(aID, aDefA var errorMsg = ". Getting default text attributes for " + aID; compareAttrs(errorMsg, defAttrs, aDefAttrs, aSkipUnexpectedAttrs); } //////////////////////////////////////////////////////////////////////////////// // Private. -function getTextAttributes(aID, aAccessible, aIncludeDefAttrs, aOffset, - aStartOffset, aEndOffset) -{ - // This function expects the passed in accessible to already be queried for - // nsIAccessibleText. - var attrs = null; - try { - attrs = aAccessible.getTextAttributes(aIncludeDefAttrs, aOffset, - aStartOffset, aEndOffset); - } catch (e) { - } - - if (attrs) - return attrs; - - ok(false, "Can't get text attributes for " + aID); - return null; -} - function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs) { var enumerate = aAttrs.enumerate(); while (enumerate.hasMoreElements()) { var prop = enumerate.getNext().QueryInterface(nsIPropertyElement); if (!(prop.key in aExpectedAttrs)) { if (!aSkipUnexpectedAttrs)
--- a/accessible/tests/mochitest/test_textattrs.html +++ b/accessible/tests/mochitest/test_textattrs.html @@ -61,20 +61,20 @@ }; testDefaultTextAttrs(ID, defAttrs); var attrs = { }; var misspelledAttrs = { "invalid": "spelling" }; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 11); - testTextAttrs(ID, 11, misspelledAttrs, defAttrs, 11, 17); - testTextAttrs(ID, 17, attrs, defAttrs, 17, 18); - testTextAttrs(ID, 18, misspelledAttrs, defAttrs, 18, 22); + testTextAttrs(ID, 0, attrs, 0, 11); + testTextAttrs(ID, 11, misspelledAttrs, 11, 17); + testTextAttrs(ID, 17, attrs, 17, 18); + testTextAttrs(ID, 18, misspelledAttrs, 18, 22); is(gTextAttrChangedEventHandler.eventNumber, 2, "Wrong count of 'text attribute changed' events for " + ID); unregisterA11yEventListener(nsIAccessibleEvent.EVENT_TEXT_ATTRIBUTE_CHANGED, gTextAttrChangedEventHandler); SimpleTest.finish(); @@ -96,25 +96,25 @@ "color": gComputedStyle.color, "font-family": gComputedStyle.fontFamily, "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); var attrs = {}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 7); + testTextAttrs(ID, 0, attrs, 0, 7); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"font-weight": gComputedStyle.fontWeight}; - testTextAttrs(ID, 7, attrs, defAttrs, 7, 11); + testTextAttrs(ID, 7, attrs, 7, 11); attrs = {}; - testTextAttrs(ID, 12, attrs, defAttrs, 11, 18); + testTextAttrs(ID, 12, attrs, 11, 18); ////////////////////////////////////////////////////////////////////////// // area2 ID = "area2"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { "font-style": gComputedStyle.fontStyle, @@ -124,36 +124,36 @@ "color": gComputedStyle.color, "font-family": gComputedStyle.fontFamily, "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); attrs = {}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 7); + testTextAttrs(ID, 0, attrs, 0, 7); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"font-weight": gComputedStyle.fontWeight}; - testTextAttrs(ID, 7, attrs, defAttrs, 7, 12); + testTextAttrs(ID, 7, attrs, 7, 12); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"font-style": gComputedStyle.fontStyle, "font-weight": gComputedStyle.fontWeight}; - testTextAttrs(ID, 13, attrs, defAttrs, 12, 19); + testTextAttrs(ID, 13, attrs, 12, 19); tempElem = tempElem.parentNode; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"font-weight": "401"}; - testTextAttrs(ID, 20, attrs, defAttrs, 19, 23); + testTextAttrs(ID, 20, attrs, 19, 23); attrs = {}; - testTextAttrs(ID, 24, attrs, defAttrs, 23, 30); + testTextAttrs(ID, 24, attrs, 23, 30); ////////////////////////////////////////////////////////////////////////// // area3 ID = "area3"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { "font-style": gComputedStyle.fontStyle, @@ -165,33 +165,33 @@ "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 6); + testTextAttrs(ID, 0, attrs, 0, 6); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 6, attrs, defAttrs, 6, 26); + testTextAttrs(ID, 6, attrs, 6, 26); tempElem = tempElem.parentNode; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 26, attrs, defAttrs, 26, 27); + testTextAttrs(ID, 26, attrs, 26, 27); tempElem = tempElem.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color, "background-color": gComputedStyle.backgroundColor}; - testTextAttrs(ID, 27, attrs, defAttrs, 27, 50); + testTextAttrs(ID, 27, attrs, 27, 50); ////////////////////////////////////////////////////////////////////////// // area4 ID = "area4"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { "font-style": gComputedStyle.fontStyle, @@ -203,27 +203,27 @@ "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 16); + testTextAttrs(ID, 0, attrs, 0, 16); tempElem = tempElem.nextSibling.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 16, attrs, defAttrs, 16, 33); + testTextAttrs(ID, 16, attrs, 16, 33); tempElem = tempElem.parentNode; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 34, attrs, defAttrs, 33, 46); + testTextAttrs(ID, 34, attrs, 33, 46); ////////////////////////////////////////////////////////////////////////// // area5 ID = "area5"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { "font-style": gComputedStyle.fontStyle, @@ -235,28 +235,28 @@ "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 5); + testTextAttrs(ID, 0, attrs, 0, 5); attrs = {}; - testTextAttrs(ID, 7, attrs, defAttrs, 5, 8); + testTextAttrs(ID, 7, attrs, 5, 8); tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 9, attrs, defAttrs, 8, 11); + testTextAttrs(ID, 9, attrs, 8, 11); attrs = {}; - testTextAttrs(ID, 11, attrs, defAttrs, 11, 18); + testTextAttrs(ID, 11, attrs, 11, 18); ////////////////////////////////////////////////////////////////////////// // area6 (CSS vertical-align property, bug 445938) ID = "area6"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { "font-style": gComputedStyle.fontStyle, @@ -266,234 +266,105 @@ "color": gComputedStyle.color, "font-family": gComputedStyle.fontFamily, "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); attrs = {}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 5); + testTextAttrs(ID, 0, attrs, 0, 5); tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"text-position": gComputedStyle.verticalAlign, "font-size": "10pt"}; - testTextAttrs(ID, 5, attrs, defAttrs, 5, 13); + testTextAttrs(ID, 5, attrs, 5, 13); attrs = {}; - testTextAttrs(ID, 13, attrs, defAttrs, 13, 27); + testTextAttrs(ID, 13, attrs, 13, 27); tempElem = tempElem.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"text-position": gComputedStyle.verticalAlign}; - testTextAttrs(ID, 27, attrs, defAttrs, 27, 35); + testTextAttrs(ID, 27, attrs, 27, 35); attrs = {}; - testTextAttrs(ID, 35, attrs, defAttrs, 35, 39); + testTextAttrs(ID, 35, attrs, 35, 39); tempElem = tempElem.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"text-position": gComputedStyle.verticalAlign, "font-size": "10pt"}; - testTextAttrs(ID, 39, attrs, defAttrs, 39, 50); + testTextAttrs(ID, 39, attrs, 39, 50); attrs = {}; - testTextAttrs(ID, 50, attrs, defAttrs, 50, 55); + testTextAttrs(ID, 50, attrs, 50, 55); tempElem = tempElem.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = {"text-position": gComputedStyle.verticalAlign}; - testTextAttrs(ID, 55, attrs, defAttrs, 55, 64); + testTextAttrs(ID, 55, attrs, 55, 64); ////////////////////////////////////////////////////////////////////////// // area7 ID = "area7"; tempElem = document.getElementById(ID); gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); defAttrs = { - "language": "en", - "font-style": gComputedStyle.fontStyle, - "font-size": "12pt", - "background-color": "rgb(255, 255, 255)", - "font-weight": gComputedStyle.fontWeight, - "color": gComputedStyle.color, - "font-family": gComputedStyle.fontFamily, - "text-position": gComputedStyle.verticalAlign - }; - - testDefaultTextAttrs(ID, defAttrs); - - attrs = {"language": "ru"}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 12); - - attrs = {}; - testTextAttrs(ID, 12, attrs, defAttrs, 12, 13); - - tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = { "background-color": gComputedStyle.backgroundColor}; - testTextAttrs(ID, 13, attrs, defAttrs, 13, 26); - - attrs = {}; - testTextAttrs(ID, 26, attrs, defAttrs, 26, 27); - - attrs = {"language": "de"}; - testTextAttrs(ID, 27, attrs, defAttrs, 27, 42); - - attrs = {}; - testTextAttrs(ID, 42, attrs, defAttrs, 42, 50); - - attrs = {}; - testTextAttrs(ID, 43, attrs, defAttrs, 42, 50); - - tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 50, attrs, defAttrs, 50, 57); - - tempElem = tempElem.firstChild.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"font-weight": gComputedStyle.fontWeight, - "color": gComputedStyle.color}; - testTextAttrs(ID, 57, attrs, defAttrs, 57, 61); - - tempElem = tempElem.parentNode; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"color": gComputedStyle.color}; - testTextAttrs(ID, 61, attrs, defAttrs, 61, 68); - - ////////////////////////////////////////////////////////////////////////// - // area9, different single style spans in styled paragraph - ID = "area9"; - tempElem = document.getElementById(ID); - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - defAttrs = { - "font-style": gComputedStyle.fontStyle, - "font-size": "10pt", - "background-color": "rgb(255, 255, 255)", - "font-weight": gComputedStyle.fontWeight, - "color": gComputedStyle.color, - "font-family": gComputedStyle.fontFamily, - "text-position": gComputedStyle.verticalAlign - }; - - testDefaultTextAttrs(ID, defAttrs); - - attrs = {}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 6); - - attrs = { "font-size": "12pt" }; - testTextAttrs(ID, 7, attrs, defAttrs, 6, 12); - - attrs = {}; - testTextAttrs(ID, 13, attrs, defAttrs, 12, 21); - - // Walk to the span with the different background color - tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = { "background-color": gComputedStyle.backgroundColor }; - testTextAttrs(ID, 22, attrs, defAttrs, 21, 36); - - attrs = {}; - testTextAttrs(ID, 37, attrs, defAttrs, 36, 44); - - // Walk from the background color span to the one with font-style - tempElem = tempElem.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = { "font-style": gComputedStyle.fontStyle }; - testTextAttrs(ID, 45, attrs, defAttrs, 44, 61); - - attrs = {}; - testTextAttrs(ID, 62, attrs, defAttrs, 61, 69); - - // Walk from span with font-style to the one with font-family. - tempElem = tempElem.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = { "font-family": gComputedStyle.fontFamily }; - testTextAttrs(ID, 70, attrs, defAttrs, 69, 83); - - attrs = {}; - testTextAttrs(ID, 84, attrs, defAttrs, 83, 91); - - attrs = { "text-underline-style": "solid" }; - testTextAttrs(ID, 92, attrs, defAttrs, 91, 101); - - attrs = {}; - testTextAttrs(ID, 102, attrs, defAttrs, 101, 109); - - attrs = { "text-line-through-style": "solid" }; - 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"; - tempElem = document.getElementById(ID); - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - defAttrs = { "font-style": gComputedStyle.fontStyle, "font-size": "12pt", "background-color": "rgb(255, 255, 255)", "font-weight": gComputedStyle.fontWeight, "color": gComputedStyle.color, "font-family": gComputedStyle.fontFamily, "text-position": gComputedStyle.verticalAlign }; testDefaultTextAttrs(ID, defAttrs); - attrs = {}; - testTextAttrs(ID, 0, attrs, defAttrs, 0, 7); + attrs = {"language": "ru"}; + testTextAttrs(ID, 0, attrs, 0, 12); - attrs = { "font-size": "14pt" }; - testTextAttrs(ID, 7, attrs, defAttrs, 7, 13); + attrs = {"language": "en"}; + testTextAttrs(ID, 12, attrs, 12, 13); - attrs = {}; - testTextAttrs(ID, 13, attrs, defAttrs, 13, 22); - - // Walk to the span with the different background color tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = { "background-color": gComputedStyle.backgroundColor }; - testTextAttrs(ID, 23, attrs, defAttrs, 22, 37); + attrs = {"language" :"en", + "background-color": gComputedStyle.backgroundColor}; + testTextAttrs(ID, 13, attrs, 13, 26); + + attrs = {"language": "en" }; + testTextAttrs(ID, 26, attrs, 26, 27); + + attrs = {"language": "de"}; + testTextAttrs(ID, 27, attrs, 27, 42); + + attrs = {"language": "en"}; + testTextAttrs(ID, 42, attrs, 42, 43); attrs = {}; - testTextAttrs(ID, 38, attrs, defAttrs, 37, 45); + testTextAttrs(ID, 43, attrs, 43, 50); - // Walk from the background color span to the one with font-style - tempElem = tempElem.nextSibling.nextSibling; + tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"font-style": gComputedStyle.fontStyle}; - testTextAttrs(ID, 46, attrs, defAttrs, 45, 62); + attrs = {"color": gComputedStyle.color}; + testTextAttrs(ID, 50, attrs, 50, 57); - attrs = {}; - testTextAttrs(ID, 63, attrs, defAttrs, 62, 70); - - // Walk from span with font-style to the one with font-family. - tempElem = tempElem.nextSibling.nextSibling; + tempElem = tempElem.firstChild.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"font-family": gComputedStyle.fontFamily}; - testTextAttrs(ID, 71, attrs, defAttrs, 70, 84); - - attrs = {}; - testTextAttrs(ID, 85, attrs, defAttrs, 84, 92); - - attrs = { "text-underline-style": "solid" }; - testTextAttrs(ID, 93, attrs, defAttrs, 92, 102); + attrs = {"font-weight": gComputedStyle.fontWeight, + "color": gComputedStyle.color}; + testTextAttrs(ID, 57, attrs, 57, 61); - attrs = {}; - testTextAttrs(ID, 103, attrs, defAttrs, 102, 110); - - attrs = { "text-line-through-style": "solid" }; - testTextAttrs(ID, 111, attrs, defAttrs, 110, 123); - - attrs = {}; - testTextAttrs(ID, 124, attrs, defAttrs, 123, 131); + tempElem = tempElem.parentNode; + gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); + attrs = {"color": gComputedStyle.color}; + testTextAttrs(ID, 61, attrs, 61, 68); ////////////////////////////////////////////////////////////////////////// // test spelling text attributes testSpellTextAttrs(); // Will call SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); @@ -549,27 +420,11 @@ <span lang="en"> Normal <span style="color: magenta">Magenta<b>Bold</b>Magenta</span> </span> </p> <input id="area8"/> - <p id="area9" style="font-size: smaller">Small - <span style="font-size: 120%">bigger</span> smaller - <span style="background-color: blue;">background blue</span> normal - <span style="font-style: italic;">Different styling</span> normal - <span style="font-family: tahoma;">Different font</span> normal - <span style="text-decoration: underline;">underlined</span> normal - <span style="text-decoration: line-through;">strikethrough</span> normal - </p> - - <p id="area10">Normal - <span style="font-size: 120%">bigger</span> smaller - <span style="background-color: blue;">background blue</span> normal - <span style="font-style: italic;">Different styling</span> normal - <span style="font-family: tahoma;">Different font</span> normal - <span style="text-decoration: underline;">underlined</span> normal - <span style="text-decoration: line-through;">strikethrough</span> normal - </p> + <p id="output"/> </body> </html>