Chromium Code Reviews| 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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 // BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm | 165 // BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm |
| 166 // http://unicode.org/reports/tr9 | 166 // http://unicode.org/reports/tr9 |
| 167 template <class Iterator, class Run> class BidiResolver { | 167 template <class Iterator, class Run> class BidiResolver { |
| 168 WTF_MAKE_NONCOPYABLE(BidiResolver); | 168 WTF_MAKE_NONCOPYABLE(BidiResolver); |
| 169 public: | 169 public: |
| 170 BidiResolver() | 170 BidiResolver() |
| 171 : m_direction(WTF::Unicode::OtherNeutral) | 171 : m_direction(WTF::Unicode::OtherNeutral) |
| 172 , m_reachedEndOfLine(false) | 172 , m_reachedEndOfLine(false) |
| 173 , m_emptyRun(true) | 173 , m_emptyRun(true) |
| 174 , m_nestedIsolateCount(0) | 174 , m_nestedIsolateCount(0) |
| 175 , m_trailingSpaceRun(0) | |
| 175 { | 176 { |
| 176 } | 177 } |
| 177 | 178 |
| 178 #ifndef NDEBUG | 179 #ifndef NDEBUG |
| 179 ~BidiResolver(); | 180 ~BidiResolver(); |
| 180 #endif | 181 #endif |
| 181 | 182 |
| 182 const Iterator& position() const { return m_current; } | 183 const Iterator& position() const { return m_current; } |
| 183 Iterator& position() { return m_current; } | 184 Iterator& position() { return m_current; } |
| 184 void setPositionIgnoringNestedIsolates(const Iterator& position) { m_current = position; } | 185 void setPositionIgnoringNestedIsolates(const Iterator& position) { m_current = position; } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 196 void setEorDir(WTF::Unicode::Direction eorDir) { m_status.eor = eorDir; } | 197 void setEorDir(WTF::Unicode::Direction eorDir) { m_status.eor = eorDir; } |
| 197 | 198 |
| 198 WTF::Unicode::Direction dir() const { return m_direction; } | 199 WTF::Unicode::Direction dir() const { return m_direction; } |
| 199 void setDir(WTF::Unicode::Direction d) { m_direction = d; } | 200 void setDir(WTF::Unicode::Direction d) { m_direction = d; } |
| 200 | 201 |
| 201 const BidiStatus& status() const { return m_status; } | 202 const BidiStatus& status() const { return m_status; } |
| 202 void setStatus(const BidiStatus s) | 203 void setStatus(const BidiStatus s) |
| 203 { | 204 { |
| 204 ASSERT(s.context); | 205 ASSERT(s.context); |
| 205 m_status = s; | 206 m_status = s; |
| 207 m_paragraphDirectionality = s.context->dir() == WTF::Unicode::LeftToRigh t ? LTR : RTL; | |
| 206 } | 208 } |
| 207 | 209 |
| 208 MidpointState<Iterator>& midpointState() { return m_midpointState; } | 210 MidpointState<Iterator>& midpointState() { return m_midpointState; } |
| 209 | 211 |
| 210 // The current algorithm handles nested isolates one layer of nesting at a t ime. | 212 // The current algorithm handles nested isolates one layer of nesting at a t ime. |
| 211 // But when we layout each isolated span, we will walk into (and ignore) all | 213 // But when we layout each isolated span, we will walk into (and ignore) all |
| 212 // child isolated spans. | 214 // child isolated spans. |
| 213 void enterIsolate() { m_nestedIsolateCount++; } | 215 void enterIsolate() { m_nestedIsolateCount++; } |
| 214 void exitIsolate() { ASSERT(m_nestedIsolateCount >= 1); m_nestedIsolateCount --; } | 216 void exitIsolate() { ASSERT(m_nestedIsolateCount >= 1); m_nestedIsolateCount --; } |
| 215 bool inIsolate() const { return m_nestedIsolateCount; } | 217 bool inIsolate() const { return m_nestedIsolateCount; } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 229 | 231 |
| 230 bool isEndOfLine(const Iterator& end) { return m_current == end || m_current .atEnd(); } | 232 bool isEndOfLine(const Iterator& end) { return m_current == end || m_current .atEnd(); } |
| 231 | 233 |
| 232 TextDirection determineParagraphDirectionality(bool* hasStrongDirectionality = 0); | 234 TextDirection determineParagraphDirectionality(bool* hasStrongDirectionality = 0); |
| 233 | 235 |
| 234 void setMidpointStateForIsolatedRun(Run*, const MidpointState<Iterator>&); | 236 void setMidpointStateForIsolatedRun(Run*, const MidpointState<Iterator>&); |
| 235 MidpointState<Iterator> midpointStateForIsolatedRun(Run*); | 237 MidpointState<Iterator> midpointStateForIsolatedRun(Run*); |
| 236 | 238 |
| 237 Iterator endOfLine() const { return m_endOfLine; } | 239 Iterator endOfLine() const { return m_endOfLine; } |
| 238 | 240 |
| 241 Run* trailingSpaceRun() const { return m_trailingSpaceRun; } | |
| 242 | |
| 239 protected: | 243 protected: |
| 240 void increment() { m_current.increment(); } | 244 void increment() { m_current.increment(); } |
| 241 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should | 245 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should |
| 242 // pass in some sort of Traits object which knows how to create runs for app ending. | 246 // pass in some sort of Traits object which knows how to create runs for app ending. |
| 243 void appendRun(); | 247 void appendRun(); |
| 244 | 248 |
| 249 Run* addTrailingRun(int, int, Run*, BidiContext*, TextDirection) { return 0; } | |
| 245 Iterator m_current; | 250 Iterator m_current; |
| 246 // sor and eor are "start of run" and "end of run" respectively and correpon d | 251 // sor and eor are "start of run" and "end of run" respectively and correpon d |
| 247 // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7 | 252 // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7 |
| 248 Iterator m_sor; // Points to the first character in the current run. | 253 Iterator m_sor; // Points to the first character in the current run. |
| 249 Iterator m_eor; // Points to the last character in the current run. | 254 Iterator m_eor; // Points to the last character in the current run. |
| 250 Iterator m_last; | 255 Iterator m_last; |
| 251 BidiStatus m_status; | 256 BidiStatus m_status; |
| 252 WTF::Unicode::Direction m_direction; | 257 WTF::Unicode::Direction m_direction; |
| 253 // m_endOfRunAtEndOfLine is "the position last eor in the end of line" | 258 // m_endOfRunAtEndOfLine is "the position last eor in the end of line" |
| 254 Iterator m_endOfRunAtEndOfLine; | 259 Iterator m_endOfRunAtEndOfLine; |
| 255 Iterator m_endOfLine; | 260 Iterator m_endOfLine; |
| 256 bool m_reachedEndOfLine; | 261 bool m_reachedEndOfLine; |
| 257 Iterator m_lastBeforeET; // Before a EuropeanNumberTerminator | 262 Iterator m_lastBeforeET; // Before a EuropeanNumberTerminator |
| 258 bool m_emptyRun; | 263 bool m_emptyRun; |
| 259 | 264 |
| 260 // FIXME: This should not belong to the resolver, but rather be passed | 265 // FIXME: This should not belong to the resolver, but rather be passed |
| 261 // into createBidiRunsForLine by the caller. | 266 // into createBidiRunsForLine by the caller. |
| 262 BidiRunList<Run> m_runs; | 267 BidiRunList<Run> m_runs; |
| 263 | 268 |
| 264 MidpointState<Iterator> m_midpointState; | 269 MidpointState<Iterator> m_midpointState; |
| 265 | 270 |
| 266 unsigned m_nestedIsolateCount; | 271 unsigned m_nestedIsolateCount; |
| 267 Vector<Run*> m_isolatedRuns; | 272 Vector<Run*> m_isolatedRuns; |
| 273 Run* m_trailingSpaceRun; | |
| 274 TextDirection m_paragraphDirectionality; | |
| 268 | 275 |
| 269 private: | 276 private: |
| 270 void raiseExplicitEmbeddingLevel(WTF::Unicode::Direction from, WTF::Unicode: :Direction to); | 277 void raiseExplicitEmbeddingLevel(WTF::Unicode::Direction from, WTF::Unicode: :Direction to); |
| 271 void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from); | 278 void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from); |
| 272 void checkDirectionInLowerRaiseEmbeddingLevel(); | 279 void checkDirectionInLowerRaiseEmbeddingLevel(); |
| 273 | 280 |
| 274 void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); | 281 void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); |
| 275 void reorderRunsFromLevels(); | 282 void reorderRunsFromLevels(); |
| 276 | 283 |
| 284 bool needsToApplyL1Rule() { return false; } | |
| 285 int findFirstTrailingSpaceAtRun(Run*) { return 0; } | |
| 286 void applyL1Rule(); | |
|
leviw_travelin_and_unemployed
2014/01/06 21:46:18
Can you add a link to the L1 rule here, as well?
| |
| 287 | |
| 277 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; | 288 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; |
| 278 HashMap<Run *, MidpointState<Iterator> > m_midpointStateForIsolatedRun; | 289 HashMap<Run *, MidpointState<Iterator> > m_midpointStateForIsolatedRun; |
| 279 }; | 290 }; |
| 280 | 291 |
| 281 #ifndef NDEBUG | 292 #ifndef NDEBUG |
| 282 template <class Iterator, class Run> | 293 template <class Iterator, class Run> |
| 283 BidiResolver<Iterator, Run>::~BidiResolver() | 294 BidiResolver<Iterator, Run>::~BidiResolver() |
| 284 { | 295 { |
| 285 // The owner of this resolver should have handled the isolated runs. | 296 // The owner of this resolver should have handled the isolated runs. |
| 286 ASSERT(m_isolatedRuns.isEmpty()); | 297 ASSERT(m_isolatedRuns.isEmpty()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 | 421 |
| 411 appendRun(); | 422 appendRun(); |
| 412 m_emptyRun = true; | 423 m_emptyRun = true; |
| 413 | 424 |
| 414 setLastDir(to); | 425 setLastDir(to); |
| 415 setLastStrongDir(to); | 426 setLastStrongDir(to); |
| 416 m_eor = Iterator(); | 427 m_eor = Iterator(); |
| 417 } | 428 } |
| 418 | 429 |
| 419 template <class Iterator, class Run> | 430 template <class Iterator, class Run> |
| 431 void BidiResolver<Iterator, Run>::applyL1Rule() | |
| 432 { | |
| 433 ASSERT(m_runs.runCount()); | |
| 434 if (!needsToApplyL1Rule()) | |
| 435 return; | |
| 436 | |
| 437 Run* trailingSpaceRun = m_runs.logicallyLastRun(); | |
| 438 | |
| 439 int firstSpace = findFirstTrailingSpaceAtRun(trailingSpaceRun); | |
| 440 if (firstSpace == trailingSpaceRun->stop()) | |
| 441 return; | |
| 442 | |
| 443 bool shouldReorder = trailingSpaceRun != (m_paragraphDirectionality == LTR ? m_runs.lastRun() : m_runs.firstRun()); | |
| 444 if (firstSpace != trailingSpaceRun->start()) { | |
| 445 BidiContext* baseContext = context(); | |
| 446 while (BidiContext* parent = baseContext->parent()) | |
| 447 baseContext = parent; | |
| 448 | |
| 449 m_trailingSpaceRun = addTrailingRun(firstSpace, trailingSpaceRun->m_stop , trailingSpaceRun, baseContext, m_paragraphDirectionality); | |
| 450 ASSERT(m_trailingSpaceRun); | |
| 451 trailingSpaceRun->m_stop = firstSpace; | |
| 452 return; | |
| 453 } | |
| 454 if (!shouldReorder) { | |
| 455 m_trailingSpaceRun = trailingSpaceRun; | |
| 456 return; | |
| 457 } | |
| 458 | |
| 459 if (m_paragraphDirectionality == LTR) { | |
| 460 m_runs.moveRunToEnd(trailingSpaceRun); | |
| 461 trailingSpaceRun->m_level = 0; | |
| 462 } else { | |
| 463 m_runs.moveRunToBeginning(trailingSpaceRun); | |
| 464 trailingSpaceRun->m_level = 1; | |
| 465 } | |
| 466 m_trailingSpaceRun = trailingSpaceRun; | |
| 467 } | |
| 468 | |
| 469 template <class Iterator, class Run> | |
| 420 bool BidiResolver<Iterator, Run>::commitExplicitEmbedding() | 470 bool BidiResolver<Iterator, Run>::commitExplicitEmbedding() |
| 421 { | 471 { |
| 422 // When we're "inIsolate()" we're resolving the parent context which | 472 // When we're "inIsolate()" we're resolving the parent context which |
| 423 // ignores (skips over) the isolated content, including embedding levels. | 473 // ignores (skips over) the isolated content, including embedding levels. |
| 424 // We should never accrue embedding levels while skipping over isolated cont ent. | 474 // We should never accrue embedding levels while skipping over isolated cont ent. |
| 425 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); | 475 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); |
| 426 | 476 |
| 427 using namespace WTF::Unicode; | 477 using namespace WTF::Unicode; |
| 428 | 478 |
| 429 unsigned char fromLevel = context()->level(); | 479 unsigned char fromLevel = context()->level(); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 *hasStrongDirectionality = false; | 632 *hasStrongDirectionality = false; |
| 583 return LTR; | 633 return LTR; |
| 584 } | 634 } |
| 585 | 635 |
| 586 template <class Iterator, class Run> | 636 template <class Iterator, class Run> |
| 587 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis ualDirectionOverride override, bool hardLineBreak) | 637 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis ualDirectionOverride override, bool hardLineBreak) |
| 588 { | 638 { |
| 589 using namespace WTF::Unicode; | 639 using namespace WTF::Unicode; |
| 590 | 640 |
| 591 ASSERT(m_direction == OtherNeutral); | 641 ASSERT(m_direction == OtherNeutral); |
| 642 m_trailingSpaceRun = 0; | |
| 592 | 643 |
| 593 m_endOfLine = end; | 644 m_endOfLine = end; |
| 594 | 645 |
| 595 if (override != NoVisualOverride) { | 646 if (override != NoVisualOverride) { |
| 596 m_emptyRun = false; | 647 m_emptyRun = false; |
| 597 m_sor = m_current; | 648 m_sor = m_current; |
| 598 m_eor = Iterator(); | 649 m_eor = Iterator(); |
| 599 while (m_current != end && !m_current.atEnd()) { | 650 while (m_current != end && !m_current.atEnd()) { |
| 600 m_eor = m_current; | 651 m_eor = m_current; |
| 601 increment(); | 652 increment(); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 m_direction = OtherNeutral; | 1029 m_direction = OtherNeutral; |
| 979 break; | 1030 break; |
| 980 } | 1031 } |
| 981 } | 1032 } |
| 982 } | 1033 } |
| 983 | 1034 |
| 984 m_runs.setLogicallyLastRun(m_runs.lastRun()); | 1035 m_runs.setLogicallyLastRun(m_runs.lastRun()); |
| 985 reorderRunsFromLevels(); | 1036 reorderRunsFromLevels(); |
| 986 m_endOfRunAtEndOfLine = Iterator(); | 1037 m_endOfRunAtEndOfLine = Iterator(); |
| 987 m_endOfLine = Iterator(); | 1038 m_endOfLine = Iterator(); |
| 1039 | |
| 1040 if (!hardLineBreak && m_runs.runCount()) | |
| 1041 applyL1Rule(); | |
| 988 } | 1042 } |
| 989 | 1043 |
| 990 template <class Iterator, class Run> | 1044 template <class Iterator, class Run> |
| 991 void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint) | 1045 void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint) |
| 992 { | 1046 { |
| 993 ASSERT(!m_midpointStateForIsolatedRun.contains(run)); | 1047 ASSERT(!m_midpointStateForIsolatedRun.contains(run)); |
| 994 m_midpointStateForIsolatedRun.add(run, midpoint); | 1048 m_midpointStateForIsolatedRun.add(run, midpoint); |
| 995 } | 1049 } |
| 996 | 1050 |
| 997 template<class Iterator, class Run> | 1051 template<class Iterator, class Run> |
| 998 MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun (Run* run) | 1052 MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun (Run* run) |
| 999 { | 1053 { |
| 1000 return m_midpointStateForIsolatedRun.take(run); | 1054 return m_midpointStateForIsolatedRun.take(run); |
| 1001 } | 1055 } |
| 1002 | 1056 |
| 1003 | 1057 |
| 1004 } // namespace WebCore | 1058 } // namespace WebCore |
| 1005 | 1059 |
| 1006 #endif // BidiResolver_h | 1060 #endif // BidiResolver_h |
| OLD | NEW |