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; |