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