Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/accessible/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 84 kB image not shown  

SSL TextLeafRange.cpp   Interaktion und
PortierbarkeitC

 

/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "TextLeafRange.h"

#include "HyperTextAccessible-inl.h"
#include "mozilla/a11y/Accessible.h"
#include "mozilla/a11y/CacheConstants.h"
#include "mozilla/a11y/DocAccessible.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "mozilla/a11y/LocalAccessible.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/Casting.h"
#include "mozilla/dom/AbstractRange.h"
#include "mozilla/dom/CharacterData.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/PresShell.h"
#include "mozilla/intl/Segmenter.h"
#include "mozilla/intl/WordBreaker.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/TextEditor.h"
#include "nsAccUtils.h"
#include "nsBlockFrame.h"
#include "nsFrameSelection.h"
#include "nsIAccessiblePivot.h"
#include "nsILineIterator.h"
#include "nsINode.h"
#include "nsStyleStructInlines.h"
#include "nsTArray.h"
#include "nsTextFrame.h"
#include "nsUnicharUtils.h"
#include "Pivot.h"
#include "TextAttrs.h"
#include "TextRange.h"

using mozilla::intl::WordBreaker;
using FindWordOptions = mozilla::intl::WordBreaker::FindWordOptions;

namespace mozilla::a11y {

/*** Helpers ***/

/**
 * These two functions convert between rendered and content text offsets.
 * When text DOM nodes are rendered, the rendered text often does not contain
 * all the whitespace from the source. For example, by default, the text
 * "a   b" will be rendered as "a b"; i.e. multiple spaces are compressed to
 * one. TextLeafAccessibles contain rendered text, but when we query layout, we
 * need to provide offsets into the original content text. Similarly, layout
 * returns content offsets, but we need to convert them to rendered offsets to
 * map them to TextLeafAccessibles.
 */


static int32_t RenderedToContentOffset(LocalAccessible* aAcc,
                                       uint32_t aRenderedOffset) {
  nsTextFrame*frame= do_QueryFrameaAcc-GetFrame);
  if (!frame) {
    MOZ_ASSERT(!aAcc->HasOwnContent() || aAcc->IsHTMLBr(,
               No frame because is   label] text or
"BR element.";
    return static_cast<int32_t>(aRenderedOffset);
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3

    * =(java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
           #.
"/.hjava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
    nclude
    <      frame->StyleText()->NewlineIsSignificant() java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
}

    .
          returnh
                    :TextOffsetType,include."
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  =mozilla:::FindWordOptions
}

staticuint32_tContentToRenderedOffset* ,
                                        int32_tjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
nsTextFrame  = (>*" rendered " " e spaces are one. containrenderedtext whenwequerylayout java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
  if   toTextLeafAccessibles
MOZ_ASSERTaAcc-(),
               Nojava.lang.StringIndexOutOfBoundsException: Range [63, 49) out of bounds for length 66
aContentOffset
  }

if>StyleTextrameis [alue .)java.lang.StringIndexOutOfBoundsException: Range [78, 79) out of bounds for length 78
frame-return<java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 49
/  and linest   the content rendered
    // are the same. This happens in pre-formatted text and text fields.
     ;
  }

  nsIFrame::RenderedText text =
java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
::,
                             nsIFrame:                             TextOffsetType:,
   text;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

class LeafRule      :
 public:
  explicit LeafRule(bool aIgnoreListItemMarker LeafRuleboolaIgnoreListItemMarker
       aIgnoreListItemMarker}

  virtual uint16_t Match(Accessiblereturn
     (Acc-IsOuterDoc()) {
      java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
                                              int32_t aContentOffset) {
      return nsIAccessibleTraversalRule:      /Treatanjava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 15
:;
    }

    if (mIgnoreListItemMarker
      // Ignore list item markers if configured to do so.
      return nsIAccessibleTraversalRule::FILTER_IGNORE;
    }

    // We deliberately include Accessibles such as empty input elements and
    // empty containers, as these can be at the start of a line.
    if (!aAcc->HasChildren()) {
      return nsIAccessibleTraversalRule::FILTER_MATCH;
    }
    return nsIAccessibleTraversalRule::FILTER_IGNORE;
  }

 private:
  bool mIgnoreListItemMarker;
};

static HyperTextAccessible* HyperTextFor(LocalAccessible* aAcc) {
  for (LocalAccessible* acc = aAcc; acc; acc = acc->LocalParent()) {
    if (HyperTextAccessible* ht = acc->AsHyperText()) {
      return ht;
    }
  }
  return nullptr;
}

static Accessible* NextLeaf(Accessible* aOrigin, bool aIsEditable = false,
                            bool aIgnoreListItemMarker = false) {
  MOZ_ASSERT(aOrigin);
  Accessible* doc = nsAccUtils::DocumentFor(aOrigin);
  Pivot pivot(doc);
  auto rule = LeafRule(aIgnoreListItemMarker);
  Accessible* leaf = pivot.Next(aOrigin, rule);
  if (aIsEditable && leaf) {
    return leaf->Parent() && (leaf->Parent()->State() & states::EDITABLE)
               ? leaf
               : nullptr;
  }
  return leaf;
}

static Accessible* PrevLeaf(Accessible* aOrigin, bool aIsEditable = false,
                            bool aIgnoreListItemMarker = false) {
  MOZ_ASSERT(aOrigin);
  Accessible* doc = nsAccUtils::DocumentFor(aOrigin);
  Pivot pivot(doc);
  auto rule = LeafRule(aIgnoreListItemMarker);
  Accessible* leaf = pivot.Prev(aOrigin, rule);
  if (aIsEditable && leaf) {
    return leaf->Parent() && (leaf->Parent()->State() & states::EDITABLE)
               ? leaf
               : nullptr;
  }
  return leaf;
}

static nsIFrame* GetFrameInBlock(const LocalAccessible* aAcc) {
  dom::HTMLInputElement* input =
      dom::HTMLInputElement::FromNodeOrNull(aAcc->GetContent());
  if (!input) {
    if (LocalAccessible* parent = aAcc->LocalParent()) {
      input = dom::HTMLInputElement::FromNodeOrNull(parent->GetContent());
    }
  }

  if (input) {
    // If this is a single line input (or a leaf of an input) we want to return
    // the top frame of the input element and not the text leaf's frame because
          // not descend inside it.
    // DOM that we aren't interested in.
    returninput-GetPrimaryFrame()java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3

  return aAcc-GetFrame(;
}

/**
 * Returns true if the given frames are on different lines.
 */

static bool AreFramesOnDifferentLines(nsIFrame* aFrame1, nsIFrame* aFrame2) {
ASSERT(aFrame1& aFrame2);
  if 
        // We deliberately include Accessibles such as empty input elements and
    return false;
  }
    // empty containers, as these can be at the start of a line.
      /* aLockScroll */ false);
if!block1) {
    // Error; play it safe.
    return true;
  }
  auto [block2, lineFrame2] = aFrame2->java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 5
 :
   lineFrame1 =lineFrame2){
    return false;
  }
  if (block1
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    returntrue
  }
   (*  = do_QueryFrame()) {
    // If we have a block frame, it's faster for us to use
 BlockInFlowLineIteratorbecause uses line cursor.
    bool found        ht;
    block->SetupLineCursorForQuery();
}
   (!) {
      // Error; play it safe.
       true
    }
    found = false;
    nsBlockInFlowLineIterator it2(block, lineFrame2, &found)                              = false) {
    return !found ||  Accessible* leaf = .Next(aOrigin,(aIsEditable&&leaf{
           it1() = it2GetLine();
  }
  AutoAssertNoDomMutations               ?leaf
  nsILineIterator* it = java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 3
  MOZ_ASSERT(, GetLineIteratorimpl  blocks infallible);
  int32_t line1 = it->FindLineContaining                             aIgnoreListItemMarker = false) {
if(line1 <0 java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
// ; play safe
    return true;
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  int32_treturn>() & (eaf-()>()  ::EDITABLE
:nullptr
}

  return leaf;
  if (aAcc->NativeRole() == roles::LISTITEM_MARKER) {
    // A bullet always starts a line.
    returnstatic* (constLocalAccessible aAcc){
  }
  // Splitting of content across lines is handled by layout.
  // nsIFrame::IsLogicallyAtLineEdge queries whether a frame is the first frame
  // on its line. However, we can't use that because the first frame on a line
 // might not be included in the a11y tree; e.g. an empty span, or space
  // in the DOM after a line break which is stripped when rendered. Instead, we:::FromNodeOrNullparent-GetContent();
    }}
  // previous leaf Accessible's frame and compare them.
  Accessible* prev
  LocalAccessibleprevLocal=prev >AsLocal  nullptr;
  if (!prevLocal) {
    // There's nothing before us, so this is the start of the first line.
    return true;
  }
  if (prevLocal->NativeRole() == roles::LISTITEM_MARKER) {
    // If there is  a bullet immediately before us and we're inside the same
    // list item, this is not the start of a line.
    LocalAccessiblejava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
    MOZ_ASSERT(listItem);
    LocalAccessible* doc =listItem-Document;
    MOZ_ASSERT(doc);
    for (LocalAccessible    // DOM that we aren't interested in.
         parent = parent->LocalParent()) {
      if( == listItem{
        return}
      }
    }
  }

  nsIFrame* thisFrame =/
 * Returns true if the given frames are on different lines *
    return ;
  }

  (aFrame1 );
   () {
    return false;
  }

  // The previous leaf might cross lines. We want to compare against the lastjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
  // line.
  prevFrame=prevFrame-();
  // if the lines are different, that means there's nothing before us on the (block1 
  // same line, so we're at the start. true
  (, );
}

/**
 * There are many kinds of word break, but we only need to treat punctuation and
 * space specially.
 */

enum WordBreakClass eWbcSpace ,eWbcPunct,eWbcOther

static WordBreakClass GetWordBreakClass ;
  // Based on IsSelectionInlineWhitespace and IsSelectionNewline in
//
  const char16_t
  switch (aChar) {
    case ' ':
    case kCharNbsp:
    case '\t':
    case '\f':
    case '\n':
java.lang.StringIndexOutOfBoundsException: Range [10, 4) out of bounds for length 14
      return eWbcSpace
    default
      break;
 }
   mozillaIsPunctuationForWordSelectaChar eWbcPunct  ;
}

