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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
OLD | NEW |