| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
| 3 * reserved. | 3 * reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 Node* boundary = position.ComputeContainerNode(); | 298 Node* boundary = position.ComputeContainerNode(); |
| 299 while (boundary != document_element && | 299 while (boundary != document_element && |
| 300 NonShadowBoundaryParentNode<Strategy>(boundary) && | 300 NonShadowBoundaryParentNode<Strategy>(boundary) && |
| 301 HasEditableStyle(*anchor_node) == | 301 HasEditableStyle(*anchor_node) == |
| 302 HasEditableStyle(*Strategy::Parent(*boundary))) | 302 HasEditableStyle(*Strategy::Parent(*boundary))) |
| 303 boundary = NonShadowBoundaryParentNode<Strategy>(boundary); | 303 boundary = NonShadowBoundaryParentNode<Strategy>(boundary); |
| 304 | 304 |
| 305 return boundary; | 305 return boundary; |
| 306 } | 306 } |
| 307 | 307 |
| 308 enum BoundarySearchContextAvailability { | |
| 309 kDontHaveMoreContext, | |
| 310 kMayHaveMoreContext | |
| 311 }; | |
| 312 | |
| 313 typedef unsigned (*BoundarySearchFunction)(const UChar*, | |
| 314 unsigned length, | |
| 315 unsigned offset, | |
| 316 BoundarySearchContextAvailability, | |
| 317 bool& need_more_context); | |
| 318 | |
| 319 template <typename Strategy> | 308 template <typename Strategy> |
| 320 static PositionTemplate<Strategy> PreviousBoundary( | 309 static PositionTemplate<Strategy> PreviousBoundaryAlgorithm( |
| 321 const VisiblePositionTemplate<Strategy>& c, | 310 const VisiblePositionTemplate<Strategy>& c, |
| 322 BoundarySearchFunction search_function) { | 311 BoundarySearchFunction search_function) { |
| 323 DCHECK(c.IsValid()) << c; | 312 DCHECK(c.IsValid()) << c; |
| 324 const PositionTemplate<Strategy> pos = c.DeepEquivalent(); | 313 const PositionTemplate<Strategy> pos = c.DeepEquivalent(); |
| 325 Node* boundary = ParentEditingBoundary(pos); | 314 Node* boundary = ParentEditingBoundary(pos); |
| 326 if (!boundary) | 315 if (!boundary) |
| 327 return PositionTemplate<Strategy>(); | 316 return PositionTemplate<Strategy>(); |
| 328 | 317 |
| 329 const PositionTemplate<Strategy> start = | 318 const PositionTemplate<Strategy> start = |
| 330 PositionTemplate<Strategy>::EditingPositionOf(boundary, 0) | 319 PositionTemplate<Strategy>::EditingPositionOf(boundary, 0) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 | 396 |
| 408 // Use the character iterator to translate the next value into a DOM | 397 // Use the character iterator to translate the next value into a DOM |
| 409 // position. | 398 // position. |
| 410 BackwardsCharacterIteratorAlgorithm<Strategy> char_it(start, end); | 399 BackwardsCharacterIteratorAlgorithm<Strategy> char_it(start, end); |
| 411 char_it.Advance(string.Size() - suffix_length - next); | 400 char_it.Advance(string.Size() - suffix_length - next); |
| 412 // TODO(yosin) charIt can get out of shadow host. | 401 // TODO(yosin) charIt can get out of shadow host. |
| 413 return char_it.EndPosition(); | 402 return char_it.EndPosition(); |
| 414 } | 403 } |
| 415 | 404 |
| 416 template <typename Strategy> | 405 template <typename Strategy> |
| 417 static PositionTemplate<Strategy> NextBoundary( | 406 static PositionTemplate<Strategy> NextBoundaryAlgorithm( |
| 418 const VisiblePositionTemplate<Strategy>& c, | 407 const VisiblePositionTemplate<Strategy>& c, |
| 419 BoundarySearchFunction search_function) { | 408 BoundarySearchFunction search_function) { |
| 420 DCHECK(c.IsValid()) << c; | 409 DCHECK(c.IsValid()) << c; |
| 421 PositionTemplate<Strategy> pos = c.DeepEquivalent(); | 410 PositionTemplate<Strategy> pos = c.DeepEquivalent(); |
| 422 Node* boundary = ParentEditingBoundary(pos); | 411 Node* boundary = ParentEditingBoundary(pos); |
| 423 if (!boundary) | 412 if (!boundary) |
| 424 return PositionTemplate<Strategy>(); | 413 return PositionTemplate<Strategy>(); |
| 425 | 414 |
| 426 Document& d = boundary->GetDocument(); | 415 Document& d = boundary->GetDocument(); |
| 427 const PositionTemplate<Strategy> start(pos.ParentAnchoredEquivalent()); | 416 const PositionTemplate<Strategy> start(pos.ParentAnchoredEquivalent()); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 CreateVisiblePosition(char_it.StartPosition()).DeepEquivalent()) { | 510 CreateVisiblePosition(char_it.StartPosition()).DeepEquivalent()) { |
| 522 char_it.Advance(1); | 511 char_it.Advance(1); |
| 523 pos = char_it.StartPosition(); | 512 pos = char_it.StartPosition(); |
| 524 } | 513 } |
| 525 } | 514 } |
| 526 } | 515 } |
| 527 | 516 |
| 528 return pos; | 517 return pos; |
| 529 } | 518 } |
| 530 | 519 |
| 531 // --------- | 520 Position NextBoundary(const VisiblePosition& visible_position, |
| 532 | 521 BoundarySearchFunction search_function) { |
| 533 static unsigned StartWordBoundary( | 522 return NextBoundaryAlgorithm(visible_position, search_function); |
| 534 const UChar* characters, | |
| 535 unsigned length, | |
| 536 unsigned offset, | |
| 537 BoundarySearchContextAvailability may_have_more_context, | |
| 538 bool& need_more_context) { | |
| 539 TRACE_EVENT0("blink", "startWordBoundary"); | |
| 540 DCHECK(offset); | |
| 541 if (may_have_more_context && | |
| 542 !StartOfLastWordBoundaryContext(characters, offset)) { | |
| 543 need_more_context = true; | |
| 544 return 0; | |
| 545 } | |
| 546 need_more_context = false; | |
| 547 int start, end; | |
| 548 U16_BACK_1(characters, 0, offset); | |
| 549 FindWordBoundary(characters, length, offset, &start, &end); | |
| 550 return start; | |
| 551 } | 523 } |
| 552 | 524 |
| 553 template <typename Strategy> | 525 PositionInFlatTree NextBoundary( |
| 554 static PositionTemplate<Strategy> StartOfWordAlgorithm( | 526 const VisiblePositionInFlatTree& visible_position, |
| 555 const VisiblePositionTemplate<Strategy>& c, | 527 BoundarySearchFunction search_function) { |
| 556 EWordSide side) { | 528 return NextBoundaryAlgorithm(visible_position, search_function); |
| 557 DCHECK(c.IsValid()) << c; | |
| 558 // TODO(yosin) This returns a null VP for c at the start of the document | |
| 559 // and |side| == |LeftWordIfOnBoundary| | |
| 560 VisiblePositionTemplate<Strategy> p = c; | |
| 561 if (side == kRightWordIfOnBoundary) { | |
| 562 // at paragraph end, the startofWord is the current position | |
| 563 if (IsEndOfParagraph(c)) | |
| 564 return c.DeepEquivalent(); | |
| 565 | |
| 566 p = NextPositionOf(c); | |
| 567 if (p.IsNull()) | |
| 568 return c.DeepEquivalent(); | |
| 569 } | |
| 570 return PreviousBoundary(p, StartWordBoundary); | |
| 571 } | 529 } |
| 572 | 530 |
| 573 Position StartOfWordPosition(const VisiblePosition& position, EWordSide side) { | 531 Position PreviousBoundary(const VisiblePosition& visible_position, |
| 574 return StartOfWordAlgorithm<EditingStrategy>(position, side); | 532 BoundarySearchFunction search_function) { |
| 533 return PreviousBoundaryAlgorithm(visible_position, search_function); |
| 575 } | 534 } |
| 576 | 535 |
| 577 VisiblePosition StartOfWord(const VisiblePosition& position, EWordSide side) { | 536 PositionInFlatTree PreviousBoundary( |
| 578 return CreateVisiblePosition(StartOfWordPosition(position, side)); | 537 const VisiblePositionInFlatTree& visible_position, |
| 579 } | 538 BoundarySearchFunction search_function) { |
| 580 | 539 return PreviousBoundaryAlgorithm(visible_position, search_function); |
| 581 PositionInFlatTree StartOfWordPosition( | |
| 582 const VisiblePositionInFlatTree& position, | |
| 583 EWordSide side) { | |
| 584 return StartOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side); | |
| 585 } | |
| 586 | |
| 587 VisiblePositionInFlatTree StartOfWord(const VisiblePositionInFlatTree& position, | |
| 588 EWordSide side) { | |
| 589 return CreateVisiblePosition(StartOfWordPosition(position, side)); | |
| 590 } | |
| 591 | |
| 592 static unsigned EndWordBoundary( | |
| 593 const UChar* characters, | |
| 594 unsigned length, | |
| 595 unsigned offset, | |
| 596 BoundarySearchContextAvailability may_have_more_context, | |
| 597 bool& need_more_context) { | |
| 598 DCHECK_LE(offset, length); | |
| 599 if (may_have_more_context && | |
| 600 EndOfFirstWordBoundaryContext(characters + offset, length - offset) == | |
| 601 static_cast<int>(length - offset)) { | |
| 602 need_more_context = true; | |
| 603 return length; | |
| 604 } | |
| 605 need_more_context = false; | |
| 606 return FindWordEndBoundary(characters, length, offset); | |
| 607 } | |
| 608 | |
| 609 template <typename Strategy> | |
| 610 static PositionTemplate<Strategy> EndOfWordAlgorithm( | |
| 611 const VisiblePositionTemplate<Strategy>& c, | |
| 612 EWordSide side) { | |
| 613 DCHECK(c.IsValid()) << c; | |
| 614 VisiblePositionTemplate<Strategy> p = c; | |
| 615 if (side == kLeftWordIfOnBoundary) { | |
| 616 if (IsStartOfParagraph(c)) | |
| 617 return c.DeepEquivalent(); | |
| 618 | |
| 619 p = PreviousPositionOf(c); | |
| 620 if (p.IsNull()) | |
| 621 return c.DeepEquivalent(); | |
| 622 } else if (IsEndOfParagraph(c)) { | |
| 623 return c.DeepEquivalent(); | |
| 624 } | |
| 625 | |
| 626 return NextBoundary(p, EndWordBoundary); | |
| 627 } | |
| 628 | |
| 629 Position EndOfWordPosition(const VisiblePosition& position, EWordSide side) { | |
| 630 return EndOfWordAlgorithm<EditingStrategy>(position, side); | |
| 631 } | |
| 632 | |
| 633 VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) { | |
| 634 return CreateVisiblePosition(EndOfWordPosition(position, side), | |
| 635 VP_UPSTREAM_IF_POSSIBLE); | |
| 636 } | |
| 637 | |
| 638 PositionInFlatTree EndOfWordPosition(const VisiblePositionInFlatTree& position, | |
| 639 EWordSide side) { | |
| 640 return EndOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side); | |
| 641 } | |
| 642 | |
| 643 VisiblePositionInFlatTree EndOfWord(const VisiblePositionInFlatTree& position, | |
| 644 EWordSide side) { | |
| 645 return CreateVisiblePosition(EndOfWordPosition(position, side), | |
| 646 VP_UPSTREAM_IF_POSSIBLE); | |
| 647 } | |
| 648 | |
| 649 static unsigned PreviousWordPositionBoundary( | |
| 650 const UChar* characters, | |
| 651 unsigned length, | |
| 652 unsigned offset, | |
| 653 BoundarySearchContextAvailability may_have_more_context, | |
| 654 bool& need_more_context) { | |
| 655 if (may_have_more_context && | |
| 656 !StartOfLastWordBoundaryContext(characters, offset)) { | |
| 657 need_more_context = true; | |
| 658 return 0; | |
| 659 } | |
| 660 need_more_context = false; | |
| 661 return FindNextWordFromIndex(characters, length, offset, false); | |
| 662 } | |
| 663 | |
| 664 VisiblePosition PreviousWordPosition(const VisiblePosition& c) { | |
| 665 DCHECK(c.IsValid()) << c; | |
| 666 VisiblePosition prev = | |
| 667 CreateVisiblePosition(PreviousBoundary(c, PreviousWordPositionBoundary)); | |
| 668 return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent()); | |
| 669 } | |
| 670 | |
| 671 static unsigned NextWordPositionBoundary( | |
| 672 const UChar* characters, | |
| 673 unsigned length, | |
| 674 unsigned offset, | |
| 675 BoundarySearchContextAvailability may_have_more_context, | |
| 676 bool& need_more_context) { | |
| 677 if (may_have_more_context && | |
| 678 EndOfFirstWordBoundaryContext(characters + offset, length - offset) == | |
| 679 static_cast<int>(length - offset)) { | |
| 680 need_more_context = true; | |
| 681 return length; | |
| 682 } | |
| 683 need_more_context = false; | |
| 684 return FindNextWordFromIndex(characters, length, offset, true); | |
| 685 } | |
| 686 | |
| 687 VisiblePosition NextWordPosition(const VisiblePosition& c) { | |
| 688 DCHECK(c.IsValid()) << c; | |
| 689 VisiblePosition next = CreateVisiblePosition( | |
| 690 NextBoundary(c, NextWordPositionBoundary), VP_UPSTREAM_IF_POSSIBLE); | |
| 691 return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent()); | |
| 692 } | 540 } |
| 693 | 541 |
| 694 // --------- | 542 // --------- |
| 695 | 543 |
| 696 static unsigned StartSentenceBoundary(const UChar* characters, | 544 static unsigned StartSentenceBoundary(const UChar* characters, |
| 697 unsigned length, | 545 unsigned length, |
| 698 unsigned, | 546 unsigned, |
| 699 BoundarySearchContextAvailability, | 547 BoundarySearchContextAvailability, |
| 700 bool&) { | 548 bool&) { |
| 701 TextBreakIterator* iterator = SentenceBreakIterator(characters, length); | 549 TextBreakIterator* iterator = SentenceBreakIterator(characters, length); |
| (...skipping 2070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2772 | 2620 |
| 2773 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { | 2621 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { |
| 2774 return EnclosingIntRect(ComputeTextRectTemplate(range)); | 2622 return EnclosingIntRect(ComputeTextRectTemplate(range)); |
| 2775 } | 2623 } |
| 2776 | 2624 |
| 2777 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { | 2625 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { |
| 2778 return ComputeTextRectTemplate(range); | 2626 return ComputeTextRectTemplate(range); |
| 2779 } | 2627 } |
| 2780 | 2628 |
| 2781 } // namespace blink | 2629 } // namespace blink |
| OLD | NEW |