Commit 66ad95f1 authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Make LayoutText::SetTextWithOffset() to use slow path for generated break opportunities

This patch changes |NGInlineNodeEditor::Prepare()| to return null for
letting |LayoutText::SetTextWithOffset()| to use slow path when text
content contains generated break opportunity because it is hard to
figure out how many characters removed from text content.

On <b><i><s>ab\n</s>\n</i>\n</b>, text content is "ab\nZZZ",
where "Z" represents U+200B, removing "\n" after "ab" makes text content
to "ab".

Bug: 1125262
Change-Id: I071822dd8be836ee947766ae1877873f35c3af99
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2395136
Auto-Submit: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804671}
parent 2661955a
......@@ -238,6 +238,21 @@ TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteWithBidiControl) {
GetItemsAsString(*text.GetLayoutObject()));
}
// http://crbug.com/1125262
TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteWithGeneratedBreakOpportunity) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return;
InsertStyleElement("#target { white-space:nowrap; }");
SetBodyInnerHTML(u"<p><b><i id=target>ab\n</i>\n</b>\n</div>");
// We have two ZWS for "</i>\n" and "</b>\n".
Text& text = To<Text>(*GetElementById("target")->firstChild());
text.deleteData(2, 1, ASSERT_NO_EXCEPTION); // remove "\n"
EXPECT_EQ("LayoutText has NeedsCollectInlines",
GetItemsAsString(*text.GetLayoutObject()));
}
// http://crbug.com/1123251
TEST_F(LayoutNGTextTest, SetTextWithOffsetEditingTextCollapsedSpace) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
......
......@@ -277,6 +277,7 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
typename OffsetMappingBuilder::SourceNodeScope scope(&mapping_builder_,
nullptr);
NGInlineItem& item = AppendBreakOpportunity(layout_object);
has_generated_break_opportunity_ = true;
item.SetIsGeneratedForLineBreak();
item.SetEndCollapseType(NGInlineItem::kOpaqueToCollapsing);
}
......@@ -1239,6 +1240,7 @@ void NGInlineItemsBuilderTemplate<
// |SegmentText()| will analyze the text and reset |is_bidi_enabled_| if it
// doesn't contain any RTL characters.
data->is_bidi_enabled_ = MayBeBidiEnabled();
data->has_generated_break_opportunity_ = HasGeneratedBreakOpportunity();
// Note: Even if |IsEmptyInline()| is true, |text_| isn't empty, e.g. it
// holds U+FFFC(ORC) for float or abspos.
data->has_line_even_if_empty_ =
......
......@@ -56,6 +56,11 @@ class NGInlineItemsBuilderTemplate {
// Returns whether the items contain any Bidi controls.
bool HasBidiControls() const { return has_bidi_controls_; }
// Returns whether the items contain any generated break opportunity.
bool HasGeneratedBreakOpportunity() const {
return has_generated_break_opportunity_;
}
// Returns if the inline node has no content. For example:
// <span></span> or <span><float></float></span>.
bool IsEmptyInline() const { return is_empty_inline_; }
......@@ -182,6 +187,7 @@ class NGInlineItemsBuilderTemplate {
bool has_bidi_controls_ = false;
bool has_ruby_ = false;
bool has_generated_break_opportunity_ = false;
bool is_empty_inline_ = true;
bool is_block_level_ = true;
bool changes_may_affect_earlier_lines_ = false;
......
......@@ -522,7 +522,8 @@ class NGInlineNodeDataEditor final {
block_flow_->NeedsLayout() ||
block_flow_->GetDocument().NeedsLayoutTreeUpdate() ||
!block_flow_->GetNGInlineNodeData() ||
block_flow_->GetNGInlineNodeData()->text_content.IsNull())
block_flow_->GetNGInlineNodeData()->text_content.IsNull() ||
block_flow_->GetNGInlineNodeData()->HasGeneratedBreakOpportunity())
return nullptr;
// Because of current text content has secured text, e.g. whole text is
......
......@@ -22,6 +22,10 @@ struct CORE_EXPORT NGInlineNodeData : NGInlineItemsData {
return static_cast<TextDirection>(base_direction_);
}
bool HasGeneratedBreakOpportunity() const {
return has_generated_break_opportunity_;
}
bool HasLineEvenIfEmpty() const { return has_line_even_if_empty_; }
bool HasRuby() const { return has_ruby_; }
bool IsEmptyInline() const { return is_empty_inline_; }
......@@ -58,6 +62,10 @@ struct CORE_EXPORT NGInlineNodeData : NGInlineItemsData {
unsigned is_bidi_enabled_ : 1;
unsigned base_direction_ : 1; // TextDirection
// True if text content has U+200B, zero width space, representing generated
// break opportunity.
unsigned has_generated_break_opportunity_ : 1;
// True if there are no inline item items and the associated block is root
// editable element or having "-internal-empty-line-height:fabricated",
// e.g. <div contenteditable></div>, <input type=button value="">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment