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

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

Issue 26315003: Bidi-Isolate inlines break layout with collapsed whitespace (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebased patch Created 7 years, 2 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
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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolv er, RenderObject* obj, unsigned pos)
471 { 471 {
472 ASSERT(obj); 472 ASSERT(obj);
473 BidiRun* isolatedRun = new BidiRun(pos, 0, obj, resolver.context(), resolver .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();
479 resolver.setMidpointStateForIsolatedRun(isolatedRun, lineMidpointState);
480 }
481
482 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBi diResolver& resolver)
483 {
484 return new BidiRun(start, end, obj, resolver.context(), resolver.dir());
485 }
486
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 }
478 } 534 }
479 535
480 class IsolateTracker { 536 class IsolateTracker {
481 public: 537 public:
482 explicit IsolateTracker(unsigned nestedIsolateCount) 538 explicit IsolateTracker(unsigned nestedIsolateCount)
483 : m_nestedIsolateCount(nestedIsolateCount) 539 : m_nestedIsolateCount(nestedIsolateCount)
484 , m_haveAddedFakeRunForRootIsolate(false) 540 , m_haveAddedFakeRunForRootIsolate(false)
485 { 541 {
486 } 542 }
487 543
488 void enterIsolate() { m_nestedIsolateCount++; } 544 void enterIsolate() { m_nestedIsolateCount++; }
489 void exitIsolate() 545 void exitIsolate()
490 { 546 {
491 ASSERT(m_nestedIsolateCount >= 1); 547 ASSERT(m_nestedIsolateCount >= 1);
492 m_nestedIsolateCount--; 548 m_nestedIsolateCount--;
493 if (!inIsolate()) 549 if (!inIsolate())
494 m_haveAddedFakeRunForRootIsolate = false; 550 m_haveAddedFakeRunForRootIsolate = false;
495 } 551 }
496 bool inIsolate() const { return m_nestedIsolateCount; } 552 bool inIsolate() const { return m_nestedIsolateCount; }
497 553
498 // We don't care if we encounter bidi directional overrides. 554 // We don't care if we encounter bidi directional overrides.
499 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } 555 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { }
500 void commitExplicitEmbedding() { } 556 void commitExplicitEmbedding() { }
501 557
502 void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, InlineBidiResolv er& resolver) 558
559 void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, unsigned end, In lineBidiResolver& resolver)
503 { 560 {
504 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine. 561 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine.
505 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls. 562 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls.
506 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats. 563 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats.
507 if (m_haveAddedFakeRunForRootIsolate || RenderBlock::shouldSkipCreatingR unsForObject(obj)) 564 if (RenderBlock::shouldSkipCreatingRunsForObject(obj))
508 return; 565 return;
509 m_haveAddedFakeRunForRootIsolate = true; 566 if (!m_haveAddedFakeRunForRootIsolate) {
567 addPlaceholderRunForIsolatedInline(resolver, obj, pos);
568 m_haveAddedFakeRunForRootIsolate = true;
569 }
570 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, pos, end, resolver);
571
510 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start. 572 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start.
511 // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the 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
512 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first. 574 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first.
513 addPlaceholderRunForIsolatedInline(resolver, obj, pos);
514 // FIXME: Inline isolates don't work properly with collapsing whitespace , see webkit.org/b/109624
515 // For now, if we enter an isolate between midpoints, we increment our c urrent midpoint or else
516 // we'll leave the isolate and ignore the content that follows.
517 MidpointState<InlineIterator>& midpointState = resolver.midpointState();
518 if (midpointState.betweenMidpoints && midpointState.midpoints[midpointSt ate.currentMidpoint].object() == obj) {
519 midpointState.betweenMidpoints = false;
520 ++midpointState.currentMidpoint;
521 }
522 } 575 }
523 576
524 private: 577 private:
525 unsigned m_nestedIsolateCount; 578 unsigned m_nestedIsolateCount;
526 bool m_haveAddedFakeRunForRootIsolate; 579 bool m_haveAddedFakeRunForRootIsolate;
527 }; 580 };
528 581
529 template <> 582 template <>
530 inline void InlineBidiResolver::appendRun() 583 inline void InlineBidiResolver::appendRun()
531 { 584 {
532 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { 585 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) {
533 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. 586 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines.
534 // Initialize our state depending on if we're starting in the middle of such an inline. 587 // Initialize our state depending on if we're starting in the middle of such an inline.
535 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree? 588 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree?
536 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor)); 589 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor));
537 int start = m_sor.m_pos; 590 int start = m_sor.m_pos;
538 RenderObject* obj = m_sor.m_obj; 591 RenderObject* obj = m_sor.m_obj;
539 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) { 592 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) {
540 if (isolateTracker.inIsolate()) 593 if (isolateTracker.inIsolate())
541 isolateTracker.addFakeRunIfNecessary(obj, start, *this); 594 isolateTracker.addFakeRunIfNecessary(obj, start, obj->length(), *this);
542 else 595 else
543 RenderBlockFlow::appendRunsForObject(m_runs, start, obj->length( ), obj, *this); 596 RenderBlockFlow::appendRunsForObject(m_runs, start, obj->length( ), obj, *this);
544 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables. 597 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables.
545 start = 0; 598 start = 0;
546 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r); 599 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r);
547 } 600 }
548 if (obj) { 601 if (obj) {
549 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX; 602 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX;
550 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) { 603 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) {
551 m_reachedEndOfLine = true; 604 m_reachedEndOfLine = true;
552 pos = endOfLine.m_pos; 605 pos = endOfLine.m_pos;
553 } 606 }
554 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be 607 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be
555 int end = obj->length() ? pos + 1 : 0; 608 int end = obj->length() ? pos + 1 : 0;
556 if (isolateTracker.inIsolate()) 609 if (isolateTracker.inIsolate())
557 isolateTracker.addFakeRunIfNecessary(obj, start, *this); 610 isolateTracker.addFakeRunIfNecessary(obj, start, end, *this);
558 else 611 else
559 RenderBlockFlow::appendRunsForObject(m_runs, start, end, obj, *t his); 612 RenderBlockFlow::appendRunsForObject(m_runs, start, end, obj, *t his);
560 } 613 }
561 614
562 m_eor.increment(); 615 m_eor.increment();
563 m_sor = m_eor; 616 m_sor = m_eor;
564 } 617 }
565 618
566 m_direction = WTF::Unicode::OtherNeutral; 619 m_direction = WTF::Unicode::OtherNeutral;
567 m_status.eor = WTF::Unicode::OtherNeutral; 620 m_status.eor = WTF::Unicode::OtherNeutral;
568 } 621 }
569 622
570 } 623 }
571 624
572 #endif // InlineIterator_h 625 #endif // InlineIterator_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698