diff options
Diffstat (limited to 'Source/WebCore/platform/text/BidiResolver.h')
| -rw-r--r-- | Source/WebCore/platform/text/BidiResolver.h | 375 |
1 files changed, 198 insertions, 177 deletions
diff --git a/Source/WebCore/platform/text/BidiResolver.h b/Source/WebCore/platform/text/BidiResolver.h index 07e9274..5b92ee2 100644 --- a/Source/WebCore/platform/text/BidiResolver.h +++ b/Source/WebCore/platform/text/BidiResolver.h @@ -75,6 +75,21 @@ struct BidiStatus { RefPtr<BidiContext> context; }; +class BidiEmbedding { +public: + BidiEmbedding(WTF::Unicode::Direction direction, BidiEmbeddingSource source) + : m_direction(direction) + , m_source(source) + { + } + + WTF::Unicode::Direction direction() const { return m_direction; } + BidiEmbeddingSource source() const { return m_source; } +private: + WTF::Unicode::Direction m_direction; + BidiEmbeddingSource m_source; +}; + inline bool operator==(const BidiStatus& status1, const BidiStatus& status2) { return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong && *(status1.context) == *(status2.context); @@ -134,10 +149,10 @@ enum VisualDirectionOverride { template <class Iterator, class Run> class BidiResolver { WTF_MAKE_NONCOPYABLE(BidiResolver); -public : +public: BidiResolver() : m_direction(WTF::Unicode::OtherNeutral) - , reachedEndOfLine(false) + , m_reachedEndOfLine(false) , emptyRun(true) , m_firstRun(0) , m_lastRun(0) @@ -146,10 +161,10 @@ public : { } - const Iterator& position() const { return current; } - void setPosition(const Iterator& position) { current = position; } + const Iterator& position() const { return m_current; } + void setPosition(const Iterator& position) { m_current = position; } - void increment() { current.increment(); } + void increment() { m_current.increment(); } BidiContext* context() const { return m_status.context.get(); } void setContext(PassRefPtr<BidiContext> c) { m_status.context = c; } @@ -166,7 +181,7 @@ public : MidpointState<Iterator>& midpointState() { return m_midpointState; } - void embed(WTF::Unicode::Direction); + void embed(WTF::Unicode::Direction, BidiEmbeddingSource); bool commitExplicitEmbedding(); void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = NoVisualOverride, bool hardLineBreak = false); @@ -188,14 +203,16 @@ protected: void appendRun(); void reverseRuns(unsigned start, unsigned end); - Iterator current; - Iterator sor; - Iterator eor; - Iterator last; + Iterator m_current; + // sor and eor are "start of run" and "end of run" respectively and correpond + // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7 + Iterator m_sor; + Iterator m_eor; + Iterator m_last; BidiStatus m_status; WTF::Unicode::Direction m_direction; Iterator endOfLine; - bool reachedEndOfLine; + bool m_reachedEndOfLine; Iterator lastBeforeET; bool emptyRun; @@ -210,7 +227,10 @@ private: void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from); void checkDirectionInLowerRaiseEmbeddingLevel(); - Vector<WTF::Unicode::Direction, 8> m_currentExplicitEmbeddingSequence; + void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); + void reorderRunsFromLevels(); + + Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; }; template <class Iterator, class Run> @@ -286,20 +306,20 @@ inline void BidiResolver<Iterator, Run>::moveRunToBeginning(Run* run) template <class Iterator, class Run> void BidiResolver<Iterator, Run>::appendRun() { - if (!emptyRun && !eor.atEnd()) { - unsigned startOffset = sor.offset(); - unsigned endOffset = eor.offset(); + if (!emptyRun && !m_eor.atEnd()) { + unsigned startOffset = m_sor.offset(); + unsigned endOffset = m_eor.offset(); if (!endOfLine.atEnd() && endOffset >= endOfLine.offset()) { - reachedEndOfLine = true; + m_reachedEndOfLine = true; endOffset = endOfLine.offset(); } if (endOffset >= startOffset) addRun(new Run(startOffset, endOffset + 1, context(), m_direction)); - eor.increment(); - sor = eor; + m_eor.increment(); + m_sor = m_eor; } m_direction = WTF::Unicode::OtherNeutral; @@ -307,12 +327,12 @@ void BidiResolver<Iterator, Run>::appendRun() } template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction d) +void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source) { using namespace WTF::Unicode; - ASSERT(d == PopDirectionalFormat || d == LeftToRightEmbedding || d == LeftToRightOverride || d == RightToLeftEmbedding || d == RightToLeftOverride); - m_currentExplicitEmbeddingSequence.append(d); + ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir == LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride); + m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); } template <class Iterator, class Run> @@ -320,7 +340,7 @@ void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel() { using namespace WTF::Unicode; - ASSERT(m_status.eor != OtherNeutral || eor.atEnd()); + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); ASSERT(m_status.last != NonSpacingMark && m_status.last != BoundaryNeutral && m_status.last != RightToLeftEmbedding @@ -337,7 +357,7 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire { using namespace WTF::Unicode; - if (!emptyRun && eor != last) { + if (!emptyRun && m_eor != m_last) { checkDirectionInLowerRaiseEmbeddingLevel(); // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last if (from == LeftToRight) { @@ -358,14 +378,14 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire appendRun(); m_direction = RightToLeft; } - eor = last; + m_eor = m_last; } appendRun(); emptyRun = true; // sor for the new run is determined by the higher level (rule X10) setLastDir(from); setLastStrongDir(from); - eor = Iterator(); + m_eor = Iterator(); } template <class Iterator, class Run> @@ -373,7 +393,7 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire { using namespace WTF::Unicode; - if (!emptyRun && eor != last) { + if (!emptyRun && m_eor != m_last) { checkDirectionInLowerRaiseEmbeddingLevel(); // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last if (to == LeftToRight) { @@ -396,13 +416,13 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire appendRun(); m_direction = RightToLeft; } - eor = last; + m_eor = m_last; } appendRun(); emptyRun = true; setLastDir(to); setLastStrongDir(to); - eor = Iterator(); + m_eor = Iterator(); } template <class Iterator, class Run> @@ -414,25 +434,20 @@ bool BidiResolver<Iterator, Run>::commitExplicitEmbedding() RefPtr<BidiContext> toContext = context(); for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) { - Direction embedding = m_currentExplicitEmbeddingSequence[i]; - if (embedding == PopDirectionalFormat) { + BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i]; + if (embedding.direction() == PopDirectionalFormat) { if (BidiContext* parentContext = toContext->parent()) toContext = parentContext; } else { - Direction direction = (embedding == RightToLeftEmbedding || embedding == RightToLeftOverride) ? RightToLeft : LeftToRight; - bool override = embedding == LeftToRightOverride || embedding == RightToLeftOverride; + Direction direction = (embedding.direction() == RightToLeftEmbedding || embedding.direction() == RightToLeftOverride) ? RightToLeft : LeftToRight; + bool override = embedding.direction() == LeftToRightOverride || embedding.direction() == RightToLeftOverride; unsigned char level = toContext->level(); - if (direction == RightToLeft) { - // Go to the least greater odd integer - level += 1; - level |= 1; - } else { - // Go to the least greater even integer - level += 2; - level &= ~1; - } + if (direction == RightToLeft) + level = nextGreaterOddLevel(level); + else + level = nextGreaterEvenLevel(level); if (level < 61) - toContext = BidiContext::create(level, direction, override, toContext.get()); + toContext = BidiContext::create(level, direction, override, embedding.source(), toContext.get()); } } @@ -520,6 +535,85 @@ void BidiResolver<Iterator, Run>::reverseRuns(unsigned start, unsigned end) } template <class Iterator, class Run> +inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent) +{ + using namespace WTF::Unicode; + switch (dirCurrent) { + case EuropeanNumberTerminator: + if (m_status.last != EuropeanNumber) + m_status.last = EuropeanNumberTerminator; + break; + case EuropeanNumberSeparator: + case CommonNumberSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + switch (m_status.last) { + case LeftToRight: + case RightToLeft: + case RightToLeftArabic: + case EuropeanNumber: + case ArabicNumber: + m_status.last = dirCurrent; + break; + default: + m_status.last = OtherNeutral; + } + break; + case NonSpacingMark: + case BoundaryNeutral: + case RightToLeftEmbedding: + case LeftToRightEmbedding: + case RightToLeftOverride: + case LeftToRightOverride: + case PopDirectionalFormat: + // ignore these + break; + case EuropeanNumber: + // fall through + default: + m_status.last = dirCurrent; + } +} + +template <class Iterator, class Run> +inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels() +{ + unsigned char levelLow = 128; + unsigned char levelHigh = 0; + for (Run* run = firstRun(); run; run = run->next()) { + levelHigh = std::max(run->level(), levelHigh); + levelLow = std::min(run->level(), levelLow); + } + + // This implements reordering of the line (L2 according to Bidi spec): + // http://unicode.org/reports/tr9/#L2 + // L2. From the highest level found in the text to the lowest odd level on each line, + // reverse any contiguous sequence of characters that are at that level or higher. + + // Reversing is only done up to the lowest odd level. + if (!(levelLow % 2)) + levelLow++; + + unsigned count = runCount() - 1; + + while (levelHigh >= levelLow) { + unsigned i = 0; + Run* run = firstRun(); + while (i < count) { + for (;i < count && run && run->level() < levelHigh; i++) + run = run->next(); + unsigned start = i; + for (;i <= count && run && run->level() >= levelHigh; i++) + run = run->next(); + unsigned end = i - 1; + reverseRuns(start, end); + } + levelHigh--; + } +} + +template <class Iterator, class Run> void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak) { using namespace WTF::Unicode; @@ -528,10 +622,10 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis if (override != NoVisualOverride) { emptyRun = false; - sor = current; - eor = Iterator(); - while (current != end && !current.atEnd()) { - eor = current; + m_sor = m_current; + m_eor = Iterator(); + while (m_current != end && !m_current.atEnd()) { + m_eor = m_current; increment(); } m_direction = override == VisualLeftToRightOverride ? LeftToRight : RightToLeft; @@ -544,29 +638,34 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis emptyRun = true; - eor = Iterator(); + m_eor = Iterator(); - last = current; + m_last = m_current; bool pastEnd = false; BidiResolver<Iterator, Run> stateAtEnd; while (true) { Direction dirCurrent; - if (pastEnd && (hardLineBreak || current.atEnd())) { + if (pastEnd && (hardLineBreak || m_current.atEnd())) { BidiContext* c = context(); - while (c->parent()) - c = c->parent(); - dirCurrent = c->dir(); if (hardLineBreak) { // A deviation from the Unicode Bidi Algorithm in order to match - // Mac OS X text and WinIE: a hard line break resets bidi state. - stateAtEnd.setContext(c); + // WinIE and user expectations: hard line breaks reset bidi state + // coming from unicode bidi control characters, but not those from + // DOM nodes with specified directionality + stateAtEnd.setContext(c->copyStackRemovingUnicodeEmbeddingContexts()); + + dirCurrent = stateAtEnd.context()->dir(); stateAtEnd.setEorDir(dirCurrent); stateAtEnd.setLastDir(dirCurrent); stateAtEnd.setLastStrongDir(dirCurrent); + } else { + while (c->parent()) + c = c->parent(); + dirCurrent = c->dir(); } } else { - dirCurrent = current.direction(); + dirCurrent = m_current.direction(); if (context()->override() && dirCurrent != RightToLeftEmbedding && dirCurrent != LeftToRightEmbedding @@ -578,7 +677,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis dirCurrent = m_status.last; } - ASSERT(m_status.eor != OtherNeutral || eor.atEnd()); + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); switch (dirCurrent) { // embedding and overrides (X1-X9 in the Bidi specs) @@ -587,7 +686,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeftOverride: case LeftToRightOverride: case PopDirectionalFormat: - embed(dirCurrent); + embed(dirCurrent, FromUnicode); commitExplicitEmbedding(); break; @@ -618,7 +717,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (context()->dir() != LeftToRight) { // the neutrals take the embedding direction, which is R - eor = last; + m_eor = m_last; m_direction = RightToLeft; appendRun(); } @@ -629,14 +728,14 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (context()->dir() != LeftToRight) { // the neutrals take the embedding direction, which is R - eor = last; + m_eor = m_last; m_direction = RightToLeft; appendRun(); } } else if (m_status.lastStrong != LeftToRight) { //last stuff takes embedding dir if (context()->dir() == RightToLeft) { - eor = last; + m_eor = m_last; m_direction = RightToLeft; } appendRun(); @@ -644,7 +743,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis default: break; } - eor = current; + m_eor = m_current; m_status.eor = LeftToRight; m_status.lastStrong = LeftToRight; m_direction = LeftToRight; @@ -669,19 +768,19 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case OtherNeutral: if (m_status.eor == EuropeanNumber) { if (m_status.lastStrong == LeftToRight && context()->dir() == LeftToRight) - eor = last; + m_eor = m_last; appendRun(); } else if (m_status.eor == ArabicNumber) appendRun(); else if (m_status.lastStrong == LeftToRight) { if (context()->dir() == LeftToRight) - eor = last; + m_eor = m_last; appendRun(); } default: break; } - eor = current; + m_eor = m_current; m_status.eor = RightToLeft; m_status.lastStrong = dirCurrent; m_direction = RightToLeft; @@ -699,7 +798,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeft: case RightToLeftArabic: case ArabicNumber: - eor = last; + m_eor = m_last; appendRun(); m_direction = EuropeanNumber; break; @@ -719,7 +818,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis // Terminate the EN run. appendRun(); // Make an R run. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -730,7 +829,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft) { // Make an R run. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -738,7 +837,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } } else if (m_status.lastStrong == RightToLeft) { // Extend the R run to include the neutrals. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -747,7 +846,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis default: break; } - eor = current; + m_eor = m_current; m_status.eor = EuropeanNumber; if (m_direction == OtherNeutral) m_direction = LeftToRight; @@ -765,7 +864,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeft: case RightToLeftArabic: case EuropeanNumber: - eor = last; + m_eor = m_last; appendRun(); break; case CommonNumberSeparator: @@ -787,12 +886,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis m_direction = RightToLeft; } else if (m_direction == OtherNeutral) m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; - eor = last; + m_eor = m_last; appendRun(); default: break; } - eor = current; + m_eor = m_current; m_status.eor = ArabicNumber; if (m_direction == OtherNeutral) m_direction = ArabicNumber; @@ -803,16 +902,16 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case EuropeanNumberTerminator: if (m_status.last == EuropeanNumber) { dirCurrent = EuropeanNumber; - eor = current; + m_eor = m_current; m_status.eor = dirCurrent; } else if (m_status.last != EuropeanNumberTerminator) - lastBeforeET = emptyRun ? eor : last; + lastBeforeET = emptyRun ? m_eor : m_last; break; // boundary neutrals should be ignored case BoundaryNeutral: - if (eor == last) - eor = current; + if (m_eor == m_last) + m_eor = m_current; break; // neutrals case BlockSeparator: @@ -829,9 +928,9 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis break; } - if (pastEnd && eor == current) { - if (!reachedEndOfLine) { - eor = endOfLine; + if (pastEnd && m_eor == m_current) { + if (!m_reachedEndOfLine) { + m_eor = endOfLine; switch (m_status.eor) { case LeftToRight: case RightToLeft: @@ -846,60 +945,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } appendRun(); } - current = end; + m_current = end; m_status = stateAtEnd.m_status; - sor = stateAtEnd.sor; - eor = stateAtEnd.eor; - last = stateAtEnd.last; - reachedEndOfLine = stateAtEnd.reachedEndOfLine; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; lastBeforeET = stateAtEnd.lastBeforeET; emptyRun = stateAtEnd.emptyRun; m_direction = OtherNeutral; break; } - // set m_status.last as needed. - switch (dirCurrent) { - case EuropeanNumberTerminator: - if (m_status.last != EuropeanNumber) - m_status.last = EuropeanNumberTerminator; - break; - case EuropeanNumberSeparator: - case CommonNumberSeparator: - case SegmentSeparator: - case WhiteSpaceNeutral: - case OtherNeutral: - switch(m_status.last) { - case LeftToRight: - case RightToLeft: - case RightToLeftArabic: - case EuropeanNumber: - case ArabicNumber: - m_status.last = dirCurrent; - break; - default: - m_status.last = OtherNeutral; - } - break; - case NonSpacingMark: - case BoundaryNeutral: - case RightToLeftEmbedding: - case LeftToRightEmbedding: - case RightToLeftOverride: - case LeftToRightOverride: - case PopDirectionalFormat: - // ignore these - break; - case EuropeanNumber: - // fall through - default: - m_status.last = dirCurrent; - } - - last = current; + updateStatusLastFromCurrentDirection(dirCurrent); + m_last = m_current; if (emptyRun) { - sor = current; + m_sor = m_current; emptyRun = false; } @@ -907,12 +969,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis if (!m_currentExplicitEmbeddingSequence.isEmpty()) { bool committed = commitExplicitEmbedding(); if (committed && pastEnd) { - current = end; + m_current = end; m_status = stateAtEnd.m_status; - sor = stateAtEnd.sor; - eor = stateAtEnd.eor; - last = stateAtEnd.last; - reachedEndOfLine = stateAtEnd.reachedEndOfLine; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; lastBeforeET = stateAtEnd.lastBeforeET; emptyRun = stateAtEnd.emptyRun; m_direction = OtherNeutral; @@ -920,64 +982,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } } - if (!pastEnd && (current == end || current.atEnd())) { + if (!pastEnd && (m_current == end || m_current.atEnd())) { if (emptyRun) break; stateAtEnd.m_status = m_status; - stateAtEnd.sor = sor; - stateAtEnd.eor = eor; - stateAtEnd.last = last; - stateAtEnd.reachedEndOfLine = reachedEndOfLine; + stateAtEnd.m_sor = m_sor; + stateAtEnd.m_eor = m_eor; + stateAtEnd.m_last = m_last; + stateAtEnd.m_reachedEndOfLine = m_reachedEndOfLine; stateAtEnd.lastBeforeET = lastBeforeET; stateAtEnd.emptyRun = emptyRun; - endOfLine = last; + endOfLine = m_last; pastEnd = true; } } m_logicallyLastRun = m_lastRun; - - // reorder line according to run structure... - // first find highest and lowest levels - unsigned char levelLow = 128; - unsigned char levelHigh = 0; - Run* r = firstRun(); - while (r) { - if (r->m_level > levelHigh) - levelHigh = r->m_level; - if (r->m_level < levelLow) - levelLow = r->m_level; - r = r->next(); - } - - // implements reordering of the line (L2 according to Bidi spec): - // L2. From the highest level found in the text to the lowest odd level on each line, - // reverse any contiguous sequence of characters that are at that level or higher. - - // reversing is only done up to the lowest odd level - if (!(levelLow % 2)) - levelLow++; - - unsigned count = runCount() - 1; - - while (levelHigh >= levelLow) { - unsigned i = 0; - Run* currRun = firstRun(); - while (i < count) { - while (i < count && currRun && currRun->m_level < levelHigh) { - i++; - currRun = currRun->next(); - } - unsigned start = i; - while (i <= count && currRun && currRun->m_level >= levelHigh) { - i++; - currRun = currRun->next(); - } - unsigned end = i - 1; - reverseRuns(start, end); - } - levelHigh--; - } + reorderRunsFromLevels(); endOfLine = Iterator(); } |
