| Index: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| index b5f765cbb5ad0760cd763ee29975d0df08b657f1..38b3da71dfb4ce36d3759f735310ad4a078693a5 100644
|
| --- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| @@ -68,22 +68,13 @@ TextIteratorBehavior AdjustBehaviorFlags(const TextIteratorBehavior&);
|
| template <>
|
| TextIteratorBehavior AdjustBehaviorFlags<EditingStrategy>(
|
| const TextIteratorBehavior& behavior) {
|
| - if (!behavior.ForSelectionToString())
|
| - return behavior;
|
| - return TextIteratorBehavior::Builder(behavior)
|
| - .SetExcludeAutofilledValue(true)
|
| - .Build();
|
| + return behavior;
|
| }
|
|
|
| template <>
|
| TextIteratorBehavior AdjustBehaviorFlags<EditingInFlatTreeStrategy>(
|
| const TextIteratorBehavior& behavior) {
|
| - return TextIteratorBehavior::Builder(behavior)
|
| - .SetExcludeAutofilledValue(behavior.ForSelectionToString() ||
|
| - behavior.ExcludeAutofilledValue())
|
| - .SetEntersOpenShadowRoots(false)
|
| - .SetEntersTextControls(false)
|
| - .Build();
|
| + return behavior;
|
| }
|
|
|
| // Checks if |advance()| skips the descendants of |node|, which is the case if
|
| @@ -247,12 +238,6 @@ TextIteratorAlgorithm<Strategy>::~TextIteratorAlgorithm() {
|
| Document* document = OwnerDocument();
|
| if (!document)
|
| return;
|
| - if (behavior_.ForInnerText())
|
| - UseCounter::Count(document, UseCounter::kInnerTextWithShadowTree);
|
| - if (behavior_.ForSelectionToString())
|
| - UseCounter::Count(document, UseCounter::kSelectionToStringWithShadowTree);
|
| - if (behavior_.ForWindowFind())
|
| - UseCounter::Count(document, UseCounter::kWindowFindWithShadowTree);
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -265,10 +250,19 @@ bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const {
|
| }
|
|
|
| template <typename Strategy>
|
| +bool TextIteratorAlgorithm<Strategy>::MayHaveMoreTextRuns() const {
|
| + if (text_box_)
|
| + return true;
|
| + return false;
|
| +}
|
| +
|
| +template <typename Strategy>
|
| void TextIteratorAlgorithm<Strategy>::Advance() {
|
| if (should_stop_)
|
| return;
|
|
|
| + LOG(ERROR) << "TextIterator::Advance";
|
| +
|
| if (node_)
|
| DCHECK(!node_->GetDocument().NeedsLayoutTreeUpdate()) << node_;
|
|
|
| @@ -292,17 +286,13 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
|
| if (ShouldProceedToRemainingText())
|
| ProceedToRemainingText();
|
| // handle remembered text box
|
| - if (text_box_) {
|
| - HandleTextBox();
|
| + if (MayHaveMoreTextRuns()) {
|
| + HandleNextTextRun();
|
| if (text_state_.PositionNode())
|
| return;
|
| }
|
|
|
| while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) {
|
| - if (!should_stop_ && StopsOnFormControls() &&
|
| - HTMLFormControlElement::EnclosingFormControlElement(node_))
|
| - should_stop_ = true;
|
| -
|
| // if the range ends at offset 0 of an element, represent the
|
| // position, but not the content, of that element e.g. if the
|
| // node is a blockflow element, emit a newline that
|
| @@ -328,34 +318,11 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
|
| } else {
|
| // Enter author shadow roots, from youngest, if any and if necessary.
|
| if (iteration_progress_ < kHandledOpenShadowRoots) {
|
| - if (EntersOpenShadowRoots() && node_->IsElementNode() &&
|
| - ToElement(node_)->openShadowRoot()) {
|
| - ShadowRoot* youngest_shadow_root = ToElement(node_)->openShadowRoot();
|
| - DCHECK(youngest_shadow_root->GetType() == ShadowRootType::V0 ||
|
| - youngest_shadow_root->GetType() == ShadowRootType::kOpen);
|
| - node_ = youngest_shadow_root;
|
| - iteration_progress_ = kHandledNone;
|
| - ++shadow_depth_;
|
| - fully_clipped_stack_.PushFullyClippedState(node_);
|
| - continue;
|
| - }
|
| -
|
| iteration_progress_ = kHandledOpenShadowRoots;
|
| }
|
|
|
| // Enter user-agent shadow root, if necessary.
|
| if (iteration_progress_ < kHandledUserAgentShadowRoot) {
|
| - if (EntersTextControls() && layout_object->IsTextControl()) {
|
| - ShadowRoot* user_agent_shadow_root =
|
| - ToElement(node_)->UserAgentShadowRoot();
|
| - DCHECK(user_agent_shadow_root->GetType() ==
|
| - ShadowRootType::kUserAgent);
|
| - node_ = user_agent_shadow_root;
|
| - iteration_progress_ = kHandledNone;
|
| - ++shadow_depth_;
|
| - fully_clipped_stack_.PushFullyClippedState(node_);
|
| - continue;
|
| - }
|
| iteration_progress_ = kHandledUserAgentShadowRoot;
|
| }
|
|
|
| @@ -365,7 +332,7 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
|
| if (layout_object->IsText() &&
|
| node_->getNodeType() ==
|
| Node::kTextNode) { // FIXME: What about kCdataSectionNode?
|
| - if (!fully_clipped_stack_.Top() || IgnoresStyleVisibility())
|
| + if (!fully_clipped_stack_.Top())
|
| handled_node = HandleTextNode();
|
| } else if (layout_object &&
|
| (layout_object->IsImage() || layout_object->IsLayoutPart() ||
|
| @@ -497,15 +464,48 @@ bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter(
|
| }
|
|
|
| template <typename Strategy>
|
| -bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| - if (ExcludesAutofilledValue()) {
|
| - TextControlElement* control = EnclosingTextControl(node_);
|
| - // For security reason, we don't expose suggested value if it is
|
| - // auto-filled.
|
| - if (control && control->IsAutofilled())
|
| - return true;
|
| +bool TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() {
|
| + Text* text_node = ToText(node_);
|
| + LayoutText* layout_object = text_node->GetLayoutObject();
|
| + String str = layout_object->GetText();
|
| +
|
| + if (ShouldHandleFirstLetter(*layout_object)) {
|
| + HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
| + if (first_letter_text_) {
|
| + String first_letter = first_letter_text_->GetText();
|
| + const unsigned run_start = offset_;
|
| + const bool stops_in_first_letter =
|
| + text_node == end_container_ &&
|
| + end_offset_ <= static_cast<int>(first_letter.length());
|
| + const unsigned run_end =
|
| + stops_in_first_letter ? end_offset_ : first_letter.length();
|
| + EmitText(text_node, first_letter_text_, run_start, run_end);
|
| + first_letter_text_ = nullptr;
|
| + text_box_ = 0;
|
| + offset_ = run_end;
|
| + return stops_in_first_letter;
|
| + }
|
| + // We are here only if the DOM and/or layout trees are broken.
|
| + NOTREACHED();
|
| }
|
| + if (layout_object->Style()->Visibility() != EVisibility::kVisible)
|
| + return false;
|
| + const unsigned run_start = offset_ - layout_object->TextStartOffset();
|
| + const unsigned str_length = str.length();
|
| + const unsigned end = (text_node == end_container_)
|
| + ? end_offset_ - layout_object->TextStartOffset()
|
| + : INT_MAX;
|
| + const unsigned run_end = std::min(str_length, end);
|
| +
|
| + if (run_start >= run_end)
|
| + return true;
|
|
|
| + EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end);
|
| + return true;
|
| +}
|
| +
|
| +template <typename Strategy>
|
| +bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| Text* text_node = ToText(node_);
|
| LayoutText* layout_object = text_node->GetLayoutObject();
|
|
|
| @@ -513,64 +513,28 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| String str = layout_object->GetText();
|
|
|
| // handle pre-formatted text
|
| - if (!layout_object->Style()->CollapseWhiteSpace()) {
|
| - if (ShouldHandleFirstLetter(*layout_object)) {
|
| - HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
| - if (first_letter_text_) {
|
| - String first_letter = first_letter_text_->GetText();
|
| - const unsigned run_start = offset_;
|
| - const bool stops_in_first_letter =
|
| - text_node == end_container_ &&
|
| - end_offset_ <= static_cast<int>(first_letter.length());
|
| - const unsigned run_end =
|
| - stops_in_first_letter ? end_offset_ : first_letter.length();
|
| - EmitText(text_node, first_letter_text_, run_start, run_end);
|
| - first_letter_text_ = nullptr;
|
| - text_box_ = 0;
|
| - offset_ = run_end;
|
| - return stops_in_first_letter;
|
| - }
|
| - // We are here only if the DOM and/or layout trees are broken.
|
| - NOTREACHED();
|
| - }
|
| - if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| - !IgnoresStyleVisibility())
|
| - return false;
|
| - const unsigned run_start = offset_ - layout_object->TextStartOffset();
|
| - const unsigned str_length = str.length();
|
| - const unsigned end = (text_node == end_container_)
|
| - ? end_offset_ - layout_object->TextStartOffset()
|
| - : INT_MAX;
|
| - const unsigned run_end = std::min(str_length, end);
|
| -
|
| - if (run_start >= run_end)
|
| - return true;
|
| -
|
| - EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end);
|
| - return true;
|
| - }
|
| + if (!layout_object->Style()->CollapseWhiteSpace())
|
| + return HandlePreFormattedTextNode();
|
|
|
| - if (layout_object->FirstTextBox())
|
| + if (layout_object->FirstTextBox()) {
|
| text_box_ = layout_object->FirstTextBox();
|
| + LOG(ERROR) << "text_box_ set to: " << str.Substring(text_box_->Start(), text_box_->Len());
|
| + }
|
|
|
| - const bool should_handle_first_letter =
|
| - ShouldHandleFirstLetter(*layout_object);
|
| - if (should_handle_first_letter)
|
| + if (ShouldHandleFirstLetter(*layout_object)) {
|
| HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
| + if (first_letter_text_) {
|
| + layout_object = first_letter_text_;
|
| + str = layout_object->GetText();
|
| + }
|
| + }
|
|
|
| - if (!layout_object->FirstTextBox() && str.length() > 0 &&
|
| - !should_handle_first_letter) {
|
| - if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| - !IgnoresStyleVisibility())
|
| + if (!layout_object->FirstTextBox() && str.length() > 0) {
|
| + if (layout_object->Style()->Visibility() != EVisibility::kVisible)
|
| return false;
|
| - last_text_node_ended_with_collapsed_space_ =
|
| - true; // entire block is collapsed space
|
| return true;
|
| }
|
|
|
| - if (first_letter_text_)
|
| - layout_object = first_letter_text_;
|
| -
|
| // Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text)
|
| if (layout_object->ContainsReversedText()) {
|
| sorted_text_boxes_.clear();
|
| @@ -584,175 +548,96 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| text_box_ = sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0];
|
| }
|
|
|
| - HandleTextBox();
|
| + // The current algorithm always sets |text_box_| to the first InlineTextBox
|
| + // under |layout_object|, regardless of the value of |offset_|. This may not
|
| + // be very efficient.
|
| + // There can be collapsed whitespace before |text_box_| that needs handling.
|
| + HandleNextTextRun();
|
| return true;
|
| }
|
|
|
| -// Restore the collapsed space for copy & paste. See http://crbug.com/318925
|
| template <typename Strategy>
|
| -size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace(
|
| - InlineTextBox* next_text_box,
|
| - size_t subrun_end) {
|
| - if (next_text_box || !text_box_->Root().NextRootBox() ||
|
| - text_box_->Root().LastChild() != text_box_)
|
| - return subrun_end;
|
| -
|
| - const String& text = ToLayoutText(node_->GetLayoutObject())->GetText();
|
| - if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 ||
|
| - text[subrun_end - 1] == ' ')
|
| - return subrun_end;
|
| -
|
| - // If there is the leading space in the next line, we don't need to restore
|
| - // the trailing space.
|
| - // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div>
|
| - InlineBox* first_box_of_next_line =
|
| - text_box_->Root().NextRootBox()->FirstChild();
|
| - if (!first_box_of_next_line)
|
| - return subrun_end + 1;
|
| - Node* first_node_of_next_line =
|
| - first_box_of_next_line->GetLineLayoutItem().GetNode();
|
| - if (!first_node_of_next_line ||
|
| - first_node_of_next_line->nodeValue()[0] != ' ')
|
| - return subrun_end + 1;
|
| -
|
| - return subrun_end;
|
| -}
|
| +void TextIteratorAlgorithm<Strategy>::ProceedToNextTextBox() {
|
| + InlineTextBox* next_text_box = nullptr;
|
|
|
| -template <typename Strategy>
|
| -void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| LayoutText* layout_object = first_letter_text_
|
| ? first_letter_text_
|
| : ToLayoutText(node_->GetLayoutObject());
|
| const unsigned text_start_offset = layout_object->TextStartOffset();
|
| + const unsigned end =
|
| + (node_ == end_container_)
|
| + ? static_cast<unsigned>(end_offset_) - text_start_offset
|
| + : INT_MAX;
|
|
|
| - if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| - !IgnoresStyleVisibility()) {
|
| - text_box_ = nullptr;
|
| + if (layout_object->ContainsReversedText()) {
|
| + if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size())
|
| + next_text_box = sorted_text_boxes_[sorted_text_boxes_position_ + 1];
|
| } else {
|
| - String str = layout_object->GetText();
|
| - // Start and end offsets in |str|, i.e., str[start..end - 1] should be
|
| - // emitted (after handling whitespace collapsing).
|
| - const unsigned start = offset_ - layout_object->TextStartOffset();
|
| - const unsigned end =
|
| - (node_ == end_container_)
|
| - ? static_cast<unsigned>(end_offset_) - text_start_offset
|
| - : INT_MAX;
|
| - while (text_box_) {
|
| - const unsigned text_box_start = text_box_->Start();
|
| - const unsigned run_start = std::max(text_box_start, start);
|
| -
|
| - // Check for collapsed space at the start of this run.
|
| - InlineTextBox* first_text_box =
|
| - layout_object->ContainsReversedText()
|
| - ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0])
|
| - : layout_object->FirstTextBox();
|
| - const bool need_space = last_text_node_ended_with_collapsed_space_ ||
|
| - (text_box_ == first_text_box &&
|
| - text_box_start == run_start && run_start > 0);
|
| - if (need_space &&
|
| - !layout_object->Style()->IsCollapsibleWhiteSpace(
|
| - text_state_.LastCharacter()) &&
|
| - text_state_.LastCharacter()) {
|
| - if (last_text_node_ == node_ && run_start > 0 &&
|
| - str[run_start - 1] == ' ') {
|
| - unsigned space_run_start = run_start - 1;
|
| - while (space_run_start > 0 && str[space_run_start - 1] == ' ')
|
| - --space_run_start;
|
| - EmitText(node_, layout_object, space_run_start, space_run_start + 1);
|
| - } else {
|
| - SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start);
|
| - }
|
| - return;
|
| - }
|
| - const unsigned text_box_end = text_box_start + text_box_->Len();
|
| - const unsigned run_end = std::min(text_box_end, end);
|
| -
|
| - // Determine what the next text box will be, but don't advance yet
|
| - InlineTextBox* next_text_box = nullptr;
|
| - if (layout_object->ContainsReversedText()) {
|
| - if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size())
|
| - next_text_box = sorted_text_boxes_[sorted_text_boxes_position_ + 1];
|
| - } else {
|
| - next_text_box = text_box_->NextTextBox();
|
| - }
|
| + next_text_box = text_box_->NextTextBox();
|
| + }
|
| + if (next_text_box && next_text_box->Start() >= end)
|
| + next_text_box = nullptr;
|
|
|
| - // FIXME: Based on the outcome of crbug.com/446502 it's possible we can
|
| - // remove this block. The reason we new it now is because BIDI and
|
| - // FirstLetter seem to have different ideas of where things can split.
|
| - // FirstLetter takes the punctuation + first letter, and BIDI will
|
| - // split out the punctuation and possibly reorder it.
|
| - if (next_text_box &&
|
| - !(next_text_box->GetLineLayoutItem().IsEqual(layout_object))) {
|
| - text_box_ = 0;
|
| - return;
|
| - }
|
| - DCHECK(!next_text_box ||
|
| - next_text_box->GetLineLayoutItem().IsEqual(layout_object));
|
| -
|
| - if (run_start < run_end) {
|
| - // Handle either a single newline character (which becomes a space),
|
| - // or a run of characters that does not include a newline.
|
| - // This effectively translates newlines to spaces without copying the
|
| - // text.
|
| - if (str[run_start] == '\n') {
|
| - // We need to preserve new lines in case of PreLine.
|
| - // See bug crbug.com/317365.
|
| - if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine)
|
| - SpliceBuffer('\n', node_, 0, run_start, run_start);
|
| - else
|
| - SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start + 1);
|
| - offset_ = text_start_offset + run_start + 1;
|
| - } else {
|
| - size_t subrun_end = str.find('\n', run_start);
|
| - if (subrun_end == kNotFound || subrun_end > run_end) {
|
| - subrun_end = run_end;
|
| - subrun_end =
|
| - RestoreCollapsedTrailingSpace(next_text_box, subrun_end);
|
| - }
|
| + DCHECK(!next_text_box ||
|
| + next_text_box->GetLineLayoutItem().IsEqual(layout_object));
|
|
|
| - offset_ = text_start_offset + subrun_end;
|
| - EmitText(node_, layout_object, run_start, subrun_end);
|
| - }
|
| + text_box_ = next_text_box;
|
| + if (text_box_)
|
| + LOG(ERROR) << "text_box_ set to: " << layout_object->GetText().Substring(text_box_->Start(), text_box_->Len());
|
| + else
|
| + LOG(ERROR) << "text_box_ set to null";
|
| + if (layout_object->ContainsReversedText())
|
| + ++sorted_text_boxes_position_;
|
| + return;
|
| +}
|
|
|
| - // If we are doing a subrun that doesn't go to the end of the text box,
|
| - // come back again to finish handling this text box; don't advance to
|
| - // the next one.
|
| - if (static_cast<unsigned>(text_state_.PositionEndOffset()) <
|
| - text_box_end)
|
| - return;
|
| +template <typename Strategy>
|
| +void TextIteratorAlgorithm<Strategy>::HandleNextTextRun() {
|
| + HandleTextBox();
|
| +}
|
|
|
| - if (behavior_.DoesNotEmitSpaceBeyondRangeEnd()) {
|
| - // If the subrun went to the text box end and this end is also the end
|
| - // of the range, do not advance to the next text box and do not
|
| - // generate a space, just stop.
|
| - if (text_box_end == end) {
|
| - text_box_ = nullptr;
|
| - return;
|
| - }
|
| - }
|
| +template <typename Strategy>
|
| +void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| + LayoutText* layout_object = first_letter_text_
|
| + ? first_letter_text_
|
| + : ToLayoutText(node_->GetLayoutObject());
|
| + // We are emitting content of text node |node_|, starting from DOM offset |offset_|.
|
| + // |layout_object| is the LayoutText from which text should be emitted.
|
| + // |text_box_| is an InlineTextBox under |layout_object|, and all visible text
|
| + // before |text_box_| has been emitted.
|
|
|
| - // Advance and return
|
| - const unsigned next_run_start =
|
| - next_text_box ? next_text_box->Start() : str.length();
|
| - if (next_run_start > run_end)
|
| - last_text_node_ended_with_collapsed_space_ =
|
| - true; // collapsed space between runs or at the end
|
| -
|
| - text_box_ = next_text_box;
|
| - if (layout_object->ContainsReversedText())
|
| - ++sorted_text_boxes_position_;
|
| - return;
|
| - }
|
| - // Advance and continue
|
| - text_box_ = next_text_box;
|
| - if (layout_object->ContainsReversedText())
|
| - ++sorted_text_boxes_position_;
|
| + const unsigned text_start_offset = layout_object->TextStartOffset();
|
| +
|
| + String str = layout_object->GetText();
|
| + LOG(ERROR) << "HandleTextBox: " << str << "@" << offset_;
|
| + // Start and end offsets in |str|, i.e., str[start..end - 1] should be
|
| + // emitted (after handling whitespace collapsing).
|
| + const unsigned start = offset_ - layout_object->TextStartOffset();
|
| + const unsigned end =
|
| + (node_ == end_container_)
|
| + ? static_cast<unsigned>(end_offset_) - text_start_offset
|
| + : INT_MAX;
|
| + while (text_box_) {
|
| + const unsigned text_box_start = text_box_->Start();
|
| + const unsigned text_box_end = text_box_start + text_box_->Len();
|
| + const unsigned run_start = std::max(text_box_start, start);
|
| + const unsigned run_end = std::min(text_box_end, end);
|
| + LOG(ERROR) << "Checking text box: " << str.Substring(run_start, run_end - run_start);
|
| +
|
| + if (run_start < run_end) {
|
| + offset_ = text_start_offset + run_end;
|
| + EmitText(node_, layout_object, run_start, run_end);
|
| + ProceedToNextTextBox();
|
| + return;
|
| }
|
| +
|
| + // Advance and continue
|
| + ProceedToNextTextBox();
|
| }
|
|
|
| if (ShouldProceedToRemainingText()) {
|
| ProceedToRemainingText();
|
| - HandleTextBox();
|
| + HandleNextTextRun();
|
| }
|
| }
|
|
|
| @@ -787,8 +672,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter(
|
| return;
|
|
|
| LayoutObject* pseudo_layout_object = first_letter_element->GetLayoutObject();
|
| - if (pseudo_layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| - !IgnoresStyleVisibility())
|
| + if (pseudo_layout_object->Style()->Visibility() != EVisibility::kVisible)
|
| return;
|
|
|
| LayoutObject* first_letter = pseudo_layout_object->SlowFirstChild();
|
| @@ -821,37 +705,11 @@ bool TextIteratorAlgorithm<Strategy>::HandleReplacedElement() {
|
| return false;
|
|
|
| LayoutObject* layout_object = node_->GetLayoutObject();
|
| - if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| - !IgnoresStyleVisibility())
|
| + if (layout_object->Style()->Visibility() != EVisibility::kVisible)
|
| return false;
|
|
|
| - if (EmitsObjectReplacementCharacter()) {
|
| - SpliceBuffer(kObjectReplacementCharacter, Strategy::Parent(*node_), node_,
|
| - 0, 1);
|
| - return true;
|
| - }
|
| -
|
| - if (EntersTextControls() && layout_object->IsTextControl()) {
|
| - // The shadow tree should be already visited.
|
| - return true;
|
| - }
|
| -
|
| - if (EmitsCharactersBetweenAllVisiblePositions()) {
|
| - // We want replaced elements to behave like punctuation for boundary
|
| - // finding, and to simply take up space for the selection preservation
|
| - // code in moveParagraphs, so we use a comma.
|
| - SpliceBuffer(',', Strategy::Parent(*node_), node_, 0, 1);
|
| - return true;
|
| - }
|
| -
|
| text_state_.UpdateForReplacedElement(node_);
|
|
|
| - if (EmitsImageAltText() && TextIterator::SupportsAltText(node_)) {
|
| - text_state_.EmitAltText(node_);
|
| - if (text_state_.length())
|
| - return true;
|
| - }
|
| -
|
| return true;
|
| }
|
|
|
| @@ -871,14 +729,12 @@ bool TextIteratorAlgorithm<Strategy>::ShouldEmitTabBeforeNode(Node* node) {
|
|
|
| template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::ShouldEmitNewlineForNode(
|
| - Node* node,
|
| - bool emits_original_text) {
|
| + Node* node, bool) {
|
| LayoutObject* layout_object = node->GetLayoutObject();
|
|
|
| if (layout_object ? !layout_object->IsBR() : !isHTMLBRElement(node))
|
| return false;
|
| - return emits_original_text || !(node->IsInShadowTree() &&
|
| - isHTMLInputElement(*node->OwnerShadowHost()));
|
| + return !(node->IsInShadowTree() && isHTMLInputElement(*node->OwnerShadowHost()));
|
| }
|
|
|
| static bool ShouldEmitNewlinesBeforeAndAfterNode(Node& node) {
|
| @@ -973,9 +829,6 @@ static bool ShouldEmitExtraNewlineForNode(Node* node) {
|
| // container) or as we hit it (if it's atomic).
|
| template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::ShouldRepresentNodeOffsetZero() {
|
| - if (EmitsCharactersBetweenAllVisiblePositions() && IsRenderedAsTable(node_))
|
| - return true;
|
| -
|
| // Leave element positioned flush with start of a paragraph
|
| // (e.g. do not insert tab before a table cell at the start of a paragraph)
|
| if (text_state_.LastCharacter() == '\n')
|
| @@ -1044,8 +897,7 @@ template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::ShouldEmitSpaceBeforeAndAfterNode(
|
| Node* node) {
|
| return IsRenderedAsTable(node) &&
|
| - (node->GetLayoutObject()->IsInline() ||
|
| - EmitsCharactersBetweenAllVisiblePositions());
|
| + (node->GetLayoutObject()->IsInline());
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -1071,11 +923,8 @@ void TextIteratorAlgorithm<Strategy>::RepresentNodeOffsetZero() {
|
|
|
| template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::HandleNonTextNode() {
|
| - if (ShouldEmitNewlineForNode(node_, EmitsOriginalText()))
|
| + if (ShouldEmitNewlineForNode(node_))
|
| SpliceBuffer('\n', Strategy::Parent(*node_), node_, 0, 1);
|
| - else if (EmitsCharactersBetweenAllVisiblePositions() &&
|
| - node_->GetLayoutObject() && node_->GetLayoutObject()->IsHR())
|
| - SpliceBuffer(kSpaceCharacter, Strategy::Parent(*node_), node_, 0, 1);
|
| else
|
| RepresentNodeOffsetZero();
|
|
|
| @@ -1137,9 +986,9 @@ void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c,
|
| // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in
|
| // TextIterator, but is always reset when we call spliceBuffer, we
|
| // wrap TextIteratorTextState::spliceBuffer() with this function.
|
| + LOG(ERROR) << "SpliceBuffer: " << c;
|
| text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
|
| text_end_offset);
|
| - last_text_node_ended_with_collapsed_space_ = false;
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -1150,9 +999,9 @@ void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node,
|
| // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in
|
| // TextIterator, but is always reset when we call spliceBuffer, we
|
| // wrap TextIteratorTextState::spliceBuffer() with this function.
|
| + LOG(ERROR) << "EmitText: " << layout_object->GetText().Substring(text_start_offset, text_end_offset - text_start_offset);
|
| text_state_.EmitText(text_node, layout_object, text_start_offset,
|
| text_end_offset);
|
| - last_text_node_ended_with_collapsed_space_ = false;
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -1303,6 +1152,8 @@ static String CreatePlainText(const EphemeralRangeTemplate<Strategy>& range,
|
| DocumentLifecycle::DisallowTransitionScope disallow_transition(
|
| range.StartPosition().GetDocument()->Lifecycle());
|
|
|
| + LOG(ERROR) << "CreatePlainText start";
|
| +
|
| TextIteratorAlgorithm<Strategy> it(range.StartPosition(), range.EndPosition(),
|
| behavior);
|
|
|
| @@ -1316,8 +1167,12 @@ static String CreatePlainText(const EphemeralRangeTemplate<Strategy>& range,
|
| StringBuilder builder;
|
| builder.ReserveCapacity(kInitialCapacity);
|
|
|
| - for (; !it.AtEnd(); it.Advance())
|
| + for (; !it.AtEnd(); it.Advance()) {
|
| it.GetText().AppendTextToStringBuilder(builder);
|
| + LOG(ERROR) << "Current builder: " << builder.ToString();
|
| + }
|
| +
|
| + LOG(ERROR) << "CreatePlainText done: " << builder.ToString();
|
|
|
| if (builder.IsEmpty())
|
| return g_empty_string;
|
|
|