gfxSkipChars.cpp 4.9 KB

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