Bug 613919 - Make characterCount fast, r=davidb, a=2.0+

This commit is contained in:
Alexander Surkov 2011-01-25 11:33:47 +08:00
Родитель 0048edbc9d
Коммит 7e7f49132d
12 изменённых файлов: 100 добавлений и 92 удалений

Просмотреть файл

@ -41,9 +41,8 @@
#include "nsMaiInterfaceText.h"
#include "nsHyperTextAccessible.h"
#include "nsRoleMap.h"
#include "nsString.h"
#include "nsIPersistentProperties2.h"
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
@ -374,14 +373,9 @@ getCharacterCountCB(AtkText *aText)
if (!accWrap)
return 0;
nsCOMPtr<nsIAccessibleText> accText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
getter_AddRefs(accText));
NS_ENSURE_TRUE(accText, 0);
PRInt32 count = 0;
nsresult rv = accText->GetCharacterCount(&count);
return (NS_FAILED(rv)) ? 0 : static_cast<gint>(count);
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(accWrap));
return textAcc->IsDefunct() ?
0 : static_cast<gint>(textAcc->CharacterCount());
}
gint

Просмотреть файл

@ -282,13 +282,13 @@ nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset,
nsAccessible **aEndAcc)
{
if (aStartOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
GetCharacterCount(&aStartOffset);
aStartOffset = CharacterCount();
}
if (aStartOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
GetCaretOffset(&aStartOffset);
}
if (aEndOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
GetCharacterCount(&aEndOffset);
aEndOffset = CharacterCount();
}
if (aEndOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
GetCaretOffset(&aEndOffset);
@ -492,14 +492,7 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCharacterCount(PRInt32 *aCharacterCount)
if (IsDefunct())
return NS_ERROR_FAILURE;
PRInt32 childCount = GetChildCount();
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
nsAccessible *childAcc = mChildren[childIdx];
PRInt32 textLength = nsAccUtils::TextLength(childAcc);
NS_ENSURE_TRUE(textLength >= 0, nsnull);
*aCharacterCount += textLength;
}
*aCharacterCount = CharacterCount();
return NS_OK;
}
@ -874,7 +867,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
}
if (aOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
GetCharacterCount(&aOffset);
aOffset = CharacterCount();
}
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
GetCaretOffset(&aOffset);
@ -958,8 +951,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
nsnull, getter_AddRefs(startAcc));
if (!startFrame) {
PRInt32 textLength;
GetCharacterCount(&textLength);
PRInt32 textLength = CharacterCount();
if (aBoundaryType == BOUNDARY_LINE_START && aOffset > 0 && aOffset == textLength) {
// Asking for start of line, while on last character
if (startAcc)
@ -1023,8 +1015,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
// that the first character is in
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
}
PRInt32 textLength;
GetCharacterCount(&textLength);
PRInt32 textLength = CharacterCount();
if (finalEndOffset < textLength) {
// This happens sometimes when current character at finalStartOffset
// is an embedded object character representing another hypertext, that
@ -1419,8 +1410,7 @@ NS_IMETHODIMP nsHyperTextAccessible::SetAttributes(PRInt32 aStartPos, PRInt32 aE
NS_IMETHODIMP nsHyperTextAccessible::SetTextContents(const nsAString &aText)
{
PRInt32 numChars;
GetCharacterCount(&numChars);
PRInt32 numChars = CharacterCount();
if (numChars == 0 || NS_SUCCEEDED(DeleteText(0, numChars))) {
return InsertText(aText, 0);
}

Просмотреть файл

@ -91,7 +91,7 @@ public:
virtual void InvalidateChildren();
// nsHyperTextAccessible
// nsHyperTextAccessible (static helper method)
// Convert content offset to rendered text offset
static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
@ -101,6 +101,9 @@ public:
static nsresult RenderedToContentOffset(nsIFrame *aFrame, PRUint32 aRenderedOffset,
PRInt32 *aContentOffset);
//////////////////////////////////////////////////////////////////////////////
// HyperLinkAccessible
/**
* Return link count within this hypertext accessible.
*/
@ -134,6 +137,9 @@ public:
return child ? GetLinkIndex(child) : -1;
}
//////////////////////////////////////////////////////////////////////////////
// nsHyperTextAccessible: DOM point to text offset conversions.
/**
* Turn a DOM Node and offset into a character offset into this hypertext.
* Will look for closest match when the DOM node does not have an accessible
@ -192,6 +198,17 @@ public:
nsIDOMNode **aEndNode,
PRInt32 *aEndOffset);
//////////////////////////////////////////////////////////////////////////////
// TextAccessible
/**
* Return character count within the hypertext accessible.
*/
inline PRUint32 CharacterCount()
{
return GetChildOffset(GetChildCount());
}
/**
* Return text offset of the given child accessible within hypertext
* accessible.

Просмотреть файл

@ -1,13 +1,12 @@
#import "mozAccessible.h"
#import "nsIAccessibleText.h"
#import "nsIAccessibleEditableText.h"
#import "nsHyperTextAccessible.h"
@interface mozTextAccessible : mozAccessible
{
// both of these are the same old mGeckoAccessible, but already
// QI'd for us, to the right type, for convenience.
nsIAccessibleText *mGeckoTextAccessible; // strong
nsHyperTextAccessible *mGeckoTextAccessible; // strong
nsIAccessibleEditableText *mGeckoEditableTextAccessible; // strong
}
@end

Просмотреть файл

@ -164,12 +164,7 @@ extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevel
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if (mGeckoTextAccessible) {
PRInt32 charCount = 0;
mGeckoTextAccessible->GetCharacterCount(&charCount);
return charCount;
}
return 0;
return mGeckoTextAccessible ? mGeckoTextAccessible->CharacterCount() : 0;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}

Просмотреть файл

@ -43,23 +43,7 @@
#include "Accessible2.h"
#include "AccessibleText_i.c"
#include "nsIAccessible.h"
#include "nsIAccessibleText.h"
#include "nsIAccessibleTypes.h"
#include "nsIWinAccessNode.h"
#include "nsAccessNodeWrap.h"
#include "nsAccessibleWrap.h"
#include "nsCOMPtr.h"
#include "nsIPersistentProperties2.h"
#include "nsString.h"
#define GET_NSIACCESSIBLETEXT \
nsCOMPtr<nsIAccessibleText> textAcc(do_QueryObject(this));\
NS_ASSERTION(textAcc,\
"Subclass of CAccessibleText doesn't implement nsIAccessibleText");\
if (!textAcc)\
return E_FAIL;\
#include "nsHyperTextAccessible.h"
// IUnknown
@ -87,8 +71,7 @@ STDMETHODIMP
CAccessibleText::addSelection(long aStartOffset, long aEndOffset)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsresult rv = textAcc->AddSelection(aStartOffset, aEndOffset);
return GetHRESULT(rv);
@ -108,7 +91,7 @@ __try {
*aEndOffset = 0;
*aTextAttributes = NULL;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRInt32 startOffset = 0, endOffset = 0;
nsCOMPtr<nsIPersistentProperties> attributes;
@ -138,7 +121,7 @@ CAccessibleText::get_caretOffset(long *aOffset)
__try {
*aOffset = -1;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRInt32 offset = 0;
nsresult rv = textAcc->GetCaretOffset(&offset);
@ -164,7 +147,7 @@ __try {
*aWidth = 0;
*aHeight = 0;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
@ -192,7 +175,7 @@ CAccessibleText::get_nSelections(long *aNSelections)
__try {
*aNSelections = 0;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRInt32 selCount = 0;
nsresult rv = textAcc->GetSelectionCount(&selCount);
@ -214,7 +197,7 @@ CAccessibleText::get_offsetAtPoint(long aX, long aY,
__try {
*aOffset = 0;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
@ -240,7 +223,7 @@ __try {
*aStartOffset = 0;
*aEndOffset = 0;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRInt32 startOffset = 0, endOffset = 0;
nsresult rv = textAcc->GetSelectionBounds(aSelectionIndex,
@ -262,7 +245,7 @@ CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
__try {
*aText = NULL;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsAutoString text;
nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
@ -290,7 +273,9 @@ __try {
*aEndOffset = 0;
*aText = NULL;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
if (textAcc->IsDefunct())
return E_FAIL;
nsresult rv = NS_OK;
nsAutoString text;
@ -298,7 +283,7 @@ __try {
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
startOffset = 0;
textAcc->GetCharacterCount(&endOffset);
endOffset = textAcc->CharacterCount();
rv = textAcc->GetText(startOffset, endOffset, text);
} else {
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
@ -335,7 +320,9 @@ __try {
*aEndOffset = 0;
*aText = NULL;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
if (textAcc->IsDefunct())
return E_FAIL;
nsresult rv = NS_OK;
nsAutoString text;
@ -343,7 +330,7 @@ __try {
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
startOffset = 0;
textAcc->GetCharacterCount(&endOffset);
endOffset = textAcc->CharacterCount();
rv = textAcc->GetText(startOffset, endOffset, text);
} else {
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
@ -380,7 +367,9 @@ __try {
*aEndOffset = 0;
*aText = NULL;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
if (textAcc->IsDefunct())
return E_FAIL;
nsresult rv = NS_OK;
nsAutoString text;
@ -388,7 +377,7 @@ __try {
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
startOffset = 0;
textAcc->GetCharacterCount(&endOffset);
endOffset = textAcc->CharacterCount();
rv = textAcc->GetText(startOffset, endOffset, text);
} else {
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
@ -418,7 +407,7 @@ STDMETHODIMP
CAccessibleText::removeSelection(long aSelectionIndex)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsresult rv = textAcc->RemoveSelection(aSelectionIndex);
return GetHRESULT(rv);
@ -431,7 +420,7 @@ STDMETHODIMP
CAccessibleText::setCaretOffset(long aOffset)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsresult rv = textAcc->SetCaretOffset(aOffset);
return GetHRESULT(rv);
@ -445,7 +434,7 @@ CAccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
long aEndOffset)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsresult rv = textAcc->SetSelectionBounds(aSelectionIndex,
aStartOffset, aEndOffset);
@ -461,14 +450,11 @@ CAccessibleText::get_nCharacters(long *aNCharacters)
__try {
*aNCharacters = 0;
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
if (textAcc->IsDefunct())
return E_FAIL;
PRInt32 charCount = 0;
nsresult rv = textAcc->GetCharacterCount(&charCount);
if (NS_FAILED(rv))
return GetHRESULT(rv);
*aNCharacters = charCount;
*aNCharacters = textAcc->CharacterCount();
return S_OK;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -480,7 +466,7 @@ CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
enum IA2ScrollType aScrollType)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
nsresult rv = textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
return GetHRESULT(rv);
@ -495,7 +481,7 @@ CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
long aX, long aY)
{
__try {
GET_NSIACCESSIBLETEXT
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :

Просмотреть файл

@ -107,11 +107,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">
Mozilla Bug 418368
</a><br>
<a target="_blank"
title="Cache links within hypertext accessible"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572394">
Mozilla Bug 572394
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">

Просмотреть файл

@ -106,6 +106,11 @@
</head>
<body>
<a target="_blank"
title="Cache links within hypertext accessible"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572394">
Mozilla Bug 572394
</a>
<a target="_blank"
title="Text offsets don't get updated when text of first child text accessible is changed"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=625009">

Просмотреть файл

@ -11,6 +11,21 @@ const BOUNDARY_ATTRIBUTE_RANGE = nsIAccessibleText.BOUNDARY_ATTRIBUTE_RANGE;
const kTodo = 1;
const kOk = 2;
/**
* Test characterCount for the given array of accessibles.
*
* @param aCount [in] the expected character count
* @param aIDs [in] array of accessible identifiers to test
*/
function testCharacterCount(aIDs, aCount)
{
for (var i = 1; i < aIDs.length; i++) {
var textacc = getAccessible(aIDs[i], [nsIAccessibleText]);
is(textacc.characterCount, aCount,
"Wrong character count for " + prettyName(aIDs[i]));
}
}
function testText(aIDs, aStartOffset, aEndOffset, aText)
{
for (var i = 0; i < aIDs.length; i++)

Просмотреть файл

@ -17,7 +17,9 @@
function doTest()
{
testText([getNode("iframe").contentDocument], 0, 14, "outbody inbody");
var iframeDoc = [ getNode("iframe").contentDocument ];
testCharacterCount(iframeDoc, 15);
testText(iframeDoc, 0, 15, "outbody inbody ");
SimpleTest.finish();
}

Просмотреть файл

@ -16,14 +16,19 @@
function doTest()
{
var IDs = ["input", "div", "textarea"];
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
////////////////////////////////////////////////////////////////////////
// characterCount
testCharacterCount(["input", "div"], 15);
testCharacterCount(["textarea"], 16);
////////////////////////////////////////////////////////////////////////
// getText
var IDs = ["input", "div", "textarea"];
testText(IDs, 0, 1, "h");
testText(IDs, 1, 3, "el");
testText(IDs, 14, 15, "d");

Просмотреть файл

@ -18,15 +18,20 @@
function doTest()
{
// Tests for elements rendering the original sring
var IDs = ["input", "div", "editable", "textarea"];
// __B__r__a__v__e__ __S__i__r__ __ __R__o__b__i__n__ __ __ __r__a__n
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
////////////////////////////////////////////////////////////////////////
// characterCount
testCharacterCount(["input", "div", "editable"], 22);
testCharacterCount(["textarea"], 23);
////////////////////////////////////////////////////////////////////////
// getText
var IDs = ["input", "div", "editable", "textarea"];
testText(IDs, 0, 1, "B");
testText(IDs, 5, 6, " ");
testText(IDs, 9, 11, " ");