Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: Source/platform/text/BidiResolver.h

Issue 119853004: Blink Unicode Bidi implementation does not support L1 rule. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Proposed patch Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/rendering/RenderBlockLineLayout.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderBlockLineLayout.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698