123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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/. */
- #ifndef GFX_SKIP_CHARS_H
- #define GFX_SKIP_CHARS_H
- #include "nsTArray.h"
- /*
- * gfxSkipChars is a data structure representing a list of characters that
- * have been skipped. The initial string is called the "original string"
- * and after skipping some characters, the result is called the "skipped string".
- * gfxSkipChars provides efficient ways to translate between offsets in the
- * original string and the skipped string. It is used by textrun code to keep
- * track of offsets before and after text transformations such as whitespace
- * compression and control code deletion.
- */
- /**
- * The gfxSkipChars is represented as a sorted array of skipped ranges.
- *
- * A freshly-created gfxSkipChars means "all chars kept".
- */
- class gfxSkipChars
- {
- friend struct SkippedRangeStartComparator;
- friend struct SkippedRangeOffsetComparator;
- private:
- class SkippedRange
- {
- public:
- SkippedRange(uint32_t aOffset, uint32_t aLength, uint32_t aDelta)
- : mOffset(aOffset), mLength(aLength), mDelta(aDelta)
- { }
- uint32_t Start() const
- {
- return mOffset;
- }
- uint32_t End() const
- {
- return mOffset + mLength;
- }
- uint32_t Length() const
- {
- return mLength;
- }
- uint32_t SkippedOffset() const
- {
- return mOffset - mDelta;
- }
- uint32_t Delta() const
- {
- return mDelta;
- }
- uint32_t NextDelta() const
- {
- return mDelta + mLength;
- }
- void Extend(uint32_t aChars)
- {
- mLength += aChars;
- }
- private:
- uint32_t mOffset; // original-string offset at which we want to skip
- uint32_t mLength; // number of skipped chars at this offset
- uint32_t mDelta; // sum of lengths of preceding skipped-ranges
- };
- public:
- gfxSkipChars()
- : mCharCount(0)
- { }
- void SkipChars(uint32_t aChars)
- {
- NS_ASSERTION(mCharCount + aChars > mCharCount,
- "Character count overflow");
- uint32_t rangeCount = mRanges.Length();
- uint32_t delta = 0;
- if (rangeCount > 0) {
- SkippedRange& lastRange = mRanges[rangeCount - 1];
- if (lastRange.End() == mCharCount) {
- lastRange.Extend(aChars);
- mCharCount += aChars;
- return;
- }
- delta = lastRange.NextDelta();
- }
- mRanges.AppendElement(SkippedRange(mCharCount, aChars, delta));
- mCharCount += aChars;
- }
- void KeepChars(uint32_t aChars)
- {
- NS_ASSERTION(mCharCount + aChars > mCharCount,
- "Character count overflow");
- mCharCount += aChars;
- }
- void SkipChar()
- {
- SkipChars(1);
- }
- void KeepChar()
- {
- KeepChars(1);
- }
- void TakeFrom(gfxSkipChars* aSkipChars)
- {
- mRanges.SwapElements(aSkipChars->mRanges);
- mCharCount = aSkipChars->mCharCount;
- aSkipChars->mCharCount = 0;
- }
- int32_t GetOriginalCharCount() const
- {
- return mCharCount;
- }
- const SkippedRange& LastRange() const
- {
- // this is only valid if mRanges is non-empty; no assertion here
- // because nsTArray will already assert if we abuse it
- return mRanges[mRanges.Length() - 1];
- }
- friend class gfxSkipCharsIterator;
- private:
- nsTArray<SkippedRange> mRanges;
- uint32_t mCharCount;
- };
- /**
- * A gfxSkipCharsIterator represents a position in the original string. It lets you
- * map efficiently to and from positions in the string after skipped characters
- * have been removed. You can also specify an offset that is added to all
- * incoming original string offsets and subtracted from all outgoing original
- * string offsets --- useful when the gfxSkipChars corresponds to something
- * offset from the original DOM coordinates, which it often does for gfxTextRuns.
- *
- * The current positions (in both the original and skipped strings) are
- * always constrained to be >= 0 and <= the string length. When the position
- * is equal to the string length, it is at the end of the string. The current
- * positions do not include any aOriginalStringToSkipCharsOffset.
- *
- * When the position in the original string corresponds to a skipped character,
- * the skipped-characters offset is the offset of the next unskipped character,
- * or the skipped-characters string length if there is no next unskipped character.
- */
- class gfxSkipCharsIterator
- {
- public:
- /**
- * @param aOriginalStringToSkipCharsOffset add this to all incoming and
- * outgoing original string offsets
- */
- gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
- int32_t aOriginalStringToSkipCharsOffset,
- int32_t aOriginalStringOffset)
- : mSkipChars(&aSkipChars),
- mOriginalStringOffset(0),
- mSkippedStringOffset(0),
- mCurrentRangeIndex(-1),
- mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
- {
- SetOriginalOffset(aOriginalStringOffset);
- }
- explicit gfxSkipCharsIterator(const gfxSkipChars& aSkipChars,
- int32_t aOriginalStringToSkipCharsOffset = 0)
- : mSkipChars(&aSkipChars),
- mOriginalStringOffset(0),
- mSkippedStringOffset(0),
- mOriginalStringToSkipCharsOffset(aOriginalStringToSkipCharsOffset)
- {
- mCurrentRangeIndex =
- mSkipChars->mRanges.IsEmpty() ||
- mSkipChars->mRanges[0].Start() > 0 ? -1 : 0;
- }
- gfxSkipCharsIterator(const gfxSkipCharsIterator& aIterator)
- : mSkipChars(aIterator.mSkipChars),
- mOriginalStringOffset(aIterator.mOriginalStringOffset),
- mSkippedStringOffset(aIterator.mSkippedStringOffset),
- mCurrentRangeIndex(aIterator.mCurrentRangeIndex),
- mOriginalStringToSkipCharsOffset(aIterator.mOriginalStringToSkipCharsOffset)
- { }
- /**
- * The empty constructor creates an object that is useless until it is assigned.
- */
- gfxSkipCharsIterator()
- : mSkipChars(nullptr)
- { }
- /**
- * Return true if this iterator is properly initialized and usable.
- */
- bool IsInitialized()
- {
- return mSkipChars != nullptr;
- }
- /**
- * Set the iterator to aOriginalStringOffset in the original string.
- * This can efficiently move forward or backward from the current position.
- * aOriginalStringOffset is clamped to [0,originalStringLength].
- */
- void SetOriginalOffset(int32_t aOriginalStringOffset);
- /**
- * Set the iterator to aSkippedStringOffset in the skipped string.
- * This can efficiently move forward or backward from the current position.
- * aSkippedStringOffset is clamped to [0,skippedStringLength].
- */
- void SetSkippedOffset(uint32_t aSkippedStringOffset);
- uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset)
- {
- SetOriginalOffset(aOriginalStringOffset);
- return GetSkippedOffset();
- }
- int32_t ConvertSkippedToOriginal(uint32_t aSkippedStringOffset)
- {
- SetSkippedOffset(aSkippedStringOffset);
- return GetOriginalOffset();
- }
- /**
- * Test if the character at the current position in the original string
- * is skipped or not. If aRunLength is non-null, then *aRunLength is set
- * to a number of characters all of which are either skipped or not, starting
- * at this character. When the current position is at the end of the original
- * string, we return true and *aRunLength is set to zero.
- */
- bool IsOriginalCharSkipped(int32_t* aRunLength = nullptr) const;
- void AdvanceOriginal(int32_t aDelta)
- {
- SetOriginalOffset(GetOriginalOffset() + aDelta);
- }
- void AdvanceSkipped(int32_t aDelta)
- {
- SetSkippedOffset(GetSkippedOffset() + aDelta);
- }
- /**
- * @return the offset within the original string
- */
- int32_t GetOriginalOffset() const
- {
- return mOriginalStringOffset - mOriginalStringToSkipCharsOffset;
- }
- /**
- * @return the offset within the skipped string corresponding to the
- * current position in the original string. If the current position
- * in the original string is a character that is skipped, then we return
- * the position corresponding to the first non-skipped character in the
- * original string after the current position, or the length of the skipped
- * string if there is no such character.
- */
- uint32_t GetSkippedOffset() const
- {
- return mSkippedStringOffset;
- }
- int32_t GetOriginalEnd() const
- {
- return mSkipChars->GetOriginalCharCount() -
- mOriginalStringToSkipCharsOffset;
- }
- private:
- const gfxSkipChars* mSkipChars;
- // Current position
- int32_t mOriginalStringOffset;
- uint32_t mSkippedStringOffset;
- // Index of the last skippedRange that precedes or contains the current
- // position in the original string.
- // If index == -1 then we are before the first skipped char.
- int32_t mCurrentRangeIndex;
- // This offset is added to map from "skipped+unskipped characters in
- // the original DOM string" character space to "skipped+unskipped
- // characters in the textrun's gfxSkipChars" character space
- int32_t mOriginalStringToSkipCharsOffset;
- };
- #endif /*GFX_SKIP_CHARS_H*/
|