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

Side by Side Diff: Source/core/rendering/InlineIterator.h

Issue 39783004: Fake Bidi run does not need to be always created (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Patch set 1 Created 7 years, 1 month 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 | « no previous file | Source/core/rendering/RenderBlockFlow.h » ('j') | 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, 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
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
OLDNEW
« no previous file with comments | « no previous file | Source/core/rendering/RenderBlockFlow.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698