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, 2009, 2010 Apple Inc. All right r eserved. | 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right r eserved. |
4 * Copyright (C) 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2010 Google Inc. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
460 while (object && object != iter.root()) { | 460 while (object && object != iter.root()) { |
461 if (isIsolatedInline(object)) | 461 if (isIsolatedInline(object)) |
462 count++; | 462 count++; |
463 object = object->parent(); | 463 object = object->parent(); |
464 } | 464 } |
465 return count; | 465 return count; |
466 } | 466 } |
467 | 467 |
468 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat ion | 468 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat ion |
469 // of BidiResolver which knows nothing about RenderObjects. | 469 // of BidiResolver which knows nothing about RenderObjects. |
470 static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolv er, RenderObject* obj, unsigned pos) | 470 static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& re solver, RenderObject* obj, unsigned pos) |
471 { | 471 { |
472 ASSERT(obj); | 472 ASSERT(obj); |
473 BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolv er.dir()); | 473 BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolv er.dir()); |
474 resolver.runs().addRun(isolatedRun); | 474 resolver.runs().addRun(isolatedRun); |
475 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch eaply | 475 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch eaply |
476 // ASSERT here that we didn't create multiple objects for the same inline. | 476 // ASSERT here that we didn't create multiple objects for the same inline. |
477 resolver.isolatedRuns().append(isolatedRun); | 477 resolver.isolatedRuns().append(isolatedRun); |
478 LineMidpointState& lineMidpointState = resolver.midpointState(); | 478 return isolatedRun; |
479 resolver.setMidpointStateForIsolatedRun(isolatedRun, lineMidpointState); | |
480 } | 479 } |
481 | 480 |
482 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBi diResolver& resolver) | 481 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBi diResolver& resolver) |
483 { | 482 { |
484 return new BidiRun(start, end, obj, resolver.context(), resolver.dir()); | 483 return new BidiRun(start, end, obj, resolver.context(), resolver.dir()); |
485 } | 484 } |
486 | 485 |
487 enum AppendRunBehavior { | |
488 AppendingFakeRun, | |
489 AppendingRunsForObject | |
490 }; | |
491 | |
492 static void adjustMidpointsAndAppendRunsForObjectIfNeeded(RenderObject* obj, uns igned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behav ior = AppendingFakeRun, BidiRunList<BidiRun>* runs = 0) | |
493 { | |
494 if (start > end || RenderBlock::shouldSkipCreatingRunsForObject(obj)) | |
495 return; | |
496 | |
497 LineMidpointState& lineMidpointState = resolver.midpointState(); | |
498 bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointSta te.numMidpoints); | |
499 InlineIterator nextMidpoint; | |
500 if (haveNextMidpoint) | |
501 nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidp oint]; | |
502 if (lineMidpointState.betweenMidpoints) { | |
503 if (!(haveNextMidpoint && nextMidpoint.m_obj == obj)) | |
504 return; | |
505 // This is a new start point. Stop ignoring objects and | |
506 // adjust our start. | |
507 lineMidpointState.betweenMidpoints = false; | |
508 start = nextMidpoint.m_pos; | |
509 lineMidpointState.currentMidpoint++; | |
510 if (start < end) | |
511 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end , resolver, behavior, runs); | |
512 } else { | |
513 if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) { | |
514 if (behavior == AppendingFakeRun) | |
515 return; | |
516 runs->addRun(createRun(start, end, obj, resolver)); | |
517 return; | |
518 } | |
519 | |
520 // An end midpoint has been encountered within our object. We | |
521 // need to go ahead and append a run with our endpoint. | |
522 if (static_cast<int>(nextMidpoint.m_pos + 1) <= end) { | |
523 lineMidpointState.betweenMidpoints = true; | |
524 lineMidpointState.currentMidpoint++; | |
525 if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it. | |
526 if (static_cast<int>(nextMidpoint.m_pos + 1) > start && behavior == AppendingRunsForObject) | |
527 runs->addRun(createRun(start, nextMidpoint.m_pos + 1, obj, r esolver)); | |
528 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMi dpoint.m_pos + 1, end, resolver, behavior, runs); | |
529 } | |
530 } else if (behavior == AppendingRunsForObject) { | |
531 runs->addRun(createRun(start, end, obj, resolver)); | |
532 } | |
533 } | |
534 } | |
535 | |
536 class IsolateTracker { | 486 class IsolateTracker { |
537 public: | 487 public: |
538 explicit IsolateTracker(unsigned nestedIsolateCount) | 488 explicit IsolateTracker(unsigned nestedIsolateCount) |
539 : m_nestedIsolateCount(nestedIsolateCount) | 489 : m_nestedIsolateCount(nestedIsolateCount) |
540 , m_haveAddedFakeRunForRootIsolate(false) | 490 , m_haveAddedFakeRunForRootIsolate(false) |
541 { | 491 { |
542 } | 492 } |
543 | 493 |
494 void setMidpointStateForRootIsolate(const LineMidpointState& midpointState) | |
495 { | |
496 m_midpointStateForRootIsolate = midpointState; | |
497 } | |
498 | |
544 void enterIsolate() { m_nestedIsolateCount++; } | 499 void enterIsolate() { m_nestedIsolateCount++; } |
545 void exitIsolate() | 500 void exitIsolate() |
546 { | 501 { |
547 ASSERT(m_nestedIsolateCount >= 1); | 502 ASSERT(m_nestedIsolateCount >= 1); |
548 m_nestedIsolateCount--; | 503 m_nestedIsolateCount--; |
549 if (!inIsolate()) | 504 if (!inIsolate()) |
550 m_haveAddedFakeRunForRootIsolate = false; | 505 m_haveAddedFakeRunForRootIsolate = false; |
551 } | 506 } |
552 bool inIsolate() const { return m_nestedIsolateCount; } | 507 bool inIsolate() const { return m_nestedIsolateCount; } |
553 | 508 |
554 // We don't care if we encounter bidi directional overrides. | 509 // We don't care if we encounter bidi directional overrides. |
555 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } | 510 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } |
556 void commitExplicitEmbedding() { } | 511 void commitExplicitEmbedding() { } |
557 | 512 |
558 | 513 void addFakeRunIfNecessary(unsigned pos, unsigned end, RenderObject* obj, In lineBidiResolver& resolver) |
559 void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, unsigned end, In lineBidiResolver& resolver) | |
560 { | 514 { |
561 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine. | 515 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine. |
562 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls. | 516 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls. |
563 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats. | 517 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats. |
564 if (RenderBlock::shouldSkipCreatingRunsForObject(obj)) | 518 if (RenderBlock::shouldSkipCreatingRunsForObject(obj)) |
565 return; | 519 return; |
566 if (!m_haveAddedFakeRunForRootIsolate) { | 520 if (!m_haveAddedFakeRunForRootIsolate) { |
567 addPlaceholderRunForIsolatedInline(resolver, obj, pos); | 521 BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos ); |
522 resolver.setMidpointStateForIsolatedRun(run, m_midpointStateForRootI solate); | |
568 m_haveAddedFakeRunForRootIsolate = true; | 523 m_haveAddedFakeRunForRootIsolate = true; |
569 } | 524 } |
570 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, pos, end, resolver); | |
571 | |
572 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start. | 525 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start. |
573 // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the | 526 // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the |
574 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first. | 527 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first. |
575 } | 528 } |
576 | 529 |
577 private: | 530 private: |
578 unsigned m_nestedIsolateCount; | 531 unsigned m_nestedIsolateCount; |
579 bool m_haveAddedFakeRunForRootIsolate; | 532 bool m_haveAddedFakeRunForRootIsolate; |
533 LineMidpointState m_midpointStateForRootIsolate; | |
580 }; | 534 }; |
581 | 535 |
536 struct AddFakeRunIfNecessaryFunctor { | |
537 IsolateTracker& isolateTracker; | |
538 void operator()(int start, int end, RenderObject* obj, InlineBidiResolver& r esolver) | |
539 { | |
540 isolateTracker.addFakeRunIfNecessary(start, end, obj, resolver); | |
541 } | |
542 }; | |
543 | |
544 struct AddRunFunctor { | |
545 void operator()(int start, int end, RenderObject* obj, InlineBidiResolver& r esolver) | |
546 { | |
547 RenderBlockFlow::appendRunsForObject(start, end, obj, resolver); | |
548 } | |
549 }; | |
550 | |
551 template <typename Functor> | |
552 static void adjustMidpointsAndAppendRunsForObjectIfNeeded(RenderObject* obj, uns igned start, unsigned end, InlineBidiResolver& resolver, Functor addRunFunction) | |
553 { | |
554 if (start > end || RenderBlock::shouldSkipCreatingRunsForObject(obj)) | |
555 return; | |
556 | |
557 LineMidpointState& lineMidpointState = resolver.midpointState(); | |
558 bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointSta te.numMidpoints); | |
559 InlineIterator nextMidpoint; | |
560 if (haveNextMidpoint) | |
561 nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidp oint]; | |
562 if (lineMidpointState.betweenMidpoints) { | |
563 if (!(haveNextMidpoint && nextMidpoint.m_obj == obj)) | |
564 return; | |
565 // This is a new start point. Stop ignoring objects and | |
566 // adjust our start. | |
567 lineMidpointState.betweenMidpoints = false; | |
568 start = nextMidpoint.m_pos; | |
569 lineMidpointState.currentMidpoint++; | |
570 if (start < end) | |
571 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end , resolver, addRunFunction); | |
572 } else { | |
573 if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) { | |
574 addRunFunction(start, end, obj, resolver); | |
575 return; | |
576 } | |
577 | |
578 // An end midpoint has been encountered within our object. We | |
579 // need to go ahead and append a run with our endpoint. | |
580 if (static_cast<int>(nextMidpoint.m_pos + 1) <= end) { | |
581 lineMidpointState.betweenMidpoints = true; | |
582 lineMidpointState.currentMidpoint++; | |
583 if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it. | |
584 if (static_cast<int>(nextMidpoint.m_pos + 1) > start) | |
585 addRunFunction(start, nextMidpoint.m_pos + 1, obj, resolver) ; | |
586 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMi dpoint.m_pos + 1, end, resolver, addRunFunction); | |
587 } | |
588 } else { | |
589 addRunFunction(start, end, obj, resolver); | |
590 } | |
591 } | |
592 } | |
593 | |
582 template <> | 594 template <> |
583 inline void InlineBidiResolver::appendRun() | 595 inline void InlineBidiResolver::appendRun() |
584 { | 596 { |
585 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { | 597 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { |
586 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. | 598 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. |
587 // Initialize our state depending on if we're starting in the middle of such an inline. | 599 // Initialize our state depending on if we're starting in the middle of such an inline. |
588 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree? | 600 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree? |
589 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor)); | 601 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor)); |
590 int start = m_sor.m_pos; | 602 int start = m_sor.m_pos; |
591 RenderObject* obj = m_sor.m_obj; | 603 RenderObject* obj = m_sor.m_obj; |
592 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) { | 604 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) { |
593 if (isolateTracker.inIsolate()) | 605 if (isolateTracker.inIsolate()) { |
594 isolateTracker.addFakeRunIfNecessary(obj, start, obj->length(), *this); | 606 AddFakeRunIfNecessaryFunctor functor = {isolateTracker}; |
595 else | 607 isolateTracker.setMidpointStateForRootIsolate(midpointState()); |
596 RenderBlockFlow::appendRunsForObject(m_runs, start, obj->length( ), obj, *this); | 608 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->l ength(), *this, functor); |
609 } else { | |
610 AddRunFunctor functor; | |
611 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj->l ength(), *this, functor); | |
612 } | |
597 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables. | 613 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables. |
598 start = 0; | 614 start = 0; |
599 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r); | 615 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r); |
600 } | 616 } |
601 if (obj) { | 617 if (obj) { |
602 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX; | 618 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX; |
603 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) { | 619 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) { |
604 m_reachedEndOfLine = true; | 620 m_reachedEndOfLine = true; |
605 pos = endOfLine.m_pos; | 621 pos = endOfLine.m_pos; |
606 } | 622 } |
607 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be | 623 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be |
608 int end = obj->length() ? pos + 1 : 0; | 624 int end = obj->length() ? pos + 1 : 0; |
609 if (isolateTracker.inIsolate()) | 625 if (isolateTracker.inIsolate()) { |
eseidel
2013/10/24 18:10:05
Why not just move this check inside adjustMidpoint
| |
610 isolateTracker.addFakeRunIfNecessary(obj, start, end, *this); | 626 AddFakeRunIfNecessaryFunctor functor = {isolateTracker}; |
611 else | 627 isolateTracker.setMidpointStateForRootIsolate(midpointState()); |
612 RenderBlockFlow::appendRunsForObject(m_runs, start, end, obj, *t his); | 628 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, * this, functor); |
629 } else { | |
630 AddRunFunctor functor; | |
631 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, * this, functor); | |
632 } | |
613 } | 633 } |
614 | 634 |
615 m_eor.increment(); | 635 m_eor.increment(); |
616 m_sor = m_eor; | 636 m_sor = m_eor; |
617 } | 637 } |
618 | 638 |
619 m_direction = WTF::Unicode::OtherNeutral; | 639 m_direction = WTF::Unicode::OtherNeutral; |
620 m_status.eor = WTF::Unicode::OtherNeutral; | 640 m_status.eor = WTF::Unicode::OtherNeutral; |
621 } | 641 } |
622 | 642 |
623 } | 643 } |
624 | 644 |
625 #endif // InlineIterator_h | 645 #endif // InlineIterator_h |
OLD | NEW |