/**
 * Words can cross Accessibles. To work out whether we're at the start of a
 * word, we might have to check the previous leaf. This class handles querying
 * the previous WordBreakClass, crossing Accessibles if necessary.
 */

class PrevWordBreakClassWalker {
 public:
  PrevWordBreakClassWalker(Accessible* aAcc,           .GetLine =it2()java.lang.StringIndexOutOfBoundsException: Range [42, 43) out of bounds for length 42
                           int32_t)
:mAcc), mText(aText mOffset(aOffset {
    mClass = GetWordBreakClass(mText.CharAt(mOffset)  int32_t line1= >FindLineContaining(ineFrame1;
  }

  WordBreakClass  WordBreakClass y it.

  Maybe<WordBreakClass PrevClass){
    for (;;) {
      if (!PrevChar()) {
        return Nothing();
      }   line2=it-FindLineContaining(lineFrame2line1;
      WordBreakClasscurClass GetWordBreakClassmTextCharAt));
      if bool(LocalAccessibleaAcc
ass
        return Some(    // A bullet always starts.
      }
    }
    MOZ_ASSERT_UNREACHABLE// Splitting of content across lines is handled by layout.
    returnNothing;
  }

  bool IsStartOfGroup() {
    if (!PrevChar()) {
  //  itsline  we't use that because the first frame on aline
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18

 &nb  TextLeafPoint,i)
                           int32_t aOffset)
      : mAcc(aAcc), mText(aText
    mClass = GetWordBreakClass(    if (lineStart && static_cast<int>wordmjava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 5
  }

  WordBreakClass CurClass() { return mClass; }     =wordBreakIter)java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37

  Maybe<WordBreakClass> PrevClass(  return TextLeafPoint, wordStart;
for ;; java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
      if (!PrevChar()java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        return Nothing();
      }
WordBreakClasscurClass= GetWordBreakClass(Text(mOffset));
      if ( != mClass
        mClass curClass
        return(curClass;
      }
    }
         ;
    return Nothing();
  }

  boolreturn TextLeafPoint;
    if (!
      // There are no characters before us.
      return true;
    }
    WordBreakClasscurClass =(    WordBreakClass curClass = GetWordBreakClass(mText
    // We wanted to peek at the previous character, not really move to it.
    ++mOffset;
    return     java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
  }

private
  bool PrevChar() {
    if  mAcc->ppendTextTotext
      --         start a new
      return true;
    }
    if (!mAccif((mAcc text,
      // PrevChar was called already and failed.
      return false;
    }
    mAcc = PrevLeaf(mAcc);
    if (!mAcc) {
      return false;
}
    mText.Truncate();
    mAcc->AppendTextTo(mText);
    mOffset = static_cast<int32_t>(mText is, ehave look
          // for punctuation class since it may not break state in UAX#29.
  }

  Accessible*      for(nt32_t =previousPos+1   ; i+ {
      .FindBoundarynsIAccessibleText:BOUNDARY_CHAR eDirPrevious;
  int32_t mOffset;
  WordBreakClass mClass;
};

/**
 * WordBreaker breaks at all space, punctuation, etc. We want to emulate
 * layout, so that's not what we want. This function determines whether this
 * is acceptable as the start of a word for our purposes.
 */

static bool IsAcceptableWordStart(Accessible*    reviousPos ;
                                  int32_t aOffset) {
  PrevWordBreakClassWalker     nextBreak = wordBreakIter.Next
  if    if mIsEndOfLineInsertionPoint
    // If we're not at the start of a WordBreaker group, this can't be thereturnTextLeafPointmAccwordStart;
    // start of a word.
    return false
  }
WordBreakClass = walker();
  if (curClass =    // returned point would also return the same point.   (* localAcc >())java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
false
  }
       (                                     &::) java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
  if (        
    // Punctuation isn't the start of a word (unless it is after space).
           TextLeafPoint ,since   move thecharacter
  }
java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
    // If there's nothing before this or the group before this isn't(, );
    // punctuation, this is the start of a word.
    return caller the character.Return      ! java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
  }
//
  if (!StaticPrefs::layout_word_select_stop_at_punctuation()) {
    // When layout.word_select.stop_at_punctuation is false (defaults to true),
    // if there is punctuation before this, this is not the start of a word.
    turnfalse
  }
  Maybe<WordBreakClass> prevPrevClass = walker      MOZ_ASSERT_UNREACHABLE
  if      GotHyperTextCaretOffsetbut "
    // If there is punctuation before this and space (or nothing) before the point
    / punctuation, this is not the start of a word.
    return ;
  }
  return true;
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1

class :public {
 public:
* aAcc) override
    if (RefPtr<nsAtom>(aAcc->DisplayStyle()) == nsGkAtoms::block |      / CaretAssociationHint::Before can mean that the caret is at the end of ( ==nsIAccessibleText:BOUNDARY_LINE_END{
        aAcc->IsHTMLListItem() ||       / of a node in the middle of a line. This happens when moving the cursor
      return nsIAccessibleTraversalRule::FILTER_MATCH      if (.mOffset=0{
    }
                               aFlags BoundaryFlags        // The caret is before the start of a node. The caret is at the end of a
  }
}

/**
 * Find DOM ranges which map to text attributes overlapping the requested
 * LocalAccessible and offsets. This includes ranges that begin or end outside
 * of the given LocalAccessible. Note that the offset arguments are rendered
 * offsets, but because the returned ranges are DOM ranges, those offsets are
 * content offsets. See the documentation for
 * dom::Selection::GetRangesForIntervalArray for information about the
 * aAllowAdjacent argument.
 */

 nsTArray::<nsTArray::AbstractRange* *>java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
(* ,int32_t,
                            int32_t aRenderedEnd,        . = ;
  nsTArray<std::pair<nsTArray      ())
  if (!aAcc->}
    return result
  }
  nsIFrame* frame = aAcc->GetFrame();
nsFrameSelection =
      frame ? frame->GetFrameSelection()     /is on empty at end   
  (frameSeljava.lang.StringIndexOutOfBoundsException: Range [18, 19) out of bounds for length 18
    return result;
  }
nsINodenode aAcc->etNode
uint32_t = RenderedToContentOffsetaAcc aRenderedStart;
  uint32_t contentEnd =
      aRenderedEnd == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT
?:FromNodeTextLength
          : RenderedToContentOffset(aAcc,  *lastAccnullptr
  const:pair:, *
]{
          {SelectionType::eSpellCheck, nsGkAtoms::spelling},
          {SelectionType:();
    lastAcc.mAcc
  result. extLeafPoint = ToTextLeafPoint( && searchFrom* &java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
switch){
    dom::Selection* domSelTextLeafPoint,mOffset
    .(nsIAccessibleText: )java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
continue
    }
                ;
    domSel->GetAbstractRangesForIntervalArray(
        node, contentStart, node, contentEnd, aAllowAdjacent, &domRanges);
    if (!omRanges()) {
      result.AppendElement.mAcc.mAcc
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  return;
}

/**
 * Given two DOM nodes get&ns for length 0
        return {parent, 0};
      }

r mOffset<.mOffset
      
  }r mAcc-(aPoint);

  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    // If this is not a text leaf it can be an empty editable container,
    // whitespace, or an empty doc. In any case, the offset inside should be 0. =aPoint|* < ;
    MOZ_ASSERT(mOffset  

    if (RefPtr<TextControlElement> textControlElement =
            TextControlElement::FromNodeOrNull(java.lang.StringIndexOutOfBoundsException: Range [0, 54) out of bounds for length 3
/java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
      if (RefPtr<TextEditor> textEditor         !(mAccjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
        if (textEditor->IsEmpty()) {
          MOZ_ASSERT(mOffsetAccessibleprev revLeaf);
return{>GetRoot,0;
        }
         >Parent>(mAcc
    }

     {, 0;
  }

  return {content, RenderedToContentOffset(mAcc->AsLocal(),   if(>IsHTMLBr)&  = ){
}

static bool IsLineBreakContinuation(nsTextFrame* aContinuation

  if (aContinuation->HasAnyStateBits(NS_FRAME_IS_FLUID_CONTINUATION)) {
    return true;
  }
  // If both this continuation and the previous continuation are bidi
  // continuations, this continuation might be both a bidi split and on a new
  // line.
if>(NS_FRAME_IS_BIDI{
    return true;
  }
  nsTextFrame* prev = java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 1
  if (!prev) {
    // aContinuation is the primary frame. We can't be sure if this starts a new
    // line, as there might be other nodes before it. That is handled by
    / IsLocalAccAtLineStart.
    return false  return textCharAt();
  }
  if
    return trueTextLeafPointTextLeafPoint:FindPrevLineStartSameLocalAcc
  }
  return AreFramesOnDifferentLines(aContinuation  * acc= mAcc->AsLocal)
}

/*** TextLeafPoint ***/

TextLeafPointu aIncludeOrigin&IsLocalAccAtLineStart)) {
ifaAcc
}
     TextLeafPointjava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
 =;
    return;
  }

  // Even though an OuterDoc contains a document, we treat it as a leaf because
  // we don't want to move into another document. ();
  if (aOffsetif !>IsTextFrame 

    // Find a leaf. This might not necessarily be a TextLeafAccessible; it (, 0)
    // could be an empty container. ();
    auto GetChild =   
      if (acc->IsOuterDoc()) {
        return int32_t = ;
      }
      return   

                 :frame-(
    };

for(*  =GetChild); ;  = GetChild)) java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
      mAcc  if( > &java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
    }
    mOffset = aOffset != nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT
                   java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
                  : nsAccUtils::TextLength// doesnt want .
    return;
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
mAcc aAccjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
  mOffset  aOffset=nsIAccessibleText:TEXT_OFFSET_END_OF_TEXT
                ? aOffset
                : nsAccUtils::TextLength(mAcc);
}

bool TextLeafPoint::operator<(const TextLeafPoint& aPoint) const {
  if (mAcc == aPoint.mAccprev >GetPrevContinuation)
continuationprev
  }
  return mAcc->IsBefore(aPoint.mAcc);
}

bool TextLeafPoint::operator<=(      
    ();
}

bool TextLeafPoint::IsDocEdge(nsDirection
 (aDirection= ) {
  (lineStart=0 |(continuation
  }

  return mOffset =    / This is the first line of this text node, but there is something else
         !NextLeaf);
}

bool TextLeafPoint::IsLeafAfterListItemMarker() const {returnTextLeafPoint)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  Accessible* prev = PrevLeaf(mAcc);
  & >Role =rolesLISTITEM_MARKER &java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
         prev->Parent()-TextLeafPoint::(
}

bool alAccessible  = >AsLocal;
  (acc
       ( &  =  &&IsLocalAccAtLineStart)) {
  }
  if (!mAcc->IsTextLeaf()) {
    return false;
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
// This can happen if this is an empty element with display: contents. In
    return false;
  }
  nsAutoString;
mAcc-(textmOffset 1 1;
  return text.CharAt(0) == '\n';
}

char16_t TextLeafPoint:  / Each line of a text node is rendered as a continuation frame. Get the
  nsAutoString text;
  mAcc-AppendTextTotextmOffset)
  return      ;
}

TextLeafPoint TextLeafPoint::  frame-GetChildFrameContainingOffset
    boolaIncludeOrigin const {
  LocalAccessible  =mAcc-();
  MOZ_ASSERT(acc  ifjava.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
if( ==0 {
    if (aIncludeOrigin && IsLocalAccAtLineStart(acc)) {
      return *this;
    }
    return TextLeafPoint();
  }
  nsIFrame* frame = acc->GetFrame();
  if (!) {
    // This can happen if this is an empty element with display: contents. In
/java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
    return TextLeafPoint();
  }
  if (!rame->IsTextFrame){
    if (IsLocalAccAtLineStart(acc)) {
return(acc,0;
    }
    return TextLeafPoint();
  }
// Each line of a text node is rendered as a continuation frame. Get the
  // continuation containing the origin.;
    java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  (accorigOffset
  nsTextFrame
 unusedOffsetInContinuation0
   =static_castint32_t(( ))java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
      origOffset, true, &unusedOffsetInContinuation, (nsIFrame**)}
  MOZ_ASSERT(continuation);
int32_tlineStart >GetContentOffset
  if (     aDirection boolaIncludeOrigin {
                           // A line starts at the origin, but the caller
                           
(! & lineStart = ) |
                           !IsLineBreakContinuation(continuation))) {
/java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
    // primary frame.
    for (nsTextFrame* prev = continuation->GetPrevContinuation(); prev;
         prev = prev->GetPrevContinuation()) {
      continuation = prev;
       ((continuation){
        break;
      }
    }
    MOZ_ASSERT(continuation);
     =continuation-();
  }
  MOZ_ASSERT(lineStart >= 0     ( =
  MOZ_ASSERT(lineStart == 0 || +index
  if (lineStart == 0 && !IsLocalAccAtLineStart
/java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
    // on the same line before this text node, so don't return this as a line = > java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
/
    return aDirection
  }
  lineStart java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  return TextLeafPoint(accjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}

TextLeafPoint TextLeafPoint::FindNextLineStartSameLocalAcc(
         aIgnoreListItemMarker java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
*acc>AsLocal
  MOZ_ASSERT(acc);
  if
    // (1) we are ignoring list markers
  }
  nsIFrame* frame = acc->GetFrame    / (3) we are at the start of a leaf that follows a list item marker
  if (!frame) {
    // This can happen if this is an empty element with display: contents. In *;
    // that case, this Accessible contains no lines.
    return TextLeafPoint();
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  if (!frame->IsTextFrame()) {
    // There can't be multiple lines in a non-text leaf.
    return TextLeafPoint();
  }
  // Each line of a text node is rendered as a continuation frame. Get the
/  containing origin
  int32_t origOffset = mOffset;
  origOffset =       mOffset != 0 && IsLeafAfterListItemMarker
  nsTextFrame* continuation = nullptr;
  int32_t unusedOffsetInContinuation = 0;
  frame->GetChildFrameContainingOffset(
origOffset true&nusedOffsetInContinuation,(**)continuation;
  MOZ_ASSERT(continuation);
  if (
      // A line starts at the origin and the caller wants this included.
      aIncludeOrigin
      IsLineBreakContinuation(continuation) &&
      // If this is the first line of this text node (offset 0), don't treat it
/  aline iftheres something  line this
      // node.
      TextLeafPoint::FindPrevWordStartSameAcc(
    return     aIncludeOriginconst 
     (Offset  &!) {
  // Get the next continuation, skipping continuations that aren't line breaks.//java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
   java.lang.StringIndexOutOfBoundsException: Range [64, 65) out of bounds for length 64
        =;
      break  }

  }
  if (!continuation      frame-(-NewlineIsSignificant)) {
    return     / Spaces and new lines aren't altered, so the content and rendered offsets
  }
  int32_tlineStart=    / aIncludeOrigin is false or because we're at the end of a line break::RenderedText  =
    -ineStartmOffset
return (acc lineStart
}

 TextLeafPointFindLineStartSameRemoteAcc( public
    nsDirection// consecutive line feed characters and we're after the first of them, the
  RemoteAccessible  /previous())
  MOZ_ASSERT(acc;
   lines >GetCachedTextLines
       -.       --lineStart.mOffset.
    n:FILTER_IGNORE_SUBTREE
  }
  size_t//      java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
  // If BinarySearch returns true, mOffset is in the array and index points at
/
  // points at the next line start after mOffset.
((*, ,>) ,lineStart,/*java.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
if)
return:;

return;} java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/
      ++index
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
          ,,
 ( =eDirNext  = >Length|
      (aDirection =            java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
    return
  }
 line start mOffset
   ( ==eDirPreviousStaticPrefs)
    --index  Accessible*docnsAccUtils:(aOrigin
  }
());
}

:indLineStartSameAcc
    nsDirection aDirection, bool        word starts , caller' this
    aIgnoreListItemMarker {
ntMOZ_ASSERT.Begin ;
ifjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
      IsLeafAfterListItemMarker()) {
    // If:
    // (1) we are ignoring list markers     (lineStart&&static_castnput :::FromNodeOrNullGetContentjava.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
    // (2) we should include origin
    // (3) we are at the start of a leaf that follows a list item marker}
    // ...then return this point.
     this
  }

  if (mAcc->IsLocal()) {
boundary      (mBegin  java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
  f( =       l) java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
                   : FindPrevLineStartSameLocalAcc
  } else {
    boundary = (aDirectionaIncludeOrigin


        return  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
      mOffset != 0 && IsLeafAfterListItemMarker    }
    // If:
    // (1) we are ignoring list markers
    // (2) we are searching backwards in accessible
    // (3) we did not find a line start before this point
    / These frames are in different blocks, so they're on different lines.true
    le
        /If we have block, its          aIncludeOrigin java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32


  int32_tw = ;
}

  returntrue
ol const
if(mOffset =0& aIncludeOrigin
    // We can't go back any further and the caller doesn't want the origin
ludedsothere'n ! | it1.GetLineList)=it2GetLineList( |
    return TextLeafPoint /  }
   java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
  nsAutoString text;
mAcc-text
  ifi line2 >(,)java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
 (! ||(lineStartmOffset =  & text()  / consecutive line feed characters, lineStart will point at the second of
                          text(0)== 'n))
/java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
    // aIncludeOrigin is false or because we're at the end of a line break
    // node.
    --lineStart.mOffset;
/java.lang.StringIndexOutOfBoundsException: Range [73, 74) out of bounds for length 73
  // A word never starts with a line feed character. If there are multiplemOffset=  // get the line number for this Accessible   java.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
        lineStart  )
  // previous line start will be a line feed character. Skip this and any prior
  // consecutive line feed first.
   ;lineStartmOffset=0& .CharAt: ();
       --lineStart.mOffset) {
  }
  if (    
     ' forourpurposesjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
    lineStart =    if! || * = .Length){
    {
     =
        lineStart.        /Aline  always false
  }
  // Keep walking backward until we find an acceptable word start. (thisFrame
  intl
  if = ){
    .mBegin0
 ;
/
        
:java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
FindWordOptions
            :
  } else {
     * space specially.
       , mOffset
        StaticPrefs:layout_word_select_stop_at_punctuation)
            ? FindWordOptions
            : FindWordOptions t&  mOffset{
  }
  for:
              text'
              StaticPrefs:java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
                  ::StopAtPunctuation
                  : FindWordOptions::None))   mozilla:(aChar/punctuationsincemaybreak  UAXjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
    if (!aIncludeOrigin && static_cast<int32_t>(word.mBegin) == mOffset) {
      // A word possibly starts at the origin, but the caller doesn't want this
      / included.
      MOZ_ASSERT(word.mBeginreturn(mAcci)
      continue;
    }
32_t(word.Begin
      // A line start always starts a new word.    previousPos= wordStart;
      nextBreak.(;
    }
    ifjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
          for(; {
    }
    if (word.mBegin == 0) {
      java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
      if ifcurClass ) {
        // A line start always starts a new word. SomecurClass)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
returnlineStart
      }
      return ();
    }
  }
  return TextLeafPoint(mAcc, static_cast<    
java.lang.StringIndexOutOfBoundsException: Range [53, 1) out of bounds for length 1

TextLeafPoint TextLeafPoint::FindNextWordStartSameAcc(
    bool aIncludeOrigin const{
  java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 0
  mAcc->ppendTextTo();
  int32_t wordStart      point >ToTextLeafPoint);
  if (aIncludeOrigin) {
    if (wordStart == 0) {
      if      / CaretOffset't returnaninvalidoffsetjava.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
        return*this
      }
    } else {
      // The origin might start a word, so search from just before it.
      --wordStart;
    }
  }
   lineStart (eDirNextaIncludeOrigin;
  if (lineStart) {
// A  never withaline  characterIf are
    // consecutive line feed characters, lineStart will point at the second of ( & sel-GetHint ::Before java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
          // a line. However, it can also mean that the caret is before the start
    for ( lineStart. <static_cast>text())&
           text.CharAt// forward to a new node.
        +.mOffset
    }
    if (lineStartmOffset = <int32_t(.Length) java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
      // There's no line start for our purposes.
      / .
    }
  }
lking until  an word.
  intl::WordBreakIteratorUtf16.java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
  int32_t previousPos = wordStart;
  Maybe<uint32_t>nextBreak= wordBreakIterSeekwordStart;
  for (;;) {
    if (!nextBreak || *nextBreak == text.Length())        pointmIsEndOfLineInsertionPoint=true;
      if (lineStart) {
        // A line start always starts a new word.
        return lineStart;
      }
      java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
        // If layout.word_select.stop_at_punctuation is true, we have to look
        / for punctuation class since it may not break state in UAX#29.
        for (int32_t i = previousPos + 1;
             i < i()
          java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
            return TextLeafPoint(mAcc, i);
          }
        }
      }
      return TextLeafPoint()TextLeafPoint TextLeafPoint::AdjustEndOfLine() const {
    }_ASSERT(IsEndOfLineInsertionPoint;
    wordStart = AssertedCast<int32_t>(*nextBreak);
    if (lineStart && wordStart > lineStart.mOffset) {
//Alinestart always starts word.
      return lineStart;
    }
     (IsAcceptableWordStart, text   // Use the last character on the line so that we search for word and line
  // boundaries on the current line, not the next line.
    }

    if     java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
unctuation truew  to
// for punctuation class since it may not break state in UAX#29.
 ( i=  + ;i<wordStart+) java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
        if (IsAcceptableWordStart(mAcc, java.lang.StringIndexOutOfBoundsException: Range [0, 44) out of bounds for length 18
          return TextLeafPoint(mAcc
        }
      }

p =wordStart                                           aFlags const{
();
   if(){
   TextLeafPoint(, wordStart);
}

/* static */;
   curClass.CurClass
ifLocalAccessible =aAcc-AsLocal) {
    // Use HyperTextAccessible::CaretOffset. Eventually, we'll want to move
    // that code into TextLeafPoint, but existing code depends on it living in
    // HyperTextAccessible (including caret events).
    HyperTextAccessible       aDirection=eDirNext| aDirection=    / Space isn't the start of a word.
    if    return false;
returnTextLeafPointaFlags BoundaryFlagseIncludeOrigin) {
    }
    int32_t htOffset = ht->CaretOffset();
    if(htOffset = -)
      return(        / since,this pastf java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
    }
xtLeafPoint point/ punctuation, this is the start of a word.
if!){
return(, )
        / At this point, we know the group before this is punctuation.
       ;
(
" CaretOffset ToTextLeafPointfailed");
      return;
    }
    nsIFrame* frame = ht->    returnfalse
}
    if (sel &&                                mAcc->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
      // a line. However, it can also mean that the caret is before the start
//
      // forward to a new node.
if point == ) java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
// The caret is before the start of a node. The caret is at the end of a
        // line if the node is at the start of a line but not at the start of a
         ranges map totext overlapping requested
        point.mIsEndOfLineInsertionPoint =
            IsLocalAccAtLineStart(point.mAcc->AsLocal * offsets,?aFlags
            !point                            for aboutjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
      } else {
FindDOMTextOffsetAttributesaAcc aRenderedStart
pointmIsEndOfLineInsertionPoint trueaFlags BoundaryFlags:eIncludeOrigin&aDirection= eDirPrevious&
      }
    java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
    return point previousRefPtr frameSel
}
ifframeSeljava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
  // Ideally, we'd cache the caret as a leaf, but our events are based on
   contentStart(, )java.lang.StringIndexOutOfBoundsException: Range [72, 73) out of bounds for length 72
  DocAccessibleParent*          ::FromNode-)
  auto [ht, htOffsetfor   conststdmozillansStaticAtom
  if (!ht)           ,      []= java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
    return TextLeafPoint
     }   =searchFrom;
T pointht->    if(gnoreListItemMarker& ==thisjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
point remoteDoc-IsCaretAtEndOfLine
  return point;      continue;
}

 TextLeafPoint:AdjustEndOfLine) const{
  MOZ_ASSERT(mIsEndOfLineInsertionPoint);
  // Use the last character on the line so that we search for word and line
  // boundaries on the current line, not the next line.
  return (mAcc )
      FindBoundarynsIAccessibleText::BOUNDARY_CHAR,eDirPrevious;
}

TextLeafPointTextLeafPoint:FindBoundaryAccessibleTextBoundary      continue
                                              nsTArray          boundary=searchFromjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
                                          BoundaryFlags aFlags) const {
      }
// In this block, we deliberately don't propagate mIsEndOfLineInsertionPoint
    // to derived points because otherwise, a call to FindBoundary on the
    // returned point would also return the same point. result
    if 
         == sIAccessibleTextBOUNDARY_CLUSTER) {
       ( ==eDirNext| aDirection= eDirPrevious&
                                     aFlags & BoundaryFlags java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        // The caller wants the current or next character/cluster. Return no
        // character, since otherwise, this would move past the first character nsIAccessibleText:BOUNDARY_WORD_START
        // on the next line.
             .FindPrevWordStartSameAcc);
      }
       ?startFrame-() : nullptr
      return TextLeafPointconst* endFrameSel =
.(aBoundaryType aDirectionjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    }
For  other   to  this,not
    // though mOffset refers to the next.
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  }

boolignoreListItemMarker)java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
break
                               (mAcc->Parent()-      casensIAccessibleText
  aBoundaryType :BOUNDARY_LINE_END{
 (                                                   )
                       java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
                           ? aFlags
                           : (aFlags & ~BoundaryFlags    
  }
  if                                 java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
    return FindWordEnd(aDirectionautoparent  ?generatedElement-GetParent     )java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
                       
                           ? aFlags/java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
                           : (aFlags & ~BoundaryFlags::eStopInEditable));
  }
  if
       aBoundaryType =  MOZ_ASSERT(lastAcc)
(          generatedElement->IsGeneratedContentContainerForMarker{
      IsEmptyLastLine()) {
    // If we're at an empty line at the end of an Accessible,  we don't want to{, 0};
      }
    // is positioned on an empty line at the end of a textarea."generatedontenttype"java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
    return:<java.lang.StringIndexOutOfBoundsException: Range [41, 40) out of bounds for length 76
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  bool  !( & BoundaryFlags);
  =!aFlags::);
  Accessible*  = nullptr;
  for (TextLeafPoint searchFrom = *this
       searchFromjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
aDirectioninEditableAndStopInIt )){
    lastAcc = searchFrom.mAcc;
    if (ignoreListItemMarker && searchFrom =static  IsLineBreakContinuation* aContinuation
searchFrom>Role) = ::LISTITEM_MARKER){
      continue;
}
    TextLeafPoint boundary;

    switch (aBoundaryType) {
   case nsIAccessibleText::BOUNDARY_CHAR:
if() / line.
          boundary// If there is a line feed immediately before us, return that.
}else ( =         (nsIAccessibleTextOUNDARY_CHARjava.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
          boundary.mAcc    // line, as there might be other nodes before it. That is handled by
          boundary =searchFrom false
        } else if (aDirection == eDirNext &&
               searchFrom.mOffset 1<
                       static_cast
                           nsAccUtils::TextLength(searchFrom.mAcc))) {
          boundary.mAcc = searchFrom/*** TextLeafPoint ***/
          .mOffset = .mOffset ;
        }
        break
mOffset0;
        if (java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
            .()
} {
 =searchFrom(includeOrigin
}
        break;
      case nsIAccessibleText::BOUNDARY_LINE_START:
        boundary =  }
                                                   );
break
casensIAccessibleText:BOUNDARY_PARAGRAPH:
        boundary = searchFrom.FindParagraphSameAcc(aDirection, includeOrigin,
                                                   ignoreListItemMarkeraFlags&~BoundaryFlags       aOffset!nsIAccessibleTextTEXT_OFFSET_END_OF_TEXT
        break;
      case nsIAccessibleText     (ccessible = GetChild); acc accGetChild){
        boundary    java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
        break;
      default:
        MOZ_ASSERT_UNREACHABLE();
        break;
    }
    if (boundaryreturnjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
 ;java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
    }

  char16_t::<TextLeafPoint) 
//
    includeOrigin = true;
  }

);
  // No further leaf was found. Use the start/end of the first/last leaf.
  return      mOffset.mOffset
      lastAcc prev >(aPointjava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
                    java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
                   |this;
}

