00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef BidiResolver_h
00023 #define BidiResolver_h
00024
00025 #include "BidiContext.h"
00026 #include <wtf/Noncopyable.h>
00027 #include <wtf/PassRefPtr.h>
00028
00029 namespace WebCore {
00030
00031
00032
00033 struct BidiStatus {
00034 BidiStatus()
00035 : eor(WTF::Unicode::OtherNeutral)
00036 , lastStrong(WTF::Unicode::OtherNeutral)
00037 , last(WTF::Unicode::OtherNeutral)
00038 {
00039 }
00040
00041 BidiStatus(WTF::Unicode::Direction eorDir, WTF::Unicode::Direction lastStrongDir, WTF::Unicode::Direction lastDir, PassRefPtr<BidiContext> bidiContext)
00042 : eor(eorDir)
00043 , lastStrong(lastStrongDir)
00044 , last(lastDir)
00045 , context(bidiContext)
00046 {
00047 }
00048
00049 WTF::Unicode::Direction eor;
00050 WTF::Unicode::Direction lastStrong;
00051 WTF::Unicode::Direction last;
00052 RefPtr<BidiContext> context;
00053 };
00054
00055 inline bool operator==(const BidiStatus& status1, const BidiStatus& status2)
00056 {
00057 return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong && *(status1.context) == *(status2.context);
00058 }
00059
00060 inline bool operator!=(const BidiStatus& status1, const BidiStatus& status2)
00061 {
00062 return !(status1 == status2);
00063 }
00064
00065 struct BidiCharacterRun {
00066 BidiCharacterRun(int start, int stop, BidiContext* context, WTF::Unicode::Direction dir)
00067 : m_start(start)
00068 , m_stop(stop)
00069 , m_override(context->override())
00070 , m_next(0)
00071 {
00072 if (dir == WTF::Unicode::OtherNeutral)
00073 dir = context->dir();
00074
00075 m_level = context->level();
00076
00077
00078 if (m_level % 2) {
00079 if (dir == WTF::Unicode::LeftToRight || dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber)
00080 m_level++;
00081 } else {
00082 if (dir == WTF::Unicode::RightToLeft)
00083 m_level++;
00084 else if (dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber)
00085 m_level += 2;
00086 }
00087 }
00088
00089 void destroy() { delete this; }
00090
00091 int start() const { return m_start; }
00092 int stop() const { return m_stop; }
00093 unsigned char level() const { return m_level; }
00094 bool reversed(bool visuallyOrdered) { return m_level % 2 && !visuallyOrdered; }
00095 bool dirOverride(bool visuallyOrdered) { return m_override || visuallyOrdered; }
00096
00097 BidiCharacterRun* next() const { return m_next; }
00098
00099 unsigned char m_level;
00100 int m_start;
00101 int m_stop;
00102 bool m_override;
00103 BidiCharacterRun* m_next;
00104 };
00105
00106 template <class Iterator, class Run> class BidiResolver : public Noncopyable {
00107 public :
00108 BidiResolver()
00109 : m_direction(WTF::Unicode::OtherNeutral)
00110 , reachedEndOfLine(false)
00111 , emptyRun(true)
00112 , m_firstRun(0)
00113 , m_lastRun(0)
00114 , m_logicallyLastRun(0)
00115 , m_runCount(0)
00116 {
00117 }
00118
00119 const Iterator& position() const { return current; }
00120 void setPosition(const Iterator& position) { current = position; }
00121
00122 void increment() { current.increment(); }
00123
00124 BidiContext* context() const { return m_status.context.get(); }
00125 void setContext(PassRefPtr<BidiContext> c) { m_status.context = c; }
00126
00127 void setLastDir(WTF::Unicode::Direction lastDir) { m_status.last = lastDir; }
00128 void setLastStrongDir(WTF::Unicode::Direction lastStrongDir) { m_status.lastStrong = lastStrongDir; }
00129 void setEorDir(WTF::Unicode::Direction eorDir) { m_status.eor = eorDir; }
00130
00131 WTF::Unicode::Direction dir() const { return m_direction; }
00132 void setDir(WTF::Unicode::Direction d) { m_direction = d; }
00133
00134 const BidiStatus& status() const { return m_status; }
00135 void setStatus(const BidiStatus s) { m_status = s; }
00136
00137 void embed(WTF::Unicode::Direction);
00138 void createBidiRunsForLine(const Iterator& end, bool visualOrder = false, bool hardLineBreak = false);
00139
00140 Run* firstRun() const { return m_firstRun; }
00141 Run* lastRun() const { return m_lastRun; }
00142 Run* logicallyLastRun() const { return m_logicallyLastRun; }
00143 unsigned runCount() const { return m_runCount; }
00144
00145 void addRun(Run*);
00146 void prependRun(Run*);
00147 void deleteRuns();
00148
00149 protected:
00150 void appendRun();
00151 void reverseRuns(unsigned start, unsigned end);
00152
00153 Iterator current;
00154 Iterator sor;
00155 Iterator eor;
00156 Iterator last;
00157 BidiStatus m_status;
00158 WTF::Unicode::Direction m_direction;
00159 Iterator endOfLine;
00160 bool reachedEndOfLine;
00161 Iterator lastBeforeET;
00162 bool emptyRun;
00163
00164 Run* m_firstRun;
00165 Run* m_lastRun;
00166 Run* m_logicallyLastRun;
00167 unsigned m_runCount;
00168 };
00169
00170 template <class Iterator, class Run>
00171 inline void BidiResolver<Iterator, Run>::addRun(Run* run)
00172 {
00173 if (!m_firstRun)
00174 m_firstRun = run;
00175 else
00176 m_lastRun->m_next = run;
00177 m_lastRun = run;
00178 m_runCount++;
00179 }
00180
00181 template <class Iterator, class Run>
00182 inline void BidiResolver<Iterator, Run>::prependRun(Run* run)
00183 {
00184 ASSERT(!run->m_next);
00185
00186 if (!m_lastRun)
00187 m_lastRun = run;
00188 else
00189 run->m_next = m_firstRun;
00190 m_firstRun = run;
00191 m_runCount++;
00192 }
00193
00194 template <class Iterator, class Run>
00195 void BidiResolver<Iterator, Run>::appendRun()
00196 {
00197 if (emptyRun || eor.atEnd())
00198 return;
00199
00200 addRun(new Run(sor.offset(), eor.offset() + 1, context(), m_direction));
00201
00202 eor.increment();
00203 sor = eor;
00204 m_direction = WTF::Unicode::OtherNeutral;
00205 m_status.eor = WTF::Unicode::OtherNeutral;
00206 }
00207
00208 template <class Iterator, class Run>
00209 void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction d)
00210 {
00211 using namespace WTF::Unicode;
00212
00213 if (d == PopDirectionalFormat) {
00214 BidiContext* c = context()->parent();
00215 if (c) {
00216 if (!emptyRun && eor != last) {
00217 ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
00218
00219 ASSERT(m_status.last == EuropeanNumberSeparator
00220 || m_status.last == EuropeanNumberTerminator
00221 || m_status.last == CommonNumberSeparator
00222 || m_status.last == BoundaryNeutral
00223 || m_status.last == BlockSeparator
00224 || m_status.last == SegmentSeparator
00225 || m_status.last == WhiteSpaceNeutral
00226 || m_status.last == OtherNeutral);
00227 if (m_direction == OtherNeutral)
00228 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
00229 if (context()->dir() == LeftToRight) {
00230
00231 if (m_status.eor == EuropeanNumber) {
00232 if (m_status.lastStrong != LeftToRight) {
00233 m_direction = EuropeanNumber;
00234 appendRun();
00235 }
00236 } else if (m_status.eor == ArabicNumber) {
00237 m_direction = ArabicNumber;
00238 appendRun();
00239 } else if (m_status.lastStrong != LeftToRight) {
00240 if (context()->dir() == RightToLeft)
00241 m_direction = RightToLeft;
00242 else {
00243 appendRun();
00244 m_direction = LeftToRight;
00245 }
00246 }
00247 } else if (m_status.eor == EuropeanNumber || m_status.eor == ArabicNumber || m_status.lastStrong == LeftToRight) {
00248 appendRun();
00249 m_direction = RightToLeft;
00250 }
00251 eor = last;
00252 }
00253 appendRun();
00254 emptyRun = true;
00255
00256 setLastDir(context()->dir());
00257 setLastStrongDir(context()->dir());
00258 setContext(c);
00259 eor = Iterator();
00260 }
00261 } else {
00262 Direction runDir;
00263 if (d == RightToLeftEmbedding || d == RightToLeftOverride)
00264 runDir = RightToLeft;
00265 else
00266 runDir = LeftToRight;
00267 bool override = d == LeftToRightOverride || d == RightToLeftOverride;
00268
00269 unsigned char level = context()->level();
00270 if (runDir == RightToLeft) {
00271 if (level % 2)
00272 level += 2;
00273 else
00274 level++;
00275 } else {
00276 if (level % 2)
00277 level++;
00278 else
00279 level += 2;
00280 }
00281
00282 if (level < 61) {
00283 if (!emptyRun && eor != last) {
00284 ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
00285
00286 ASSERT(m_status.last == EuropeanNumberSeparator
00287 || m_status.last == EuropeanNumberTerminator
00288 || m_status.last == CommonNumberSeparator
00289 || m_status.last == BoundaryNeutral
00290 || m_status.last == BlockSeparator
00291 || m_status.last == SegmentSeparator
00292 || m_status.last == WhiteSpaceNeutral
00293 || m_status.last == OtherNeutral);
00294 if (m_direction == OtherNeutral)
00295 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
00296 if (runDir == LeftToRight) {
00297
00298 if (m_status.eor == EuropeanNumber) {
00299 if (m_status.lastStrong != LeftToRight) {
00300 m_direction = EuropeanNumber;
00301 appendRun();
00302 }
00303 } else if (m_status.eor == ArabicNumber) {
00304 m_direction = ArabicNumber;
00305 appendRun();
00306 } else if (m_status.lastStrong != LeftToRight && context()->dir() == LeftToRight) {
00307 appendRun();
00308 m_direction = LeftToRight;
00309 }
00310 } else if (m_status.eor == ArabicNumber
00311 || m_status.eor == EuropeanNumber && (m_status.lastStrong != LeftToRight || context()->dir() == RightToLeft)
00312 || m_status.eor != EuropeanNumber && m_status.lastStrong == LeftToRight && context()->dir() == RightToLeft) {
00313 appendRun();
00314 m_direction = RightToLeft;
00315 }
00316 eor = last;
00317 }
00318 appendRun();
00319 emptyRun = true;
00320 setContext(new BidiContext(level, runDir, override, context()));
00321 setLastDir(runDir);
00322 setLastStrongDir(runDir);
00323 eor = Iterator();
00324 }
00325 }
00326 }
00327
00328 template <class Iterator, class Run>
00329 void BidiResolver<Iterator, Run>::deleteRuns()
00330 {
00331 emptyRun = true;
00332 if (!m_firstRun)
00333 return;
00334
00335 Run* curr = m_firstRun;
00336 while (curr) {
00337 Run* s = curr->next();
00338 curr->destroy();
00339 curr = s;
00340 }
00341
00342 m_firstRun = 0;
00343 m_lastRun = 0;
00344 m_runCount = 0;
00345 }
00346
00347 template <class Iterator, class Run>
00348 void BidiResolver<Iterator, Run>::reverseRuns(unsigned start, unsigned end)
00349 {
00350 if (start >= end)
00351 return;
00352
00353 ASSERT(end < m_runCount);
00354
00355
00356
00357 Run* curr = m_firstRun;
00358 Run* beforeStart = 0;
00359 unsigned i = 0;
00360 while (i < start) {
00361 i++;
00362 beforeStart = curr;
00363 curr = curr->next();
00364 }
00365
00366 Run* startRun = curr;
00367 while (i < end) {
00368 i++;
00369 curr = curr->next();
00370 }
00371 Run* endRun = curr;
00372 Run* afterEnd = curr->next();
00373
00374 i = start;
00375 curr = startRun;
00376 Run* newNext = afterEnd;
00377 while (i <= end) {
00378
00379 Run* next = curr->next();
00380 curr->m_next = newNext;
00381 newNext = curr;
00382 curr = next;
00383 i++;
00384 }
00385
00386
00387 if (beforeStart)
00388 beforeStart->m_next = endRun;
00389 else
00390 m_firstRun = endRun;
00391
00392 startRun->m_next = afterEnd;
00393 if (!afterEnd)
00394 m_lastRun = startRun;
00395 }
00396
00397 template <class Iterator, class Run>
00398 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, bool visualOrder, bool hardLineBreak)
00399 {
00400 using namespace WTF::Unicode;
00401
00402 ASSERT(m_direction == OtherNeutral);
00403
00404 emptyRun = true;
00405
00406 eor = Iterator();
00407
00408 last = current;
00409 bool pastEnd = false;
00410 BidiResolver<Iterator, Run> stateAtEnd;
00411
00412 while (true) {
00413 Direction dirCurrent;
00414 if (pastEnd && (hardLineBreak || current.atEnd())) {
00415 BidiContext* c = context();
00416 while (c->parent())
00417 c = c->parent();
00418 dirCurrent = c->dir();
00419 if (hardLineBreak) {
00420
00421
00422 stateAtEnd.setContext(c);
00423 stateAtEnd.setEorDir(dirCurrent);
00424 stateAtEnd.setLastDir(dirCurrent);
00425 stateAtEnd.setLastStrongDir(dirCurrent);
00426 }
00427 } else {
00428 dirCurrent = current.direction();
00429 if (context()->override()
00430 && dirCurrent != RightToLeftEmbedding
00431 && dirCurrent != LeftToRightEmbedding
00432 && dirCurrent != RightToLeftOverride
00433 && dirCurrent != LeftToRightOverride
00434 && dirCurrent != PopDirectionalFormat)
00435 dirCurrent = context()->dir();
00436 else if (dirCurrent == NonSpacingMark)
00437 dirCurrent = m_status.last;
00438 }
00439
00440 ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
00441 switch (dirCurrent) {
00442
00443
00444 case RightToLeftEmbedding:
00445 case LeftToRightEmbedding:
00446 case RightToLeftOverride:
00447 case LeftToRightOverride:
00448 case PopDirectionalFormat:
00449 embed(dirCurrent);
00450 break;
00451
00452
00453 case LeftToRight:
00454 switch(m_status.last) {
00455 case RightToLeft:
00456 case RightToLeftArabic:
00457 case EuropeanNumber:
00458 case ArabicNumber:
00459 if (m_status.last != EuropeanNumber || m_status.lastStrong != LeftToRight)
00460 appendRun();
00461 break;
00462 case LeftToRight:
00463 break;
00464 case EuropeanNumberSeparator:
00465 case EuropeanNumberTerminator:
00466 case CommonNumberSeparator:
00467 case BoundaryNeutral:
00468 case BlockSeparator:
00469 case SegmentSeparator:
00470 case WhiteSpaceNeutral:
00471 case OtherNeutral:
00472 if (m_status.eor == EuropeanNumber) {
00473 if (m_status.lastStrong != LeftToRight) {
00474
00475 m_direction = EuropeanNumber;
00476 appendRun();
00477 if (context()->dir() != LeftToRight) {
00478
00479 eor = last;
00480 m_direction = RightToLeft;
00481 appendRun();
00482 }
00483 }
00484 } else if (m_status.eor == ArabicNumber) {
00485
00486 m_direction = ArabicNumber;
00487 appendRun();
00488 if (context()->dir() != LeftToRight) {
00489
00490 eor = last;
00491 m_direction = RightToLeft;
00492 appendRun();
00493 }
00494 } else if (m_status.lastStrong != LeftToRight) {
00495
00496 if (context()->dir() == RightToLeft) {
00497 eor = last;
00498 m_direction = RightToLeft;
00499 }
00500 appendRun();
00501 }
00502 default:
00503 break;
00504 }
00505 eor = current;
00506 m_status.eor = LeftToRight;
00507 m_status.lastStrong = LeftToRight;
00508 m_direction = LeftToRight;
00509 break;
00510 case RightToLeftArabic:
00511 case RightToLeft:
00512 switch (m_status.last) {
00513 case LeftToRight:
00514 case EuropeanNumber:
00515 case ArabicNumber:
00516 appendRun();
00517 case RightToLeft:
00518 case RightToLeftArabic:
00519 break;
00520 case EuropeanNumberSeparator:
00521 case EuropeanNumberTerminator:
00522 case CommonNumberSeparator:
00523 case BoundaryNeutral:
00524 case BlockSeparator:
00525 case SegmentSeparator:
00526 case WhiteSpaceNeutral:
00527 case OtherNeutral:
00528 if (m_status.eor == EuropeanNumber) {
00529 if (m_status.lastStrong == LeftToRight && context()->dir() == LeftToRight)
00530 eor = last;
00531 appendRun();
00532 } else if (m_status.eor == ArabicNumber)
00533 appendRun();
00534 else if (m_status.lastStrong == LeftToRight) {
00535 if (context()->dir() == LeftToRight)
00536 eor = last;
00537 appendRun();
00538 }
00539 default:
00540 break;
00541 }
00542 eor = current;
00543 m_status.eor = RightToLeft;
00544 m_status.lastStrong = dirCurrent;
00545 m_direction = RightToLeft;
00546 break;
00547
00548
00549
00550 case EuropeanNumber:
00551 if (m_status.lastStrong != RightToLeftArabic) {
00552
00553 switch (m_status.last) {
00554 case EuropeanNumber:
00555 case LeftToRight:
00556 break;
00557 case RightToLeft:
00558 case RightToLeftArabic:
00559 case ArabicNumber:
00560 eor = last;
00561 appendRun();
00562 m_direction = EuropeanNumber;
00563 break;
00564 case EuropeanNumberSeparator:
00565 case CommonNumberSeparator:
00566 if (m_status.eor == EuropeanNumber)
00567 break;
00568 case EuropeanNumberTerminator:
00569 case BoundaryNeutral:
00570 case BlockSeparator:
00571 case SegmentSeparator:
00572 case WhiteSpaceNeutral:
00573 case OtherNeutral:
00574 if (m_status.eor == EuropeanNumber) {
00575 if (m_status.lastStrong == RightToLeft) {
00576
00577
00578 appendRun();
00579
00580 eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
00581 m_direction = RightToLeft;
00582 appendRun();
00583
00584 m_direction = EuropeanNumber;
00585 }
00586 } else if (m_status.eor == ArabicNumber) {
00587
00588 appendRun();
00589 if (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft) {
00590
00591 eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
00592 m_direction = RightToLeft;
00593 appendRun();
00594
00595 m_direction = EuropeanNumber;
00596 }
00597 } else if (m_status.lastStrong == RightToLeft) {
00598
00599 eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last;
00600 m_direction = RightToLeft;
00601 appendRun();
00602
00603 m_direction = EuropeanNumber;
00604 }
00605 default:
00606 break;
00607 }
00608 eor = current;
00609 m_status.eor = EuropeanNumber;
00610 if (m_direction == OtherNeutral)
00611 m_direction = LeftToRight;
00612 break;
00613 }
00614 case ArabicNumber:
00615 dirCurrent = ArabicNumber;
00616 switch (m_status.last) {
00617 case LeftToRight:
00618 if (context()->dir() == LeftToRight)
00619 appendRun();
00620 break;
00621 case ArabicNumber:
00622 break;
00623 case RightToLeft:
00624 case RightToLeftArabic:
00625 case EuropeanNumber:
00626 eor = last;
00627 appendRun();
00628 break;
00629 case CommonNumberSeparator:
00630 if (m_status.eor == ArabicNumber)
00631 break;
00632 case EuropeanNumberSeparator:
00633 case EuropeanNumberTerminator:
00634 case BoundaryNeutral:
00635 case BlockSeparator:
00636 case SegmentSeparator:
00637 case WhiteSpaceNeutral:
00638 case OtherNeutral:
00639 if (m_status.eor == ArabicNumber
00640 || m_status.eor == EuropeanNumber && (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft)
00641 || m_status.eor != EuropeanNumber && m_status.lastStrong == LeftToRight && context()->dir() == RightToLeft) {
00642
00643 appendRun();
00644
00645 m_direction = RightToLeft;
00646 } else if (m_direction == OtherNeutral)
00647 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
00648 eor = last;
00649 appendRun();
00650 default:
00651 break;
00652 }
00653 eor = current;
00654 m_status.eor = ArabicNumber;
00655 if (m_direction == OtherNeutral)
00656 m_direction = ArabicNumber;
00657 break;
00658 case EuropeanNumberSeparator:
00659 case CommonNumberSeparator:
00660 break;
00661 case EuropeanNumberTerminator:
00662 if (m_status.last == EuropeanNumber) {
00663 dirCurrent = EuropeanNumber;
00664 eor = current;
00665 m_status.eor = dirCurrent;
00666 } else if (m_status.last != EuropeanNumberTerminator)
00667 lastBeforeET = emptyRun ? eor : last;
00668 break;
00669
00670
00671 case BoundaryNeutral:
00672 if (eor == last)
00673 eor = current;
00674 break;
00675
00676 case BlockSeparator:
00677
00678 break;
00679 case SegmentSeparator:
00680
00681 break;
00682 case WhiteSpaceNeutral:
00683 break;
00684 case OtherNeutral:
00685 break;
00686 default:
00687 break;
00688 }
00689
00690 if (pastEnd) {
00691 if (eor == current) {
00692 if (!reachedEndOfLine) {
00693 eor = endOfLine;
00694 switch (m_status.eor) {
00695 case LeftToRight:
00696 case RightToLeft:
00697 case ArabicNumber:
00698 m_direction = m_status.eor;
00699 break;
00700 case EuropeanNumber:
00701 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : EuropeanNumber;
00702 break;
00703 default:
00704 ASSERT(false);
00705 }
00706 appendRun();
00707 }
00708 current = end;
00709 m_status = stateAtEnd.m_status;
00710 sor = stateAtEnd.sor;
00711 eor = stateAtEnd.eor;
00712 last = stateAtEnd.last;
00713 reachedEndOfLine = stateAtEnd.reachedEndOfLine;
00714 lastBeforeET = stateAtEnd.lastBeforeET;
00715 emptyRun = stateAtEnd.emptyRun;
00716 m_direction = OtherNeutral;
00717 break;
00718 }
00719 }
00720
00721
00722 switch (dirCurrent) {
00723 case EuropeanNumberTerminator:
00724 if (m_status.last != EuropeanNumber)
00725 m_status.last = EuropeanNumberTerminator;
00726 break;
00727 case EuropeanNumberSeparator:
00728 case CommonNumberSeparator:
00729 case SegmentSeparator:
00730 case WhiteSpaceNeutral:
00731 case OtherNeutral:
00732 switch(m_status.last) {
00733 case LeftToRight:
00734 case RightToLeft:
00735 case RightToLeftArabic:
00736 case EuropeanNumber:
00737 case ArabicNumber:
00738 m_status.last = dirCurrent;
00739 break;
00740 default:
00741 m_status.last = OtherNeutral;
00742 }
00743 break;
00744 case NonSpacingMark:
00745 case BoundaryNeutral:
00746 case RightToLeftEmbedding:
00747 case LeftToRightEmbedding:
00748 case RightToLeftOverride:
00749 case LeftToRightOverride:
00750 case PopDirectionalFormat:
00751
00752 break;
00753 case EuropeanNumber:
00754
00755 default:
00756 m_status.last = dirCurrent;
00757 }
00758
00759 last = current;
00760
00761 if (emptyRun && !(dirCurrent == RightToLeftEmbedding
00762 || dirCurrent == LeftToRightEmbedding
00763 || dirCurrent == RightToLeftOverride
00764 || dirCurrent == LeftToRightOverride
00765 || dirCurrent == PopDirectionalFormat)) {
00766 sor = current;
00767 emptyRun = false;
00768 }
00769
00770 increment();
00771 if (emptyRun && (dirCurrent == RightToLeftEmbedding
00772 || dirCurrent == LeftToRightEmbedding
00773 || dirCurrent == RightToLeftOverride
00774 || dirCurrent == LeftToRightOverride
00775 || dirCurrent == PopDirectionalFormat)) {
00776
00777 eor = Iterator();
00778 last = current;
00779 sor = current;
00780 }
00781
00782 if (!pastEnd && (current == end || current.atEnd())) {
00783 if (emptyRun)
00784 break;
00785 stateAtEnd.m_status = m_status;
00786 stateAtEnd.sor = sor;
00787 stateAtEnd.eor = eor;
00788 stateAtEnd.last = last;
00789 stateAtEnd.reachedEndOfLine = reachedEndOfLine;
00790 stateAtEnd.lastBeforeET = lastBeforeET;
00791 stateAtEnd.emptyRun = emptyRun;
00792 endOfLine = last;
00793 pastEnd = true;
00794 }
00795 }
00796
00797 m_logicallyLastRun = m_lastRun;
00798
00799
00800
00801 if (!visualOrder) {
00802
00803
00804 unsigned char levelLow = 128;
00805 unsigned char levelHigh = 0;
00806 Run* r = firstRun();
00807 while (r) {
00808 if (r->m_level > levelHigh)
00809 levelHigh = r->m_level;
00810 if (r->m_level < levelLow)
00811 levelLow = r->m_level;
00812 r = r->next();
00813 }
00814
00815
00816
00817
00818
00819
00820 if (!(levelLow % 2))
00821 levelLow++;
00822
00823 unsigned count = runCount() - 1;
00824
00825 while (levelHigh >= levelLow) {
00826 unsigned i = 0;
00827 Run* currRun = firstRun();
00828 while (i < count) {
00829 while (i < count && currRun && currRun->m_level < levelHigh) {
00830 i++;
00831 currRun = currRun->next();
00832 }
00833 unsigned start = i;
00834 while (i <= count && currRun && currRun->m_level >= levelHigh) {
00835 i++;
00836 currRun = currRun->next();
00837 }
00838 unsigned end = i - 1;
00839 reverseRuns(start, end);
00840 }
00841 levelHigh--;
00842 }
00843 }
00844 endOfLine = Iterator();
00845 }
00846
00847 }
00848
00849 #endif // BidiResolver_h