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

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: Proposed patch fixing crash 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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 object = object->parent(); 462 object = object->parent();
463 } 463 }
464 return count; 464 return count;
465 } 465 }
466 466
467 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat ion 467 // FIXME: This belongs on InlineBidiResolver, except it's a template specializat ion
468 // of BidiResolver which knows nothing about RenderObjects. 468 // of BidiResolver which knows nothing about RenderObjects.
469 static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolv er, RenderObject* obj, unsigned pos) 469 static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolv er, RenderObject* obj, unsigned pos)
470 { 470 {
471 ASSERT(obj); 471 ASSERT(obj);
472 BidiRun* isolatedRun = new BidiRun(pos, 0, obj, resolver.context(), resolver .dir()); 472 BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolv er.dir());
473 resolver.runs().addRun(isolatedRun); 473 resolver.runs().addRun(isolatedRun);
474 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch eaply 474 // FIXME: isolatedRuns() could be a hash of object->run and then we could ch eaply
475 // ASSERT here that we didn't create multiple objects for the same inline. 475 // ASSERT here that we didn't create multiple objects for the same inline.
476 resolver.isolatedRuns().append(isolatedRun); 476 resolver.isolatedRuns().append(isolatedRun);
477 LineMidpointState& lineMidpointState = resolver.midpointState();
478 resolver.setMidpointStateForIsolatedRun(isolatedRun, lineMidpointState);
479 }
480
481 static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBi diResolver& resolver)
482 {
483 return new BidiRun(start, end, obj, resolver.context(), resolver.dir());
484 }
485
486 enum AppendRunBehavior {
487 AppendingFakeRun,
488 AppendingRunsForObject
489 };
490
491 static void adjustMidpointsAndAppendRunsForObjectIfNeeded(RenderObject* obj, uns igned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behav ior = AppendingFakeRun, BidiRunList<BidiRun>* runs = 0)
492 {
493 if (start > end || RenderBlock::shouldSkipCreatingRunsForObject(obj))
494 return;
495
496 LineMidpointState& lineMidpointState = resolver.midpointState();
497 bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointSta te.numMidpoints);
498 InlineIterator nextMidpoint;
499 if (haveNextMidpoint)
500 nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidp oint];
501 if (lineMidpointState.betweenMidpoints) {
502 if (!(haveNextMidpoint && nextMidpoint.m_obj == obj))
503 return;
504 // This is a new start point. Stop ignoring objects and
505 // adjust our start.
506 lineMidpointState.betweenMidpoints = false;
507 start = nextMidpoint.m_pos;
508 lineMidpointState.currentMidpoint++;
509 if (start < end)
510 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end , resolver, behavior, runs);
511 } else {
512 if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) {
513 if (behavior == AppendingFakeRun)
514 return;
515 runs->addRun(createRun(start, end, obj, resolver));
516 return;
517 }
518
519 // An end midpoint has been encountered within our object. We
520 // need to go ahead and append a run with our endpoint.
521 if (static_cast<int>(nextMidpoint.m_pos + 1) <= end) {
522 lineMidpointState.betweenMidpoints = true;
523 lineMidpointState.currentMidpoint++;
524 if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it.
525 if (static_cast<int>(nextMidpoint.m_pos + 1) > start && behavior == AppendingRunsForObject)
526 runs->addRun(createRun(start, nextMidpoint.m_pos + 1, obj, r esolver));
527 return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMi dpoint.m_pos + 1, end, resolver, behavior, runs);
528 }
529 } else if (behavior == AppendingRunsForObject) {
530 runs->addRun(createRun(start, end, obj, resolver));
531 }
532 }
477 } 533 }
478 534
479 class IsolateTracker { 535 class IsolateTracker {
480 public: 536 public:
481 explicit IsolateTracker(unsigned nestedIsolateCount) 537 explicit IsolateTracker(unsigned nestedIsolateCount)
482 : m_nestedIsolateCount(nestedIsolateCount) 538 : m_nestedIsolateCount(nestedIsolateCount)
483 , m_haveAddedFakeRunForRootIsolate(false) 539 , m_haveAddedFakeRunForRootIsolate(false)
484 { 540 {
485 } 541 }
486 542
487 void enterIsolate() { m_nestedIsolateCount++; } 543 void enterIsolate() { m_nestedIsolateCount++; }
488 void exitIsolate() 544 void exitIsolate()
489 { 545 {
490 ASSERT(m_nestedIsolateCount >= 1); 546 ASSERT(m_nestedIsolateCount >= 1);
491 m_nestedIsolateCount--; 547 m_nestedIsolateCount--;
492 if (!inIsolate()) 548 if (!inIsolate())
493 m_haveAddedFakeRunForRootIsolate = false; 549 m_haveAddedFakeRunForRootIsolate = false;
494 } 550 }
495 bool inIsolate() const { return m_nestedIsolateCount; } 551 bool inIsolate() const { return m_nestedIsolateCount; }
496 552
497 // We don't care if we encounter bidi directional overrides. 553 // We don't care if we encounter bidi directional overrides.
498 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { } 554 void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { }
499 void commitExplicitEmbedding() { } 555 void commitExplicitEmbedding() { }
500 556
501 void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, InlineBidiResolv er& resolver) 557
558 void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, unsigned end, In lineBidiResolver& resolver)
502 { 559 {
503 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine. 560 // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine.
504 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls. 561 // We'll be called for every span inside the isolated span so we just ig nore subsequent calls.
505 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats. 562 // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats.
506 if (m_haveAddedFakeRunForRootIsolate || RenderBlock::shouldSkipCreatingR unsForObject(obj)) 563 if (RenderBlock::shouldSkipCreatingRunsForObject(obj))
leviw_travelin_and_unemployed 2013/10/22 22:25:13 This makes a lot more sense.
507 return; 564 return;
508 m_haveAddedFakeRunForRootIsolate = true; 565 if (!m_haveAddedFakeRunForRootIsolate) {
566 addPlaceholderRunForIsolatedInline(resolver, obj, pos);
567 m_haveAddedFakeRunForRootIsolate = true;
568 }
569 adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, pos, end, resolver);
570
509 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start. 571 // obj and pos together denote a single position in the inline, from whi ch the parsing of the isolate will start.
510 // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the 572 // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the
511 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first. 573 // isolate, when we call createBidiRunsForLine it will stop at whichever comes first.
512 addPlaceholderRunForIsolatedInline(resolver, obj, pos);
513 // FIXME: Inline isolates don't work properly with collapsing whitespace , see webkit.org/b/109624
514 // For now, if we enter an isolate between midpoints, we increment our c urrent midpoint or else
515 // we'll leave the isolate and ignore the content that follows.
516 MidpointState<InlineIterator>& midpointState = resolver.midpointState();
517 if (midpointState.betweenMidpoints && midpointState.midpoints[midpointSt ate.currentMidpoint].object() == obj) {
518 midpointState.betweenMidpoints = false;
519 ++midpointState.currentMidpoint;
520 }
521 } 574 }
522 575
523 private: 576 private:
524 unsigned m_nestedIsolateCount; 577 unsigned m_nestedIsolateCount;
525 bool m_haveAddedFakeRunForRootIsolate; 578 bool m_haveAddedFakeRunForRootIsolate;
526 }; 579 };
527 580
528 template <> 581 template <>
529 inline void InlineBidiResolver::appendRun() 582 inline void InlineBidiResolver::appendRun()
530 { 583 {
531 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) { 584 if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) {
532 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines. 585 // Keep track of when we enter/leave "unicode-bidi: isolate" inlines.
533 // Initialize our state depending on if we're starting in the middle of such an inline. 586 // Initialize our state depending on if we're starting in the middle of such an inline.
534 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree? 587 // FIXME: Could this initialize from this->inIsolate() instead of walkin g up the render tree?
535 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor)); 588 IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor));
536 int start = m_sor.m_pos; 589 int start = m_sor.m_pos;
537 RenderObject* obj = m_sor.m_obj; 590 RenderObject* obj = m_sor.m_obj;
538 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) { 591 while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) {
539 if (isolateTracker.inIsolate()) 592 if (isolateTracker.inIsolate())
540 isolateTracker.addFakeRunIfNecessary(obj, start, *this); 593 isolateTracker.addFakeRunIfNecessary(obj, start, obj->length(), *this);
541 else 594 else
542 RenderBlock::appendRunsForObject(m_runs, start, obj->length(), o bj, *this); 595 RenderBlock::appendRunsForObject(m_runs, start, obj->length(), o bj, *this);
543 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables. 596 // FIXME: start/obj should be an InlineIterator instead of two separ ate variables.
544 start = 0; 597 start = 0;
545 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r); 598 obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracke r);
546 } 599 }
547 if (obj) { 600 if (obj) {
548 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX; 601 unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : INT_MAX;
549 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) { 602 if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) {
550 m_reachedEndOfLine = true; 603 m_reachedEndOfLine = true;
551 pos = endOfLine.m_pos; 604 pos = endOfLine.m_pos;
552 } 605 }
553 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be 606 // It's OK to add runs for zero-length RenderObjects, just don't mak e the run larger than it should be
554 int end = obj->length() ? pos + 1 : 0; 607 int end = obj->length() ? pos + 1 : 0;
555 if (isolateTracker.inIsolate()) 608 if (isolateTracker.inIsolate())
556 isolateTracker.addFakeRunIfNecessary(obj, start, *this); 609 isolateTracker.addFakeRunIfNecessary(obj, start, end, *this);
557 else 610 else
558 RenderBlock::appendRunsForObject(m_runs, start, end, obj, *this) ; 611 RenderBlock::appendRunsForObject(m_runs, start, end, obj, *this) ;
559 } 612 }
560 613
561 m_eor.increment(); 614 m_eor.increment();
562 m_sor = m_eor; 615 m_sor = m_eor;
563 } 616 }
564 617
565 m_direction = WTF::Unicode::OtherNeutral; 618 m_direction = WTF::Unicode::OtherNeutral;
566 m_status.eor = WTF::Unicode::OtherNeutral; 619 m_status.eor = WTF::Unicode::OtherNeutral;
567 } 620 }
568 621
569 } 622 }
570 623
571 #endif // InlineIterator_h 624 #endif // InlineIterator_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698