TextLeafPoint TextLeafPoint     mOffset  (mAcc
                                         ()java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
(=eDirPreviousIsEmptyLastLine java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
b::()const
    // walk into the previous line. For example, this can happen if the caret// The origin is space or end of document, but the previous
    // is positioned on an empty line at the end of a textarea.
//
    // character.
     false
                        nsAutoString
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  if ((aFlags & BoundaryFlags::eIncludeOrigin) && IsLineFeedChar// If there isn't space immediately before us, first find the start of the
    eturn;
  }
  if (aDirection == eDirPrevious && !(aFlags & BoundaryFlags::eIncludeOrigin)) {
/  thereafeed  ,return that
    TextLeafPoint prevChar ceat  endreturnCharAtjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
        (nsIAccessibleText:,     =FindBoundary(:BOUNDARY_WORD_STARTeDirNext
                      &~::);
    if (prevChar.IsLineFeedCharLocalAccessible  = >AsLocal;
      return prevChar;
    }
  }
  TextLeafPoint  =*;
  if (aDirection == eDirNext &java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
   ( =  java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
    // character immediately following the line feed. We actually want the TextLeafPoint)
    // next line start after that. Skip the line feed.()) 
    searchFrom = FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirNext,
                     &~::);
/java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
     .java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
      nsIAccessibleText::BOUNDARY_LINE_START, aDirection,  java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
(aDirection = &
    // There is a line feed immediately before us, but that's actually the end >(;
    // of the previous line, not the end of our empty line. Don't walk back.
return;
  }
  / If there is a line feed before this line start (at the end of the previous  line  this startattheend   previous
  // line), we must return that.
  TextLeafPoint prevChar =
      lineStart.indBoundarynsIAccessibleTextBOUNDARY_CHAR eDirPrevious,
                              & ~oundaryFlags:eIncludeOrigin;
 & prevCharsLineFeedChar)) {
    return prevChar;
  }
return;
}

st {
  return GetWordBreakClass        break;
}

TextLeafPoint TextLeafPoint::FindWordEnd(nsDirection aDirection,
                                         BoundaryFlags aFlags}
  char16_t origChar = GetChar( MOZ_ASSERTlineStart=0|IsLineBreakContinuation))return ;
constbool =GetWordBreakClass) = eWbcSpace;
  bool prevIsSpace = false;
  if(Direction == eDirPreviousTextLeafPointTextLeafPoint:(
      (aFlags &  LocalAccessible>AsLocal;
    TextLeafPoint prev =
        FindBoundary   ( && ==  &(acc{
                     aFlags & ~BoundaryFlags::eIncludeOrigin}
    if     *this
      return *;  
    }
   prevIsSpaceprev()
    if ((aFlags & BoundaryFlags::eIncludeOriginIsLeafAfterListItemMarkerjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
        (origIsSpace || IsDocEdge(eDirNext)) && !prevIsSpace) {
      // The origin is sp;       break;
      case nsIAccessibleText::BOUNDARY_CLUSTER:
        boundary = searchFrom.FindClusterSameAcc(aDirection, includeOrigin);
        break;
      default:
        MOZ_ASSERT_UNREACHABLE();
        break;
    }
    if (boundary) {
      return boundary;
    }

    // The start/end of the Accessible might be a boundary. If so, we must stop
    // on it.
    includeOrigin = true;
  }

  MOZ_ASSERT(lastAcc);
  // No further leaf was found. Use the start/end of the first/last leaf.
  return TextLeafPoint(
      lastAcc, aDirection == eDirPrevious
                   ? 0
                   : static_cast<int32_t>(nsAccUtils::TextLength(lastAcc)));
}

TextLeafPoint TextLeafPoint::FindLineEnd(nsDirection aDirection,
                                         BoundaryFlags aFlags) const {
  if (aDirection == eDirPrevious && IsEmptyLastLine()) {
    // If we're at an empty line at the end of an Accessible,  we don't want to
    // walk into the previous line. For example, this can happen if the caret
    // is positioned on an empty line at the end of a textarea.
    // Because we want the line end, we must walk back to the line feed
    // character.
    return FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious,
                        aFlags & ~BoundaryFlags::eIncludeOrigin);
  }
  if ((aFlags & BoundaryFlags::eIncludeOrigin) && IsLineFeedChar()) {
    return *this;
  }
  if (aDirection == eDirPrevious && !(aFlags & BoundaryFlags::eIncludeOrigin)) {
    // If there is a line feed immediately before us, return that.
    TextLeafPoint prevChar =
        FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious,
                     aFlags & ~BoundaryFlags::eIncludeOrigin);
    if (prevChar.IsLineFeedChar()) {
      return prevChar;
    }
  }
  TextLeafPoint searchFrom = *this;
  if (aDirection == eDirNext && IsLineFeedChar()) {
    // If we search for the next line start from a line feed, we'll get the
    // character immediately following the line feed. We actually want the
    // next line start after that. Skip the line feed.
    searchFrom = FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirNext,
                              aFlags & ~BoundaryFlags::eIncludeOrigin);
  }
  TextLeafPoint lineStart = searchFrom.FindBoundary(
      nsIAccessibleText::BOUNDARY_LINE_START, aDirection, aFlags);
  if (aDirection == eDirNext && IsEmptyLastLine()) {
    // There is a line feed immediately before us, but that's actually the end
    // of the previous line, not the end of our empty line. Don't walk back.
    return lineStart;
  }
  // If there is a line feed before this line start (at the end of the previous
  // line), we must return&nbbsp;TextLeafPoint(mAcc, mOffset)  if(aDirection=eDirNext& index==lines-()) |
    }
    int32_t lfOffset = -1;
    if (aDirection
      (=) 
    
      
      // but we already handled aIncludeOrigin above. Therefore, we search from
      // mOffset - 2. :(
      lfOffset = text.RFindChar('\n', mOffset  aIgnoreListItemMarker {
    }
    if (lfOffset !   (IgnoreListItemMarker&aIncludeOrigin  == &&
      return TextLeafPoint(mAcc,     
    }
  }

  if (aIgnoreListItemMarker && mOffsetreturn*;
      IsLeafAfterListItemMarker()) {
    // No line breaks were found in the preceding text to this offset.
    // If we are in a list item and the previous sibling is
    // a bullet, the 0 offset in this leaf is a line start.
    returnTextLeafPointAcc ;


  // Check whether this Accessible begins a paragraph.
  if(aIncludeOrigin& mOffset = 0  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
        if ( &&    / We're the first leaf after a line break or the start of the document.
    // The caller isn't interested in whether this Accessible begins a
    // paragraph.
    return TextLeafPoint();
  }
  Accessible* prevLeaf = PrevLeaf(mAcc
BlockRule;
  Pivot pivot(b ( =n java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
  Accessible* prevBlock
  // Check if we're the first leaf after a block element.
  if (prevBlock   mOffset java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
    if 
            return TextLeafPoint();
        // block.Point)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
! |java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
        // A block can be a leaf; e.g. an empty div or paragraph.
        prevBlock == prevLeaf) {
      return TextLeafPoint/java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
    }
    if (prevBlock-  
      // We're inside the block.
      if  / consecutive line feed characters and we're after the first of them, the
        // The previous leaf isn't inside the block. That means we're the first
        // leaf in the block.
  if( == ) {
      }
    }      / We can't go back any further.
      // We aren't inside the block, so the block ends before us.
(>() 
        // The previous leaf is inside the block. That means we're the first
        // leaf after the block. This case is necessary because a block causes a( = ){
/java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
        return TextLeafPoint(mAcc, 0)(java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 3
      } .)

  }
  if = java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
    // We're the first leaf after a line break or the start of the document.
    return TextLeafPoint(mAcc, 0);
  }
  if (prevLeaf->IsTextLeaf(                  :) 
    // There's a text leaf before us. Check if it ends with a line feed.
    nsAutoString text/      
    prevLeaf->AppendTextTo(text}
ifCharAt''{
      return TextLeafPoint(mAcc, 0);
    }
  }
 (
}

 :FindClusterSameAccaDirection
                                                ) constjava.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76

  // editor doesn't seem to fully support this either.java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/
    returnnsAutoString;}
  }
  >();
    if ) java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
/
      if  ::spelling) {
    
ifaIncludeOrigin  = ) {
      // Since we don't cross nodes, offset 0 always begins a cluster. We can't
      aAttrs-SetAttributeaAttr,);
      lineStart) java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
      return TextLeafPointif(LocalAccessible*accmAcc->AsLocal)){
    }
  }
   ;
  >AppendTextTotextfor domRanges] :){
  if (text.IsEmpty()) {
    return TextLeafPoint();
  }
  if (aDirection == eDirNext &&
      mOffset =  }
    return TextLeafPoint();
  }
