gfx/thebes/gfxSkipChars.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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*/

mercurial