No bug - tagging 2af34b4c9adf8c8defd3251b569af9c38cc0a429 with FIREFOX_BETA_124_BASE...
[gecko.git] / gfx / thebes / gfxSkipChars.h
blob39b46c2806cda98a90ccd9db0e5d5ffc673af687
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef GFX_SKIP_CHARS_H
7 #define GFX_SKIP_CHARS_H
9 #include "mozilla/Attributes.h"
10 #include "nsTArray.h"
13 * gfxSkipChars is a data structure representing a list of characters that
14 * have been skipped. The initial string is called the "original string"
15 * and after skipping some characters, the result is called the "skipped
16 * string". gfxSkipChars provides efficient ways to translate between offsets in
17 * the original string and the skipped string. It is used by textrun code to
18 * keep track of offsets before and after text transformations such as
19 * whitespace compression and control code deletion.
22 /**
23 * The gfxSkipChars is represented as a sorted array of skipped ranges.
25 * A freshly-created gfxSkipChars means "all chars kept".
27 class gfxSkipChars {
28 friend struct SkippedRangeStartComparator;
29 friend struct SkippedRangeOffsetComparator;
31 private:
32 class SkippedRange {
33 public:
34 SkippedRange(uint32_t aOffset, uint32_t aLength, uint32_t aDelta)
35 : mOffset(aOffset), mLength(aLength), mDelta(aDelta) {}
37 uint32_t Start() const { return mOffset; }
39 uint32_t End() const { return mOffset + mLength; }
41 uint32_t Length() const { return mLength; }
43 uint32_t SkippedOffset() const { return mOffset - mDelta; }
45 uint32_t Delta() const { return mDelta; }
47 uint32_t NextDelta() const { return mDelta + mLength; }
49 void Extend(uint32_t aChars) { mLength += aChars; }
51 private:
52 uint32_t mOffset; // original-string offset at which we want to skip
53 uint32_t mLength; // number of skipped chars at this offset
54 uint32_t mDelta; // sum of lengths of preceding skipped-ranges
57 public:
58 gfxSkipChars() : mCharCount(0) {}
60 void SkipChars(uint32_t aChars) {
61 NS_ASSERTION(mCharCount + aChars > mCharCount, "Character count overflow");
62 uint32_t rangeCount = mRanges.Length();
63 uint32_t delta = 0;
64 if (rangeCount > 0) {
65 SkippedRange& lastRange = mRanges[rangeCount - 1];
66 if (lastRange.End() == mCharCount) {
67 lastRange.Extend(aChars);
68 mCharCount += aChars;
69 return;
71 delta = lastRange.NextDelta();
73 mRanges.AppendElement(SkippedRange(mCharCount, aChars, delta));
74 mCharCount += aChars;
77 void KeepChars(uint32_t aChars) {
78 NS_ASSERTION(mCharCount + aChars > mCharCount, "Character count overflow");
79 mCharCount += aChars;
82 void SkipChar() { SkipChars(1); }
84 void KeepChar() { KeepChars(1); }
86 void TakeFrom(gfxSkipChars* aSkipChars) {
87 mRanges = std::move(aSkipChars->mRanges);
88 mCharCount = aSkipChars->mCharCount;
89 aSkipChars->mCharCount = 0;
92 int32_t GetOriginalCharCount() const { return mCharCount; }
94 const SkippedRange& LastRange() const {
95 // this is only valid if mRanges is non-empty; no assertion here
96 // because nsTArray will already assert if we abuse it
97 return mRanges[mRanges.Length() - 1];
100 friend class gfxSkipCharsIterator;
102 private:
103 nsTArray<SkippedRange> mRanges;
104 uint32_t mCharCount;
108 * A gfxSkipCharsIterator represents a position in the original string. It lets
109 * you map efficiently to and from positions in the string after skipped
110 * characters have been removed. You can also specify an offset that is added to
111 * all incoming original string offsets and subtracted from all outgoing
112 * original string offsets --- useful when the gfxSkipChars corresponds to
113 * something offset from the original DOM coordinates, which it often does for
114 * gfxTextRuns.
116 * The current positions (in both the original and skipped strings) are
117 * always constrained to be >= 0 and <= the string length. When the position
118 * is equal to the string length, it is at the end of the string. The current
119 * positions do not include any aOriginalStringToSkipCharsOffset.
121 * When the position in the original string corresponds to a skipped character,
122 * the skipped-characters offset is the offset of the next unskipped character,
123 * or the skipped-characters string length if there is no next unskipped
124 * character.
126 class MOZ_STACK_CLASS gfxSkipCharsIterator {
127 public:
129 * @param aOriginalStringToSkipCharsOffset add this to all incoming and
130 * outgoing original string offsets
132 gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
133 int32_t aOriginalStringToSkipCharsOffset,
134 int32_t aOriginalStringOffset)
135 : mSkipChars(&aSkipChars),
136 mOriginalStringOffset(0),
137 mSkippedStringOffset(0),
138 mCurrentRangeIndex(-1),
139 mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset) {
140 SetOriginalOffset(aOriginalStringOffset);
143 explicit gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
144 int32_t aOriginalStringToSkipCharsOffset = 0)
145 : mSkipChars(&aSkipChars),
146 mOriginalStringOffset(0),
147 mSkippedStringOffset(0),
148 mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset) {
149 mCurrentRangeIndex =
150 mSkipChars->mRanges.IsEmpty() || mSkipChars->mRanges[0].Start() > 0 ? -1
151 : 0;
154 gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator) = default;
157 * The empty constructor creates an object that is useless until it is
158 * assigned.
160 gfxSkipCharsIterator()
161 : mSkipChars(nullptr),
162 mOriginalStringOffset(0),
163 mSkippedStringOffset(0),
164 mCurrentRangeIndex(0),
165 mOriginalStringToSkipCharsOffset(0) {}
168 * Return true if this iterator is properly initialized and usable.
170 bool IsInitialized() const { return mSkipChars != nullptr; }
173 * Set the iterator to aOriginalStringOffset in the original string.
174 * This can efficiently move forward or backward from the current position.
175 * aOriginalStringOffset is clamped to [0,originalStringLength].
177 void SetOriginalOffset(int32_t aOriginalStringOffset);
180 * Set the iterator to aSkippedStringOffset in the skipped string.
181 * This can efficiently move forward or backward from the current position.
182 * aSkippedStringOffset is clamped to [0,skippedStringLength].
184 void SetSkippedOffset(uint32_t aSkippedStringOffset);
186 uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset) {
187 SetOriginalOffset(aOriginalStringOffset);
188 return GetSkippedOffset();
191 int32_t ConvertSkippedToOriginal(uint32_t aSkippedStringOffset) {
192 SetSkippedOffset(aSkippedStringOffset);
193 return GetOriginalOffset();
197 * Test if the character at the current position in the original string
198 * is skipped or not. If aRunLength is non-null, then *aRunLength is set
199 * to a number of characters all of which are either skipped or not, starting
200 * at this character. When the current position is at the end of the original
201 * string, we return true and *aRunLength is set to zero.
203 bool IsOriginalCharSkipped(int32_t* aRunLength = nullptr) const;
205 void AdvanceOriginal(int32_t aDelta) {
206 SetOriginalOffset(GetOriginalOffset() + aDelta);
209 void AdvanceSkipped(int32_t aDelta) {
210 SetSkippedOffset(GetSkippedOffset() + aDelta);
214 * @return the offset within the original string
216 int32_t GetOriginalOffset() const {
217 return mOriginalStringOffset - mOriginalStringToSkipCharsOffset;
221 * @return the offset within the skipped string corresponding to the
222 * current position in the original string. If the current position
223 * in the original string is a character that is skipped, then we return
224 * the position corresponding to the first non-skipped character in the
225 * original string after the current position, or the length of the skipped
226 * string if there is no such character.
228 uint32_t GetSkippedOffset() const { return mSkippedStringOffset; }
230 int32_t GetOriginalEnd() const {
231 return mSkipChars->GetOriginalCharCount() -
232 mOriginalStringToSkipCharsOffset;
235 private:
236 const gfxSkipChars* mSkipChars;
238 // Current position
239 int32_t mOriginalStringOffset;
240 uint32_t mSkippedStringOffset;
242 // Index of the last skippedRange that precedes or contains the current
243 // position in the original string.
244 // If index == -1 then we are before the first skipped char.
245 int32_t mCurrentRangeIndex;
247 // This offset is added to map from "skipped+unskipped characters in
248 // the original DOM string" character space to "skipped+unskipped
249 // characters in the textrun's gfxSkipChars" character space
250 int32_t mOriginalStringToSkipCharsOffset;
253 #endif /*GFX_SKIP_CHARS_H*/