Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 "nsTArray.h"
11 /*
12 * gfxSkipChars is a data structure representing a list of characters that
13 * have been skipped. The initial string is called the "original string"
14 * and after skipping some characters, the result is called the "skipped string".
15 * gfxSkipChars provides efficient ways to translate between offsets in the
16 * original string and the skipped string. It is used by textrun code to keep
17 * track of offsets before and after text transformations such as whitespace
18 * compression and control code deletion.
19 */
21 /**
22 * The gfxSkipChars is represented as a sorted array of skipped ranges.
23 *
24 * A freshly-created gfxSkipChars means "all chars kept".
25 */
26 class gfxSkipChars
27 {
28 private:
29 class SkippedRange
30 {
31 public:
32 SkippedRange(uint32_t aOffset, uint32_t aLength, uint32_t aDelta)
33 : mOffset(aOffset), mLength(aLength), mDelta(aDelta)
34 { }
36 uint32_t Start() const
37 {
38 return mOffset;
39 }
41 uint32_t End() const
42 {
43 return mOffset + mLength;
44 }
46 uint32_t Length() const
47 {
48 return mLength;
49 }
51 uint32_t SkippedOffset() const
52 {
53 return mOffset - mDelta;
54 }
56 uint32_t Delta() const
57 {
58 return mDelta;
59 }
61 uint32_t NextDelta() const
62 {
63 return mDelta + mLength;
64 }
66 void Extend(uint32_t aChars)
67 {
68 mLength += aChars;
69 }
71 private:
72 uint32_t mOffset; // original-string offset at which we want to skip
73 uint32_t mLength; // number of skipped chars at this offset
74 uint32_t mDelta; // sum of lengths of preceding skipped-ranges
75 };
77 public:
78 gfxSkipChars()
79 : mCharCount(0)
80 { }
82 void SkipChars(uint32_t aChars)
83 {
84 NS_ASSERTION(mCharCount + aChars > mCharCount,
85 "Character count overflow");
86 uint32_t rangeCount = mRanges.Length();
87 uint32_t delta = 0;
88 if (rangeCount > 0) {
89 SkippedRange& lastRange = mRanges[rangeCount - 1];
90 if (lastRange.End() == mCharCount) {
91 lastRange.Extend(aChars);
92 mCharCount += aChars;
93 return;
94 }
95 delta = lastRange.NextDelta();
96 }
97 mRanges.AppendElement(SkippedRange(mCharCount, aChars, delta));
98 mCharCount += aChars;
99 }
101 void KeepChars(uint32_t aChars)
102 {
103 NS_ASSERTION(mCharCount + aChars > mCharCount,
104 "Character count overflow");
105 mCharCount += aChars;
106 }
108 void SkipChar()
109 {
110 SkipChars(1);
111 }
113 void KeepChar()
114 {
115 KeepChars(1);
116 }
118 void TakeFrom(gfxSkipChars* aSkipChars)
119 {
120 mRanges.SwapElements(aSkipChars->mRanges);
121 mCharCount = aSkipChars->mCharCount;
122 aSkipChars->mCharCount = 0;
123 }
125 int32_t GetOriginalCharCount() const
126 {
127 return mCharCount;
128 }
130 const SkippedRange& LastRange() const
131 {
132 // this is only valid if mRanges is non-empty; no assertion here
133 // because nsTArray will already assert if we abuse it
134 return mRanges[mRanges.Length() - 1];
135 }
137 friend class gfxSkipCharsIterator;
139 private:
140 nsTArray<SkippedRange> mRanges;
141 uint32_t mCharCount;
142 };
144 /**
145 * A gfxSkipCharsIterator represents a position in the original string. It lets you
146 * map efficiently to and from positions in the string after skipped characters
147 * have been removed. You can also specify an offset that is added to all
148 * incoming original string offsets and subtracted from all outgoing original
149 * string offsets --- useful when the gfxSkipChars corresponds to something
150 * offset from the original DOM coordinates, which it often does for gfxTextRuns.
151 *
152 * The current positions (in both the original and skipped strings) are
153 * always constrained to be >= 0 and <= the string length. When the position
154 * is equal to the string length, it is at the end of the string. The current
155 * positions do not include any aOriginalStringToSkipCharsOffset.
156 *
157 * When the position in the original string corresponds to a skipped character,
158 * the skipped-characters offset is the offset of the next unskipped character,
159 * or the skipped-characters string length if there is no next unskipped character.
160 */
161 class gfxSkipCharsIterator
162 {
163 public:
164 /**
165 * @param aOriginalStringToSkipCharsOffset add this to all incoming and
166 * outgoing original string offsets
167 */
168 gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
169 int32_t aOriginalStringToSkipCharsOffset,
170 int32_t aOriginalStringOffset)
171 : mSkipChars(&aSkipChars),
172 mOriginalStringOffset(0),
173 mSkippedStringOffset(0),
174 mCurrentRangeIndex(-1),
175 mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
176 {
177 SetOriginalOffset(aOriginalStringOffset);
178 }
180 gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
181 int32_t aOriginalStringToSkipCharsOffset = 0)
182 : mSkipChars(&aSkipChars),
183 mOriginalStringOffset(0),
184 mSkippedStringOffset(0),
185 mCurrentRangeIndex(-1),
186 mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
187 { }
189 gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator)
190 : mSkipChars(aIterator.mSkipChars),
191 mOriginalStringOffset(aIterator.mOriginalStringOffset),
192 mSkippedStringOffset(aIterator.mSkippedStringOffset),
193 mCurrentRangeIndex(aIterator.mCurrentRangeIndex),
194 mOriginalStringToSkipCharsOffset(aIterator.mOriginalStringToSkipCharsOffset)
195 { }
197 /**
198 * The empty constructor creates an object that is useless until it is assigned.
199 */
200 gfxSkipCharsIterator()
201 : mSkipChars(nullptr)
202 { }
204 /**
205 * Return true if this iterator is properly initialized and usable.
206 */
207 bool IsInitialized()
208 {
209 return mSkipChars != nullptr;
210 }
212 /**
213 * Set the iterator to aOriginalStringOffset in the original string.
214 * This can efficiently move forward or backward from the current position.
215 * aOriginalStringOffset is clamped to [0,originalStringLength].
216 */
217 void SetOriginalOffset(int32_t aOriginalStringOffset);
219 /**
220 * Set the iterator to aSkippedStringOffset in the skipped string.
221 * This can efficiently move forward or backward from the current position.
222 * aSkippedStringOffset is clamped to [0,skippedStringLength].
223 */
224 void SetSkippedOffset(uint32_t aSkippedStringOffset);
226 uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset)
227 {
228 SetOriginalOffset(aOriginalStringOffset);
229 return GetSkippedOffset();
230 }
232 uint32_t ConvertSkippedToOriginal(int32_t aSkippedStringOffset)
233 {
234 SetSkippedOffset(aSkippedStringOffset);
235 return GetOriginalOffset();
236 }
238 /**
239 * Test if the character at the current position in the original string
240 * is skipped or not. If aRunLength is non-null, then *aRunLength is set
241 * to a number of characters all of which are either skipped or not, starting
242 * at this character. When the current position is at the end of the original
243 * string, we return true and *aRunLength is set to zero.
244 */
245 bool IsOriginalCharSkipped(int32_t* aRunLength = nullptr) const;
247 void AdvanceOriginal(int32_t aDelta)
248 {
249 SetOriginalOffset(GetOriginalOffset() + aDelta);
250 }
252 void AdvanceSkipped(int32_t aDelta)
253 {
254 SetSkippedOffset(GetSkippedOffset() + aDelta);
255 }
257 /**
258 * @return the offset within the original string
259 */
260 int32_t GetOriginalOffset() const
261 {
262 return mOriginalStringOffset - mOriginalStringToSkipCharsOffset;
263 }
265 /**
266 * @return the offset within the skipped string corresponding to the
267 * current position in the original string. If the current position
268 * in the original string is a character that is skipped, then we return
269 * the position corresponding to the first non-skipped character in the
270 * original string after the current position, or the length of the skipped
271 * string if there is no such character.
272 */
273 uint32_t GetSkippedOffset() const
274 {
275 return mSkippedStringOffset;
276 }
278 int32_t GetOriginalEnd() const
279 {
280 return mSkipChars->GetOriginalCharCount() -
281 mOriginalStringToSkipCharsOffset;
282 }
284 private:
285 const gfxSkipChars* mSkipChars;
287 // Current position
288 int32_t mOriginalStringOffset;
289 uint32_t mSkippedStringOffset;
291 // Index of the last skippedRange that precedes or contains the current
292 // position in the original string.
293 // If index == -1 then we are before the first skipped char.
294 int32_t mCurrentRangeIndex;
296 // This offset is added to map from "skipped+unskipped characters in
297 // the original DOM string" character space to "skipped+unskipped
298 // characters in the textrun's gfxSkipChars" character space
299 int32_t mOriginalStringToSkipCharsOffset;
300 };
302 #endif /*GFX_SKIP_CHARS_H*/