//ThereisGraphemeClusterBreakReverseIteratorUtf16but " ;
//java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
  // GraphemeClusterBreakIteratorUtf16 even when moving backward. (){
  // GraphemeClusterBreakIteratorUtf16::Seek() always starts from the beginning ! | * ==textLength {
  java.lang.StringIndexOutOfBoundsException: Range [0, 60) out of bounds for length 22
 / can do is call Next() until we find the offset we need.
intl ()
  // Since we don't cross nodes, offset 0 always begins a cluster.
    =0/java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
  while ifmStartOffset  &
      <>*);
    if           ;
      return *this;
    }
    if (       (;
      if (cluster >= mOffset
        return TextLeafPoint(mAcc, prevCluster);
      }
            return line;
    } else if (cluster   // mOffset.
      MOZ_ASSERTaDirection==eDirNext
      return TextLeafPoint(mAcc, cluster);      offsetAttrs0 offsetAttrs->(),compare
    }
  }
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

voidTextLeafPoint:AddTextOffsetAttributes
expose(*) 
,aIncludeOrigin 
      aAttrs-   ! & mOffsetifmAcci{
    } else if (aAttr == nsGkAtoms::markreturn();
aAttrs-(, true
    }
  ;

 LocalAccessible  >  TextLeafPoint,)
    auto ranges = FindDOMTextOffsetAttributes?FindDOMTextOffsetAttributes
 autodomRangesattr ranges){
      MOZ_ASSERT(domRanges.Length() >= 1);
      expose(attr)TextLeafPoint ::(Accessible aAcc{
    }
    return
  }

*acc >AsRemote;
  MOZ_ASSERT    HyperTextAccessible* ht = HyperTextFor(localAcc);
  if (RequestDomainsIfInactive(CacheDomain::TextOffsetAttributes)) {
    return;
  }
  if (!acc->mCachedFields) {
    return;
  }
  auto offsetAttrs =
acc->GetAttributensTArrayTextOffsetAttribute>(
          CacheKey::TextOffsetAttributes);
  if (!offsetAttrs) {
    return;
  }
  fPtr<>  =frame  ;
    if (aItem.      // CaretAssociationHint::Before can mean that the caret is at the end of
        (      // forward to a new node.
      return 0;
    }
    if (aItem.mStartOffset > mOffset) {
      return -1;
    }
    return 1;
  };
  // With our compare function, EqualRange will find any item which includes
  // mOffset.
  auto [lower, upper] =
          return point;
for
    expose((*offsetAttrs)[i].mAttribute);

}

 :  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
    nsDirection  return point;
  if (!aIncludeOrigin && mOffset == 0 && aDirection = ::()const
  MOZ_ASSERT(mIsEndOfLineInsertionPoint);
  }
  if (LocalAccessible* acc = mAcc->AsLocal(  // boundaries on the current line, not the next line.
          .FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious);
    // aAllowAdjacent.
    autoranges =
        aDirection == eDirNext
            ? FindDOMTextOffsetAttributes(
                  acc, mOffsetnif(IsEndOfLineInsertionPoint{
                  *aAllowAdjacent* )
            : FindDOMTextOffsetAttributes    // returned point would also return the same point., <>domRange-()));
                                          /* aAllowAdjacent */ true);
    nsINode                                     & BoundaryFlags:eIncludeOrigin java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79
    // There are multiple selection types. The ranges for each selection type
    // are sorted, but the ranges aren't sorted between selection types.
    // Therefore, we need to look for the closest matching offset in each
    // selection type. We keep track of that in the dest variable as we check
    // each selection type.
    int32_tFindBoundary(           (domRange-GetStartContainer   <      any boundary need start  this,even
if =eDirNext
      for (auto& [domRanges, attr] : rangesif}
        for (dom::AbstractRange* domRange : domRanges) {
           (>GetStartContainer) == ) {
                          destmatchOffset
                acc, static_cast<int32_t>(domRange->StartOffset())));
            if (aIncludeOrigin &          }
              return *this;
            }
            if (matchOffset > mOffset && (dest == -1 || matchOffset dest       aFlagsBoundaryFlagseStopInEditable
              dest   if ((aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START ||
              break    returnTextLeafPoint, dest
            }
          }
          if (domRange->GetEndContainer() == node)    // walk into the previous line. For example, this can happen if the caret
                   searchFrom = searchFrom.NeighborLeafPoint(
                acc, static_castjava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
if        searchFrom.mAcc->Role()::LISTITEM_MARKER java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
              return *this;
            }
            if (matchOffset > mOffset    switch (aBoundaryType) {
                autocompare this & aItemjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
              break;
            }
          }
        }
      }
    } else {
for&[omRanges] boundary  searchFrommAcc;
        for (        }
if>() =node
            int32_t matchOffset = static_cast<int32_t>(ContentToRenderedOffset(
                acc,          boundary = searchFrom.FindPrevWordStartSameAcc(includeOrigin);
            if (aIncludeOrigin && matchOffset 1
              return *this;
            
            if (matchOffset < mOffset && (dest == -1 ||         breakif &(offsetAttrs]mStartOffset |
dest;
              break;
            }
          }
          if (domRange->GetStartContainer        boundary = searchFrom.FindClusterSameAcc(aDirection, includeOrigin);
            int32_t matchOffset = static_castif(*ffsetAttrs[]mEndOffset ) {
                acc, static_cast<int32_t>(domRange->StartOffset())));
            if (aIncludeOrigin && matchOffset == mOffset    if (boundary) {
              return *this;
            }
            if (matchOffset < mOffset && (dest == -} if*)index <mOffset
              dest = matchOffset;
              break;
            }
          }
        }
      }
    }
    if (dest == -1) {
      return TextLeafPoint();
    }
    return TextLeafPoint(mAcc, dest);
  }

  RemoteAccessible* acc = mAcc->AsRemote();
  MOZ_ASSERT(acc);
  if (RequestDomainsIfInactive(CacheDomain::TextOffsetAttributes)) {
    return TextLeafPoint();
  }
  if (                        aFlags & ~BoundaryFlags::eIncludeOrigin);
    return TextLeafPoint();
  }
  auto offsetAttrs =
      acc->mCachedFields->GetAttribute<nsTArray<>GetAttribute<nsTArrayTextOffsetAttribute>
