mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-14 12:13:22 +00:00
Bug 445677 - optimization for text attributes offset (do not look into embedded characters, r=marcoz
This commit is contained in:
parent
4dac627a91
commit
3b24543774
@ -81,11 +81,11 @@ static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
|
||||
// nsTextAttrs
|
||||
|
||||
nsTextAttrsMgr::nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc,
|
||||
nsIDOMNode *aHyperTextNode,
|
||||
PRBool aIncludeDefAttrs,
|
||||
nsIDOMNode *aOffsetNode) :
|
||||
mHyperTextAcc(aHyperTextAcc), mHyperTextNode(aHyperTextNode),
|
||||
mIncludeDefAttrs(aIncludeDefAttrs), mOffsetNode(aOffsetNode)
|
||||
nsAccessible *aOffsetAcc,
|
||||
PRInt32 aOffsetAccIdx) :
|
||||
mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(aIncludeDefAttrs),
|
||||
mOffsetAcc(aOffsetAcc), mOffsetAccIdx(aOffsetAccIdx)
|
||||
{
|
||||
}
|
||||
|
||||
@ -94,33 +94,61 @@ 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
|
||||
// 1. Hyper text accessible must be specified always.
|
||||
// 2. Offset accessible and result hyper text offsets must be specified 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 &&
|
||||
// 3. Offset accessible and result hyper text offsets must not be specified
|
||||
// but include default text attributes flag and attributes list must be
|
||||
// specified in the case of default text attributes.
|
||||
NS_PRECONDITION(mHyperTextAcc &&
|
||||
((mOffsetAcc && mOffsetAccIdx != -1 &&
|
||||
aStartHTOffset && aEndHTOffset) ||
|
||||
(!mOffsetAcc && mOffsetAccIdx == -1 &&
|
||||
!aStartHTOffset && !aEndHTOffset &&
|
||||
mIncludeDefAttrs && aAttributes)),
|
||||
"Wrong usage of nsTextAttrsMgr!");
|
||||
|
||||
nsCOMPtr<nsIDOMElement> hyperTextElm =
|
||||
nsCoreUtils::GetDOMElementFor(mHyperTextNode);
|
||||
nsCOMPtr<nsIDOMElement> offsetElm;
|
||||
if (mOffsetNode)
|
||||
offsetElm = nsCoreUtils::GetDOMElementFor(mOffsetNode);
|
||||
// Embedded objects are combined into own range with empty attributes set.
|
||||
if (mOffsetAcc && nsAccUtils::IsEmbeddedObject(mOffsetAcc)) {
|
||||
for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
|
||||
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
||||
if (!nsAccUtils::IsEmbeddedObject(currAcc))
|
||||
break;
|
||||
|
||||
(*aStartHTOffset)--;
|
||||
}
|
||||
|
||||
PRInt32 childCount = mHyperTextAcc->GetChildCount();
|
||||
for (PRInt32 childIdx = mOffsetAccIdx + 1; childIdx < childCount;
|
||||
childIdx++) {
|
||||
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
||||
if (!nsAccUtils::IsEmbeddedObject(currAcc))
|
||||
break;
|
||||
|
||||
(*aEndHTOffset)++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDOMNode *hyperTextNode = mHyperTextAcc->GetDOMNode();
|
||||
nsCOMPtr<nsIDOMElement> hyperTextElm =
|
||||
nsCoreUtils::GetDOMElementFor(mHyperTextAcc->GetDOMNode());
|
||||
nsIFrame *rootFrame = nsCoreUtils::GetFrameFor(hyperTextElm);
|
||||
|
||||
nsIDOMNode *offsetNode = nsnull;
|
||||
nsCOMPtr<nsIDOMElement> offsetElm;
|
||||
nsIFrame *frame = nsnull;
|
||||
if (offsetElm)
|
||||
if (mOffsetAcc) {
|
||||
offsetNode = mOffsetAcc->GetDOMNode();
|
||||
offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
|
||||
frame = nsCoreUtils::GetFrameFor(offsetElm);
|
||||
}
|
||||
|
||||
nsTPtrArray<nsITextAttr> textAttrArray(10);
|
||||
|
||||
// "language" text attribute
|
||||
nsLangTextAttr langTextAttr(mHyperTextAcc, mHyperTextNode, mOffsetNode);
|
||||
nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextNode, offsetNode);
|
||||
textAttrArray.AppendElement(static_cast<nsITextAttr*>(&langTextAttr));
|
||||
|
||||
// "color" text attribute
|
||||
@ -174,7 +202,7 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes,
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Expose text attributes range where they are applied if applicable.
|
||||
if (mOffsetNode)
|
||||
if (mOffsetAcc)
|
||||
rv = GetRange(textAttrArray, aStartHTOffset, aEndHTOffset);
|
||||
|
||||
textAttrArray.Clear();
|
||||
@ -185,211 +213,68 @@ nsresult
|
||||
nsTextAttrsMgr::GetRange(const nsTPtrArray<nsITextAttr>& aTextAttrArray,
|
||||
PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> rootElm =
|
||||
nsCoreUtils::GetDOMElementFor(mHyperTextNode);
|
||||
NS_ENSURE_STATE(rootElm);
|
||||
PRUint32 attrLen = aTextAttrArray.Length();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tmpNode(mOffsetNode);
|
||||
nsCOMPtr<nsIDOMNode> currNode(mOffsetNode);
|
||||
// Navigate backward from anchor accessible to find start offset.
|
||||
for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
|
||||
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
||||
|
||||
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;
|
||||
nsAccessible *startAcc = mHyperTextAcc->
|
||||
DOMPointToHypertextOffset(tmpNode, -1, &startHTOffset);
|
||||
|
||||
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;
|
||||
mHyperTextAcc->DOMPointToHypertextOffset(currNode, -1, &endHTOffset);
|
||||
|
||||
if (endHTOffset < *aEndHTOffset)
|
||||
*aEndHTOffset = endHTOffset;
|
||||
|
||||
stop = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stop)
|
||||
// Stop on embedded accessible since embedded accessibles are combined into
|
||||
// own range.
|
||||
if (nsAccUtils::IsEmbeddedObject(currAcc))
|
||||
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);
|
||||
nsCOMPtr<nsIDOMElement> currElm =
|
||||
nsCoreUtils::GetDOMElementFor(currAcc->GetDOMNode());
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
PRBool offsetFound = PR_FALSE;
|
||||
for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
|
||||
nsITextAttr *textAttr = aTextAttrArray[attrIdx];
|
||||
if (!textAttr->Equal(currElm)) {
|
||||
offsetFound = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
currNode->GetNextSibling(getter_AddRefs(tmpNode));
|
||||
moveIntoSubtree = PR_TRUE;
|
||||
if (!tmpNode) {
|
||||
currNode->GetParentNode(getter_AddRefs(tmpNode));
|
||||
moveIntoSubtree = PR_FALSE;
|
||||
if (offsetFound)
|
||||
break;
|
||||
|
||||
*(aStartHTOffset) -= nsAccUtils::TextLength(currAcc);
|
||||
}
|
||||
|
||||
// Navigate forward from anchor accessible to find end offset.
|
||||
PRInt32 childLen = mHyperTextAcc->GetChildCount();
|
||||
for (PRInt32 childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
|
||||
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
||||
if (nsAccUtils::IsEmbeddedObject(currAcc))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> currElm =
|
||||
nsCoreUtils::GetDOMElementFor(currAcc->GetDOMNode());
|
||||
NS_ENSURE_STATE(currElm);
|
||||
|
||||
PRBool offsetFound = PR_FALSE;
|
||||
for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
|
||||
nsITextAttr *textAttr = aTextAttrArray[attrIdx];
|
||||
|
||||
// Alter the end offset when text attribute changes its value and stop
|
||||
// the search.
|
||||
if (!textAttr->Equal(currElm)) {
|
||||
offsetFound = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
currNode.swap(tmpNode);
|
||||
if (offsetFound)
|
||||
break;
|
||||
|
||||
(*aEndHTOffset) += nsAccUtils::TextLength(currAcc);
|
||||
}
|
||||
|
||||
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));
|
||||
if (!currElm)
|
||||
return PR_FALSE;
|
||||
|
||||
// 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;
|
||||
mHyperTextAcc->DOMPointToHypertextOffset(aCurrNode, -1, &endHTOffset);
|
||||
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));
|
||||
if (!currElm)
|
||||
return PR_FALSE;
|
||||
|
||||
// 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;
|
||||
nsAccessible *startAcc = mHyperTextAcc->
|
||||
DOMPointToHypertextOffset(aPrevNode, -1, &startHTOffset);
|
||||
|
||||
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
|
||||
|
||||
|
@ -69,7 +69,7 @@ class nsTextAttrsMgr
|
||||
public:
|
||||
/**
|
||||
* Constructor. If instance of the class is intended to expose default text
|
||||
* attributes then 'aIncludeDefAttrs' and 'oOffsetNode' argument must be
|
||||
* attributes then 'aIncludeDefAttrs' and 'aOffsetNode' argument must be
|
||||
* skiped.
|
||||
*
|
||||
* @param aHyperTextAcc hyper text accessible text attributes are
|
||||
@ -82,9 +82,9 @@ public:
|
||||
* inside hyper text accessible
|
||||
*/
|
||||
nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc,
|
||||
nsIDOMNode *aHyperTextNode,
|
||||
PRBool aIncludeDefAttrs = PR_TRUE,
|
||||
nsIDOMNode *oOffsetNode = nsnull);
|
||||
nsAccessible *aOffsetAcc = nsnull,
|
||||
PRInt32 aOffsetAccIdx = -1);
|
||||
|
||||
/*
|
||||
* Return text attributes and hyper text offsets where these attributes are
|
||||
@ -115,41 +115,13 @@ protected:
|
||||
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;
|
||||
|
||||
nsRefPtr<nsAccessible> mOffsetAcc;
|
||||
PRInt32 mOffsetAccIdx;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1084,23 +1084,16 @@ nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
||||
PRInt32 *aEndOffset,
|
||||
nsIPersistentProperties **aAttributes)
|
||||
{
|
||||
// 1. First we get spell check, then language, then the set of CSS-based
|
||||
// attributes.
|
||||
// 1. Get each attribute and its ranges one after another.
|
||||
// 2. As we get each new attribute, we pass the current start and end offsets
|
||||
// as in/out parameters. In other words, as attributes are collected,
|
||||
// the attribute range itself can only stay the same or get smaller.
|
||||
//
|
||||
// Example:
|
||||
// Current: range 5-10
|
||||
// Adding: range 7-12
|
||||
// Result: range 7-10
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aStartOffset);
|
||||
*aStartOffset = 0;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aEndOffset);
|
||||
nsresult rv = GetCharacterCount(aEndOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*aEndOffset = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1115,62 +1108,49 @@ nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
||||
NS_ADDREF(*aAttributes = attributes);
|
||||
}
|
||||
|
||||
// Offset 0 is correct offset when accessible has empty text. Include
|
||||
// default attributes if they were requested, otherwise return empty set.
|
||||
if (aOffset == 0) {
|
||||
// XXX: bug 567321. We handle here the cases when there are no children
|
||||
// or when existing children have zero length.
|
||||
PRBool isEmpty = PR_TRUE;
|
||||
PRInt32 childCount = GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible *child = mChildren[childIdx];
|
||||
if (!nsAccUtils::IsText(child) || nsAccUtils::TextLength(child) > 0) {
|
||||
isEmpty = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
PRInt32 offsetAccIdx = -1;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
nsAccessible *offsetAcc = GetAccessibleAtOffset(aOffset, &offsetAccIdx,
|
||||
&startOffset, &endOffset);
|
||||
if (!offsetAcc) {
|
||||
// Offset 0 is correct offset when accessible has empty text. Include
|
||||
// default attributes if they were requested, otherwise return empty set.
|
||||
if (aOffset == 0) {
|
||||
if (aIncludeDefAttrs) {
|
||||
nsTextAttrsMgr textAttrsMgr(this, mDOMNode, PR_TRUE, nsnull);
|
||||
nsTextAttrsMgr textAttrsMgr(this, PR_TRUE, nsnull, -1);
|
||||
return textAttrsMgr.GetAttributes(*aAttributes);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Get the frame and accessible at the given offset.
|
||||
PRInt32 startOffset = aOffset, endOffset = aOffset;
|
||||
nsRefPtr<nsAccessible> startAcc;
|
||||
nsIFrame *startFrame = GetPosAndText(startOffset, endOffset,
|
||||
nsnull, nsnull, nsnull,
|
||||
getter_AddRefs(startAcc), nsnull);
|
||||
PRInt32 offsetInAcc = aOffset - startOffset;
|
||||
|
||||
// No start frame or accessible means wrong given offset.
|
||||
if (!startFrame || !startAcc)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 nodeOffset = 0;
|
||||
rv = GetDOMPointByFrameOffset(startFrame, startOffset, startAcc,
|
||||
getter_AddRefs(node), &nodeOffset);
|
||||
nsTextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, offsetAcc, offsetAccIdx);
|
||||
nsresult rv = textAttrsMgr.GetAttributes(*aAttributes, &startOffset,
|
||||
&endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set 'misspelled' text attribute.
|
||||
rv = GetSpellTextAttribute(node, nodeOffset, aStartOffset, aEndOffset,
|
||||
aAttributes ? *aAttributes : nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Compute spelling attributes on text accessible only.
|
||||
nsIFrame *offsetFrame = offsetAcc->GetFrame();
|
||||
if (offsetFrame && offsetFrame->GetType() == nsAccessibilityAtoms::textFrame) {
|
||||
nsCOMPtr<nsIDOMNode> node = offsetAcc->GetDOMNode();
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
|
||||
if (content && content->IsElement())
|
||||
node = do_QueryInterface(content->GetChildAt(nodeOffset));
|
||||
PRInt32 nodeOffset = 0;
|
||||
nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc,
|
||||
&nodeOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!node)
|
||||
return NS_OK;
|
||||
// Set 'misspelled' text attribute.
|
||||
rv = GetSpellTextAttribute(node, nodeOffset, &startOffset, &endOffset,
|
||||
aAttributes ? *aAttributes : nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsTextAttrsMgr textAttrsMgr(this, mDOMNode, aIncludeDefAttrs, node);
|
||||
return textAttrsMgr.GetAttributes(*aAttributes, aStartOffset, aEndOffset);
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIPersistentProperties
|
||||
@ -1181,16 +1161,16 @@ nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttri
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
*aAttributes = nsnull;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> attributes =
|
||||
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);
|
||||
nsTextAttrsMgr textAttrsMgr(this, PR_TRUE);
|
||||
return textAttrsMgr.GetAttributes(*aAttributes);
|
||||
}
|
||||
|
||||
@ -2130,6 +2110,32 @@ nsresult nsHyperTextAccessible::RenderedToContentOffset(nsIFrame *aFrame, PRUint
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHyperTextAccessible protected
|
||||
|
||||
nsAccessible *
|
||||
nsHyperTextAccessible::GetAccessibleAtOffset(PRInt32 aOffset, PRInt32 *aAccIdx,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset)
|
||||
{
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRInt32 childCount = GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible *child = mChildren[childIdx];
|
||||
endOffset += nsAccUtils::TextLength(child);
|
||||
if (endOffset > aOffset) {
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
*aAccIdx = childIdx;
|
||||
return child;
|
||||
}
|
||||
|
||||
startOffset = endOffset;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame *aFrame,
|
||||
PRInt32 aOffset,
|
||||
|
@ -252,6 +252,18 @@ protected:
|
||||
*/
|
||||
PRInt32 GetCaretLineNumber();
|
||||
|
||||
/**
|
||||
* Return an accessible at the given hypertext offset.
|
||||
*
|
||||
* @param aOffset [out] the given hypertext offset
|
||||
* @param aAccIdx [out] child index of returned accessible
|
||||
* @param aStartOffset [out] start hypertext offset of returned accessible
|
||||
* @param aEndOffset [out] end hypertext offset of returned accessible
|
||||
*/
|
||||
nsAccessible *GetAccessibleAtOffset(PRInt32 aOffset, PRInt32 *aAccIdx,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset);
|
||||
|
||||
// Helpers
|
||||
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
|
||||
nsIAccessible *aAccessible,
|
||||
|
@ -162,24 +162,36 @@
|
||||
testTextAttrs(ID, 34, attrs, defAttrs, 33, 46);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area5
|
||||
// area5: "Green!*!RedNormal"
|
||||
ID = "area5";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt");
|
||||
testDefaultTextAttrs(ID, defAttrs);
|
||||
|
||||
// Green
|
||||
tempElem = getNode(ID).firstChild.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 5);
|
||||
|
||||
// br
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 5, 8);
|
||||
testTextAttrs(ID, 5, attrs, defAttrs, 5, 6);
|
||||
|
||||
// img, embedded accessible, no attributes
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 6, attrs, {}, 6, 7);
|
||||
|
||||
// br
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 7, attrs, defAttrs, 7, 8);
|
||||
|
||||
// Red
|
||||
tempElem = tempElem.nextSibling.nextSibling.nextSibling.nextSibling;
|
||||
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
|
||||
attrs = {"color": gComputedStyle.color};
|
||||
testTextAttrs(ID, 9, attrs, defAttrs, 8, 11);
|
||||
|
||||
// Normal
|
||||
attrs = {};
|
||||
testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
|
||||
|
||||
@ -419,6 +431,32 @@
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area15, embed char tests, "*plain*plain**bold*bold*"
|
||||
ID = "area15";
|
||||
defAttrs = buildDefaultTextAttrs(ID, "12pt");
|
||||
|
||||
// p
|
||||
testTextAttrs(ID, 0, { }, { }, 0, 1);
|
||||
// plain
|
||||
testTextAttrs(ID, 1, { }, defAttrs, 1, 6);
|
||||
// p
|
||||
testTextAttrs(ID, 6, { }, { }, 6, 7);
|
||||
// plain
|
||||
testTextAttrs(ID, 7, { }, defAttrs, 7, 12);
|
||||
// p and img
|
||||
testTextAttrs(ID, 12, { }, { }, 12, 14);
|
||||
// bold
|
||||
attrs = { "font-weight": kBoldFontWeight };
|
||||
testTextAttrs(ID, 14, attrs, defAttrs, 14, 18);
|
||||
// p
|
||||
testTextAttrs(ID, 18, { }, { }, 18, 19);
|
||||
// bold
|
||||
attrs = { "font-weight": kBoldFontWeight };
|
||||
testTextAttrs(ID, 19, attrs, defAttrs, 19, 23);
|
||||
// p
|
||||
testTextAttrs(ID, 23, { }, { }, 23, 24);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// test spelling text attributes
|
||||
testSpellTextAttrs(); // Will call SimpleTest.finish();
|
||||
@ -459,9 +497,10 @@
|
||||
Green again
|
||||
</span>
|
||||
</p>
|
||||
<!-- Green!*!RedNormal-->
|
||||
<p id="area5">
|
||||
<span style="color: green">Green</span>
|
||||
<img src="moz.png" alt="image"/>
|
||||
<img src="../moz.png" alt="image"/>
|
||||
<span style="color: red">Red</span>Normal
|
||||
</p>
|
||||
<p id="area6">
|
||||
@ -515,5 +554,8 @@
|
||||
<p id="area12">hello</p>
|
||||
<p id="area13"></p>
|
||||
<input id="area14">
|
||||
|
||||
<!-- *plain*plain**bold*bold*-->
|
||||
<div id="area15"><p>embed</p>plain<p>embed</p>plain<p>embed</p><img src="../moz.png" alt="image"/><b>bold</b><p>embed</p><b>bold</b><p>embed</p></div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user