| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008 Apple Inc. All right reserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008 Apple Inc. All right reserved. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 void startIgnoringSpaces(const Iterator& midpoint) { | 52 void startIgnoringSpaces(const Iterator& midpoint) { |
| 53 ASSERT(!(m_numMidpoints % 2)); | 53 ASSERT(!(m_numMidpoints % 2)); |
| 54 addMidpoint(midpoint); | 54 addMidpoint(midpoint); |
| 55 } | 55 } |
| 56 | 56 |
| 57 void stopIgnoringSpaces(const Iterator& midpoint) { | 57 void stopIgnoringSpaces(const Iterator& midpoint) { |
| 58 ASSERT(m_numMidpoints % 2); | 58 ASSERT(m_numMidpoints % 2); |
| 59 addMidpoint(midpoint); | 59 addMidpoint(midpoint); |
| 60 } | 60 } |
| 61 | 61 |
| 62 // Adding a pair of midpoints before a character will split it out into a new
line box. | 62 // Adding a pair of midpoints before a character will split it out into a new |
| 63 // line box. |
| 63 void ensureCharacterGetsLineBox(Iterator& textParagraphSeparator) { | 64 void ensureCharacterGetsLineBox(Iterator& textParagraphSeparator) { |
| 64 startIgnoringSpaces(Iterator(0, textParagraphSeparator.getLineLayoutItem(), | 65 startIgnoringSpaces(Iterator(0, textParagraphSeparator.getLineLayoutItem(), |
| 65 textParagraphSeparator.offset() - 1)); | 66 textParagraphSeparator.offset() - 1)); |
| 66 stopIgnoringSpaces(Iterator(0, textParagraphSeparator.getLineLayoutItem(), | 67 stopIgnoringSpaces(Iterator(0, textParagraphSeparator.getLineLayoutItem(), |
| 67 textParagraphSeparator.offset())); | 68 textParagraphSeparator.offset())); |
| 68 } | 69 } |
| 69 | 70 |
| 70 void checkMidpoints(Iterator& lBreak) { | 71 void checkMidpoints(Iterator& lBreak) { |
| 71 // Check to see if our last midpoint is a start point beyond the line break.
If so, | 72 // Check to see if our last midpoint is a start point beyond the line break. |
| 72 // shave it off the list, and shave off a trailing space if the previous end
point doesn't | 73 // If so, shave it off the list, and shave off a trailing space if the |
| 73 // preserve whitespace. | 74 // previous end point doesn't preserve whitespace. |
| 74 if (lBreak.getLineLayoutItem() && m_numMidpoints && !(m_numMidpoints % 2)) { | 75 if (lBreak.getLineLayoutItem() && m_numMidpoints && !(m_numMidpoints % 2)) { |
| 75 Iterator* midpointsIterator = m_midpoints.data(); | 76 Iterator* midpointsIterator = m_midpoints.data(); |
| 76 Iterator& endpoint = midpointsIterator[m_numMidpoints - 2]; | 77 Iterator& endpoint = midpointsIterator[m_numMidpoints - 2]; |
| 77 const Iterator& startpoint = midpointsIterator[m_numMidpoints - 1]; | 78 const Iterator& startpoint = midpointsIterator[m_numMidpoints - 1]; |
| 78 Iterator currpoint = endpoint; | 79 Iterator currpoint = endpoint; |
| 79 while (!currpoint.atEnd() && currpoint != startpoint && | 80 while (!currpoint.atEnd() && currpoint != startpoint && |
| 80 currpoint != lBreak) | 81 currpoint != lBreak) |
| 81 currpoint.increment(); | 82 currpoint.increment(); |
| 82 if (currpoint == lBreak) { | 83 if (currpoint == lBreak) { |
| 83 // We hit the line break before the start point. Shave off the start poi
nt. | 84 // We hit the line break before the start point. Shave off the start |
| 85 // point. |
| 84 m_numMidpoints--; | 86 m_numMidpoints--; |
| 85 if (endpoint.getLineLayoutItem().style()->collapseWhiteSpace() && | 87 if (endpoint.getLineLayoutItem().style()->collapseWhiteSpace() && |
| 86 endpoint.getLineLayoutItem().isText()) | 88 endpoint.getLineLayoutItem().isText()) |
| 87 endpoint.setOffset(endpoint.offset() - 1); | 89 endpoint.setOffset(endpoint.offset() - 1); |
| 88 } | 90 } |
| 89 } | 91 } |
| 90 } | 92 } |
| 91 | 93 |
| 92 Vector<Iterator>& midpoints() { return m_midpoints; } | 94 Vector<Iterator>& midpoints() { return m_midpoints; } |
| 93 const unsigned& numMidpoints() const { return m_numMidpoints; } | 95 const unsigned& numMidpoints() const { return m_numMidpoints; } |
| 94 const unsigned& currentMidpoint() const { return m_currentMidpoint; } | 96 const unsigned& currentMidpoint() const { return m_currentMidpoint; } |
| 95 void incrementCurrentMidpoint() { m_currentMidpoint++; } | 97 void incrementCurrentMidpoint() { m_currentMidpoint++; } |
| 96 const bool& betweenMidpoints() const { return m_betweenMidpoints; } | 98 const bool& betweenMidpoints() const { return m_betweenMidpoints; } |
| 97 void setBetweenMidpoints(bool betweenMidpoint) { | 99 void setBetweenMidpoints(bool betweenMidpoint) { |
| 98 m_betweenMidpoints = betweenMidpoint; | 100 m_betweenMidpoints = betweenMidpoint; |
| 99 } | 101 } |
| 100 | 102 |
| 101 private: | 103 private: |
| 102 // The goal is to reuse the line state across multiple | 104 // The goal is to reuse the line state across multiple |
| 103 // lines so we just keep an array around for midpoints and never clear it acro
ss multiple | 105 // lines so we just keep an array around for midpoints and never clear it |
| 104 // lines. We track the number of items and position using the two other variab
les. | 106 // across multiple lines. We track the number of items and position using the |
| 107 // two other variables. |
| 105 Vector<Iterator> m_midpoints; | 108 Vector<Iterator> m_midpoints; |
| 106 unsigned m_numMidpoints; | 109 unsigned m_numMidpoints; |
| 107 unsigned m_currentMidpoint; | 110 unsigned m_currentMidpoint; |
| 108 bool m_betweenMidpoints; | 111 bool m_betweenMidpoints; |
| 109 | 112 |
| 110 void addMidpoint(const Iterator& midpoint) { | 113 void addMidpoint(const Iterator& midpoint) { |
| 111 if (m_midpoints.size() <= m_numMidpoints) | 114 if (m_midpoints.size() <= m_numMidpoints) |
| 112 m_midpoints.grow(m_numMidpoints + 10); | 115 m_midpoints.grow(m_numMidpoints + 10); |
| 113 | 116 |
| 114 Iterator* midpointsIterator = m_midpoints.data(); | 117 Iterator* midpointsIterator = m_midpoints.data(); |
| 115 midpointsIterator[m_numMidpoints++] = midpoint; | 118 midpointsIterator[m_numMidpoints++] = midpoint; |
| 116 } | 119 } |
| 117 }; | 120 }; |
| 118 | 121 |
| 119 // The BidiStatus at a given position (typically the end of a line) can | 122 // The BidiStatus at a given position (typically the end of a line) can |
| 120 // be cached and then used to restart bidi resolution at that position. | 123 // be cached and then used to restart bidi resolution at that position. |
| 121 struct BidiStatus final { | 124 struct BidiStatus final { |
| 122 DISALLOW_NEW(); | 125 DISALLOW_NEW(); |
| 123 BidiStatus() | 126 BidiStatus() |
| 124 : eor(WTF::Unicode::OtherNeutral), | 127 : eor(WTF::Unicode::OtherNeutral), |
| 125 lastStrong(WTF::Unicode::OtherNeutral), | 128 lastStrong(WTF::Unicode::OtherNeutral), |
| 126 last(WTF::Unicode::OtherNeutral) {} | 129 last(WTF::Unicode::OtherNeutral) {} |
| 127 | 130 |
| 128 // Creates a BidiStatus representing a new paragraph root with a default direc
tion. | 131 // Creates a BidiStatus representing a new paragraph root with a default |
| 129 // Uses TextDirection as it only has two possibilities instead of WTF::Unicode
::Direction which has 19. | 132 // direction. Uses TextDirection as it only has two possibilities instead of |
| 133 // WTF::Unicode::Direction which has 19. |
| 130 BidiStatus(TextDirection textDirection, bool isOverride) { | 134 BidiStatus(TextDirection textDirection, bool isOverride) { |
| 131 WTF::Unicode::CharDirection direction = textDirection == LTR | 135 WTF::Unicode::CharDirection direction = textDirection == LTR |
| 132 ? WTF::Unicode::LeftToRight | 136 ? WTF::Unicode::LeftToRight |
| 133 : WTF::Unicode::RightToLeft; | 137 : WTF::Unicode::RightToLeft; |
| 134 eor = lastStrong = last = direction; | 138 eor = lastStrong = last = direction; |
| 135 context = BidiContext::create(textDirection == LTR ? 0 : 1, direction, | 139 context = BidiContext::create(textDirection == LTR ? 0 : 1, direction, |
| 136 isOverride); | 140 isOverride); |
| 137 } | 141 } |
| 138 | 142 |
| 139 BidiStatus(WTF::Unicode::CharDirection eorDir, | 143 BidiStatus(WTF::Unicode::CharDirection eorDir, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 const BidiStatus& status() const { return m_status; } | 256 const BidiStatus& status() const { return m_status; } |
| 253 void setStatus(const BidiStatus s) { | 257 void setStatus(const BidiStatus s) { |
| 254 ASSERT(s.context); | 258 ASSERT(s.context); |
| 255 m_status = s; | 259 m_status = s; |
| 256 m_paragraphDirectionality = | 260 m_paragraphDirectionality = |
| 257 s.context->dir() == WTF::Unicode::LeftToRight ? LTR : RTL; | 261 s.context->dir() == WTF::Unicode::LeftToRight ? LTR : RTL; |
| 258 } | 262 } |
| 259 | 263 |
| 260 MidpointState<Iterator>& midpointState() { return m_midpointState; } | 264 MidpointState<Iterator>& midpointState() { return m_midpointState; } |
| 261 | 265 |
| 262 // The current algorithm handles nested isolates one layer of nesting at a tim
e. | 266 // The current algorithm handles nested isolates one layer of nesting at a |
| 263 // But when we layout each isolated span, we will walk into (and ignore) all | 267 // time. But when we layout each isolated span, we will walk into (and |
| 264 // child isolated spans. | 268 // ignore) all child isolated spans. |
| 265 void enterIsolate() { m_nestedIsolateCount++; } | 269 void enterIsolate() { m_nestedIsolateCount++; } |
| 266 void exitIsolate() { | 270 void exitIsolate() { |
| 267 ASSERT(m_nestedIsolateCount >= 1); | 271 ASSERT(m_nestedIsolateCount >= 1); |
| 268 m_nestedIsolateCount--; | 272 m_nestedIsolateCount--; |
| 269 } | 273 } |
| 270 bool inIsolate() const { return m_nestedIsolateCount; } | 274 bool inIsolate() const { return m_nestedIsolateCount; } |
| 271 | 275 |
| 272 void embed(WTF::Unicode::CharDirection, BidiEmbeddingSource); | 276 void embed(WTF::Unicode::CharDirection, BidiEmbeddingSource); |
| 273 bool commitExplicitEmbedding(BidiRunList<Run>&); | 277 bool commitExplicitEmbedding(BidiRunList<Run>&); |
| 274 | 278 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 304 void setMidpointStateForIsolatedRun(Run&, const MidpointState<Iterator>&); | 308 void setMidpointStateForIsolatedRun(Run&, const MidpointState<Iterator>&); |
| 305 MidpointState<Iterator> midpointStateForIsolatedRun(Run&); | 309 MidpointState<Iterator> midpointStateForIsolatedRun(Run&); |
| 306 | 310 |
| 307 Iterator endOfLine() const { return m_endOfLine; } | 311 Iterator endOfLine() const { return m_endOfLine; } |
| 308 | 312 |
| 309 Run* trailingSpaceRun() const { return m_trailingSpaceRun; } | 313 Run* trailingSpaceRun() const { return m_trailingSpaceRun; } |
| 310 | 314 |
| 311 protected: | 315 protected: |
| 312 void increment() { m_current.increment(); } | 316 void increment() { m_current.increment(); } |
| 313 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should | 317 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should |
| 314 // pass in some sort of Traits object which knows how to create runs for appen
ding. | 318 // pass in some sort of Traits object which knows how to create runs for |
| 319 // appending. |
| 315 void appendRun(BidiRunList<Run>&); | 320 void appendRun(BidiRunList<Run>&); |
| 316 | 321 |
| 317 Run* addTrailingRun(BidiRunList<Run>&, | 322 Run* addTrailingRun(BidiRunList<Run>&, |
| 318 int, | 323 int, |
| 319 int, | 324 int, |
| 320 Run*, | 325 Run*, |
| 321 BidiContext*, | 326 BidiContext*, |
| 322 TextDirection) const { | 327 TextDirection) const { |
| 323 return 0; | 328 return 0; |
| 324 } | 329 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 } | 455 } |
| 451 | 456 |
| 452 template <class Iterator, class Run, class IsolatedRun> | 457 template <class Iterator, class Run, class IsolatedRun> |
| 453 void BidiResolver<Iterator, Run, IsolatedRun>::lowerExplicitEmbeddingLevel( | 458 void BidiResolver<Iterator, Run, IsolatedRun>::lowerExplicitEmbeddingLevel( |
| 454 BidiRunList<Run>& runs, | 459 BidiRunList<Run>& runs, |
| 455 WTF::Unicode::CharDirection from) { | 460 WTF::Unicode::CharDirection from) { |
| 456 using namespace WTF::Unicode; | 461 using namespace WTF::Unicode; |
| 457 | 462 |
| 458 if (!m_emptyRun && m_eor != m_last) { | 463 if (!m_emptyRun && m_eor != m_last) { |
| 459 checkDirectionInLowerRaiseEmbeddingLevel(); | 464 checkDirectionInLowerRaiseEmbeddingLevel(); |
| 460 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi
.eor run or extend it through bidi.last | 465 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the |
| 466 // bidi.sor-bidi.eor run or extend it through bidi.last |
| 461 if (from == LeftToRight) { | 467 if (from == LeftToRight) { |
| 462 // bidi.sor ... bidi.eor ... bidi.last L | 468 // bidi.sor ... bidi.eor ... bidi.last L |
| 463 if (m_status.eor == EuropeanNumber) { | 469 if (m_status.eor == EuropeanNumber) { |
| 464 if (m_status.lastStrong != LeftToRight) { | 470 if (m_status.lastStrong != LeftToRight) { |
| 465 m_direction = EuropeanNumber; | 471 m_direction = EuropeanNumber; |
| 466 appendRun(runs); | 472 appendRun(runs); |
| 467 } | 473 } |
| 468 } else if (m_status.eor == ArabicNumber) { | 474 } else if (m_status.eor == ArabicNumber) { |
| 469 m_direction = ArabicNumber; | 475 m_direction = ArabicNumber; |
| 470 appendRun(runs); | 476 appendRun(runs); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 491 | 497 |
| 492 template <class Iterator, class Run, class IsolatedRun> | 498 template <class Iterator, class Run, class IsolatedRun> |
| 493 void BidiResolver<Iterator, Run, IsolatedRun>::raiseExplicitEmbeddingLevel( | 499 void BidiResolver<Iterator, Run, IsolatedRun>::raiseExplicitEmbeddingLevel( |
| 494 BidiRunList<Run>& runs, | 500 BidiRunList<Run>& runs, |
| 495 WTF::Unicode::CharDirection from, | 501 WTF::Unicode::CharDirection from, |
| 496 WTF::Unicode::CharDirection to) { | 502 WTF::Unicode::CharDirection to) { |
| 497 using namespace WTF::Unicode; | 503 using namespace WTF::Unicode; |
| 498 | 504 |
| 499 if (!m_emptyRun && m_eor != m_last) { | 505 if (!m_emptyRun && m_eor != m_last) { |
| 500 checkDirectionInLowerRaiseEmbeddingLevel(); | 506 checkDirectionInLowerRaiseEmbeddingLevel(); |
| 501 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi
.eor run or extend it through bidi.last | 507 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the |
| 508 // bidi.sor-bidi.eor run or extend it through bidi.last |
| 502 if (to == LeftToRight) { | 509 if (to == LeftToRight) { |
| 503 // bidi.sor ... bidi.eor ... bidi.last L | 510 // bidi.sor ... bidi.eor ... bidi.last L |
| 504 if (m_status.eor == EuropeanNumber) { | 511 if (m_status.eor == EuropeanNumber) { |
| 505 if (m_status.lastStrong != LeftToRight) { | 512 if (m_status.lastStrong != LeftToRight) { |
| 506 m_direction = EuropeanNumber; | 513 m_direction = EuropeanNumber; |
| 507 appendRun(runs); | 514 appendRun(runs); |
| 508 } | 515 } |
| 509 } else if (m_status.eor == ArabicNumber) { | 516 } else if (m_status.eor == ArabicNumber) { |
| 510 m_direction = ArabicNumber; | 517 m_direction = ArabicNumber; |
| 511 appendRun(runs); | 518 appendRun(runs); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 trailingSpaceRun->m_level = 1; | 580 trailingSpaceRun->m_level = 1; |
| 574 } | 581 } |
| 575 m_trailingSpaceRun = trailingSpaceRun; | 582 m_trailingSpaceRun = trailingSpaceRun; |
| 576 } | 583 } |
| 577 | 584 |
| 578 template <class Iterator, class Run, class IsolatedRun> | 585 template <class Iterator, class Run, class IsolatedRun> |
| 579 bool BidiResolver<Iterator, Run, IsolatedRun>::commitExplicitEmbedding( | 586 bool BidiResolver<Iterator, Run, IsolatedRun>::commitExplicitEmbedding( |
| 580 BidiRunList<Run>& runs) { | 587 BidiRunList<Run>& runs) { |
| 581 // When we're "inIsolate()" we're resolving the parent context which | 588 // When we're "inIsolate()" we're resolving the parent context which |
| 582 // ignores (skips over) the isolated content, including embedding levels. | 589 // ignores (skips over) the isolated content, including embedding levels. |
| 583 // We should never accrue embedding levels while skipping over isolated conten
t. | 590 // We should never accrue embedding levels while skipping over isolated |
| 591 // content. |
| 584 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); | 592 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); |
| 585 | 593 |
| 586 using namespace WTF::Unicode; | 594 using namespace WTF::Unicode; |
| 587 | 595 |
| 588 unsigned char fromLevel = context()->level(); | 596 unsigned char fromLevel = context()->level(); |
| 589 RefPtr<BidiContext> toContext = context(); | 597 RefPtr<BidiContext> toContext = context(); |
| 590 | 598 |
| 591 for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) { | 599 for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) { |
| 592 BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i]; | 600 BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i]; |
| 593 if (embedding.direction() == PopDirectionalFormat) { | 601 if (embedding.direction() == PopDirectionalFormat) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 BidiRunList<Run>& runs) const { | 684 BidiRunList<Run>& runs) const { |
| 677 unsigned char levelLow = BidiContext::kMaxLevel; | 685 unsigned char levelLow = BidiContext::kMaxLevel; |
| 678 unsigned char levelHigh = 0; | 686 unsigned char levelHigh = 0; |
| 679 for (Run* run = runs.firstRun(); run; run = run->next()) { | 687 for (Run* run = runs.firstRun(); run; run = run->next()) { |
| 680 levelHigh = std::max(run->level(), levelHigh); | 688 levelHigh = std::max(run->level(), levelHigh); |
| 681 levelLow = std::min(run->level(), levelLow); | 689 levelLow = std::min(run->level(), levelLow); |
| 682 } | 690 } |
| 683 | 691 |
| 684 // This implements reordering of the line (L2 according to Bidi spec): | 692 // This implements reordering of the line (L2 according to Bidi spec): |
| 685 // http://unicode.org/reports/tr9/#L2 | 693 // http://unicode.org/reports/tr9/#L2 |
| 686 // L2. From the highest level found in the text to the lowest odd level on eac
h line, | 694 // L2. From the highest level found in the text to the lowest odd level on |
| 687 // reverse any contiguous sequence of characters that are at that level or hig
her. | 695 // each line, reverse any contiguous sequence of characters that are at that |
| 696 // level or higher. |
| 688 | 697 |
| 689 // Reversing is only done up to the lowest odd level. | 698 // Reversing is only done up to the lowest odd level. |
| 690 if (!(levelLow % 2)) | 699 if (!(levelLow % 2)) |
| 691 levelLow++; | 700 levelLow++; |
| 692 | 701 |
| 693 unsigned count = runs.runCount() - 1; | 702 unsigned count = runs.runCount() - 1; |
| 694 | 703 |
| 695 while (levelHigh >= levelLow) { | 704 while (levelHigh >= levelLow) { |
| 696 unsigned i = 0; | 705 unsigned i = 0; |
| 697 Run* run = runs.firstRun(); | 706 Run* run = runs.firstRun(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 716 while (!m_current.atEnd()) { | 725 while (!m_current.atEnd()) { |
| 717 if (inIsolate()) { | 726 if (inIsolate()) { |
| 718 increment(); | 727 increment(); |
| 719 continue; | 728 continue; |
| 720 } | 729 } |
| 721 if (breakOnParagraph && m_current.atParagraphSeparator()) | 730 if (breakOnParagraph && m_current.atParagraphSeparator()) |
| 722 break; | 731 break; |
| 723 UChar32 current = m_current.current(); | 732 UChar32 current = m_current.current(); |
| 724 if (UNLIKELY(U16_IS_SURROGATE(current))) { | 733 if (UNLIKELY(U16_IS_SURROGATE(current))) { |
| 725 increment(); | 734 increment(); |
| 726 // If this not the high part of the surrogate pair, then drop it and move
to the next. | 735 // If this not the high part of the surrogate pair, then drop it and move |
| 736 // to the next. |
| 727 if (!U16_IS_SURROGATE_LEAD(current)) | 737 if (!U16_IS_SURROGATE_LEAD(current)) |
| 728 continue; | 738 continue; |
| 729 UChar high = static_cast<UChar>(current); | 739 UChar high = static_cast<UChar>(current); |
| 730 if (m_current.atEnd()) | 740 if (m_current.atEnd()) |
| 731 continue; | 741 continue; |
| 732 UChar low = m_current.current(); | 742 UChar low = m_current.current(); |
| 733 // Verify the low part. If invalid, then assume an invalid surrogate pair
and retry. | 743 // Verify the low part. If invalid, then assume an invalid surrogate pair |
| 744 // and retry. |
| 734 if (!U16_IS_TRAIL(low)) | 745 if (!U16_IS_TRAIL(low)) |
| 735 continue; | 746 continue; |
| 736 current = U16_GET_SUPPLEMENTARY(high, low); | 747 current = U16_GET_SUPPLEMENTARY(high, low); |
| 737 } | 748 } |
| 738 WTF::Unicode::CharDirection charDirection = | 749 WTF::Unicode::CharDirection charDirection = |
| 739 WTF::Unicode::direction(current); | 750 WTF::Unicode::direction(current); |
| 740 if (charDirection == WTF::Unicode::LeftToRight) { | 751 if (charDirection == WTF::Unicode::LeftToRight) { |
| 741 if (hasStrongDirectionality) | 752 if (hasStrongDirectionality) |
| 742 *hasStrongDirectionality = true; | 753 *hasStrongDirectionality = true; |
| 743 return LTR; | 754 return LTR; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 if (context()->override() && dirCurrent != RightToLeftEmbedding && | 857 if (context()->override() && dirCurrent != RightToLeftEmbedding && |
| 847 dirCurrent != LeftToRightEmbedding && | 858 dirCurrent != LeftToRightEmbedding && |
| 848 dirCurrent != RightToLeftOverride && | 859 dirCurrent != RightToLeftOverride && |
| 849 dirCurrent != LeftToRightOverride && | 860 dirCurrent != LeftToRightOverride && |
| 850 dirCurrent != PopDirectionalFormat) | 861 dirCurrent != PopDirectionalFormat) |
| 851 dirCurrent = context()->dir(); | 862 dirCurrent = context()->dir(); |
| 852 else if (dirCurrent == NonSpacingMark) | 863 else if (dirCurrent == NonSpacingMark) |
| 853 dirCurrent = m_status.last; | 864 dirCurrent = m_status.last; |
| 854 } | 865 } |
| 855 | 866 |
| 856 // We ignore all character directionality while in unicode-bidi: isolate spa
ns. | 867 // We ignore all character directionality while in unicode-bidi: isolate |
| 857 // We'll handle ordering the isolated characters in a second pass. | 868 // spans. We'll handle ordering the isolated characters in a second pass. |
| 858 if (inIsolate()) | 869 if (inIsolate()) |
| 859 dirCurrent = OtherNeutral; | 870 dirCurrent = OtherNeutral; |
| 860 | 871 |
| 861 ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); | 872 ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); |
| 862 switch (dirCurrent) { | 873 switch (dirCurrent) { |
| 863 // embedding and overrides (X1-X9 in the Bidi specs) | 874 // embedding and overrides (X1-X9 in the Bidi specs) |
| 864 case RightToLeftEmbedding: | 875 case RightToLeftEmbedding: |
| 865 case LeftToRightEmbedding: | 876 case LeftToRightEmbedding: |
| 866 case RightToLeftOverride: | 877 case RightToLeftOverride: |
| 867 case LeftToRightOverride: | 878 case LeftToRightOverride: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 886 case EuropeanNumberSeparator: | 897 case EuropeanNumberSeparator: |
| 887 case EuropeanNumberTerminator: | 898 case EuropeanNumberTerminator: |
| 888 case CommonNumberSeparator: | 899 case CommonNumberSeparator: |
| 889 case BoundaryNeutral: | 900 case BoundaryNeutral: |
| 890 case BlockSeparator: | 901 case BlockSeparator: |
| 891 case SegmentSeparator: | 902 case SegmentSeparator: |
| 892 case WhiteSpaceNeutral: | 903 case WhiteSpaceNeutral: |
| 893 case OtherNeutral: | 904 case OtherNeutral: |
| 894 if (m_status.eor == EuropeanNumber) { | 905 if (m_status.eor == EuropeanNumber) { |
| 895 if (m_status.lastStrong != LeftToRight) { | 906 if (m_status.lastStrong != LeftToRight) { |
| 896 // the numbers need to be on a higher embedding level, so let's
close that run | 907 // the numbers need to be on a higher embedding level, so let's |
| 908 // close that run |
| 897 m_direction = EuropeanNumber; | 909 m_direction = EuropeanNumber; |
| 898 appendRun(m_runs); | 910 appendRun(m_runs); |
| 899 if (context()->dir() != LeftToRight) { | 911 if (context()->dir() != LeftToRight) { |
| 900 // the neutrals take the embedding direction, which is R | 912 // the neutrals take the embedding direction, which is R |
| 901 m_eor = m_last; | 913 m_eor = m_last; |
| 902 m_direction = RightToLeft; | 914 m_direction = RightToLeft; |
| 903 appendRun(m_runs); | 915 appendRun(m_runs); |
| 904 } | 916 } |
| 905 } | 917 } |
| 906 } else if (m_status.eor == ArabicNumber) { | 918 } else if (m_status.eor == ArabicNumber) { |
| 907 // Arabic numbers are always on a higher embedding level, so let's
close that run | 919 // Arabic numbers are always on a higher embedding level, so let's |
| 920 // close that run |
| 908 m_direction = ArabicNumber; | 921 m_direction = ArabicNumber; |
| 909 appendRun(m_runs); | 922 appendRun(m_runs); |
| 910 if (context()->dir() != LeftToRight) { | 923 if (context()->dir() != LeftToRight) { |
| 911 // the neutrals take the embedding direction, which is R | 924 // the neutrals take the embedding direction, which is R |
| 912 m_eor = m_last; | 925 m_eor = m_last; |
| 913 m_direction = RightToLeft; | 926 m_direction = RightToLeft; |
| 914 appendRun(m_runs); | 927 appendRun(m_runs); |
| 915 } | 928 } |
| 916 } else if (m_status.lastStrong != LeftToRight) { | 929 } else if (m_status.lastStrong != LeftToRight) { |
| 917 // last stuff takes embedding dir | 930 // last stuff takes embedding dir |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 if (m_status.eor == EuropeanNumber) | 1002 if (m_status.eor == EuropeanNumber) |
| 990 break; | 1003 break; |
| 991 case EuropeanNumberTerminator: | 1004 case EuropeanNumberTerminator: |
| 992 case BoundaryNeutral: | 1005 case BoundaryNeutral: |
| 993 case BlockSeparator: | 1006 case BlockSeparator: |
| 994 case SegmentSeparator: | 1007 case SegmentSeparator: |
| 995 case WhiteSpaceNeutral: | 1008 case WhiteSpaceNeutral: |
| 996 case OtherNeutral: | 1009 case OtherNeutral: |
| 997 if (m_status.eor == EuropeanNumber) { | 1010 if (m_status.eor == EuropeanNumber) { |
| 998 if (m_status.lastStrong == RightToLeft) { | 1011 if (m_status.lastStrong == RightToLeft) { |
| 999 // ENs on both sides behave like Rs, so the neutrals should be
R. | 1012 // ENs on both sides behave like Rs, so the neutrals should be |
| 1000 // Terminate the EN run. | 1013 // R. Terminate the EN run. |
| 1001 appendRun(m_runs); | 1014 appendRun(m_runs); |
| 1002 // Make an R run. | 1015 // Make an R run. |
| 1003 m_eor = m_status.last == EuropeanNumberTerminator | 1016 m_eor = m_status.last == EuropeanNumberTerminator |
| 1004 ? m_lastBeforeET | 1017 ? m_lastBeforeET |
| 1005 : m_last; | 1018 : m_last; |
| 1006 m_direction = RightToLeft; | 1019 m_direction = RightToLeft; |
| 1007 appendRun(m_runs); | 1020 appendRun(m_runs); |
| 1008 // Begin a new EN run. | 1021 // Begin a new EN run. |
| 1009 m_direction = EuropeanNumber; | 1022 m_direction = EuropeanNumber; |
| 1010 } | 1023 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 } | 1117 } |
| 1105 break; | 1118 break; |
| 1106 | 1119 |
| 1107 // boundary neutrals should be ignored | 1120 // boundary neutrals should be ignored |
| 1108 case BoundaryNeutral: | 1121 case BoundaryNeutral: |
| 1109 if (m_eor == m_last) | 1122 if (m_eor == m_last) |
| 1110 m_eor = m_current; | 1123 m_eor = m_current; |
| 1111 break; | 1124 break; |
| 1112 // neutrals | 1125 // neutrals |
| 1113 case BlockSeparator: | 1126 case BlockSeparator: |
| 1114 // ### what do we do with newline and paragraph seperators that come to
here? | 1127 // ### what do we do with newline and paragraph seperators that come to |
| 1128 // here? |
| 1115 break; | 1129 break; |
| 1116 case SegmentSeparator: | 1130 case SegmentSeparator: |
| 1117 // ### implement rule L1 | 1131 // ### implement rule L1 |
| 1118 break; | 1132 break; |
| 1119 case WhiteSpaceNeutral: | 1133 case WhiteSpaceNeutral: |
| 1120 break; | 1134 break; |
| 1121 case OtherNeutral: | 1135 case OtherNeutral: |
| 1122 break; | 1136 break; |
| 1123 default: | 1137 default: |
| 1124 break; | 1138 break; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 template <class Iterator, class Run, class IsolatedRun> | 1215 template <class Iterator, class Run, class IsolatedRun> |
| 1202 MidpointState<Iterator> | 1216 MidpointState<Iterator> |
| 1203 BidiResolver<Iterator, Run, IsolatedRun>::midpointStateForIsolatedRun( | 1217 BidiResolver<Iterator, Run, IsolatedRun>::midpointStateForIsolatedRun( |
| 1204 Run& run) { | 1218 Run& run) { |
| 1205 return m_midpointStateForIsolatedRun.take(&run); | 1219 return m_midpointStateForIsolatedRun.take(&run); |
| 1206 } | 1220 } |
| 1207 | 1221 |
| 1208 } // namespace blink | 1222 } // namespace blink |
| 1209 | 1223 |
| 1210 #endif // BidiResolver_h | 1224 #endif // BidiResolver_h |
| OLD | NEW |