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

Side by Side Diff: third_party/WebKit/Source/core/editing/VisibleUnits.cpp

Issue 2928703002: Refactor Most{Back,For}wardCaretPosition() (Closed)
Patch Set: 2017-06-07T13:55:09 Created 3 years, 6 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 position.AnchorNode(), Strategy::CaretMaxOffset(*position.AnchorNode())); 1580 position.AnchorNode(), Strategy::CaretMaxOffset(*position.AnchorNode()));
1581 } 1581 }
1582 1582
1583 template <typename Strategy> 1583 template <typename Strategy>
1584 static PositionTemplate<Strategy> MostBackwardCaretPosition( 1584 static PositionTemplate<Strategy> MostBackwardCaretPosition(
1585 const PositionTemplate<Strategy>& position, 1585 const PositionTemplate<Strategy>& position,
1586 EditingBoundaryCrossingRule rule) { 1586 EditingBoundaryCrossingRule rule) {
1587 DCHECK(!NeedsLayoutTreeUpdate(position)) << position; 1587 DCHECK(!NeedsLayoutTreeUpdate(position)) << position;
1588 TRACE_EVENT0("input", "VisibleUnits::mostBackwardCaretPosition"); 1588 TRACE_EVENT0("input", "VisibleUnits::mostBackwardCaretPosition");
1589 1589
1590 Node* start_node = position.AnchorNode(); 1590 Node* const start_node = position.AnchorNode();
1591 if (!start_node) 1591 if (!start_node)
1592 return PositionTemplate<Strategy>(); 1592 return PositionTemplate<Strategy>();
1593 1593
1594 // iterate backward from there, looking for a qualified position 1594 // iterate backward from there, looking for a qualified position
1595 Node* boundary = EnclosingVisualBoundary<Strategy>(start_node); 1595 Node* const boundary = EnclosingVisualBoundary<Strategy>(start_node);
1596 // FIXME: PositionIterator should respect Before and After positions. 1596 // FIXME: PositionIterator should respect Before and After positions.
1597 PositionIteratorAlgorithm<Strategy> last_visible( 1597 PositionIteratorAlgorithm<Strategy> last_visible(
1598 AdjustPositionForBackwardIteration<Strategy>(position)); 1598 AdjustPositionForBackwardIteration<Strategy>(position));
1599 PositionIteratorAlgorithm<Strategy> current_pos = last_visible; 1599 const bool start_editable = HasEditableStyle(*start_node);
1600 bool start_editable = HasEditableStyle(*start_node);
1601 Node* last_node = start_node; 1600 Node* last_node = start_node;
1602 bool boundary_crossed = false; 1601 bool boundary_crossed = false;
1603 for (; !current_pos.AtStart(); current_pos.Decrement()) { 1602 for (PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
1603 !current_pos.AtStart(); current_pos.Decrement()) {
1604 Node* current_node = current_pos.GetNode(); 1604 Node* current_node = current_pos.GetNode();
1605 // Don't check for an editability change if we haven't moved to a different 1605 // Don't check for an editability change if we haven't moved to a different
1606 // node, to avoid the expense of computing hasEditableStyle(). 1606 // node, to avoid the expense of computing hasEditableStyle().
1607 if (current_node != last_node) { 1607 if (current_node != last_node) {
1608 // Don't change editability. 1608 // Don't change editability.
1609 bool current_editable = HasEditableStyle(*current_node); 1609 const bool current_editable = HasEditableStyle(*current_node);
1610 if (start_editable != current_editable) { 1610 if (start_editable != current_editable) {
1611 if (rule == kCannotCrossEditingBoundary) 1611 if (rule == kCannotCrossEditingBoundary)
1612 break; 1612 break;
1613 boundary_crossed = true; 1613 boundary_crossed = true;
1614 } 1614 }
1615 last_node = current_node; 1615 last_node = current_node;
1616 } 1616 }
1617 1617
1618 // If we've moved to a position that is visually distinct, return the last 1618 // If we've moved to a position that is visually distinct, return the last
1619 // saved position. There is code below that terminates early if we're 1619 // saved position. There is code below that terminates early if we're
1620 // *about* to move to a visually distinct position. 1620 // *about* to move to a visually distinct position.
1621 if (EndsOfNodeAreVisuallyDistinctPositions(current_node) && 1621 if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
1622 current_node != boundary) 1622 current_node != boundary)
1623 return last_visible.DeprecatedComputePosition(); 1623 return last_visible.DeprecatedComputePosition();
1624 1624
1625 // skip position in non-laid out or invisible node 1625 // skip position in non-laid out or invisible node
1626 LayoutObject* layout_object = 1626 LayoutObject* const layout_object =
1627 AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode()); 1627 AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode());
1628 if (!layout_object || 1628 if (!layout_object ||
1629 layout_object->Style()->Visibility() != EVisibility::kVisible) 1629 layout_object->Style()->Visibility() != EVisibility::kVisible)
1630 continue; 1630 continue;
1631 1631
1632 if (rule == kCanCrossEditingBoundary && boundary_crossed) { 1632 if (rule == kCanCrossEditingBoundary && boundary_crossed) {
1633 last_visible = current_pos; 1633 last_visible = current_pos;
1634 break; 1634 break;
1635 } 1635 }
1636 1636
(...skipping 11 matching lines...) Expand all
1648 // Return position after tables and nodes which have content that can be 1648 // Return position after tables and nodes which have content that can be
1649 // ignored. 1649 // ignored.
1650 if (EditingIgnoresContent(*current_node) || 1650 if (EditingIgnoresContent(*current_node) ||
1651 IsDisplayInsideTable(current_node)) { 1651 IsDisplayInsideTable(current_node)) {
1652 if (current_pos.AtEndOfNode()) 1652 if (current_pos.AtEndOfNode())
1653 return PositionTemplate<Strategy>::AfterNode(current_node); 1653 return PositionTemplate<Strategy>::AfterNode(current_node);
1654 continue; 1654 continue;
1655 } 1655 }
1656 1656
1657 // return current position if it is in laid out text 1657 // return current position if it is in laid out text
1658 if (layout_object->IsText() && 1658 if (!layout_object->IsText())
1659 ToLayoutText(layout_object)->FirstTextBox()) { 1659 continue;
1660 LayoutText* const text_layout_object = ToLayoutText(layout_object); 1660 LayoutText* const text_layout_object = ToLayoutText(layout_object);
1661 const unsigned text_start_offset = text_layout_object->TextStartOffset(); 1661 if (!text_layout_object->FirstTextBox())
1662 if (current_node != start_node) { 1662 continue;
1663 // This assertion fires in layout tests in the case-transform.html test 1663 const unsigned text_start_offset = text_layout_object->TextStartOffset();
1664 // because of a mix-up between offsets in the text in the DOM tree with 1664 if (current_node != start_node) {
1665 // text in the layout tree which can have a different length due to case 1665 // This assertion fires in layout tests in the case-transform.html test
1666 // transformation. 1666 // because of a mix-up between offsets in the text in the DOM tree with
1667 // Until we resolve that, disable this so we can run the layout tests! 1667 // text in the layout tree which can have a different length due to case
1668 // DCHECK_GE(currentOffset, layoutObject->caretMaxOffset()); 1668 // transformation.
1669 return PositionTemplate<Strategy>( 1669 // Until we resolve that, disable this so we can run the layout tests!
1670 current_node, layout_object->CaretMaxOffset() + text_start_offset); 1670 // DCHECK_GE(currentOffset, layoutObject->caretMaxOffset());
1671 } 1671 return PositionTemplate<Strategy>(
1672 current_node, layout_object->CaretMaxOffset() + text_start_offset);
1673 }
1672 1674
1673 if (CanBeBackwardCaretPosition(text_layout_object, 1675 if (CanBeBackwardCaretPosition(text_layout_object,
1674 current_pos.OffsetInLeafNode())) { 1676 current_pos.OffsetInLeafNode())) {
1675 return current_pos.ComputePosition(); 1677 return current_pos.ComputePosition();
1676 }
1677 } 1678 }
1678 } 1679 }
1679 return last_visible.DeprecatedComputePosition(); 1680 return last_visible.DeprecatedComputePosition();
1680 } 1681 }
1681 1682
1682 // The text continues on the next line only if the last text box is not on this 1683 // The text continues on the next line only if the last text box is not on this
1683 // line and none of the boxes on this line have a larger start offset. 1684 // line and none of the boxes on this line have a larger start offset.
1684 static bool DoesContinueOnNextLine(const LayoutText& text_layout_object, 1685 static bool DoesContinueOnNextLine(const LayoutText& text_layout_object,
1685 InlineBox* box, 1686 InlineBox* box,
1686 unsigned text_offset) { 1687 unsigned text_offset) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1764 return MostBackwardCaretPosition<EditingInFlatTreeStrategy>(position, rule); 1765 return MostBackwardCaretPosition<EditingInFlatTreeStrategy>(position, rule);
1765 } 1766 }
1766 1767
1767 template <typename Strategy> 1768 template <typename Strategy>
1768 PositionTemplate<Strategy> MostForwardCaretPosition( 1769 PositionTemplate<Strategy> MostForwardCaretPosition(
1769 const PositionTemplate<Strategy>& position, 1770 const PositionTemplate<Strategy>& position,
1770 EditingBoundaryCrossingRule rule) { 1771 EditingBoundaryCrossingRule rule) {
1771 DCHECK(!NeedsLayoutTreeUpdate(position)) << position; 1772 DCHECK(!NeedsLayoutTreeUpdate(position)) << position;
1772 TRACE_EVENT0("input", "VisibleUnits::mostForwardCaretPosition"); 1773 TRACE_EVENT0("input", "VisibleUnits::mostForwardCaretPosition");
1773 1774
1774 Node* start_node = position.AnchorNode(); 1775 Node* const start_node = position.AnchorNode();
1775 if (!start_node) 1776 if (!start_node)
1776 return PositionTemplate<Strategy>(); 1777 return PositionTemplate<Strategy>();
1777 1778
1778 // iterate forward from there, looking for a qualified position 1779 // iterate forward from there, looking for a qualified position
1779 Node* boundary = EnclosingVisualBoundary<Strategy>(start_node); 1780 Node* const boundary = EnclosingVisualBoundary<Strategy>(start_node);
1780 // FIXME: PositionIterator should respect Before and After positions. 1781 // FIXME: PositionIterator should respect Before and After positions.
1781 PositionIteratorAlgorithm<Strategy> last_visible( 1782 PositionIteratorAlgorithm<Strategy> last_visible(
1782 position.IsAfterAnchor() 1783 position.IsAfterAnchor()
1783 ? PositionTemplate<Strategy>::EditingPositionOf( 1784 ? PositionTemplate<Strategy>::EditingPositionOf(
1784 position.AnchorNode(), 1785 position.AnchorNode(),
1785 Strategy::CaretMaxOffset(*position.AnchorNode())) 1786 Strategy::CaretMaxOffset(*position.AnchorNode()))
1786 : position); 1787 : position);
1787 PositionIteratorAlgorithm<Strategy> current_pos = last_visible; 1788 const bool start_editable = HasEditableStyle(*start_node);
1788 bool start_editable = HasEditableStyle(*start_node);
1789 Node* last_node = start_node; 1789 Node* last_node = start_node;
1790 bool boundary_crossed = false; 1790 bool boundary_crossed = false;
1791 for (; !current_pos.AtEnd(); current_pos.Increment()) { 1791 for (PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
1792 !current_pos.AtEnd(); current_pos.Increment()) {
1792 Node* current_node = current_pos.GetNode(); 1793 Node* current_node = current_pos.GetNode();
1793 // Don't check for an editability change if we haven't moved to a different 1794 // Don't check for an editability change if we haven't moved to a different
1794 // node, to avoid the expense of computing hasEditableStyle(). 1795 // node, to avoid the expense of computing hasEditableStyle().
1795 if (current_node != last_node) { 1796 if (current_node != last_node) {
1796 // Don't change editability. 1797 // Don't change editability.
1797 bool current_editable = HasEditableStyle(*current_node); 1798 const bool current_editable = HasEditableStyle(*current_node);
1798 if (start_editable != current_editable) { 1799 if (start_editable != current_editable) {
1799 if (rule == kCannotCrossEditingBoundary) 1800 if (rule == kCannotCrossEditingBoundary)
1800 break; 1801 break;
1801 boundary_crossed = true; 1802 boundary_crossed = true;
1802 } 1803 }
1803 1804
1804 last_node = current_node; 1805 last_node = current_node;
1805 } 1806 }
1806 1807
1807 // stop before going above the body, up into the head 1808 // stop before going above the body, up into the head
1808 // return the last visible streamer position 1809 // return the last visible streamer position
1809 if (isHTMLBodyElement(*current_node) && current_pos.AtEndOfNode()) 1810 if (isHTMLBodyElement(*current_node) && current_pos.AtEndOfNode())
1810 break; 1811 break;
1811 1812
1812 // Do not move to a visually distinct position. 1813 // Do not move to a visually distinct position.
1813 if (EndsOfNodeAreVisuallyDistinctPositions(current_node) && 1814 if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
1814 current_node != boundary) 1815 current_node != boundary)
1815 return last_visible.DeprecatedComputePosition(); 1816 return last_visible.DeprecatedComputePosition();
1816 // Do not move past a visually disinct position. 1817 // Do not move past a visually disinct position.
1817 // Note: The first position after the last in a node whose ends are visually 1818 // Note: The first position after the last in a node whose ends are visually
1818 // distinct positions will be [boundary->parentNode(), 1819 // distinct positions will be [boundary->parentNode(),
1819 // originalBlock->nodeIndex() + 1]. 1820 // originalBlock->nodeIndex() + 1].
1820 if (boundary && Strategy::Parent(*boundary) == current_node) 1821 if (boundary && Strategy::Parent(*boundary) == current_node)
1821 return last_visible.DeprecatedComputePosition(); 1822 return last_visible.DeprecatedComputePosition();
1822 1823
1823 // skip position in non-laid out or invisible node 1824 // skip position in non-laid out or invisible node
1824 LayoutObject* layout_object = 1825 LayoutObject* const layout_object =
1825 AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode()); 1826 AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode());
1826 if (!layout_object || 1827 if (!layout_object ||
1827 layout_object->Style()->Visibility() != EVisibility::kVisible) 1828 layout_object->Style()->Visibility() != EVisibility::kVisible)
1828 continue; 1829 continue;
1829 1830
1830 if (rule == kCanCrossEditingBoundary && boundary_crossed) { 1831 if (rule == kCanCrossEditingBoundary && boundary_crossed)
1831 last_visible = current_pos; 1832 return current_pos.DeprecatedComputePosition();
1832 break;
1833 }
1834 1833
1835 // track last visible streamer position 1834 // track last visible streamer position
1836 if (IsStreamer<Strategy>(current_pos)) 1835 if (IsStreamer<Strategy>(current_pos))
1837 last_visible = current_pos; 1836 last_visible = current_pos;
1838 1837
1839 // Return position before tables and nodes which have content that can be 1838 // Return position before tables and nodes which have content that can be
1840 // ignored. 1839 // ignored.
1841 if (EditingIgnoresContent(*current_node) || 1840 if (EditingIgnoresContent(*current_node) ||
1842 IsDisplayInsideTable(current_node)) { 1841 IsDisplayInsideTable(current_node)) {
1843 if (current_pos.OffsetInLeafNode() <= layout_object->CaretMinOffset()) 1842 if (current_pos.OffsetInLeafNode() <= layout_object->CaretMinOffset())
1844 return PositionTemplate<Strategy>::EditingPositionOf( 1843 return PositionTemplate<Strategy>::EditingPositionOf(
1845 current_node, layout_object->CaretMinOffset()); 1844 current_node, layout_object->CaretMinOffset());
1846 continue; 1845 continue;
1847 } 1846 }
1848 1847
1849 // return current position if it is in laid out text 1848 // return current position if it is in laid out text
1850 if (layout_object->IsText() && 1849 if (!layout_object->IsText())
1851 ToLayoutText(layout_object)->FirstTextBox()) { 1850 continue;
1852 LayoutText* const text_layout_object = ToLayoutText(layout_object); 1851 LayoutText* const text_layout_object = ToLayoutText(layout_object);
1853 const unsigned text_start_offset = text_layout_object->TextStartOffset(); 1852 if (!text_layout_object->FirstTextBox())
1854 if (current_node != start_node) { 1853 continue;
1855 DCHECK(current_pos.AtStartOfNode()); 1854 const unsigned text_start_offset = text_layout_object->TextStartOffset();
1856 return PositionTemplate<Strategy>( 1855 if (current_node != start_node) {
1857 current_node, layout_object->CaretMinOffset() + text_start_offset); 1856 DCHECK(current_pos.AtStartOfNode());
1858 } 1857 return PositionTemplate<Strategy>(
1858 current_node, layout_object->CaretMinOffset() + text_start_offset);
1859 }
1859 1860
1860 if (CanBeForwardCaretPosition(text_layout_object, 1861 if (CanBeForwardCaretPosition(text_layout_object,
1861 current_pos.OffsetInLeafNode())) { 1862 current_pos.OffsetInLeafNode())) {
1862 return current_pos.ComputePosition(); 1863 return current_pos.ComputePosition();
1863 }
1864 } 1864 }
1865 } 1865 }
1866 return last_visible.DeprecatedComputePosition(); 1866 return last_visible.DeprecatedComputePosition();
1867 } 1867 }
1868 1868
1869 // TODO(editing-dev): This function is just moved out from 1869 // TODO(editing-dev): This function is just moved out from
1870 // |MostForwardCaretPosition()|. We should study this function more and 1870 // |MostForwardCaretPosition()|. We should study this function more and
1871 // name it appropriately. See https://trac.webkit.org/changeset/32438/ 1871 // name it appropriately. See https://trac.webkit.org/changeset/32438/
1872 // which introduce this. 1872 // which introduce this.
1873 static bool CanBeForwardCaretPosition(const LayoutText* text_layout_object, 1873 static bool CanBeForwardCaretPosition(const LayoutText* text_layout_object,
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
2772 2772
2773 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { 2773 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) {
2774 return EnclosingIntRect(ComputeTextRectTemplate(range)); 2774 return EnclosingIntRect(ComputeTextRectTemplate(range));
2775 } 2775 }
2776 2776
2777 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { 2777 FloatRect ComputeTextFloatRect(const EphemeralRange& range) {
2778 return ComputeTextRectTemplate(range); 2778 return ComputeTextRectTemplate(range);
2779 } 2779 }
2780 2780
2781 } // namespace blink 2781 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698