зеркало из https://github.com/mozilla/pjs.git
Bug 475522 - walk subtree once for all text attributes, r=marcoz, davidb, sr=neil
--HG-- rename : accessible/src/base/nsTextUtils.cpp => accessible/src/base/nsTextAttrs.cpp rename : accessible/src/base/nsTextUtils.h => accessible/src/base/nsTextAttrs.h
This commit is contained in:
Родитель
8b18359400
Коммит
0dcbd2432d
|
@ -93,7 +93,7 @@ CPPSRCS = \
|
|||
nsApplicationAccessible.cpp \
|
||||
nsCaretAccessible.cpp \
|
||||
nsTextAccessible.cpp \
|
||||
nsTextUtils.cpp \
|
||||
nsTextAttrs.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
|
|
@ -193,10 +193,17 @@ 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
|
||||
|
|
|
@ -0,0 +1,605 @@
|
|||
/* -*- 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;
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
/* -*- 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
|
|
@ -1,298 +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 "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;
|
||||
}
|
|
@ -1,190 +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 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
|
|
@ -41,7 +41,7 @@
|
|||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccessibleTreeWalker.h"
|
||||
#include "nsTextUtils.h"
|
||||
#include "nsTextAttrs.h"
|
||||
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsContentCID.h"
|
||||
|
@ -1174,17 +1174,8 @@ nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
|||
if (!node)
|
||||
return NS_OK;
|
||||
|
||||
// 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;
|
||||
nsTextAttrsMgr textAttrsMgr(this, mDOMNode, aIncludeDefAttrs, node);
|
||||
return textAttrsMgr.GetAttributes(*aAttributes, aStartOffset, aEndOffset);
|
||||
}
|
||||
|
||||
// nsIPersistentProperties
|
||||
|
@ -1204,35 +1195,8 @@ nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttri
|
|||
if (!mDOMNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
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;
|
||||
nsTextAttrsMgr textAttrsMgr(this, mDOMNode, PR_TRUE, nsnull);
|
||||
return textAttrsMgr.GetAttributes(*aAttributes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -2320,275 +2284,3 @@ nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "nsIAccessibleHyperText.h"
|
||||
#include "nsIAccessibleEditableText.h"
|
||||
#include "nsAccessibleEventData.h"
|
||||
#include "nsTextUtils.h"
|
||||
#include "nsTextAttrs.h"
|
||||
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
|
@ -293,88 +293,6 @@ protected:
|
|||
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,
|
||||
|
|
|
@ -62,7 +62,10 @@ function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel)
|
|||
* @param aOffset [in] the offset inside text accessible to fetch
|
||||
* text attributes
|
||||
* @param aAttrs [in] the map of expected text attributes
|
||||
* (name/value pairs)
|
||||
* (name/value pairs) exposed at the offset
|
||||
* @param aDefAttrs [in] the map of expected text attributes
|
||||
* (name/value pairs) exposed on hyper text
|
||||
* accessible
|
||||
* @param aStartOffset [in] expected start offset where text attributes
|
||||
* are applied
|
||||
* @param aEndOffset [in] expected end offset where text attribute
|
||||
|
@ -70,8 +73,8 @@ function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel)
|
|||
* @param aSkipUnexpectedAttrs [in] points the function doesn't fail if
|
||||
* unexpected attribute is encountered
|
||||
*/
|
||||
function testTextAttrs(aID, aOffset, aAttrs, aStartOffset, aEndOffset,
|
||||
aSkipUnexpectedAttrs)
|
||||
function testTextAttrs(aID, aOffset, aAttrs, aDefAttrs,
|
||||
aStartOffset, aEndOffset, aSkipUnexpectedAttrs)
|
||||
{
|
||||
var accessible = getAccessible(aID, [nsIAccessibleText]);
|
||||
if (!accessible)
|
||||
|
@ -79,17 +82,13 @@ function testTextAttrs(aID, aOffset, aAttrs, aStartOffset, aEndOffset,
|
|||
|
||||
var startOffset = { value: -1 };
|
||||
var endOffset = { value: -1 };
|
||||
var attrs = null;
|
||||
try {
|
||||
attrs = accessible.getTextAttributes(false, aOffset,
|
||||
startOffset, endOffset);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
if (!attrs) {
|
||||
ok(false, "Can't get text attributes for " + aID);
|
||||
// do not include attributes exposed on hyper text accessbile
|
||||
var attrs = getTextAttributes(aID, accessible, false, aOffset,
|
||||
startOffset, endOffset);
|
||||
|
||||
if (!attrs)
|
||||
return;
|
||||
}
|
||||
|
||||
var errorMsg = " for " + aID + " at offset " + aOffset;
|
||||
|
||||
|
@ -97,6 +96,24 @@ function testTextAttrs(aID, aOffset, aAttrs, aStartOffset, aEndOffset,
|
|||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,6 +150,25 @@ function testDefaultTextAttrs(aID, 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();
|
||||
|
|
|
@ -66,10 +66,10 @@
|
|||
"invalid": "spelling"
|
||||
};
|
||||
|
||||
testTextAttrs(ID, 0, attrs, 0, 11);
|
||||
testTextAttrs(ID, 11, misspelledAttrs, 11, 17);
|
||||
testTextAttrs(ID, 17, attrs, 17, 18);
|
||||
testTextAttrs(ID, 18, misspelledAttrs, 18, 22);
|
||||
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);
|
||||
|
||||
is(gTextAttrChangedEventHandler.eventNumber, 2,
|
||||
"Wrong count of 'text attribute changed' events for " + ID);
|
||||
|
@ -101,15 +101,15 @@
|
|||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
var attrs = {};
|
||||
testTextAttrs(ID, 0, attrs, 0, 7);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-weight": gComputedStyle.fontWeight};
|
||||
testTextAttrs(ID, 7, attrs, 7, 11);
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 7, 11);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 12, attrs, 11, 18);
|
||||
testTextAttrs(ID, 12, attrs, defAttrs, 11, 18);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area2
|
||||
|
@ -129,26 +129,26 @@
|
|||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 0, attrs, 0, 7);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-weight": gComputedStyle.fontWeight};
|
||||
testTextAttrs(ID, 7, attrs, 7, 12);
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 7, 12);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-style": gComputedStyle.fontStyle,
|
||||
"font-weight": gComputedStyle.fontWeight};
|
||||
testTextAttrs(ID, 13, attrs, 12, 19);
|
||||
testTextAttrs(ID, 13, attrs, defAttrs, 12, 19);
|
||||
|
||||
tempElem = tempElem.parentNode;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-weight": "401"};
|
||||
testTextAttrs(ID, 20, attrs, 19, 23);
|
||||
testTextAttrs(ID, 20, attrs, defAttrs, 19, 23);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 24, attrs, 23, 30);
|
||||
testTextAttrs(ID, 24, attrs, defAttrs, 23, 30);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area3
|
||||
|
@ -170,23 +170,23 @@
|
|||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 0, attrs, 0, 6);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 6);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 6, attrs, 6, 26);
|
||||
testTextAttrs(ID, 6, attrs, defAttrs, 6, 26);
|
||||
|
||||
tempElem = tempElem.parentNode;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 26, attrs, 26, 27);
|
||||
testTextAttrs(ID, 26, attrs, defAttrs, 26, 27);
|
||||
|
||||
tempElem = tempElem.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color,
|
||||
"background-color": gComputedStyle.backgroundColor};
|
||||
testTextAttrs(ID, 27, attrs, 27, 50);
|
||||
testTextAttrs(ID, 27, attrs, defAttrs, 27, 50);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area4
|
||||
|
@ -208,17 +208,17 @@
|
|||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 0, attrs, 0, 16);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 16);
|
||||
|
||||
tempElem = tempElem.nextSibling.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 16, attrs, 16, 33);
|
||||
testTextAttrs(ID, 16, attrs, defAttrs, 16, 33);
|
||||
|
||||
tempElem = tempElem.parentNode;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 34, attrs, 33, 46);
|
||||
testTextAttrs(ID, 34, attrs, defAttrs, 33, 46);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area5
|
||||
|
@ -240,18 +240,18 @@
|
|||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 0, attrs, 0, 5);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 7, attrs, 5, 8);
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 5, 8);
|
||||
|
||||
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 9, attrs, 8, 11);
|
||||
testTextAttrs(ID, 9, attrs, defAttrs, 8, 11);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 11, attrs, 11, 18);
|
||||
testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area6 (CSS vertical-align property, bug 445938)
|
||||
|
@ -271,44 +271,165 @@
|
|||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 0, attrs, 0, 5);
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"text-position": gComputedStyle.verticalAlign,
|
||||
"font-size": "10pt"};
|
||||
testTextAttrs(ID, 5, attrs, 5, 13);
|
||||
testTextAttrs(ID, 5, attrs, defAttrs, 5, 13);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 13, attrs, 13, 27);
|
||||
testTextAttrs(ID, 13, attrs, defAttrs, 13, 27);
|
||||
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"text-position": gComputedStyle.verticalAlign};
|
||||
testTextAttrs(ID, 27, attrs, 27, 35);
|
||||
testTextAttrs(ID, 27, attrs, defAttrs, 27, 35);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 35, attrs, 35, 39);
|
||||
testTextAttrs(ID, 35, attrs, defAttrs, 35, 39);
|
||||
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"text-position": gComputedStyle.verticalAlign,
|
||||
"font-size": "10pt"};
|
||||
testTextAttrs(ID, 39, attrs, 39, 50);
|
||||
testTextAttrs(ID, 39, attrs, defAttrs, 39, 50);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 50, attrs, 50, 55);
|
||||
testTextAttrs(ID, 50, attrs, defAttrs, 50, 55);
|
||||
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"text-position": gComputedStyle.verticalAlign};
|
||||
testTextAttrs(ID, 55, attrs, 55, 64);
|
||||
testTextAttrs(ID, 55, attrs, defAttrs, 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",
|
||||
|
@ -321,45 +442,53 @@
|
|||
|
||||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
attrs = {"language": "ru"};
|
||||
testTextAttrs(ID, 0, attrs, 0, 12);
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 7);
|
||||
|
||||
attrs = {"language": "en"};
|
||||
testTextAttrs(ID, 12, attrs, 12, 13);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
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 = { "font-size": "14pt" };
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 7, 13);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 43, attrs, 43, 50);
|
||||
testTextAttrs(ID, 13, attrs, defAttrs, 13, 22);
|
||||
|
||||
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nextSibling;
|
||||
// Walk to the span with the different background color
|
||||
tempElem = tempElem.firstChild.nextSibling.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 50, attrs, 50, 57);
|
||||
attrs = { "background-color": gComputedStyle.backgroundColor };
|
||||
testTextAttrs(ID, 23, attrs, defAttrs, 22, 37);
|
||||
|
||||
tempElem = tempElem.firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"font-weight": gComputedStyle.fontWeight,
|
||||
"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 57, attrs, 57, 61);
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 38, attrs, defAttrs, 37, 45);
|
||||
|
||||
tempElem = tempElem.parentNode;
|
||||
// Walk from the background color span to the one with font-style
|
||||
tempElem = tempElem.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 61, attrs, 61, 68);
|
||||
attrs = {"font-style": gComputedStyle.fontStyle};
|
||||
testTextAttrs(ID, 46, attrs, defAttrs, 45, 62);
|
||||
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 63, attrs, defAttrs, 62, 70);
|
||||
|
||||
// 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, 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 = {};
|
||||
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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// test spelling text attributes
|
||||
|
@ -425,6 +554,22 @@
|
|||
|
||||
<input id="area8"/>
|
||||
|
||||
<p id="output"/>
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Загрузка…
Ссылка в новой задаче