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 |