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

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: Patch for landing 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 // http://www.unicode.org/reports/tr9/#L1
287 void applyL1Rule();
288
277 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; 289 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence;
278 HashMap<Run *, MidpointState<Iterator> > m_midpointStateForIsolatedRun; 290 HashMap<Run *, MidpointState<Iterator> > m_midpointStateForIsolatedRun;
279 }; 291 };
280 292
281 #ifndef NDEBUG 293 #ifndef NDEBUG
282 template <class Iterator, class Run> 294 template <class Iterator, class Run>
283 BidiResolver<Iterator, Run>::~BidiResolver() 295 BidiResolver<Iterator, Run>::~BidiResolver()
284 { 296 {
285 // The owner of this resolver should have handled the isolated runs. 297 // The owner of this resolver should have handled the isolated runs.
286 ASSERT(m_isolatedRuns.isEmpty()); 298 ASSERT(m_isolatedRuns.isEmpty());
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 422
411 appendRun(); 423 appendRun();
412 m_emptyRun = true; 424 m_emptyRun = true;
413 425
414 setLastDir(to); 426 setLastDir(to);
415 setLastStrongDir(to); 427 setLastStrongDir(to);
416 m_eor = Iterator(); 428 m_eor = Iterator();
417 } 429 }
418 430
419 template <class Iterator, class Run> 431 template <class Iterator, class Run>
432 void BidiResolver<Iterator, Run>::applyL1Rule()
433 {
434 ASSERT(m_runs.runCount());
435 if (!needsToApplyL1Rule())
436 return;
437
438 Run* trailingSpaceRun = m_runs.logicallyLastRun();
439
440 int firstSpace = findFirstTrailingSpaceAtRun(trailingSpaceRun);
441 if (firstSpace == trailingSpaceRun->stop())
442 return;
443
444 bool shouldReorder = trailingSpaceRun != (m_paragraphDirectionality == LTR ? m_runs.lastRun() : m_runs.firstRun());
445 if (firstSpace != trailingSpaceRun->start()) {
446 BidiContext* baseContext = context();
447 while (BidiContext* parent = baseContext->parent())
448 baseContext = parent;
449
450 m_trailingSpaceRun = addTrailingRun(firstSpace, trailingSpaceRun->m_stop , trailingSpaceRun, baseContext, m_paragraphDirectionality);
451 ASSERT(m_trailingSpaceRun);
452 trailingSpaceRun->m_stop = firstSpace;
453 return;
454 }
455 if (!shouldReorder) {
456 m_trailingSpaceRun = trailingSpaceRun;
457 return;
458 }
459
460 if (m_paragraphDirectionality == LTR) {
461 m_runs.moveRunToEnd(trailingSpaceRun);
462 trailingSpaceRun->m_level = 0;
463 } else {
464 m_runs.moveRunToBeginning(trailingSpaceRun);
465 trailingSpaceRun->m_level = 1;
466 }
467 m_trailingSpaceRun = trailingSpaceRun;
468 }
469
470 template <class Iterator, class Run>
420 bool BidiResolver<Iterator, Run>::commitExplicitEmbedding() 471 bool BidiResolver<Iterator, Run>::commitExplicitEmbedding()
421 { 472 {
422 // When we're "inIsolate()" we're resolving the parent context which 473 // When we're "inIsolate()" we're resolving the parent context which
423 // ignores (skips over) the isolated content, including embedding levels. 474 // ignores (skips over) the isolated content, including embedding levels.
424 // We should never accrue embedding levels while skipping over isolated cont ent. 475 // We should never accrue embedding levels while skipping over isolated cont ent.
425 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); 476 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty());
426 477
427 using namespace WTF::Unicode; 478 using namespace WTF::Unicode;
428 479
429 unsigned char fromLevel = context()->level(); 480 unsigned char fromLevel = context()->level();
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 *hasStrongDirectionality = false; 633 *hasStrongDirectionality = false;
583 return LTR; 634 return LTR;
584 } 635 }
585 636
586 template <class Iterator, class Run> 637 template <class Iterator, class Run>
587 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis ualDirectionOverride override, bool hardLineBreak) 638 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis ualDirectionOverride override, bool hardLineBreak)
588 { 639 {
589 using namespace WTF::Unicode; 640 using namespace WTF::Unicode;
590 641
591 ASSERT(m_direction == OtherNeutral); 642 ASSERT(m_direction == OtherNeutral);
643 m_trailingSpaceRun = 0;
592 644
593 m_endOfLine = end; 645 m_endOfLine = end;
594 646
595 if (override != NoVisualOverride) { 647 if (override != NoVisualOverride) {
596 m_emptyRun = false; 648 m_emptyRun = false;
597 m_sor = m_current; 649 m_sor = m_current;
598 m_eor = Iterator(); 650 m_eor = Iterator();
599 while (m_current != end && !m_current.atEnd()) { 651 while (m_current != end && !m_current.atEnd()) {
600 m_eor = m_current; 652 m_eor = m_current;
601 increment(); 653 increment();
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 m_direction = OtherNeutral; 1030 m_direction = OtherNeutral;
979 break; 1031 break;
980 } 1032 }
981 } 1033 }
982 } 1034 }
983 1035
984 m_runs.setLogicallyLastRun(m_runs.lastRun()); 1036 m_runs.setLogicallyLastRun(m_runs.lastRun());
985 reorderRunsFromLevels(); 1037 reorderRunsFromLevels();
986 m_endOfRunAtEndOfLine = Iterator(); 1038 m_endOfRunAtEndOfLine = Iterator();
987 m_endOfLine = Iterator(); 1039 m_endOfLine = Iterator();
1040
1041 if (!hardLineBreak && m_runs.runCount())
1042 applyL1Rule();
988 } 1043 }
989 1044
990 template <class Iterator, class Run> 1045 template <class Iterator, class Run>
991 void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint) 1046 void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint)
992 { 1047 {
993 ASSERT(!m_midpointStateForIsolatedRun.contains(run)); 1048 ASSERT(!m_midpointStateForIsolatedRun.contains(run));
994 m_midpointStateForIsolatedRun.add(run, midpoint); 1049 m_midpointStateForIsolatedRun.add(run, midpoint);
995 } 1050 }
996 1051
997 template<class Iterator, class Run> 1052 template<class Iterator, class Run>
998 MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun (Run* run) 1053 MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun (Run* run)
999 { 1054 {
1000 return m_midpointStateForIsolatedRun.take(run); 1055 return m_midpointStateForIsolatedRun.take(run);
1001 } 1056 }
1002 1057
1003 1058
1004 } // namespace WebCore 1059 } // namespace WebCore
1005 1060
1006 #endif // BidiResolver_h 1061 #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