summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxSkipChars.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/gfxSkipChars.cpp')
-rw-r--r--gfx/thebes/gfxSkipChars.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/gfx/thebes/gfxSkipChars.cpp b/gfx/thebes/gfxSkipChars.cpp
new file mode 100644
index 000000000..d0fad53e2
--- /dev/null
+++ b/gfx/thebes/gfxSkipChars.cpp
@@ -0,0 +1,153 @@
+/* -*- 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/. */
+
+#include "gfxSkipChars.h"
+#include "mozilla/BinarySearch.h"
+
+struct SkippedRangeStartComparator
+{
+ const uint32_t mOffset;
+ explicit SkippedRangeStartComparator(const uint32_t aOffset) : mOffset(aOffset) {}
+ int operator()(const gfxSkipChars::SkippedRange& aRange) const {
+ return (mOffset < aRange.Start()) ? -1 : 1;
+ }
+};
+
+void
+gfxSkipCharsIterator::SetOriginalOffset(int32_t aOffset)
+{
+ aOffset += mOriginalStringToSkipCharsOffset;
+ if (MOZ_UNLIKELY(uint32_t(aOffset) > mSkipChars->mCharCount)) {
+ gfxCriticalError() <<
+ "invalid offset " << aOffset <<
+ " for gfxSkipChars length " << mSkipChars->mCharCount;
+ aOffset = mSkipChars->mCharCount;
+ }
+
+ mOriginalStringOffset = aOffset;
+
+ const uint32_t rangeCount = mSkipChars->mRanges.Length();
+ if (rangeCount == 0) {
+ mSkippedStringOffset = aOffset;
+ return;
+ }
+
+ // at start of string?
+ if (aOffset == 0) {
+ mSkippedStringOffset = 0;
+ mCurrentRangeIndex =
+ rangeCount && mSkipChars->mRanges[0].Start() == 0 ? 0 : -1;
+ return;
+ }
+
+ // find the range that includes or precedes aOffset
+ const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges;
+ size_t idx;
+ mozilla::BinarySearchIf(ranges, 0, rangeCount,
+ SkippedRangeStartComparator(aOffset),
+ &idx);
+
+ if (idx == rangeCount) {
+ mCurrentRangeIndex = rangeCount - 1;
+ } else if (uint32_t(aOffset) < ranges[idx].Start()) {
+ mCurrentRangeIndex = idx - 1;
+ if (mCurrentRangeIndex == -1) {
+ mSkippedStringOffset = aOffset;
+ return;
+ }
+ } else {
+ mCurrentRangeIndex = idx;
+ }
+
+ const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
+ if (uint32_t(aOffset) < r.End()) {
+ mSkippedStringOffset = r.SkippedOffset();
+ return;
+ }
+
+ mSkippedStringOffset = aOffset - r.NextDelta();
+}
+
+struct SkippedRangeOffsetComparator
+{
+ const uint32_t mOffset;
+ explicit SkippedRangeOffsetComparator(const uint32_t aOffset) : mOffset(aOffset) {}
+ int operator()(const gfxSkipChars::SkippedRange& aRange) const {
+ return (mOffset < aRange.SkippedOffset()) ? -1 : 1;
+ }
+};
+
+void
+gfxSkipCharsIterator::SetSkippedOffset(uint32_t aOffset)
+{
+ NS_ASSERTION((mSkipChars->mRanges.IsEmpty() &&
+ aOffset <= mSkipChars->mCharCount) ||
+ (aOffset <= mSkipChars->LastRange().SkippedOffset() +
+ mSkipChars->mCharCount -
+ mSkipChars->LastRange().End()),
+ "Invalid skipped offset");
+ mSkippedStringOffset = aOffset;
+
+ uint32_t rangeCount = mSkipChars->mRanges.Length();
+ if (rangeCount == 0) {
+ mOriginalStringOffset = aOffset;
+ return;
+ }
+
+ const nsTArray<gfxSkipChars::SkippedRange>& ranges = mSkipChars->mRanges;
+ size_t idx;
+ mozilla::BinarySearchIf(ranges, 0, rangeCount,
+ SkippedRangeOffsetComparator(aOffset),
+ &idx);
+
+ if (idx == rangeCount) {
+ mCurrentRangeIndex = rangeCount - 1;
+ } else if (aOffset < ranges[idx].SkippedOffset()) {
+ mCurrentRangeIndex = idx - 1;
+ if (mCurrentRangeIndex == -1) {
+ mOriginalStringOffset = aOffset;
+ return;
+ }
+ } else {
+ mCurrentRangeIndex = idx;
+ }
+
+ const gfxSkipChars::SkippedRange& r = ranges[mCurrentRangeIndex];
+ mOriginalStringOffset = r.End() + aOffset - r.SkippedOffset();
+}
+
+bool
+gfxSkipCharsIterator::IsOriginalCharSkipped(int32_t* aRunLength) const
+{
+ if (mCurrentRangeIndex == -1) {
+ // we're before the first skipped range (if any)
+ if (aRunLength) {
+ uint32_t end = mSkipChars->mRanges.IsEmpty() ?
+ mSkipChars->mCharCount : mSkipChars->mRanges[0].Start();
+ *aRunLength = end - mOriginalStringOffset;
+ }
+ return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
+ }
+
+ const gfxSkipChars::SkippedRange& range =
+ mSkipChars->mRanges[mCurrentRangeIndex];
+
+ if (uint32_t(mOriginalStringOffset) < range.End()) {
+ if (aRunLength) {
+ *aRunLength = range.End() - mOriginalStringOffset;
+ }
+ return true;
+ }
+
+ if (aRunLength) {
+ uint32_t end =
+ uint32_t(mCurrentRangeIndex) + 1 < mSkipChars->mRanges.Length() ?
+ mSkipChars->mRanges[mCurrentRangeIndex + 1].Start() :
+ mSkipChars->mCharCount;
+ *aRunLength = end - mOriginalStringOffset;
+ }
+
+ return mSkipChars->mCharCount == uint32_t(mOriginalStringOffset);
+}