Commit 0c0641a63e670967f3641aff3af4388c1c39ba88

Authored by samuel thibault
1 parent c368bef0
Exists in master

Fix reading word-by-word from Orca

firefox-patches/patches-60/text-at-offset-word 0 → 100644
... ... @@ -0,0 +1,764 @@
  1 +Fix reading word-by-word from Orca
  2 +
  3 +# HG changeset patch
  4 +# User Samuel Thibault <samuel.thibault@ens-lyon.org>
  5 +# Date 1550588324 -3600
  6 +# Tue Feb 19 15:58:44 2019 +0100
  7 +# Branch trim-offset
  8 +# Node ID fbdb5d7ff36319d91c9063ea66b778ff72e51ff1
  9 +# Parent dd4aa59c6a1271cbf6ca10813d73f62e7cb072d5
  10 +nsTextFrame::GetTrimmedOffsets: Rework flag parameters r=jfkthame
  11 +
  12 +diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp
  13 +--- a/layout/generic/nsTextFrame.cpp
  14 ++++ b/layout/generic/nsTextFrame.cpp
  15 +@@ -2941,19 +2941,19 @@ static uint32_t GetEndOfTrimmedText(cons
  16 + aIterator->AdvanceSkipped(-1);
  17 + if (!IsTrimmableSpace(aFrag, aIterator->GetOriginalOffset(), aStyleText))
  18 + return aIterator->GetSkippedOffset() + 1;
  19 + }
  20 + return aStart;
  21 + }
  22 +
  23 + nsTextFrame::TrimmedOffsets nsTextFrame::GetTrimmedOffsets(
  24 +- const nsTextFragment* aFrag, bool aTrimAfter, bool aPostReflow) const {
  25 ++ const nsTextFragment* aFrag, TrimmedOffsetFlags aFlags) const {
  26 + NS_ASSERTION(mTextRun, "Need textrun here");
  27 +- if (aPostReflow) {
  28 ++ if (!(aFlags & TrimmedOffsetFlags::kNoPostReflow)) {
  29 + // This should not be used during reflow. We need our TEXT_REFLOW_FLAGS
  30 + // to be set correctly. If our parent wasn't reflowed due to the frame
  31 + // tree being too deep then the return value doesn't matter.
  32 + NS_ASSERTION(
  33 + !(GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
  34 + (GetParent()->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE),
  35 + "Can only call this on frames that have been reflowed");
  36 + NS_ASSERTION(!(GetStateBits() & NS_FRAME_IN_REFLOW),
  37 +@@ -2961,24 +2961,27 @@ nsTextFrame::TrimmedOffsets nsTextFrame:
  38 + }
  39 +
  40 + TrimmedOffsets offsets = {GetContentOffset(), GetContentLength()};
  41 + const nsStyleText* textStyle = StyleText();
  42 + // Note that pre-line newlines should still allow us to trim spaces
  43 + // for display
  44 + if (textStyle->WhiteSpaceIsSignificant()) return offsets;
  45 +
  46 +- if (!aPostReflow || (GetStateBits() & TEXT_START_OF_LINE)) {
  47 ++ if ((aFlags & TrimmedOffsetFlags::kNoPostReflow) ||
  48 ++ (GetStateBits() & TEXT_START_OF_LINE)) {
  49 + int32_t whitespaceCount =
  50 + GetTrimmableWhitespaceCount(aFrag, offsets.mStart, offsets.mLength, 1);
  51 + offsets.mStart += whitespaceCount;
  52 + offsets.mLength -= whitespaceCount;
  53 + }
  54 +
  55 +- if (aTrimAfter && (!aPostReflow || (GetStateBits() & TEXT_END_OF_LINE))) {
  56 ++ if (!(aFlags & TrimmedOffsetFlags::kNoTrimAfter) &&
  57 ++ ((aFlags & TrimmedOffsetFlags::kNoPostReflow) ||
  58 ++ (GetStateBits() & TEXT_END_OF_LINE))) {
  59 + // This treats a trailing 'pre-line' newline as trimmable. That's fine,
  60 + // it's actually what we want since we want whitespace before it to
  61 + // be trimmed.
  62 + int32_t whitespaceCount = GetTrimmableWhitespaceCount(
  63 + aFrag, offsets.GetEnd() - 1, offsets.mLength, -1);
  64 + offsets.mLength -= whitespaceCount;
  65 + }
  66 + return offsets;
  67 +@@ -3706,25 +3709,28 @@ void PropertyProvider::GetHyphenationBre
  68 + aBreakBefore[i] = HyphenType::AutoWithoutManualInSameWord;
  69 + }
  70 + }
  71 + }
  72 + }
  73 +
  74 + void PropertyProvider::InitializeForDisplay(bool aTrimAfter) {
  75 + nsTextFrame::TrimmedOffsets trimmed =
  76 +- mFrame->GetTrimmedOffsets(mFrag, aTrimAfter);
  77 ++ mFrame->GetTrimmedOffsets(mFrag,
  78 ++ (aTrimAfter ? nsTextFrame::TrimmedOffsetFlags::kDefaultTrimFlags :
  79 ++ nsTextFrame::TrimmedOffsetFlags::kNoTrimAfter));
  80 + mStart.SetOriginalOffset(trimmed.mStart);
  81 + mLength = trimmed.mLength;
  82 + SetupJustificationSpacing(true);
  83 + }
  84 +
  85 + void PropertyProvider::InitializeForMeasure() {
  86 + nsTextFrame::TrimmedOffsets trimmed =
  87 +- mFrame->GetTrimmedOffsets(mFrag, true, false);
  88 ++ mFrame->GetTrimmedOffsets(mFrag,
  89 ++ nsTextFrame::TrimmedOffsetFlags::kNoPostReflow);
  90 + mStart.SetOriginalOffset(trimmed.mStart);
  91 + mLength = trimmed.mLength;
  92 + SetupJustificationSpacing(false);
  93 + }
  94 +
  95 + void PropertyProvider::SetupJustificationSpacing(bool aPostReflow) {
  96 + MOZ_ASSERT(mLength != INT32_MAX, "Can't call this with undefined length");
  97 +
  98 +@@ -3732,17 +3738,19 @@ void PropertyProvider::SetupJustificatio
  99 + return;
  100 + }
  101 +
  102 + gfxSkipCharsIterator start(mStart), end(mStart);
  103 + // We can't just use our mLength here; when InitializeForDisplay is
  104 + // called with false for aTrimAfter, we still shouldn't be assigning
  105 + // justification space to any trailing whitespace.
  106 + nsTextFrame::TrimmedOffsets trimmed =
  107 +- mFrame->GetTrimmedOffsets(mFrag, true, aPostReflow);
  108 ++ mFrame->GetTrimmedOffsets(mFrag,
  109 ++ (aPostReflow ? nsTextFrame::TrimmedOffsetFlags::kDefaultTrimFlags :
  110 ++ nsTextFrame::TrimmedOffsetFlags::kNoPostReflow));
  111 + end.AdvanceOriginal(trimmed.mLength);
  112 + gfxSkipCharsIterator realEnd(end);
  113 +
  114 + Range range(uint32_t(start.GetOriginalOffset()),
  115 + uint32_t(end.GetOriginalOffset()));
  116 + nsTArray<JustificationAssignment> assignments;
  117 + JustificationInfo info = ComputeJustification(range, &assignments);
  118 +
  119 +@@ -7698,17 +7706,17 @@ nsresult nsTextFrame::GetChildFrameConta
  120 + nsIFrame::FrameSearchResult nsTextFrame::PeekOffsetNoAmount(bool aForward,
  121 + int32_t* aOffset) {
  122 + NS_ASSERTION(aOffset && *aOffset <= GetContentLength(),
  123 + "aOffset out of range");
  124 +
  125 + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
  126 + if (!mTextRun) return CONTINUE_EMPTY;
  127 +
  128 +- TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), true);
  129 ++ TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText());
  130 + // Check whether there are nonskipped characters in the trimmmed range
  131 + return (iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
  132 + iter.ConvertOriginalToSkipped(trimmed.mStart))
  133 + ? FOUND
  134 + : CONTINUE;
  135 + }
  136 +
  137 + /**
  138 +@@ -7821,17 +7829,18 @@ nsIFrame::FrameSearchResult nsTextFrame:
  139 + if (selectStyle == StyleUserSelect::All) {
  140 + return CONTINUE_UNSELECTABLE;
  141 + }
  142 + }
  143 +
  144 + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
  145 + if (!mTextRun) return CONTINUE_EMPTY;
  146 +
  147 +- TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), false);
  148 ++ TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(),
  149 ++ TrimmedOffsetFlags::kNoTrimAfter);
  150 +
  151 + // A negative offset means "end of frame".
  152 + int32_t startOffset =
  153 + GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
  154 +
  155 + if (!aForward) {
  156 + // If at the beginning of the line, look at the previous continuation
  157 + for (int32_t i = std::min(trimmed.GetEnd(), startOffset) - 1;
  158 +@@ -7954,17 +7963,17 @@ ClusterIterator::ClusterIterator(nsTextF
  159 + mIterator = aTextFrame->EnsureTextRun(nsTextFrame::eInflated);
  160 + if (!aTextFrame->GetTextRun(nsTextFrame::eInflated)) {
  161 + mDirection = 0; // signal failure
  162 + return;
  163 + }
  164 + mIterator.SetOriginalOffset(aPosition);
  165 +
  166 + mFrag = aTextFrame->GetContent()->GetText();
  167 +- mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, true);
  168 ++ mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag);
  169 +
  170 + int32_t textOffset = aTextFrame->GetContentOffset();
  171 + int32_t textLen = aTextFrame->GetContentLength();
  172 + if (!mWordBreaks.AppendElements(textLen + 1)) {
  173 + mDirection = 0; // signal failure
  174 + return;
  175 + }
  176 + memset(mWordBreaks.Elements(), false, (textLen + 1) * sizeof(bool));
  177 +@@ -9556,17 +9565,17 @@ nsTextFrame::TrimOutput nsTextFrame::Tri
  178 +
  179 + gfxSkipCharsIterator start =
  180 + EnsureTextRun(nsTextFrame::eInflated, aDrawTarget);
  181 + NS_ENSURE_TRUE(mTextRun, result);
  182 +
  183 + uint32_t trimmedStart = start.GetSkippedOffset();
  184 +
  185 + const nsTextFragment* frag = mContent->GetText();
  186 +- TrimmedOffsets trimmed = GetTrimmedOffsets(frag, true);
  187 ++ TrimmedOffsets trimmed = GetTrimmedOffsets(frag);
  188 + gfxSkipCharsIterator trimmedEndIter = start;
  189 + const nsStyleText* textStyle = StyleText();
  190 + gfxFloat delta = 0;
  191 + uint32_t trimmedEnd =
  192 + trimmedEndIter.ConvertOriginalToSkipped(trimmed.GetEnd());
  193 +
  194 + if (!(GetStateBits() & TEXT_TRIMMED_TRAILING_WHITESPACE) &&
  195 + trimmed.GetEnd() < GetContentEnd()) {
  196 +@@ -9762,17 +9771,19 @@ nsIFrame::RenderedText nsTextFrame::GetR
  197 + } else {
  198 + // Weird situation where we have a line layout without a block.
  199 + // No soft breaks occur in this situation.
  200 + trimAfter = true;
  201 + }
  202 +
  203 + // Skip to the start of the text run, past ignored chars at start of line
  204 + TrimmedOffsets trimmedOffsets =
  205 +- textFrame->GetTrimmedOffsets(textFrag, trimAfter);
  206 ++ textFrame->GetTrimmedOffsets(textFrag,
  207 ++ (trimAfter ? TrimmedOffsetFlags::kDefaultTrimFlags :
  208 ++ TrimmedOffsetFlags::kNoTrimAfter));
  209 + bool trimmedSignificantNewline =
  210 + trimmedOffsets.GetEnd() < GetContentEnd() &&
  211 + HasSignificantTerminalNewline();
  212 + uint32_t skippedToRenderedStringOffset =
  213 + offsetInRenderedString -
  214 + tmpIter.ConvertOriginalToSkipped(trimmedOffsets.mStart);
  215 + uint32_t nextOffsetInRenderedString =
  216 + tmpIter.ConvertOriginalToSkipped(trimmedOffsets.GetEnd()) +
  217 +@@ -10101,11 +10112,12 @@ bool nsTextFrame::HasNonSuppressedText()
  218 + NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW)) {
  219 + return true;
  220 + }
  221 +
  222 + if (!GetTextRun(nsTextFrame::eInflated)) {
  223 + return false;
  224 + }
  225 +
  226 +- TrimmedOffsets offsets = GetTrimmedOffsets(mContent->GetText(), false);
  227 ++ TrimmedOffsets offsets = GetTrimmedOffsets(mContent->GetText(),
  228 ++ TrimmedOffsetFlags::kNoTrimAfter);
  229 + return offsets.mLength != 0;
  230 + }
  231 +diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h
  232 +--- a/layout/generic/nsTextFrame.h
  233 ++++ b/layout/generic/nsTextFrame.h
  234 +@@ -568,18 +568,23 @@ class nsTextFrame : public nsFrame {
  235 + // Get the DOM content range mapped by this frame after excluding
  236 + // whitespace subject to start-of-line and end-of-line trimming.
  237 + // The textrun must have been created before calling this.
  238 + struct TrimmedOffsets {
  239 + int32_t mStart;
  240 + int32_t mLength;
  241 + int32_t GetEnd() const { return mStart + mLength; }
  242 + };
  243 +- TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, bool aTrimAfter,
  244 +- bool aPostReflow = true) const;
  245 ++ enum class TrimmedOffsetFlags : uint8_t {
  246 ++ kDefaultTrimFlags = 0,
  247 ++ kNoPostReflow = 1 << 0,
  248 ++ kNoTrimAfter = 1 << 1
  249 ++ };
  250 ++ TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
  251 ++ TrimmedOffsetFlags aFlags = TrimmedOffsetFlags::kDefaultTrimFlags) const;
  252 +
  253 + // Similar to Reflow(), but for use from nsLineLayout
  254 + void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
  255 + DrawTarget* aDrawTarget, ReflowOutput& aMetrics,
  256 + nsReflowStatus& aStatus);
  257 +
  258 + bool IsFloatingFirstLetterChild() const;
  259 +
  260 +@@ -801,9 +806,11 @@ class nsTextFrame : public nsFrame {
  261 + void UpdateIteratorFromOffset(const PropertyProvider& aProperties,
  262 + int32_t& aInOffset,
  263 + gfxSkipCharsIterator& aIter);
  264 +
  265 + nsPoint GetPointFromIterator(const gfxSkipCharsIterator& aIter,
  266 + PropertyProvider& aProperties);
  267 + };
  268 +
  269 ++MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsTextFrame::TrimmedOffsetFlags)
  270 ++
  271 + #endif
  272 +diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp
  273 +--- a/layout/svg/SVGTextFrame.cpp
  274 ++++ b/layout/svg/SVGTextFrame.cpp
  275 +@@ -979,17 +979,17 @@ void TextRenderedRun::GetClipEdges(nscoo
  276 + // Get the offset/length of the whole nsTextFrame.
  277 + uint32_t frameOffset = mFrame->GetContentOffset();
  278 + uint32_t frameLength = mFrame->GetContentLength();
  279 +
  280 + // Trim the whole-nsTextFrame offset/length to remove any leading/trailing
  281 + // white space, as the nsTextFrame when painting does not include them when
  282 + // interpreting clip edges.
  283 + nsTextFrame::TrimmedOffsets trimmedOffsets =
  284 +- mFrame->GetTrimmedOffsets(mFrame->GetContent()->GetText(), true);
  285 ++ mFrame->GetTrimmedOffsets(mFrame->GetContent()->GetText());
  286 + TrimOffsets(frameOffset, frameLength, trimmedOffsets);
  287 +
  288 + // Convert the trimmed whole-nsTextFrame offset/length into skipped
  289 + // characters.
  290 + Range frameRange = ConvertOriginalToSkipped(it, frameOffset, frameLength);
  291 +
  292 + // Measure the advance width in the text run between the start of
  293 + // frame's content and the start of the rendered run's content,
  294 +@@ -1884,17 +1884,17 @@ TextRenderedRun TextRenderedRunIterator:
  295 + baseline = GetBaselinePosition(
  296 + frame, frame->GetTextRun(nsTextFrame::eInflated),
  297 + mFrameIterator.DominantBaseline(), mFontSizeScaleFactor);
  298 +
  299 + // Trim the offset/length to remove any leading/trailing white space.
  300 + uint32_t untrimmedOffset = offset;
  301 + uint32_t untrimmedLength = length;
  302 + nsTextFrame::TrimmedOffsets trimmedOffsets =
  303 +- frame->GetTrimmedOffsets(frame->GetContent()->GetText(), true);
  304 ++ frame->GetTrimmedOffsets(frame->GetContent()->GetText());
  305 + TrimOffsets(offset, length, trimmedOffsets);
  306 + charIndex += offset - untrimmedOffset;
  307 +
  308 + // Get the position and rotation of the character that begins this
  309 + // rendered run.
  310 + pt = Root()->mPositions[charIndex].mPosition;
  311 + rotate = Root()->mPositions[charIndex].mAngle;
  312 +
  313 +@@ -2366,17 +2366,18 @@ bool CharIterator::IsOriginalCharTrimmed
  314 + // Since we do a lot of trim checking, we cache the trimmed offsets and
  315 + // lengths while we are in the same frame.
  316 + mFrameForTrimCheck = TextFrame();
  317 + uint32_t offset = mFrameForTrimCheck->GetContentOffset();
  318 + uint32_t length = mFrameForTrimCheck->GetContentLength();
  319 + nsIContent* content = mFrameForTrimCheck->GetContent();
  320 + nsTextFrame::TrimmedOffsets trim = mFrameForTrimCheck->GetTrimmedOffsets(
  321 + content->GetText(),
  322 +- /* aTrimAfter */ true, mPostReflow);
  323 ++ (mPostReflow ? nsTextFrame::TrimmedOffsetFlags::kDefaultTrimFlags :
  324 ++ nsTextFrame::TrimmedOffsetFlags::kNoPostReflow));
  325 + TrimOffsets(offset, length, trim);
  326 + mTrimmedOffset = offset;
  327 + mTrimmedLength = length;
  328 + }
  329 +
  330 + // A character is trimmed if it is outside the mTrimmedOffset/mTrimmedLength
  331 + // range and it is not a significant newline character.
  332 + uint32_t index = mSkipCharsIterator.GetOriginalOffset();
  333 +@@ -3818,18 +3819,17 @@ nsresult SVGTextFrame::GetSubStringLengt
  334 + const uint32_t untrimmedOffset = frame->GetContentOffset();
  335 + const uint32_t untrimmedLength = frame->GetContentEnd() - untrimmedOffset;
  336 +
  337 + // Trim the offset/length to remove any leading/trailing white space.
  338 + uint32_t trimmedOffset = untrimmedOffset;
  339 + uint32_t trimmedLength = untrimmedLength;
  340 + nsTextFrame::TrimmedOffsets trimmedOffsets =
  341 + frame->GetTrimmedOffsets(frame->GetContent()->GetText(),
  342 +- /* aTrimAfter */ true,
  343 +- /* aPostReflow */ false);
  344 ++ nsTextFrame::TrimmedOffsetFlags::kNoPostReflow);
  345 + TrimOffsets(trimmedOffset, trimmedLength, trimmedOffsets);
  346 +
  347 + textElementCharIndex += trimmedOffset - untrimmedOffset;
  348 +
  349 + if (textElementCharIndex >= charnum + nchars) {
  350 + break; // we're past the end of the substring
  351 + }
  352 +
  353 +@@ -4427,17 +4427,17 @@ void SVGTextFrame::DetermineCharPosition
  354 +
  355 + // Any characters not in a frame, e.g. when display:none.
  356 + for (uint32_t i = 0; i < frit.UndisplayedCharacters(); i++) {
  357 + aPositions.AppendElement(position);
  358 + }
  359 +
  360 + // Any white space characters trimmed at the start of the line of text.
  361 + nsTextFrame::TrimmedOffsets trimmedOffsets =
  362 +- frame->GetTrimmedOffsets(frame->GetContent()->GetText(), true);
  363 ++ frame->GetTrimmedOffsets(frame->GetContent()->GetText());
  364 + while (it.GetOriginalOffset() < trimmedOffsets.mStart) {
  365 + aPositions.AppendElement(position);
  366 + it.AdvanceOriginal(1);
  367 + }
  368 +
  369 + // If a ligature was started in the previous frame, we should record
  370 + // the ligature's start position, not any partial position.
  371 + while (it.GetOriginalOffset() < frame->GetContentEnd() &&
  372 +
  373 +# HG changeset patch
  374 +# User Samuel Thibault <samuel.thibault@ens-lyon.org>
  375 +# Date 1550767631 -3600
  376 +# Thu Feb 21 17:47:11 2019 +0100
  377 +# Branch trim-offset2
  378 +# Node ID bf487fadc54796a6559570e9fdafd746a863f76e
  379 +# Parent fbdb5d7ff36319d91c9063ea66b778ff72e51ff1
  380 +Bug 919508 layout: Do not trim spaces when inspected from accessibility layer r=jfkthame
  381 +
  382 +diff --git a/accessible/generic/HyperTextAccessible.cpp b/accessible/generic/HyperTextAccessible.cpp
  383 +--- a/accessible/generic/HyperTextAccessible.cpp
  384 ++++ b/accessible/generic/HyperTextAccessible.cpp
  385 +@@ -514,17 +514,17 @@ uint32_t HyperTextAccessible::FindOffset
  386 +
  387 + const bool kIsJumpLinesOk = true; // okay to jump lines
  388 + const bool kIsScrollViewAStop = false; // do not stop at scroll views
  389 + const bool kIsKeyboardSelect = true; // is keyboard selection
  390 + const bool kIsVisualBidi = false; // use visual order for bidi text
  391 + nsPeekOffsetStruct pos(
  392 + aAmount, aDirection, innerContentOffset, nsPoint(0, 0), kIsJumpLinesOk,
  393 + kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi, false,
  394 +- nsPeekOffsetStruct::ForceEditableRegion::No, aWordMovementType);
  395 ++ nsPeekOffsetStruct::ForceEditableRegion::No, aWordMovementType, false);
  396 + nsresult rv = frameAtOffset->PeekOffset(&pos);
  397 +
  398 + // PeekOffset fails on last/first lines of the text in certain cases.
  399 + if (NS_FAILED(rv) && aAmount == eSelectLine) {
  400 + pos.mAmount = (aDirection == eDirNext) ? eSelectEndLine : eSelectBeginLine;
  401 + frameAtOffset->PeekOffset(&pos);
  402 + }
  403 + if (!pos.mResultContent) {
  404 +diff --git a/layout/generic/BRFrame.cpp b/layout/generic/BRFrame.cpp
  405 +--- a/layout/generic/BRFrame.cpp
  406 ++++ b/layout/generic/BRFrame.cpp
  407 +@@ -40,17 +40,18 @@ class BRFrame final : public nsFrame {
  408 + virtual FrameSearchResult PeekOffsetCharacter(
  409 + bool aForward, int32_t* aOffset,
  410 + PeekOffsetCharacterOptions aOptions =
  411 + PeekOffsetCharacterOptions()) override;
  412 + virtual FrameSearchResult PeekOffsetWord(bool aForward,
  413 + bool aWordSelectEatSpace,
  414 + bool aIsKeyboardSelect,
  415 + int32_t* aOffset,
  416 +- PeekWordState* aState) override;
  417 ++ PeekWordState* aState,
  418 ++ bool aTrimSpaces) override;
  419 +
  420 + virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
  421 + const ReflowInput& aReflowInput,
  422 + nsReflowStatus& aStatus) override;
  423 + virtual void AddInlineMinISize(gfxContext* aRenderingContext,
  424 + InlineMinISizeData* aData) override;
  425 + virtual void AddInlinePrefISize(gfxContext* aRenderingContext,
  426 + InlinePrefISizeData* aData) override;
  427 +@@ -233,17 +234,18 @@ nsIFrame::FrameSearchResult BRFrame::Pee
  428 + // Keep going. The actual line jumping will stop us.
  429 + return CONTINUE;
  430 + }
  431 +
  432 + nsIFrame::FrameSearchResult BRFrame::PeekOffsetWord(bool aForward,
  433 + bool aWordSelectEatSpace,
  434 + bool aIsKeyboardSelect,
  435 + int32_t* aOffset,
  436 +- PeekWordState* aState) {
  437 ++ PeekWordState* aState,
  438 ++ bool aTrimSpaces) {
  439 + NS_ASSERTION(aOffset && *aOffset <= 1, "aOffset out of range");
  440 + // Keep going. The actual line jumping will stop us.
  441 + return CONTINUE;
  442 + }
  443 +
  444 + #ifdef ACCESSIBILITY
  445 + a11y::AccType BRFrame::AccessibleType() {
  446 + nsIContent* parent = mContent->GetParent();
  447 +diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
  448 +--- a/layout/generic/nsFrame.cpp
  449 ++++ b/layout/generic/nsFrame.cpp
  450 +@@ -8135,17 +8135,18 @@ nsresult nsIFrame::PeekOffset(nsPeekOffs
  451 + int32_t offsetAdjustment = 0;
  452 + bool done = false;
  453 + while (!done) {
  454 + bool movingInFrameDirection =
  455 + IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
  456 +
  457 + done = current->PeekOffsetWord(
  458 + movingInFrameDirection, wordSelectEatSpace,
  459 +- aPos->mIsKeyboardSelect, &offset, &state) == FOUND;
  460 ++ aPos->mIsKeyboardSelect, &offset, &state,
  461 ++ aPos->mTrimSpaces) == FOUND;
  462 +
  463 + if (!done) {
  464 + nsIFrame* nextFrame;
  465 + int32_t nextFrameOffset;
  466 + bool jumpedLine, movedOverNonSelectableText;
  467 + result = current->GetFrameFromDirection(
  468 + aPos->mDirection, aPos->mVisual, aPos->mJumpLines,
  469 + aPos->mScrollViewStop, aPos->mForceEditableRegion, &nextFrame,
  470 +@@ -8386,17 +8387,18 @@ nsIFrame::FrameSearchResult nsFrame::Pee
  471 + }
  472 + return CONTINUE;
  473 + }
  474 +
  475 + nsIFrame::FrameSearchResult nsFrame::PeekOffsetWord(bool aForward,
  476 + bool aWordSelectEatSpace,
  477 + bool aIsKeyboardSelect,
  478 + int32_t* aOffset,
  479 +- PeekWordState* aState) {
  480 ++ PeekWordState* aState,
  481 ++ bool aTrimSpaces) {
  482 + NS_ASSERTION(aOffset && *aOffset <= 1, "aOffset out of range");
  483 + int32_t startOffset = *aOffset;
  484 + // This isn't text, so truncate the context
  485 + aState->mContext.Truncate();
  486 + if (startOffset < 0) startOffset = 1;
  487 + if (aForward == (startOffset == 0)) {
  488 + // We're before the frame and moving forward, or after it and moving
  489 + // backwards. If we're looking for non-whitespace, we found it (without
  490 +diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h
  491 +--- a/layout/generic/nsFrame.h
  492 ++++ b/layout/generic/nsFrame.h
  493 +@@ -211,17 +211,18 @@ class nsFrame : public nsBox {
  494 + FrameSearchResult PeekOffsetNoAmount(bool aForward,
  495 + int32_t* aOffset) override;
  496 + FrameSearchResult PeekOffsetCharacter(
  497 + bool aForward, int32_t* aOffset,
  498 + PeekOffsetCharacterOptions aOptions =
  499 + PeekOffsetCharacterOptions()) override;
  500 + FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
  501 + bool aIsKeyboardSelect, int32_t* aOffset,
  502 +- PeekWordState* aState) override;
  503 ++ PeekWordState* aState, bool aTrimSpaces)
  504 ++ override;
  505 + /**
  506 + * Check whether we should break at a boundary between punctuation and
  507 + * non-punctuation. Only call it at a punctuation boundary
  508 + * (i.e. exactly one of the previous and next characters are punctuation).
  509 + * @param aForward true if we're moving forward in content order
  510 + * @param aPunctAfter true if the next character is punctuation
  511 + * @param aWhitespaceAfter true if the next character is whitespace
  512 + */
  513 +diff --git a/layout/generic/nsFrameSelection.cpp b/layout/generic/nsFrameSelection.cpp
  514 +--- a/layout/generic/nsFrameSelection.cpp
  515 ++++ b/layout/generic/nsFrameSelection.cpp
  516 +@@ -106,23 +106,25 @@ static void printRange(nsRange* aDomRang
  517 +
  518 + //#define DEBUG_TABLE_SELECTION 1
  519 +
  520 + nsPeekOffsetStruct::nsPeekOffsetStruct(
  521 + nsSelectionAmount aAmount, nsDirection aDirection, int32_t aStartOffset,
  522 + nsPoint aDesiredPos, bool aJumpLines, bool aScrollViewStop,
  523 + bool aIsKeyboardSelect, bool aVisual, bool aExtend,
  524 + ForceEditableRegion aForceEditableRegion,
  525 +- EWordMovementType aWordMovementType)
  526 ++ EWordMovementType aWordMovementType,
  527 ++ bool aTrimSpaces)
  528 + : mAmount(aAmount),
  529 + mDirection(aDirection),
  530 + mStartOffset(aStartOffset),
  531 + mDesiredPos(aDesiredPos),
  532 + mWordMovementType(aWordMovementType),
  533 + mJumpLines(aJumpLines),
  534 ++ mTrimSpaces(aTrimSpaces),
  535 + mScrollViewStop(aScrollViewStop),
  536 + mIsKeyboardSelect(aIsKeyboardSelect),
  537 + mVisual(aVisual),
  538 + mExtend(aExtend),
  539 + mForceEditableRegion(aForceEditableRegion == ForceEditableRegion::Yes),
  540 + mResultContent(),
  541 + mResultFrame(nullptr),
  542 + mContentOffset(0),
  543 +diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h
  544 +--- a/layout/generic/nsFrameSelection.h
  545 ++++ b/layout/generic/nsFrameSelection.h
  546 +@@ -67,17 +67,18 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruc
  547 + Yes,
  548 + };
  549 +
  550 + nsPeekOffsetStruct(
  551 + nsSelectionAmount aAmount, nsDirection aDirection, int32_t aStartOffset,
  552 + nsPoint aDesiredPos, bool aJumpLines, bool aScrollViewStop,
  553 + bool aIsKeyboardSelect, bool aVisual, bool aExtend,
  554 + ForceEditableRegion = ForceEditableRegion::No,
  555 +- mozilla::EWordMovementType aWordMovementType = mozilla::eDefaultBehavior);
  556 ++ mozilla::EWordMovementType aWordMovementType = mozilla::eDefaultBehavior,
  557 ++ bool aTrimSpaces = true);
  558 +
  559 + // Note: Most arguments (input and output) are only used with certain values
  560 + // of mAmount. These values are indicated for each argument below.
  561 + // Arguments with no such indication are used with all values of mAmount.
  562 +
  563 + /*** Input arguments ***/
  564 + // Note: The value of some of the input arguments may be changed upon exit.
  565 +
  566 +@@ -114,16 +115,19 @@ struct MOZ_STACK_CLASS nsPeekOffsetStruc
  567 + // platform-based pref "layout.word_select.eat_space_to_next_word"
  568 + mozilla::EWordMovementType mWordMovementType;
  569 +
  570 + // Whether to allow jumping across line boundaries.
  571 + //
  572 + // Used with: eSelectCharacter, eSelectWord.
  573 + bool mJumpLines;
  574 +
  575 ++ // mTrimSpaces: Whether we should trim spaces at begin/end of content
  576 ++ bool mTrimSpaces;
  577 ++
  578 + // Whether to stop when reaching a scroll view boundary.
  579 + //
  580 + // Used with: eSelectCharacter, eSelectWord, eSelectLine.
  581 + bool mScrollViewStop;
  582 +
  583 + // Whether the peeking is done in response to a keyboard action.
  584 + //
  585 + // Used with: eSelectWord.
  586 +diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h
  587 +--- a/layout/generic/nsIFrame.h
  588 ++++ b/layout/generic/nsIFrame.h
  589 +@@ -4484,17 +4484,18 @@ class nsIFrame : public nsQueryFrame {
  590 + }
  591 + mAtStart = false;
  592 + }
  593 + };
  594 + virtual FrameSearchResult PeekOffsetWord(bool aForward,
  595 + bool aWordSelectEatSpace,
  596 + bool aIsKeyboardSelect,
  597 + int32_t* aOffset,
  598 +- PeekWordState* aState) = 0;
  599 ++ PeekWordState* aState,
  600 ++ bool aTrimSpaces) = 0;
  601 +
  602 + /**
  603 + * Search for the first paragraph boundary before or after the given position
  604 + * @param aPos See description in nsFrameSelection.h. The following fields
  605 + * are used by this method:
  606 + * Input: mDirection
  607 + * Output: mResultContent, mContentOffset
  608 + */
  609 +diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp
  610 +--- a/layout/generic/nsTextFrame.cpp
  611 ++++ b/layout/generic/nsTextFrame.cpp
  612 +@@ -2961,18 +2961,19 @@ nsTextFrame::TrimmedOffsets nsTextFrame:
  613 + }
  614 +
  615 + TrimmedOffsets offsets = {GetContentOffset(), GetContentLength()};
  616 + const nsStyleText* textStyle = StyleText();
  617 + // Note that pre-line newlines should still allow us to trim spaces
  618 + // for display
  619 + if (textStyle->WhiteSpaceIsSignificant()) return offsets;
  620 +
  621 +- if ((aFlags & TrimmedOffsetFlags::kNoPostReflow) ||
  622 +- (GetStateBits() & TEXT_START_OF_LINE)) {
  623 ++ if (!(aFlags & TrimmedOffsetFlags::kNoTrimBefore) &&
  624 ++ ((aFlags & TrimmedOffsetFlags::kNoPostReflow) ||
  625 ++ (GetStateBits() & TEXT_START_OF_LINE))) {
  626 + int32_t whitespaceCount =
  627 + GetTrimmableWhitespaceCount(aFrag, offsets.mStart, offsets.mLength, 1);
  628 + offsets.mStart += whitespaceCount;
  629 + offsets.mLength -= whitespaceCount;
  630 + }
  631 +
  632 + if (!(aFlags & TrimmedOffsetFlags::kNoTrimAfter) &&
  633 + ((aFlags & TrimmedOffsetFlags::kNoPostReflow) ||
  634 +@@ -7725,17 +7726,18 @@ nsIFrame::FrameSearchResult nsTextFrame:
  635 + * to see if it's whitespace (as far as selection/caret movement is concerned),
  636 + * or punctuation, or if there is a word break before the cluster. ("Before"
  637 + * is interpreted according to aDirection, so if aDirection is -1, "before"
  638 + * means actually *after* the cluster content.)
  639 + */
  640 + class MOZ_STACK_CLASS ClusterIterator {
  641 + public:
  642 + ClusterIterator(nsTextFrame* aTextFrame, int32_t aPosition,
  643 +- int32_t aDirection, nsString& aContext);
  644 ++ int32_t aDirection, nsString& aContext,
  645 ++ bool aTrimSpaces = true);
  646 +
  647 + bool NextCluster();
  648 + bool IsWhitespace();
  649 + bool IsPunctuation();
  650 + bool HaveWordBreakBefore() { return mHaveWordBreak; }
  651 +
  652 + // Get the charIndex that corresponds to the "before" side of the current
  653 + // character, according to the direction of iteration: so for a forward
  654 +@@ -7950,30 +7952,34 @@ bool ClusterIterator::NextCluster() {
  655 + if (mWordBreaks[GetBeforeOffset() - mTextFrame->GetContentOffset()]) {
  656 + mHaveWordBreak = true;
  657 + }
  658 + if (!keepGoing) return true;
  659 + }
  660 + }
  661 +
  662 + ClusterIterator::ClusterIterator(nsTextFrame* aTextFrame, int32_t aPosition,
  663 +- int32_t aDirection, nsString& aContext)
  664 ++ int32_t aDirection, nsString& aContext,
  665 ++ bool aTrimSpaces)
  666 + : mTextFrame(aTextFrame),
  667 + mDirection(aDirection),
  668 + mCharIndex(-1),
  669 + mHaveWordBreak(false) {
  670 + mIterator = aTextFrame->EnsureTextRun(nsTextFrame::eInflated);
  671 + if (!aTextFrame->GetTextRun(nsTextFrame::eInflated)) {
  672 + mDirection = 0; // signal failure
  673 + return;
  674 + }
  675 + mIterator.SetOriginalOffset(aPosition);
  676 +
  677 + mFrag = aTextFrame->GetContent()->GetText();
  678 +- mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag);
  679 ++ mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag,
  680 ++ aTrimSpaces ? nsTextFrame::TrimmedOffsetFlags::kDefaultTrimFlags :
  681 ++ nsTextFrame::TrimmedOffsetFlags::kNoTrimAfter |
  682 ++ nsTextFrame::TrimmedOffsetFlags::kNoTrimBefore);
  683 +
  684 + int32_t textOffset = aTextFrame->GetContentOffset();
  685 + int32_t textLen = aTextFrame->GetContentLength();
  686 + if (!mWordBreaks.AppendElements(textLen + 1)) {
  687 + mDirection = 0; // signal failure
  688 + return;
  689 + }
  690 + memset(mWordBreaks.Elements(), false, (textLen + 1) * sizeof(bool));
  691 +@@ -8001,27 +8007,28 @@ ClusterIterator::ClusterIterator(nsTextF
  692 + mWordBreaks[i] |= wordBreaker->BreakInBetween(
  693 + aContext.get(), indexInText, aContext.get() + indexInText,
  694 + aContext.Length() - indexInText);
  695 + }
  696 + }
  697 +
  698 + nsIFrame::FrameSearchResult nsTextFrame::PeekOffsetWord(
  699 + bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
  700 +- int32_t* aOffset, PeekWordState* aState) {
  701 ++ int32_t* aOffset, PeekWordState* aState, bool aTrimSpaces) {
  702 + int32_t contentLength = GetContentLength();
  703 + NS_ASSERTION(aOffset && *aOffset <= contentLength, "aOffset out of range");
  704 +
  705 + StyleUserSelect selectStyle;
  706 + IsSelectable(&selectStyle);
  707 + if (selectStyle == StyleUserSelect::All) return CONTINUE_UNSELECTABLE;
  708 +
  709 + int32_t offset =
  710 + GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
  711 +- ClusterIterator cIter(this, offset, aForward ? 1 : -1, aState->mContext);
  712 ++ ClusterIterator cIter(this, offset, aForward ? 1 : -1, aState->mContext,
  713 ++ aTrimSpaces);
  714 +
  715 + if (!cIter.NextCluster()) return CONTINUE_EMPTY;
  716 +
  717 + do {
  718 + bool isPunctuation = cIter.IsPunctuation();
  719 + bool isWhitespace = cIter.IsWhitespace();
  720 + bool isWordBreakBefore = cIter.HaveWordBreakBefore();
  721 + if (aWordSelectEatSpace == isWhitespace && !aState->mSawBeforeType) {
  722 +diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h
  723 +--- a/layout/generic/nsTextFrame.h
  724 ++++ b/layout/generic/nsTextFrame.h
  725 +@@ -178,17 +178,18 @@ class nsTextFrame : public nsFrame {
  726 + SelectionType aSelectionType);
  727 +
  728 + FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) final;
  729 + FrameSearchResult PeekOffsetCharacter(
  730 + bool aForward, int32_t* aOffset,
  731 + PeekOffsetCharacterOptions aOptions = PeekOffsetCharacterOptions()) final;
  732 + FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
  733 + bool aIsKeyboardSelect, int32_t* aOffset,
  734 +- PeekWordState* aState) final;
  735 ++ PeekWordState* aState, bool aTrimSpaces)
  736 ++ final;
  737 +
  738 + nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex,
  739 + int32_t aEndIndex, bool aRecurse, bool* aFinished,
  740 + bool* _retval) final;
  741 +
  742 + // Flags for aSetLengthFlags
  743 + enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 };
  744 +
  745 +@@ -571,17 +572,18 @@ class nsTextFrame : public nsFrame {
  746 + struct TrimmedOffsets {
  747 + int32_t mStart;
  748 + int32_t mLength;
  749 + int32_t GetEnd() const { return mStart + mLength; }
  750 + };
  751 + enum class TrimmedOffsetFlags : uint8_t {
  752 + kDefaultTrimFlags = 0,
  753 + kNoPostReflow = 1 << 0,
  754 +- kNoTrimAfter = 1 << 1
  755 ++ kNoTrimAfter = 1 << 1,
  756 ++ kNoTrimBefore = 1 << 2
  757 + };
  758 + TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
  759 + TrimmedOffsetFlags aFlags = TrimmedOffsetFlags::kDefaultTrimFlags) const;
  760 +
  761 + // Similar to Reflow(), but for use from nsLineLayout
  762 + void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
  763 + DrawTarget* aDrawTarget, ReflowOutput& aMetrics,
  764 + nsReflowStatus& aStatus);
... ...
firefox-patches/series-60
... ... @@ -6,3 +6,4 @@ scrollto
6 6 scrollsubstringto
7 7 #jumpedline
8 8 control-enter
  9 +text-at-offset-word
... ...
firefox-patches/version
1   -3
  1 +4
... ...