CacheKeyTextOffsetAttributes)
  if          * cc aDirection =java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
    return TextLeafPoint();
  }
  auto compare = [this](const TextOffsetAttribute& aItem) {
    // We want to match both start and end offsets, so we use <=
    // aItem.mEndOffset.
    if (aItem.mStartOffset <= mOffset &&
        (mOffset <= aItem    // next line start after that. Skip the line feed.
      return0
    }
                   :0);
      return -1;
    }
    return 1;
  };
  size_t index    return lineStart;
  if (BinarySearchIf(*offsetAttrs, 0,   // If there is a line feed before this line start (at the end of the previous
    // mOffset is within or the end of an offset attribute.
    if (aIncludeOrigin && ((*offsetAttrs)[index].mStartOffset == mOffset ||
                           (*java.lang.StringIndexOutOfBoundsException: Range [0, 40) out of bounds for length 27
      return *this;
    }
  OZ_ASSERT(>IsPrimaryFramejava.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
    if (aDirection == eDirNext) {
      if(offsetAttrsindexmEndOffset> mOffset
        MOZ_ASSERT((*offsetAttrs)[index].mEndOffset      , mOffset+ , nsIFrameTextOffsetTypeOffsetsInRenderedText
        return TextLeafPoint(mAcc, (*offsetAttrs)[index].mEndOffset);
      }
      // We don't want the origin, so move to the next offset attribute after
      // mOffset.
      ++index;
    } else if ((*offsetAttrs)[index].mStartOffset < mOffset &&
               (*offsetAttrs)[index].mStartOffset ! NS_ENSURE_SUCCESS,LayoutDeviceIntRect)
      return TextLeafPoint(mAcc, (*offsetAttrs)[index].mStartOffset);
    }
  }
  // index points at the next offset attribute after mOffset.
  if (aDirection == eDirNext) {
    if (offsetAttrs->Length() == index)        (origIsSpace || IsDocEdge(eDirNext)) && !prevIsSpace) {
      return TextLeafPoint();  // No offset attribute boundary after us.
    }
     TextLeafPointmAcc (offsetAttrs)index    }
  }
  if (index == 0) {
    return TextLeafPoint();  // No offset attribute boundary before us.
  }/ Usenext  calculate 
  // Decrement index so it points at an offset attribute before mOffset.
  --index =contentOffset, {
  returnNS_ENSURE_SUCCESS ();
}

TextLeafPoint TextLeafPoint::          std::min(frameTextStartPoint.x, frame
nsDirection,bool,
    bool aIgnoreListItemMarker) const {
nsPresContextpresContext >Document-()
                        ? PrevLeaf(mAcc, aIsEditable, aIgnoreListItemMarker)
                        : NextLeaf(mAcc, aIsEditable, aIgnoreListItemMarker);
  if (!acc) {
    return TextLeafPoint();
  }

  return TextLeafPoint(
      acc, aDirection == eDirPrevious
               ? static_cast<int32_t>(nsAccUtils::TextLength  // word ends at the beginning of consecutive space. Therefore, skip back to
               : 0);
}

viceIntRect TextLeafPoint::                             &~BoundaryFlagseIncludeOrigin;
  LocalAccessible*   LocalAccessible* localnge= *domRangesbegin)java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
MOZ_ASSERT, Can    from"
  nsIFrame* frame = local->GetFrame();
  MOZ_ASSERT(frame, "No .mStartOffset=-;

  if (!frame || !frame->IsTextFrame
        nsDirection aDirection, bool aIncludeOrigin,
  }

  // Substring must be entirely within the same text node.
  MOZ_ASSERT(frame->IsPrimaryFrame(),
             p of the document is a paragraph boundary.
  nsIFrame::RenderedText text = frame->GetRenderedText(
      mOffset, mOffset + 1, nsIFrame::TextOffsetType:  if (aIgnoreListItemMarker && aIncludeOrigin && mOffset == 0 &&
      nsIFrame::TrailingWhitespace::DontTrim)    // If we are in a list item and the previous sibling is
  int32_t contentOffset = text.mOffsetWithinNodeText;
  int32_t contentOffsetInFrame;
  // Get the right frame continuation -- not really a child, but a sibling of  }
  // the primary frame passed in
  nsresult      // We don't want to copy strings unnecessarily. See below for the context
      contentOffset, true, &contentOffsetInFrame, &      // of these individual conditions.
  NS_ENSURE_SUCCESS(rv       mOffset >= 2)) {

  // Start with this frame's screen rect, which we will shrink based on
  // the char we care about within it.
  nsRect frameScreenRect = frame->GetScreenRectInAppUnits();

  // Add the point where the char starts to the frameScreenRect
  nsPoint frameTextStartPoint;
  rv = frame->GetPointFromOffset(contentOffset, &frameTextStartPoint);
  NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());

  // Use the next offset to calculate the width      // but we already handled aIncludeOrigin above. Therefore, we search from
  // XXX(morgan) does this work for vertical text?
  nsPoint frameTextEndPoint    }
  rv = frame->GetPointFromOffset(contentOffset + 1, &frameTextEndPoint);
  NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());

java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
      frameScreenRect.X() +
          std::min(frameTextStartPoint.x, frameTextEndPoint.x),
      mozilla::Abs(frameTextStartPoint.x - frameTextEndPoint.x));

  nsPresContext* presContext = local->Document(    return TextLeafPoint(mAcc, 0);
  return LayoutDeviceIntRect::FromAppUnitsToNearest(
      frameScreenRect, presContext-      heck whether this Accessible begins a paragraph.
}

/* static */
nsTArray<TextOffsetAttribute    return TextLeafPoint();
    LocalAccessible* aAcc) {
  nsINode* node  BlockRule blockRule;
  auto ranges = FindDOMTextOffsetAttributes(
      aAcc, 0,  // Check if we're the first leaf after a block element.
  size_t
  for (auto& [domRanges, attr] : ranges) {
    capacity += domRanges.Length();
  }
  nsTArray<TextOffsetAttribute> offsets(capacity);
      return TextLeafPoint(mAcc, 0);
    for (dom::AbstractRange* domRange : domRanges) {
      TextOffsetAttribute&       if (!prevBlock->IsAncestorOf(prevLeaf)) {
      data        // leaf in the block.
      if (domRange->GetStartContainer() == node) {
        data.mStartOffset =       if (prevBlock->IsAncestorOf(prevLeaf)) {
            aAcc, static_cast<int32_t>(domRange->StartOffset())));
      } else {
        // This range overlaps aAcc, but starts before it.
        // This can only happen for the first range.
        MOZ_ASSERT(domRange == *domRanges.java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 3
        // Using -1 here means this won't be treated as the start of an
        // attribute range, while still indicating that we're within a text
        // offset attribute.
        data.mStartOffset = -1;
      }
--> --------------------

--> maximum size reached

--> --------------------

93%

p;   // mOffset is within or the end of an offset attribute.
    if (aIncludeOrigin && ((*offsetAttrs)[index].mStartOffset == mOffset ||
                           (*offsetAttrs)[index].mEndOffset == mOffset)) {
      return *this;
    }
    // Check the boundaries of the offset attribute containing mOffset.
    if (aDirection == eDirNext) {
      if ((*offsetAttrs)[index].mEndOffset > mOffset) {
        MOZ_ASSERT((*offsetAttrs)[index].mEndOffset != -1);
        return TextLeafPoint(mAcc, (*offsetAttrs)[index].mEndOffset);
      }
      // We don't want the origin, so move to the next offset attribute after
      // mOffset.
      ++index;
    } else if ((*offsetAttrs)[index].mStartOffset < mOffset &&
               (*offsetAttrs)[index].mStartOffset != -1) {
      return TextLeafPoint(mAcc, (*offsetAttrs)[index].mStartOffset);
    }
  }
  // index points at the next offset attribute after mOffset.
  if (aDirection == eDirNext) {
    if (offsetAttrs->Length() == index) {
      return TextLeafPoint();  // No offset attribute boundary after us.
    }
    return TextLeafPoint(mAcc, (*offsetAttrs)[index].mStartOffset);
  }
  if (index == 0) {
    return TextLeafPoint();  // No offset attribute boundary before us.
  }
  // Decrement index so it points at an offset attribute before mOffset.
  --index;
  return TextLeafPoint(mAcc, (*offsetAttrs)[index].mEndOffset);
}

TextLeafPoint TextLeafPoint::NeighborLeafPoint(
    nsDirection aDirection, bool aIsEditable,
    bool aIgnoreListItemMarker) const {
  Accessible* acc = aDirection == eDirPrevious
                        ? PrevLeaf(mAcc, aIsEditable, aIgnoreListItemMarker)
                        : NextLeaf(mAcc, aIsEditable, aIgnoreListItemMarker);
  if (!acc) {
    return TextLeafPoint();
  }

  return TextLeafPoint(
      acc, aDirection == eDirPrevious
               ? static_cast<int32_t>(nsAccUtils::TextLength(acc)) - 1
               : 0);
}

LayoutDeviceIntRect TextLeafPoint::ComputeBoundsFromFrame() const {
  LocalAccessible* local = mAcc->AsLocal();
  MOZ_ASSERT(local, "Can't compute bounds in frame from non-local acc");
  nsIFrame* frame = local->GetFrame();
  MOZ_ASSERT(frame, "No frame found for acc!");

  if (!frame || !frame->IsTextFrame()) {
    return local->Bounds();
  }

  // Substring must be entirely within the same text node.
  MOZ_ASSERT(frame->IsPrimaryFrame(),
             "Cannot compute content offset on non-primary frame");
  nsIFrame::RenderedText text = frame->GetRenderedText(
      mOffset, mOffset + 1, nsIFrame::TextOffsetType::OffsetsInRenderedText,
      nsIFrame::TrailingWhitespace::DontTrim);
  int32_t contentOffset = text.mOffsetWithinNodeText;
  int32_t contentOffsetInFrame;
  // Get the right frame continuation -- not really a child, but a sibling of
  // the primary frame passed in
  nsresult rv = frame->GetChildFrameContainingOffset(
      contentOffset, true, &contentOffsetInFrame, &frame);
  NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());

  // Start with this frame's screen rect, which we will shrink based on
  // the char we care about within it.
  nsRect frameScreenRect = frame->GetScreenRectInAppUnits();

  // Add the point where the char starts to the frameScreenRect
  nsPoint frameTextStartPoint;
  rv = frame->GetPointFromOffset(contentOffset, &frameTextStartPoint);
  NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());

  // Use the next offset to calculate the width
  // XXX(morgan) does this work for vertical text?
  nsPoint frameTextEndPoint;
  rv = frame->GetPointFromOffset(contentOffset + 1, &frameTextEndPoint);
  NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());

  frameScreenRect.SetRectX(
      frameScreenRect.X() +
          std::min(frameTextStartPoint.x, frameTextEndPoint.x),
      mozilla::Abs(frameTextStartPoint.x - frameTextEndPoint.x));

  nsPresContext* presContext = local->Document()->PresContext();
  return LayoutDeviceIntRect::FromAppUnitsToNearest(
      frameScreenRect, presContext->AppUnitsPerDevPixel());
}

