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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 { | 171 { |
172 return !(status1 == status2); | 172 return !(status1 == status2); |
173 } | 173 } |
174 | 174 |
175 enum VisualDirectionOverride { | 175 enum VisualDirectionOverride { |
176 NoVisualOverride, | 176 NoVisualOverride, |
177 VisualLeftToRightOverride, | 177 VisualLeftToRightOverride, |
178 VisualRightToLeftOverride | 178 VisualRightToLeftOverride |
179 }; | 179 }; |
180 | 180 |
| 181 class NoIsolatedRun { |
| 182 }; |
| 183 |
181 // BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm | 184 // BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm |
182 // http://unicode.org/reports/tr9 | 185 // http://unicode.org/reports/tr9 |
183 template <class Iterator, class Run> class BidiResolver { | 186 template <class Iterator, class Run, class IsolatedRun = NoIsolatedRun> class Bi
diResolver { |
184 WTF_MAKE_NONCOPYABLE(BidiResolver); | 187 WTF_MAKE_NONCOPYABLE(BidiResolver); |
185 public: | 188 public: |
186 BidiResolver() | 189 BidiResolver() |
187 : m_direction(WTF::Unicode::OtherNeutral) | 190 : m_direction(WTF::Unicode::OtherNeutral) |
188 , m_reachedEndOfLine(false) | 191 , m_reachedEndOfLine(false) |
189 , m_emptyRun(true) | 192 , m_emptyRun(true) |
190 , m_nestedIsolateCount(0) | 193 , m_nestedIsolateCount(0) |
191 , m_trailingSpaceRun(0) | 194 , m_trailingSpaceRun(0) |
192 { | 195 { |
193 } | 196 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 bool commitExplicitEmbedding(BidiRunList<Run>&); | 239 bool commitExplicitEmbedding(BidiRunList<Run>&); |
237 | 240 |
238 void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = No
VisualOverride, bool hardLineBreak = false, bool reorderRuns = true); | 241 void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = No
VisualOverride, bool hardLineBreak = false, bool reorderRuns = true); |
239 | 242 |
240 BidiRunList<Run>& runs() { return m_runs; } | 243 BidiRunList<Run>& runs() { return m_runs; } |
241 | 244 |
242 // FIXME: This used to be part of deleteRuns() but was a layering violation. | 245 // FIXME: This used to be part of deleteRuns() but was a layering violation. |
243 // It's unclear if this is still needed. | 246 // It's unclear if this is still needed. |
244 void markCurrentRunEmpty() { m_emptyRun = true; } | 247 void markCurrentRunEmpty() { m_emptyRun = true; } |
245 | 248 |
246 Vector<Run*>& isolatedRuns() { return m_isolatedRuns; } | 249 Vector<IsolatedRun>& isolatedRuns() { return m_isolatedRuns; } |
247 | 250 |
248 bool isEndOfLine(const Iterator& end) { return m_current == end || m_current
.atEnd(); } | 251 bool isEndOfLine(const Iterator& end) { return m_current == end || m_current
.atEnd(); } |
249 | 252 |
250 TextDirection determineParagraphDirectionality(bool* hasStrongDirectionality
= 0) | 253 TextDirection determineParagraphDirectionality(bool* hasStrongDirectionality
= 0) |
251 { | 254 { |
252 bool breakOnParagraph = true; | 255 bool breakOnParagraph = true; |
253 return determineDirectionalityInternal(breakOnParagraph, hasStrongDirect
ionality); | 256 return determineDirectionalityInternal(breakOnParagraph, hasStrongDirect
ionality); |
254 } | 257 } |
255 TextDirection determineDirectionality(bool* hasStrongDirectionality = 0) | 258 TextDirection determineDirectionality(bool* hasStrongDirectionality = 0) |
256 { | 259 { |
257 bool breakOnParagraph = false; | 260 bool breakOnParagraph = false; |
258 return determineDirectionalityInternal(breakOnParagraph, hasStrongDirect
ionality); | 261 return determineDirectionalityInternal(breakOnParagraph, hasStrongDirect
ionality); |
259 } | 262 } |
260 | 263 |
261 void setMidpointStateForIsolatedRun(Run*, const MidpointState<Iterator>&); | 264 void setMidpointStateForIsolatedRun(Run&, const MidpointState<Iterator>&); |
262 MidpointState<Iterator> midpointStateForIsolatedRun(Run*); | 265 MidpointState<Iterator> midpointStateForIsolatedRun(Run&); |
263 | 266 |
264 Iterator endOfLine() const { return m_endOfLine; } | 267 Iterator endOfLine() const { return m_endOfLine; } |
265 | 268 |
266 Run* trailingSpaceRun() const { return m_trailingSpaceRun; } | 269 Run* trailingSpaceRun() const { return m_trailingSpaceRun; } |
267 | 270 |
268 protected: | 271 protected: |
269 void increment() { m_current.increment(); } | 272 void increment() { m_current.increment(); } |
270 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should | 273 // FIXME: Instead of InlineBidiResolvers subclassing this method, we should |
271 // pass in some sort of Traits object which knows how to create runs for app
ending. | 274 // pass in some sort of Traits object which knows how to create runs for app
ending. |
272 void appendRun(BidiRunList<Run>&); | 275 void appendRun(BidiRunList<Run>&); |
(...skipping 14 matching lines...) Expand all Loading... |
287 Iterator m_lastBeforeET; // Before a EuropeanNumberTerminator | 290 Iterator m_lastBeforeET; // Before a EuropeanNumberTerminator |
288 bool m_emptyRun; | 291 bool m_emptyRun; |
289 | 292 |
290 // FIXME: This should not belong to the resolver, but rather be passed | 293 // FIXME: This should not belong to the resolver, but rather be passed |
291 // into createBidiRunsForLine by the caller. | 294 // into createBidiRunsForLine by the caller. |
292 BidiRunList<Run> m_runs; | 295 BidiRunList<Run> m_runs; |
293 | 296 |
294 MidpointState<Iterator> m_midpointState; | 297 MidpointState<Iterator> m_midpointState; |
295 | 298 |
296 unsigned m_nestedIsolateCount; | 299 unsigned m_nestedIsolateCount; |
297 Vector<Run*> m_isolatedRuns; | 300 Vector<IsolatedRun> m_isolatedRuns; |
298 Run* m_trailingSpaceRun; | 301 Run* m_trailingSpaceRun; |
299 TextDirection m_paragraphDirectionality; | 302 TextDirection m_paragraphDirectionality; |
300 | 303 |
301 private: | 304 private: |
302 void raiseExplicitEmbeddingLevel(BidiRunList<Run>&, WTF::Unicode::Direction
from, WTF::Unicode::Direction to); | 305 void raiseExplicitEmbeddingLevel(BidiRunList<Run>&, WTF::Unicode::Direction
from, WTF::Unicode::Direction to); |
303 void lowerExplicitEmbeddingLevel(BidiRunList<Run>&, WTF::Unicode::Direction
from); | 306 void lowerExplicitEmbeddingLevel(BidiRunList<Run>&, WTF::Unicode::Direction
from); |
304 void checkDirectionInLowerRaiseEmbeddingLevel(); | 307 void checkDirectionInLowerRaiseEmbeddingLevel(); |
305 | 308 |
306 void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); | 309 void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); |
307 void reorderRunsFromLevels(BidiRunList<Run>&) const; | 310 void reorderRunsFromLevels(BidiRunList<Run>&) const; |
308 | 311 |
309 bool needsToApplyL1Rule(BidiRunList<Run>&) { return false; } | 312 bool needsToApplyL1Rule(BidiRunList<Run>&) { return false; } |
310 int findFirstTrailingSpaceAtRun(Run*) { return 0; } | 313 int findFirstTrailingSpaceAtRun(Run*) { return 0; } |
311 // http://www.unicode.org/reports/tr9/#L1 | 314 // http://www.unicode.org/reports/tr9/#L1 |
312 void applyL1Rule(BidiRunList<Run>&); | 315 void applyL1Rule(BidiRunList<Run>&); |
313 | 316 |
314 TextDirection determineDirectionalityInternal(bool breakOnParagraph, bool* h
asStrongDirectionality); | 317 TextDirection determineDirectionalityInternal(bool breakOnParagraph, bool* h
asStrongDirectionality); |
315 | 318 |
316 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; | 319 Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; |
317 HashMap<Run *, MidpointState<Iterator>> m_midpointStateForIsolatedRun; | 320 HashMap<Run *, MidpointState<Iterator>> m_midpointStateForIsolatedRun; |
318 }; | 321 }; |
319 | 322 |
320 #if ENABLE(ASSERT) | 323 #if ENABLE(ASSERT) |
321 template <class Iterator, class Run> | 324 template <class Iterator, class Run, class IsolatedRun> |
322 BidiResolver<Iterator, Run>::~BidiResolver() | 325 BidiResolver<Iterator, Run, IsolatedRun>::~BidiResolver() |
323 { | 326 { |
324 // The owner of this resolver should have handled the isolated runs. | 327 // The owner of this resolver should have handled the isolated runs. |
325 ASSERT(m_isolatedRuns.isEmpty()); | 328 ASSERT(m_isolatedRuns.isEmpty()); |
326 } | 329 } |
327 #endif | 330 #endif |
328 | 331 |
329 template <class Iterator, class Run> | 332 template <class Iterator, class Run, class IsolatedRun> |
330 void BidiResolver<Iterator, Run>::appendRun(BidiRunList<Run>& runs) | 333 void BidiResolver<Iterator, Run, IsolatedRun>::appendRun(BidiRunList<Run>& runs) |
331 { | 334 { |
332 if (!m_emptyRun && !m_eor.atEnd()) { | 335 if (!m_emptyRun && !m_eor.atEnd()) { |
333 unsigned startOffset = m_sor.offset(); | 336 unsigned startOffset = m_sor.offset(); |
334 unsigned endOffset = m_eor.offset(); | 337 unsigned endOffset = m_eor.offset(); |
335 | 338 |
336 if (!m_endOfRunAtEndOfLine.atEnd() && endOffset >= m_endOfRunAtEndOfLine
.offset()) { | 339 if (!m_endOfRunAtEndOfLine.atEnd() && endOffset >= m_endOfRunAtEndOfLine
.offset()) { |
337 m_reachedEndOfLine = true; | 340 m_reachedEndOfLine = true; |
338 endOffset = m_endOfRunAtEndOfLine.offset(); | 341 endOffset = m_endOfRunAtEndOfLine.offset(); |
339 } | 342 } |
340 | 343 |
(...skipping 13 matching lines...) Expand all Loading... |
354 } | 357 } |
355 | 358 |
356 m_eor.increment(); | 359 m_eor.increment(); |
357 m_sor = m_eor; | 360 m_sor = m_eor; |
358 } | 361 } |
359 | 362 |
360 m_direction = WTF::Unicode::OtherNeutral; | 363 m_direction = WTF::Unicode::OtherNeutral; |
361 m_status.eor = WTF::Unicode::OtherNeutral; | 364 m_status.eor = WTF::Unicode::OtherNeutral; |
362 } | 365 } |
363 | 366 |
364 template <class Iterator, class Run> | 367 template <class Iterator, class Run, class IsolatedRun> |
365 void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddi
ngSource source) | 368 void BidiResolver<Iterator, Run, IsolatedRun>::embed(WTF::Unicode::Direction dir
, BidiEmbeddingSource source) |
366 { | 369 { |
367 // Isolated spans compute base directionality during their own UBA run. | 370 // Isolated spans compute base directionality during their own UBA run. |
368 // Do not insert fake embed characters once we enter an isolated span. | 371 // Do not insert fake embed characters once we enter an isolated span. |
369 ASSERT(!inIsolate()); | 372 ASSERT(!inIsolate()); |
370 using namespace WTF::Unicode; | 373 using namespace WTF::Unicode; |
371 | 374 |
372 ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir ==
LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride
); | 375 ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir ==
LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride
); |
373 m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); | 376 m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); |
374 } | 377 } |
375 | 378 |
376 template <class Iterator, class Run> | 379 template <class Iterator, class Run, class IsolatedRun> |
377 void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel() | 380 void BidiResolver<Iterator, Run, IsolatedRun>::checkDirectionInLowerRaiseEmbeddi
ngLevel() |
378 { | 381 { |
379 using namespace WTF::Unicode; | 382 using namespace WTF::Unicode; |
380 | 383 |
381 ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); | 384 ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); |
382 ASSERT(m_status.last != NonSpacingMark | 385 ASSERT(m_status.last != NonSpacingMark |
383 && m_status.last != BoundaryNeutral | 386 && m_status.last != BoundaryNeutral |
384 && m_status.last != RightToLeftEmbedding | 387 && m_status.last != RightToLeftEmbedding |
385 && m_status.last != LeftToRightEmbedding | 388 && m_status.last != LeftToRightEmbedding |
386 && m_status.last != RightToLeftOverride | 389 && m_status.last != RightToLeftOverride |
387 && m_status.last != LeftToRightOverride | 390 && m_status.last != LeftToRightOverride |
388 && m_status.last != PopDirectionalFormat); | 391 && m_status.last != PopDirectionalFormat); |
389 if (m_direction == OtherNeutral) | 392 if (m_direction == OtherNeutral) |
390 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightTo
Left; | 393 m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightTo
Left; |
391 } | 394 } |
392 | 395 |
393 template <class Iterator, class Run> | 396 template <class Iterator, class Run, class IsolatedRun> |
394 void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(BidiRunList<Run>&
runs, WTF::Unicode::Direction from) | 397 void BidiResolver<Iterator, Run, IsolatedRun>::lowerExplicitEmbeddingLevel(BidiR
unList<Run>& runs, WTF::Unicode::Direction from) |
395 { | 398 { |
396 using namespace WTF::Unicode; | 399 using namespace WTF::Unicode; |
397 | 400 |
398 if (!m_emptyRun && m_eor != m_last) { | 401 if (!m_emptyRun && m_eor != m_last) { |
399 checkDirectionInLowerRaiseEmbeddingLevel(); | 402 checkDirectionInLowerRaiseEmbeddingLevel(); |
400 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-
bidi.eor run or extend it through bidi.last | 403 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-
bidi.eor run or extend it through bidi.last |
401 if (from == LeftToRight) { | 404 if (from == LeftToRight) { |
402 // bidi.sor ... bidi.eor ... bidi.last L | 405 // bidi.sor ... bidi.eor ... bidi.last L |
403 if (m_status.eor == EuropeanNumber) { | 406 if (m_status.eor == EuropeanNumber) { |
404 if (m_status.lastStrong != LeftToRight) { | 407 if (m_status.lastStrong != LeftToRight) { |
(...skipping 16 matching lines...) Expand all Loading... |
421 | 424 |
422 appendRun(runs); | 425 appendRun(runs); |
423 m_emptyRun = true; | 426 m_emptyRun = true; |
424 | 427 |
425 // sor for the new run is determined by the higher level (rule X10) | 428 // sor for the new run is determined by the higher level (rule X10) |
426 setLastDir(from); | 429 setLastDir(from); |
427 setLastStrongDir(from); | 430 setLastStrongDir(from); |
428 m_eor = Iterator(); | 431 m_eor = Iterator(); |
429 } | 432 } |
430 | 433 |
431 template <class Iterator, class Run> | 434 template <class Iterator, class Run, class IsolatedRun> |
432 void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(BidiRunList<Run>&
runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to) | 435 void BidiResolver<Iterator, Run, IsolatedRun>::raiseExplicitEmbeddingLevel(BidiR
unList<Run>& runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to) |
433 { | 436 { |
434 using namespace WTF::Unicode; | 437 using namespace WTF::Unicode; |
435 | 438 |
436 if (!m_emptyRun && m_eor != m_last) { | 439 if (!m_emptyRun && m_eor != m_last) { |
437 checkDirectionInLowerRaiseEmbeddingLevel(); | 440 checkDirectionInLowerRaiseEmbeddingLevel(); |
438 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-
bidi.eor run or extend it through bidi.last | 441 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-
bidi.eor run or extend it through bidi.last |
439 if (to == LeftToRight) { | 442 if (to == LeftToRight) { |
440 // bidi.sor ... bidi.eor ... bidi.last L | 443 // bidi.sor ... bidi.eor ... bidi.last L |
441 if (m_status.eor == EuropeanNumber) { | 444 if (m_status.eor == EuropeanNumber) { |
442 if (m_status.lastStrong != LeftToRight) { | 445 if (m_status.lastStrong != LeftToRight) { |
(...skipping 17 matching lines...) Expand all Loading... |
460 } | 463 } |
461 | 464 |
462 appendRun(runs); | 465 appendRun(runs); |
463 m_emptyRun = true; | 466 m_emptyRun = true; |
464 | 467 |
465 setLastDir(to); | 468 setLastDir(to); |
466 setLastStrongDir(to); | 469 setLastStrongDir(to); |
467 m_eor = Iterator(); | 470 m_eor = Iterator(); |
468 } | 471 } |
469 | 472 |
470 template <class Iterator, class Run> | 473 template <class Iterator, class Run, class IsolatedRun> |
471 void BidiResolver<Iterator, Run>::applyL1Rule(BidiRunList<Run>& runs) | 474 void BidiResolver<Iterator, Run, IsolatedRun>::applyL1Rule(BidiRunList<Run>& run
s) |
472 { | 475 { |
473 ASSERT(runs.runCount()); | 476 ASSERT(runs.runCount()); |
474 if (!needsToApplyL1Rule(runs)) | 477 if (!needsToApplyL1Rule(runs)) |
475 return; | 478 return; |
476 | 479 |
477 Run* trailingSpaceRun = runs.logicallyLastRun(); | 480 Run* trailingSpaceRun = runs.logicallyLastRun(); |
478 | 481 |
479 int firstSpace = findFirstTrailingSpaceAtRun(trailingSpaceRun); | 482 int firstSpace = findFirstTrailingSpaceAtRun(trailingSpaceRun); |
480 if (firstSpace == trailingSpaceRun->stop()) | 483 if (firstSpace == trailingSpaceRun->stop()) |
481 return; | 484 return; |
(...skipping 17 matching lines...) Expand all Loading... |
499 if (m_paragraphDirectionality == LTR) { | 502 if (m_paragraphDirectionality == LTR) { |
500 runs.moveRunToEnd(trailingSpaceRun); | 503 runs.moveRunToEnd(trailingSpaceRun); |
501 trailingSpaceRun->m_level = 0; | 504 trailingSpaceRun->m_level = 0; |
502 } else { | 505 } else { |
503 runs.moveRunToBeginning(trailingSpaceRun); | 506 runs.moveRunToBeginning(trailingSpaceRun); |
504 trailingSpaceRun->m_level = 1; | 507 trailingSpaceRun->m_level = 1; |
505 } | 508 } |
506 m_trailingSpaceRun = trailingSpaceRun; | 509 m_trailingSpaceRun = trailingSpaceRun; |
507 } | 510 } |
508 | 511 |
509 template <class Iterator, class Run> | 512 template <class Iterator, class Run, class IsolatedRun> |
510 bool BidiResolver<Iterator, Run>::commitExplicitEmbedding(BidiRunList<Run>& runs
) | 513 bool BidiResolver<Iterator, Run, IsolatedRun>::commitExplicitEmbedding(BidiRunLi
st<Run>& runs) |
511 { | 514 { |
512 // When we're "inIsolate()" we're resolving the parent context which | 515 // When we're "inIsolate()" we're resolving the parent context which |
513 // ignores (skips over) the isolated content, including embedding levels. | 516 // ignores (skips over) the isolated content, including embedding levels. |
514 // We should never accrue embedding levels while skipping over isolated cont
ent. | 517 // We should never accrue embedding levels while skipping over isolated cont
ent. |
515 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); | 518 ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); |
516 | 519 |
517 using namespace WTF::Unicode; | 520 using namespace WTF::Unicode; |
518 | 521 |
519 unsigned char fromLevel = context()->level(); | 522 unsigned char fromLevel = context()->level(); |
520 RefPtr<BidiContext> toContext = context(); | 523 RefPtr<BidiContext> toContext = context(); |
(...skipping 23 matching lines...) Expand all Loading... |
544 else if (toLevel < fromLevel) | 547 else if (toLevel < fromLevel) |
545 lowerExplicitEmbeddingLevel(runs, fromLevel % 2 ? RightToLeft : LeftToRi
ght); | 548 lowerExplicitEmbeddingLevel(runs, fromLevel % 2 ? RightToLeft : LeftToRi
ght); |
546 | 549 |
547 setContext(toContext); | 550 setContext(toContext); |
548 | 551 |
549 m_currentExplicitEmbeddingSequence.clear(); | 552 m_currentExplicitEmbeddingSequence.clear(); |
550 | 553 |
551 return fromLevel != toLevel; | 554 return fromLevel != toLevel; |
552 } | 555 } |
553 | 556 |
554 template <class Iterator, class Run> | 557 template <class Iterator, class Run, class IsolatedRun> |
555 inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WT
F::Unicode::Direction dirCurrent) | 558 inline void BidiResolver<Iterator, Run, IsolatedRun>::updateStatusLastFromCurren
tDirection(WTF::Unicode::Direction dirCurrent) |
556 { | 559 { |
557 using namespace WTF::Unicode; | 560 using namespace WTF::Unicode; |
558 switch (dirCurrent) { | 561 switch (dirCurrent) { |
559 case EuropeanNumberTerminator: | 562 case EuropeanNumberTerminator: |
560 if (m_status.last != EuropeanNumber) | 563 if (m_status.last != EuropeanNumber) |
561 m_status.last = EuropeanNumberTerminator; | 564 m_status.last = EuropeanNumberTerminator; |
562 break; | 565 break; |
563 case EuropeanNumberSeparator: | 566 case EuropeanNumberSeparator: |
564 case CommonNumberSeparator: | 567 case CommonNumberSeparator: |
565 case SegmentSeparator: | 568 case SegmentSeparator: |
(...skipping 20 matching lines...) Expand all Loading... |
586 case PopDirectionalFormat: | 589 case PopDirectionalFormat: |
587 // ignore these | 590 // ignore these |
588 break; | 591 break; |
589 case EuropeanNumber: | 592 case EuropeanNumber: |
590 // fall through | 593 // fall through |
591 default: | 594 default: |
592 m_status.last = dirCurrent; | 595 m_status.last = dirCurrent; |
593 } | 596 } |
594 } | 597 } |
595 | 598 |
596 template <class Iterator, class Run> | 599 template <class Iterator, class Run, class IsolatedRun> |
597 inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels(BidiRunList<Run>&
runs) const | 600 inline void BidiResolver<Iterator, Run, IsolatedRun>::reorderRunsFromLevels(Bidi
RunList<Run>& runs) const |
598 { | 601 { |
599 unsigned char levelLow = BidiContext::kMaxLevel; | 602 unsigned char levelLow = BidiContext::kMaxLevel; |
600 unsigned char levelHigh = 0; | 603 unsigned char levelHigh = 0; |
601 for (Run* run = runs.firstRun(); run; run = run->next()) { | 604 for (Run* run = runs.firstRun(); run; run = run->next()) { |
602 levelHigh = std::max(run->level(), levelHigh); | 605 levelHigh = std::max(run->level(), levelHigh); |
603 levelLow = std::min(run->level(), levelLow); | 606 levelLow = std::min(run->level(), levelLow); |
604 } | 607 } |
605 | 608 |
606 // This implements reordering of the line (L2 according to Bidi spec): | 609 // This implements reordering of the line (L2 according to Bidi spec): |
607 // http://unicode.org/reports/tr9/#L2 | 610 // http://unicode.org/reports/tr9/#L2 |
(...skipping 15 matching lines...) Expand all Loading... |
623 unsigned start = i; | 626 unsigned start = i; |
624 for (;i <= count && run && run->level() >= levelHigh; i++) | 627 for (;i <= count && run && run->level() >= levelHigh; i++) |
625 run = run->next(); | 628 run = run->next(); |
626 unsigned end = i - 1; | 629 unsigned end = i - 1; |
627 runs.reverseRuns(start, end); | 630 runs.reverseRuns(start, end); |
628 } | 631 } |
629 levelHigh--; | 632 levelHigh--; |
630 } | 633 } |
631 } | 634 } |
632 | 635 |
633 template <class Iterator, class Run> | 636 template <class Iterator, class Run, class IsolatedRun> |
634 TextDirection BidiResolver<Iterator, Run>::determineDirectionalityInternal( | 637 TextDirection BidiResolver<Iterator, Run, IsolatedRun>::determineDirectionalityI
nternal( |
635 bool breakOnParagraph, bool* hasStrongDirectionality) | 638 bool breakOnParagraph, bool* hasStrongDirectionality) |
636 { | 639 { |
637 while (!m_current.atEnd()) { | 640 while (!m_current.atEnd()) { |
638 if (inIsolate()) { | 641 if (inIsolate()) { |
639 increment(); | 642 increment(); |
640 continue; | 643 continue; |
641 } | 644 } |
642 if (breakOnParagraph && m_current.atParagraphSeparator()) | 645 if (breakOnParagraph && m_current.atParagraphSeparator()) |
643 break; | 646 break; |
644 UChar32 current = m_current.current(); | 647 UChar32 current = m_current.current(); |
(...skipping 30 matching lines...) Expand all Loading... |
675 } | 678 } |
676 | 679 |
677 inline TextDirection directionForCharacter(UChar32 character) | 680 inline TextDirection directionForCharacter(UChar32 character) |
678 { | 681 { |
679 WTF::Unicode::Direction charDirection = WTF::Unicode::direction(character); | 682 WTF::Unicode::Direction charDirection = WTF::Unicode::direction(character); |
680 if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unic
ode::RightToLeftArabic) | 683 if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unic
ode::RightToLeftArabic) |
681 return RTL; | 684 return RTL; |
682 return LTR; | 685 return LTR; |
683 } | 686 } |
684 | 687 |
685 template <class Iterator, class Run> | 688 template <class Iterator, class Run, class IsolatedRun> |
686 void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
ualDirectionOverride override, bool hardLineBreak, bool reorderRuns) | 689 void BidiResolver<Iterator, Run, IsolatedRun>::createBidiRunsForLine(const Itera
tor& end, VisualDirectionOverride override, bool hardLineBreak, bool reorderRuns
) |
687 { | 690 { |
688 using namespace WTF::Unicode; | 691 using namespace WTF::Unicode; |
689 | 692 |
690 ASSERT(m_direction == OtherNeutral); | 693 ASSERT(m_direction == OtherNeutral); |
691 m_trailingSpaceRun = 0; | 694 m_trailingSpaceRun = 0; |
692 | 695 |
693 m_endOfLine = end; | 696 m_endOfLine = end; |
694 | 697 |
695 if (override != NoVisualOverride) { | 698 if (override != NoVisualOverride) { |
696 m_emptyRun = false; | 699 m_emptyRun = false; |
(...skipping 10 matching lines...) Expand all Loading... |
707 m_runs.reverseRuns(0, m_runs.runCount() - 1); | 710 m_runs.reverseRuns(0, m_runs.runCount() - 1); |
708 return; | 711 return; |
709 } | 712 } |
710 | 713 |
711 m_emptyRun = true; | 714 m_emptyRun = true; |
712 | 715 |
713 m_eor = Iterator(); | 716 m_eor = Iterator(); |
714 | 717 |
715 m_last = m_current; | 718 m_last = m_current; |
716 bool lastLineEnded = false; | 719 bool lastLineEnded = false; |
717 BidiResolver<Iterator, Run> stateAtEnd; | 720 BidiResolver<Iterator, Run, IsolatedRun> stateAtEnd; |
718 | 721 |
719 while (true) { | 722 while (true) { |
720 if (inIsolate() && m_emptyRun) { | 723 if (inIsolate() && m_emptyRun) { |
721 m_sor = m_current; | 724 m_sor = m_current; |
722 m_emptyRun = false; | 725 m_emptyRun = false; |
723 } | 726 } |
724 | 727 |
725 if (!lastLineEnded && isEndOfLine(end)) { | 728 if (!lastLineEnded && isEndOfLine(end)) { |
726 if (m_emptyRun) | 729 if (m_emptyRun) |
727 break; | 730 break; |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1084 m_runs.setLogicallyLastRun(m_runs.lastRun()); | 1087 m_runs.setLogicallyLastRun(m_runs.lastRun()); |
1085 if (reorderRuns) | 1088 if (reorderRuns) |
1086 reorderRunsFromLevels(m_runs); | 1089 reorderRunsFromLevels(m_runs); |
1087 m_endOfRunAtEndOfLine = Iterator(); | 1090 m_endOfRunAtEndOfLine = Iterator(); |
1088 m_endOfLine = Iterator(); | 1091 m_endOfLine = Iterator(); |
1089 | 1092 |
1090 if (!hardLineBreak && m_runs.runCount()) | 1093 if (!hardLineBreak && m_runs.runCount()) |
1091 applyL1Rule(m_runs); | 1094 applyL1Rule(m_runs); |
1092 } | 1095 } |
1093 | 1096 |
1094 template <class Iterator, class Run> | 1097 template <class Iterator, class Run, class IsolatedRun> |
1095 void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const
MidpointState<Iterator>& midpoint) | 1098 void BidiResolver<Iterator, Run, IsolatedRun>::setMidpointStateForIsolatedRun(Ru
n& run, const MidpointState<Iterator>& midpoint) |
1096 { | 1099 { |
1097 ASSERT(!m_midpointStateForIsolatedRun.contains(run)); | 1100 ASSERT(!m_midpointStateForIsolatedRun.contains(&run)); |
1098 m_midpointStateForIsolatedRun.add(run, midpoint); | 1101 m_midpointStateForIsolatedRun.add(&run, midpoint); |
1099 } | 1102 } |
1100 | 1103 |
1101 template<class Iterator, class Run> | 1104 template<class Iterator, class Run, class IsolatedRun> |
1102 MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun
(Run* run) | 1105 MidpointState<Iterator> BidiResolver<Iterator, Run, IsolatedRun>::midpointStateF
orIsolatedRun(Run& run) |
1103 { | 1106 { |
1104 return m_midpointStateForIsolatedRun.take(run); | 1107 return m_midpointStateForIsolatedRun.take(&run); |
1105 } | 1108 } |
1106 | 1109 |
1107 | |
1108 } // namespace blink | 1110 } // namespace blink |
1109 | 1111 |
1110 #endif // BidiResolver_h | 1112 #endif // BidiResolver_h |
OLD | NEW |