gfxSkipChars.cpp (4688B)
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/. */ 5 6 #include "gfxSkipChars.h" 7 #include "mozilla/BinarySearch.h" 8 #include "mozilla/gfx/Logging.h" 9 10 struct SkippedRangeStartComparator { 11 const uint32_t mOffset; 12 explicit SkippedRangeStartComparator(const uint32_t aOffset) 13 : mOffset(aOffset) {} 14 int operator()(const gfxSkipChars::SkippedRange& aRange) const { 15 return (mOffset < aRange.Start()) ? -1 : 1; 16 } 17 }; 18 19 void gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset) { 20 aOffset += mOriginalStringToSkipCharsOffset; 21 if (MOZ_UNLIKELY(uint32_t(aOffset) > mSkipChars->mCharCount)) { 22 gfxCriticalError() << "invalid offset " << aOffset 23 << " for gfxSkipChars length " << mSkipChars->mCharCount; 24 aOffset = mSkipChars->mCharCount; 25 } 26 27 mOriginalStringOffset = aOffset; 28 29 const uint32_t rangeCount = mSkipChars->mRanges.Length(); 30 if (rangeCount == 0) { 31 mSkippedStringOffset = aOffset; 32 return; 33 } 34 35 // at start of string? 36 if (aOffset == 0) { 37 mSkippedStringOffset = 0; 38 mCurrentRangeIndex = 39 rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1; 40 return; 41 } 42 43 // find the range that includes or precedes aOffset 44 const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges; 45 size_t idx; 46 mozilla::BinarySearchIf(ranges, 0, rangeCount, 47 SkippedRangeStartComparator(aOffset), &idx); 48 49 if (idx == rangeCount) { 50 mCurrentRangeIndex = rangeCount - 1; 51 } else if (uint32_t(aOffset) < ranges[idx].Start()) { 52 mCurrentRangeIndex = idx - 1; 53 if (mCurrentRangeIndex == -1) { 54 mSkippedStringOffset = aOffset; 55 return; 56 } 57 } else { 58 mCurrentRangeIndex = idx; 59 } 60 61 const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; 62 if (uint32_t(aOffset) < r.End()) { 63 mSkippedStringOffset = r.SkippedOffset(); 64 return; 65 } 66 67 mSkippedStringOffset = aOffset - r.NextDelta(); 68 } 69 70 struct SkippedRangeOffsetComparator { 71 const uint32_t mOffset; 72 explicit SkippedRangeOffsetComparator(const uint32_t aOffset) 73 : mOffset(aOffset) {} 74 int operator()(const gfxSkipChars::SkippedRange& aRange) const { 75 return (mOffset < aRange.SkippedOffset()) ? -1 : 1; 76 } 77 }; 78 79 void gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset) { 80 NS_ASSERTION( 81 (mSkipChars->mRanges.IsEmpty() && aOffset <= mSkipChars->mCharCount) || 82 (aOffset <= mSkipChars->LastRange().SkippedOffset() + 83 mSkipChars->mCharCount - 84 mSkipChars->LastRange().End()), 85 "Invalid skipped offset"); 86 mSkippedStringOffset = aOffset; 87 88 uint32_t rangeCount = mSkipChars->mRanges.Length(); 89 if (rangeCount == 0) { 90 mOriginalStringOffset = aOffset; 91 return; 92 } 93 94 const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges; 95 size_t idx; 96 mozilla::BinarySearchIf(ranges, 0, rangeCount, 97 SkippedRangeOffsetComparator(aOffset), &idx); 98 99 if (idx == rangeCount) { 100 mCurrentRangeIndex = rangeCount - 1; 101 } else if (aOffset < ranges[idx].SkippedOffset()) { 102 mCurrentRangeIndex = idx - 1; 103 if (mCurrentRangeIndex == -1) { 104 mOriginalStringOffset = aOffset; 105 return; 106 } 107 } else { 108 mCurrentRangeIndex = idx; 109 } 110 111 const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex]; 112 mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset(); 113 } 114 115 bool gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const { 116 if (mCurrentRangeIndex == -1) { 117 // we're before the first skipped range (if any) 118 if (aRunLength) { 119 uint32_t end = mSkipChars->mRanges.IsEmpty() 120 ? mSkipChars->mCharCount 121 : mSkipChars->mRanges[0].Start(); 122 *aRunLength = end - mOriginalStringOffset; 123 } 124 return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); 125 } 126 127 const gfxSkipChars::SkippedRange& range = 128 mSkipChars->mRanges[mCurrentRangeIndex]; 129 130 if (uint32_t(mOriginalStringOffset) < range.End()) { 131 if (aRunLength) { 132 *aRunLength = range.End() - mOriginalStringOffset; 133 } 134 return true; 135 } 136 137 if (aRunLength) { 138 uint32_t end = 139 uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() 140 ? mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() 141 : mSkipChars->mCharCount; 142 *aRunLength = end - mOriginalStringOffset; 143 } 144 145 return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset); 146 }