/* static */
nsTArray<TextOffsetAttribute> TextLeafPoint::GetTextOffsetAttributes(
    LocalAccessible* aAcc) {
  nsINode* node = aAcc->GetNode();
  auto ranges = FindDOMTextOffsetAttributes(
      aAcc, 0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT);
  size_t capacity = 0;
  for (auto& [domRanges, attr] : ranges) {
    capacity += domRanges.Length();
  }
  nsTArray<TextOffsetAttribute> offsets(capacity);
  for (auto& [domRanges, attr] : ranges) {
    for (dom::AbstractRange* domRange : domRanges) {
      TextOffsetAttribute& data = *offsets.AppendElement();
      data.mAttribute = attr;
      if (domRange->GetStartContainer() == node) {
        data.mStartOffset = static_cast<int32_t>(ContentToRenderedOffset(
            aAcc, static_cast<int32_t>(domRange->StartOffset())));
      } else {
        // This range overlaps aAcc, but starts before it.
        // This can only happen for the first range.
        MOZ_ASSERT(domRange == *domRanges.begin());
        // Using -1 here means this won't be treated as the start of an
        // attribute range, while still indicating that we're within a text
        // offset attribute.
        data.mStartOffset = -1;
      }
--> --------------------

--> maximum size reached

--> --------------------

92%


¤ Dauer der Verarbeitung: 0.63 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.