| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/ng/inline/ng_inline_items_builder.h" | 5 #include "core/layout/ng/inline/ng_inline_items_builder.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutInline.h" | 7 #include "core/layout/LayoutInline.h" |
| 8 #include "core/layout/ng/inline/ng_inline_node.h" | 8 #include "core/layout/ng/inline/ng_inline_node.h" |
| 9 #include "core/layout/ng/inline/ng_offset_mapping_builder.h" |
| 9 #include "core/style/ComputedStyle.h" | 10 #include "core/style/ComputedStyle.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 12 |
| 12 namespace blink { | 13 namespace blink { |
| 13 | 14 |
| 14 namespace { | 15 namespace { |
| 15 | 16 |
| 16 static PassRefPtr<ComputedStyle> CreateWhitespaceStyle(EWhiteSpace whitespace) { | 17 static PassRefPtr<ComputedStyle> CreateWhitespaceStyle(EWhiteSpace whitespace) { |
| 17 RefPtr<ComputedStyle> style(ComputedStyle::Create()); | 18 RefPtr<ComputedStyle> style(ComputedStyle::Create()); |
| 18 style->SetWhiteSpace(whitespace); | 19 style->SetWhiteSpace(whitespace); |
| 19 return style; | 20 return style; |
| 20 } | 21 } |
| 21 | 22 |
| 23 static String GetCollapsed(const NGOffsetMappingBuilder& builder) { |
| 24 Vector<unsigned> mapping = builder.DumpOffsetMappingForTesting(); |
| 25 |
| 26 Vector<unsigned> collapsed_indexes; |
| 27 for (unsigned i = 0; i + 1 < mapping.size(); ++i) { |
| 28 if (mapping[i] == mapping[i + 1]) |
| 29 collapsed_indexes.push_back(i); |
| 30 } |
| 31 |
| 32 StringBuilder result; |
| 33 result.Append('{'); |
| 34 bool first = true; |
| 35 for (unsigned index : collapsed_indexes) { |
| 36 if (!first) |
| 37 result.Append(", "); |
| 38 result.AppendNumber(index); |
| 39 first = false; |
| 40 } |
| 41 result.Append('}'); |
| 42 return result.ToString(); |
| 43 } |
| 44 |
| 22 class NGInlineItemsBuilderTest : public ::testing::Test { | 45 class NGInlineItemsBuilderTest : public ::testing::Test { |
| 23 protected: | 46 protected: |
| 24 void SetUp() override { style_ = ComputedStyle::Create(); } | 47 void SetUp() override { style_ = ComputedStyle::Create(); } |
| 25 | 48 |
| 26 void SetWhiteSpace(EWhiteSpace whitespace) { | 49 void SetWhiteSpace(EWhiteSpace whitespace) { |
| 27 style_->SetWhiteSpace(whitespace); | 50 style_->SetWhiteSpace(whitespace); |
| 28 } | 51 } |
| 29 | 52 |
| 30 const String& TestAppend(const String inputs[], int size) { | 53 const String& TestAppend(const String inputs[], int size) { |
| 31 items_.clear(); | 54 items_.clear(); |
| 32 NGInlineItemsBuilder builder(&items_); | 55 NGInlineItemsBuilderForOffsetMapping builder(&items_); |
| 33 for (int i = 0; i < size; i++) | 56 for (int i = 0; i < size; i++) |
| 34 builder.Append(inputs[i], style_.Get()); | 57 builder.Append(inputs[i], style_.Get()); |
| 35 text_ = builder.ToString(); | 58 text_ = builder.ToString(); |
| 59 collapsed_ = GetCollapsed(builder.GetOffsetMappingBuilder()); |
| 36 ValidateItems(); | 60 ValidateItems(); |
| 37 return text_; | 61 return text_; |
| 38 } | 62 } |
| 39 | 63 |
| 40 const String& TestAppend(const String& input) { | 64 const String& TestAppend(const String& input) { |
| 41 String inputs[] = {input}; | 65 String inputs[] = {input}; |
| 42 return TestAppend(inputs, 1); | 66 return TestAppend(inputs, 1); |
| 43 } | 67 } |
| 44 | 68 |
| 45 const String& TestAppend(const String& input1, const String& input2) { | 69 const String& TestAppend(const String& input1, const String& input2) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 60 const NGInlineItem& item = items_[i]; | 84 const NGInlineItem& item = items_[i]; |
| 61 EXPECT_EQ(current_offset, item.StartOffset()); | 85 EXPECT_EQ(current_offset, item.StartOffset()); |
| 62 EXPECT_LT(item.StartOffset(), item.EndOffset()); | 86 EXPECT_LT(item.StartOffset(), item.EndOffset()); |
| 63 current_offset = item.EndOffset(); | 87 current_offset = item.EndOffset(); |
| 64 } | 88 } |
| 65 EXPECT_EQ(current_offset, text_.length()); | 89 EXPECT_EQ(current_offset, text_.length()); |
| 66 } | 90 } |
| 67 | 91 |
| 68 Vector<NGInlineItem> items_; | 92 Vector<NGInlineItem> items_; |
| 69 String text_; | 93 String text_; |
| 94 String collapsed_; |
| 70 RefPtr<ComputedStyle> style_; | 95 RefPtr<ComputedStyle> style_; |
| 71 }; | 96 }; |
| 72 | 97 |
| 73 #define TestWhitespaceValue(expected, input, whitespace) \ | 98 #define TestWhitespaceValue(expected_text, expected_collapsed, input, \ |
| 74 SetWhiteSpace(whitespace); \ | 99 whitespace) \ |
| 75 EXPECT_EQ(expected, TestAppend(input)) << "white-space: " #whitespace; | 100 SetWhiteSpace(whitespace); \ |
| 101 EXPECT_EQ(expected_text, TestAppend(input)) << "white-space: " #whitespace; \ |
| 102 EXPECT_EQ(expected_collapsed, collapsed_); |
| 76 | 103 |
| 77 TEST_F(NGInlineItemsBuilderTest, CollapseSpaces) { | 104 TEST_F(NGInlineItemsBuilderTest, CollapseSpaces) { |
| 78 String input("text text text text"); | 105 String input("text text text text"); |
| 79 String collapsed("text text text text"); | 106 String collapsed("text text text text"); |
| 80 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNormal); | 107 String collapsed_indexes("{10, 16, 17}"); |
| 81 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNowrap); | 108 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 82 TestWhitespaceValue(collapsed, input, EWhiteSpace::kWebkitNowrap); | 109 EWhiteSpace::kNormal); |
| 83 TestWhitespaceValue(collapsed, input, EWhiteSpace::kPreLine); | 110 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 84 TestWhitespaceValue(input, input, EWhiteSpace::kPre); | 111 EWhiteSpace::kNowrap); |
| 85 TestWhitespaceValue(input, input, EWhiteSpace::kPreWrap); | 112 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 113 EWhiteSpace::kWebkitNowrap); |
| 114 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 115 EWhiteSpace::kPreLine); |
| 116 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPre); |
| 117 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPreWrap); |
| 86 } | 118 } |
| 87 | 119 |
| 88 TEST_F(NGInlineItemsBuilderTest, CollapseTabs) { | 120 TEST_F(NGInlineItemsBuilderTest, CollapseTabs) { |
| 89 String input("text\ttext\t text \t text"); | 121 String input("text text text text"); |
| 90 String collapsed("text text text text"); | 122 String collapsed("text text text text"); |
| 91 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNormal); | 123 String collapsed_indexes("{10, 16, 17}"); |
| 92 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNowrap); | 124 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 93 TestWhitespaceValue(collapsed, input, EWhiteSpace::kWebkitNowrap); | 125 EWhiteSpace::kNormal); |
| 94 TestWhitespaceValue(collapsed, input, EWhiteSpace::kPreLine); | 126 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 95 TestWhitespaceValue(input, input, EWhiteSpace::kPre); | 127 EWhiteSpace::kNowrap); |
| 96 TestWhitespaceValue(input, input, EWhiteSpace::kPreWrap); | 128 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 129 EWhiteSpace::kWebkitNowrap); |
| 130 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 131 EWhiteSpace::kPreLine); |
| 132 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPre); |
| 133 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPreWrap); |
| 97 } | 134 } |
| 98 | 135 |
| 99 TEST_F(NGInlineItemsBuilderTest, CollapseNewLines) { | 136 TEST_F(NGInlineItemsBuilderTest, CollapseNewLines) { |
| 100 String input("text\ntext \n text\n\ntext"); | 137 String input("text\ntext \n text\n\ntext"); |
| 101 String collapsed("text text text text"); | 138 String collapsed("text text text text"); |
| 102 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNormal); | 139 String collapsed_indexes("{10, 11, 17}"); |
| 103 TestWhitespaceValue(collapsed, input, EWhiteSpace::kNowrap); | 140 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 104 TestWhitespaceValue("text\ntext\ntext\n\ntext", input, EWhiteSpace::kPreLine); | 141 EWhiteSpace::kNormal); |
| 105 TestWhitespaceValue(input, input, EWhiteSpace::kPre); | 142 TestWhitespaceValue(collapsed, collapsed_indexes, input, |
| 106 TestWhitespaceValue(input, input, EWhiteSpace::kPreWrap); | 143 EWhiteSpace::kNowrap); |
| 144 TestWhitespaceValue("text\ntext\ntext\n\ntext", "{9, 11}", input, |
| 145 EWhiteSpace::kPreLine); |
| 146 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPre); |
| 147 TestWhitespaceValue(input, "{}", input, EWhiteSpace::kPreWrap); |
| 107 } | 148 } |
| 108 | 149 |
| 109 TEST_F(NGInlineItemsBuilderTest, CollapseNewlinesAsSpaces) { | 150 TEST_F(NGInlineItemsBuilderTest, CollapseNewlinesAsSpaces) { |
| 110 EXPECT_EQ("text text", TestAppend("text\ntext")); | 151 EXPECT_EQ("text text", TestAppend("text\ntext")); |
| 152 EXPECT_EQ("{}", collapsed_); |
| 111 EXPECT_EQ("text text", TestAppend("text\n\ntext")); | 153 EXPECT_EQ("text text", TestAppend("text\n\ntext")); |
| 154 EXPECT_EQ("{5}", collapsed_); |
| 112 EXPECT_EQ("text text", TestAppend("text \n\n text")); | 155 EXPECT_EQ("text text", TestAppend("text \n\n text")); |
| 156 EXPECT_EQ("{5, 6, 7}", collapsed_); |
| 113 EXPECT_EQ("text text", TestAppend("text \n \n text")); | 157 EXPECT_EQ("text text", TestAppend("text \n \n text")); |
| 158 EXPECT_EQ("{5, 6, 7, 8}", collapsed_); |
| 114 } | 159 } |
| 115 | 160 |
| 116 TEST_F(NGInlineItemsBuilderTest, CollapseAcrossElements) { | 161 TEST_F(NGInlineItemsBuilderTest, CollapseAcrossElements) { |
| 117 EXPECT_EQ("text text", TestAppend("text ", " text")) | 162 EXPECT_EQ("text text", TestAppend("text ", " text")) |
| 118 << "Spaces are collapsed even when across elements."; | 163 << "Spaces are collapsed even when across elements."; |
| 164 EXPECT_EQ("{5}", collapsed_); |
| 119 } | 165 } |
| 120 | 166 |
| 121 TEST_F(NGInlineItemsBuilderTest, CollapseLeadingSpaces) { | 167 TEST_F(NGInlineItemsBuilderTest, CollapseLeadingSpaces) { |
| 122 EXPECT_EQ("text", TestAppend(" text")); | 168 EXPECT_EQ("text", TestAppend(" text")); |
| 169 EXPECT_EQ("{0, 1}", collapsed_); |
| 123 EXPECT_EQ("text", TestAppend(" ", "text")); | 170 EXPECT_EQ("text", TestAppend(" ", "text")); |
| 171 EXPECT_EQ("{0}", collapsed_); |
| 124 EXPECT_EQ("text", TestAppend(" ", " text")); | 172 EXPECT_EQ("text", TestAppend(" ", " text")); |
| 173 EXPECT_EQ("{0, 1}", collapsed_); |
| 125 } | 174 } |
| 126 | 175 |
| 127 TEST_F(NGInlineItemsBuilderTest, CollapseTrailingSpaces) { | 176 TEST_F(NGInlineItemsBuilderTest, CollapseTrailingSpaces) { |
| 128 EXPECT_EQ("text", TestAppend("text ")); | 177 EXPECT_EQ("text", TestAppend("text ")); |
| 178 EXPECT_EQ("{4, 5}", collapsed_); |
| 129 EXPECT_EQ("text", TestAppend("text", " ")); | 179 EXPECT_EQ("text", TestAppend("text", " ")); |
| 180 EXPECT_EQ("{4}", collapsed_); |
| 130 EXPECT_EQ("text", TestAppend("text ", " ")); | 181 EXPECT_EQ("text", TestAppend("text ", " ")); |
| 182 EXPECT_EQ("{4, 5}", collapsed_); |
| 131 } | 183 } |
| 132 | 184 |
| 133 TEST_F(NGInlineItemsBuilderTest, CollapseAllSpaces) { | 185 TEST_F(NGInlineItemsBuilderTest, CollapseAllSpaces) { |
| 134 EXPECT_EQ("", TestAppend(" ")); | 186 EXPECT_EQ("", TestAppend(" ")); |
| 187 EXPECT_EQ("{0, 1}", collapsed_); |
| 135 EXPECT_EQ("", TestAppend(" ", " ")); | 188 EXPECT_EQ("", TestAppend(" ", " ")); |
| 189 EXPECT_EQ("{0, 1, 2, 3}", collapsed_); |
| 136 EXPECT_EQ("", TestAppend(" ", "\n")); | 190 EXPECT_EQ("", TestAppend(" ", "\n")); |
| 191 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 137 EXPECT_EQ("", TestAppend("\n", " ")); | 192 EXPECT_EQ("", TestAppend("\n", " ")); |
| 193 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 138 } | 194 } |
| 139 | 195 |
| 140 TEST_F(NGInlineItemsBuilderTest, CollapseLeadingNewlines) { | 196 TEST_F(NGInlineItemsBuilderTest, CollapseLeadingNewlines) { |
| 141 EXPECT_EQ("text", TestAppend("\ntext")); | 197 EXPECT_EQ("text", TestAppend("\ntext")); |
| 198 EXPECT_EQ("{0}", collapsed_); |
| 142 EXPECT_EQ("text", TestAppend("\n\ntext")); | 199 EXPECT_EQ("text", TestAppend("\n\ntext")); |
| 200 EXPECT_EQ("{0, 1}", collapsed_); |
| 143 EXPECT_EQ("text", TestAppend("\n", "text")); | 201 EXPECT_EQ("text", TestAppend("\n", "text")); |
| 202 EXPECT_EQ("{0}", collapsed_); |
| 144 EXPECT_EQ("text", TestAppend("\n\n", "text")); | 203 EXPECT_EQ("text", TestAppend("\n\n", "text")); |
| 204 EXPECT_EQ("{0, 1}", collapsed_); |
| 145 EXPECT_EQ("text", TestAppend(" \n", "text")); | 205 EXPECT_EQ("text", TestAppend(" \n", "text")); |
| 206 EXPECT_EQ("{0, 1}", collapsed_); |
| 146 EXPECT_EQ("text", TestAppend("\n", " text")); | 207 EXPECT_EQ("text", TestAppend("\n", " text")); |
| 208 EXPECT_EQ("{0, 1}", collapsed_); |
| 147 EXPECT_EQ("text", TestAppend("\n\n", " text")); | 209 EXPECT_EQ("text", TestAppend("\n\n", " text")); |
| 210 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 148 EXPECT_EQ("text", TestAppend(" \n", " text")); | 211 EXPECT_EQ("text", TestAppend(" \n", " text")); |
| 212 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 149 EXPECT_EQ("text", TestAppend("\n", "\ntext")); | 213 EXPECT_EQ("text", TestAppend("\n", "\ntext")); |
| 214 EXPECT_EQ("{0, 1}", collapsed_); |
| 150 EXPECT_EQ("text", TestAppend("\n\n", "\ntext")); | 215 EXPECT_EQ("text", TestAppend("\n\n", "\ntext")); |
| 216 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 151 EXPECT_EQ("text", TestAppend(" \n", "\ntext")); | 217 EXPECT_EQ("text", TestAppend(" \n", "\ntext")); |
| 218 EXPECT_EQ("{0, 1, 2}", collapsed_); |
| 152 } | 219 } |
| 153 | 220 |
| 154 TEST_F(NGInlineItemsBuilderTest, CollapseTrailingNewlines) { | 221 TEST_F(NGInlineItemsBuilderTest, CollapseTrailingNewlines) { |
| 155 EXPECT_EQ("text", TestAppend("text\n")); | 222 EXPECT_EQ("text", TestAppend("text\n")); |
| 223 EXPECT_EQ("{4}", collapsed_); |
| 156 EXPECT_EQ("text", TestAppend("text", "\n")); | 224 EXPECT_EQ("text", TestAppend("text", "\n")); |
| 225 EXPECT_EQ("{4}", collapsed_); |
| 157 EXPECT_EQ("text", TestAppend("text\n", "\n")); | 226 EXPECT_EQ("text", TestAppend("text\n", "\n")); |
| 227 EXPECT_EQ("{4, 5}", collapsed_); |
| 158 EXPECT_EQ("text", TestAppend("text\n", " ")); | 228 EXPECT_EQ("text", TestAppend("text\n", " ")); |
| 229 EXPECT_EQ("{4, 5}", collapsed_); |
| 159 EXPECT_EQ("text", TestAppend("text ", "\n")); | 230 EXPECT_EQ("text", TestAppend("text ", "\n")); |
| 231 EXPECT_EQ("{4, 5}", collapsed_); |
| 160 } | 232 } |
| 161 | 233 |
| 162 TEST_F(NGInlineItemsBuilderTest, CollapseBeforeNewlineAcrossElements) { | 234 TEST_F(NGInlineItemsBuilderTest, CollapseBeforeNewlineAcrossElements) { |
| 163 EXPECT_EQ("text text", TestAppend("text ", "\ntext")); | 235 EXPECT_EQ("text text", TestAppend("text ", "\ntext")); |
| 236 EXPECT_EQ("{5}", collapsed_); |
| 164 EXPECT_EQ("text text", TestAppend("text", " ", "\ntext")); | 237 EXPECT_EQ("text text", TestAppend("text", " ", "\ntext")); |
| 238 EXPECT_EQ("{5}", collapsed_); |
| 165 } | 239 } |
| 166 | 240 |
| 167 TEST_F(NGInlineItemsBuilderTest, CollapseBeforeAndAfterNewline) { | 241 TEST_F(NGInlineItemsBuilderTest, CollapseBeforeAndAfterNewline) { |
| 168 SetWhiteSpace(EWhiteSpace::kPreLine); | 242 SetWhiteSpace(EWhiteSpace::kPreLine); |
| 169 EXPECT_EQ("text\ntext", TestAppend("text \n text")) | 243 EXPECT_EQ("text\ntext", TestAppend("text \n text")) |
| 170 << "Spaces before and after newline are removed."; | 244 << "Spaces before and after newline are removed."; |
| 245 EXPECT_EQ("{4, 5, 7, 8}", collapsed_); |
| 171 } | 246 } |
| 172 | 247 |
| 173 TEST_F(NGInlineItemsBuilderTest, | 248 TEST_F(NGInlineItemsBuilderTest, |
| 174 CollapsibleSpaceAfterNonCollapsibleSpaceAcrossElements) { | 249 CollapsibleSpaceAfterNonCollapsibleSpaceAcrossElements) { |
| 175 NGInlineItemsBuilder builder(&items_); | 250 NGInlineItemsBuilderForOffsetMapping builder(&items_); |
| 176 RefPtr<ComputedStyle> pre_wrap(CreateWhitespaceStyle(EWhiteSpace::kPreWrap)); | 251 RefPtr<ComputedStyle> pre_wrap(CreateWhitespaceStyle(EWhiteSpace::kPreWrap)); |
| 177 builder.Append("text ", pre_wrap.Get()); | 252 builder.Append("text ", pre_wrap.Get()); |
| 178 builder.Append(" text", style_.Get()); | 253 builder.Append(" text", style_.Get()); |
| 179 EXPECT_EQ("text text", builder.ToString()) | 254 EXPECT_EQ("text text", builder.ToString()) |
| 180 << "The whitespace in constructions like '<span style=\"white-space: " | 255 << "The whitespace in constructions like '<span style=\"white-space: " |
| 181 "pre-wrap\">text <span><span> text</span>' does not collapse."; | 256 "pre-wrap\">text <span><span> text</span>' does not collapse."; |
| 257 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 182 } | 258 } |
| 183 | 259 |
| 184 TEST_F(NGInlineItemsBuilderTest, CollapseZeroWidthSpaces) { | 260 TEST_F(NGInlineItemsBuilderTest, CollapseZeroWidthSpaces) { |
| 185 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B\ntext")) | 261 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B\ntext")) |
| 186 << "Newline is removed if the character before is ZWS."; | 262 << "Newline is removed if the character before is ZWS."; |
| 263 EXPECT_EQ("{5}", collapsed_); |
| 187 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\n\u200Btext")) | 264 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\n\u200Btext")) |
| 188 << "Newline is removed if the character after is ZWS."; | 265 << "Newline is removed if the character after is ZWS."; |
| 266 EXPECT_EQ("{4}", collapsed_); |
| 189 EXPECT_EQ(String(u"text\u200B\u200Btext"), | 267 EXPECT_EQ(String(u"text\u200B\u200Btext"), |
| 190 TestAppend(u"text\u200B\n\u200Btext")) | 268 TestAppend(u"text\u200B\n\u200Btext")) |
| 191 << "Newline is removed if the character before/after is ZWS."; | 269 << "Newline is removed if the character before/after is ZWS."; |
| 270 EXPECT_EQ("{5}", collapsed_); |
| 192 | 271 |
| 193 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\n", u"\u200Btext")) | 272 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\n", u"\u200Btext")) |
| 194 << "Newline is removed if the character after across elements is ZWS."; | 273 << "Newline is removed if the character after across elements is ZWS."; |
| 274 EXPECT_EQ("{4}", collapsed_); |
| 195 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B", u"\ntext")) | 275 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B", u"\ntext")) |
| 196 << "Newline is removed if the character before is ZWS even across " | 276 << "Newline is removed if the character before is ZWS even across " |
| 197 "elements."; | 277 "elements."; |
| 278 EXPECT_EQ("{5}", collapsed_); |
| 198 | 279 |
| 199 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text \n", u"\u200Btext")) | 280 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text \n", u"\u200Btext")) |
| 200 << "Collapsible space before newline does not affect the result."; | 281 << "Collapsible space before newline does not affect the result."; |
| 282 EXPECT_EQ("{4, 5}", collapsed_); |
| 201 | 283 |
| 202 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B\n", u" text")) | 284 EXPECT_EQ(String(u"text\u200Btext"), TestAppend(u"text\u200B\n", u" text")) |
| 203 << "Collapsible space after newline is removed even when the " | 285 << "Collapsible space after newline is removed even when the " |
| 204 "newline was removed."; | 286 "newline was removed."; |
| 287 EXPECT_EQ("{5, 6}", collapsed_); |
| 205 } | 288 } |
| 206 | 289 |
| 207 TEST_F(NGInlineItemsBuilderTest, CollapseEastAsianWidth) { | 290 TEST_F(NGInlineItemsBuilderTest, CollapseEastAsianWidth) { |
| 208 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00\n\u4E00")) | 291 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00\n\u4E00")) |
| 209 << "Newline is removed when both sides are Wide."; | 292 << "Newline is removed when both sides are Wide."; |
| 293 EXPECT_EQ("{1}", collapsed_); |
| 210 | 294 |
| 211 EXPECT_EQ(String(u"\u4E00 A"), TestAppend(u"\u4E00\nA")) | 295 EXPECT_EQ(String(u"\u4E00 A"), TestAppend(u"\u4E00\nA")) |
| 212 << "Newline is not removed when after is Narrow."; | 296 << "Newline is not removed when after is Narrow."; |
| 297 EXPECT_EQ("{}", collapsed_); |
| 213 EXPECT_EQ(String(u"A \u4E00"), TestAppend(u"A\n\u4E00")) | 298 EXPECT_EQ(String(u"A \u4E00"), TestAppend(u"A\n\u4E00")) |
| 214 << "Newline is not removed when before is Narrow."; | 299 << "Newline is not removed when before is Narrow."; |
| 300 EXPECT_EQ("{}", collapsed_); |
| 215 | 301 |
| 216 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00\n", u"\u4E00")) | 302 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00\n", u"\u4E00")) |
| 217 << "Newline at the end of elements is removed when both sides are Wide."; | 303 << "Newline at the end of elements is removed when both sides are Wide."; |
| 304 EXPECT_EQ("{1}", collapsed_); |
| 218 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00", u"\n\u4E00")) | 305 EXPECT_EQ(String(u"\u4E00\u4E00"), TestAppend(u"\u4E00", u"\n\u4E00")) |
| 219 << "Newline at the beginning of elements is removed " | 306 << "Newline at the beginning of elements is removed " |
| 220 "when both sides are Wide."; | 307 "when both sides are Wide."; |
| 308 EXPECT_EQ("{1}", collapsed_); |
| 221 } | 309 } |
| 222 | 310 |
| 223 TEST_F(NGInlineItemsBuilderTest, OpaqueToSpaceCollapsing) { | 311 TEST_F(NGInlineItemsBuilderTest, OpaqueToSpaceCollapsing) { |
| 224 NGInlineItemsBuilder builder(&items_); | 312 NGInlineItemsBuilderForOffsetMapping builder(&items_); |
| 225 builder.Append("Hello ", style_.Get()); | 313 builder.Append("Hello ", style_.Get()); |
| 226 builder.AppendOpaque(NGInlineItem::kBidiControl, | 314 builder.AppendOpaque(NGInlineItem::kBidiControl, |
| 227 kFirstStrongIsolateCharacter); | 315 kFirstStrongIsolateCharacter); |
| 228 builder.Append(" ", style_.Get()); | 316 builder.Append(" ", style_.Get()); |
| 229 builder.AppendOpaque(NGInlineItem::kBidiControl, | 317 builder.AppendOpaque(NGInlineItem::kBidiControl, |
| 230 kFirstStrongIsolateCharacter); | 318 kFirstStrongIsolateCharacter); |
| 231 builder.Append(" World", style_.Get()); | 319 builder.Append(" World", style_.Get()); |
| 232 EXPECT_EQ(String(u"Hello \u2068\u2068World"), builder.ToString()); | 320 EXPECT_EQ(String(u"Hello \u2068\u2068World"), builder.ToString()); |
| 321 EXPECT_EQ("{7, 9}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 233 } | 322 } |
| 234 | 323 |
| 235 TEST_F(NGInlineItemsBuilderTest, CollapseAroundReplacedElement) { | 324 TEST_F(NGInlineItemsBuilderTest, CollapseAroundReplacedElement) { |
| 236 NGInlineItemsBuilder builder(&items_); | 325 NGInlineItemsBuilderForOffsetMapping builder(&items_); |
| 237 builder.Append("Hello ", style_.Get()); | 326 builder.Append("Hello ", style_.Get()); |
| 238 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); | 327 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); |
| 239 builder.Append(" World", style_.Get()); | 328 builder.Append(" World", style_.Get()); |
| 240 EXPECT_EQ(String(u"Hello \uFFFC World"), builder.ToString()); | 329 EXPECT_EQ(String(u"Hello \uFFFC World"), builder.ToString()); |
| 330 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 241 } | 331 } |
| 242 | 332 |
| 243 TEST_F(NGInlineItemsBuilderTest, CollapseNewlineAfterObject) { | 333 TEST_F(NGInlineItemsBuilderTest, CollapseNewlineAfterObject) { |
| 244 NGInlineItemsBuilder builder(&items_); | 334 NGInlineItemsBuilderForOffsetMapping builder(&items_); |
| 245 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); | 335 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); |
| 246 builder.Append("\n", style_.Get()); | 336 builder.Append("\n", style_.Get()); |
| 247 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); | 337 builder.Append(NGInlineItem::kAtomicInline, kObjectReplacementCharacter); |
| 248 EXPECT_EQ(String(u"\uFFFC \uFFFC"), builder.ToString()); | 338 EXPECT_EQ(String(u"\uFFFC \uFFFC"), builder.ToString()); |
| 249 EXPECT_EQ(3u, items_.size()); | 339 EXPECT_EQ(3u, items_.size()); |
| 250 EXPECT_EQ(nullptr, items_[0].Style()); | 340 EXPECT_EQ(nullptr, items_[0].Style()); |
| 251 EXPECT_EQ(style_.Get(), items_[1].Style()); | 341 EXPECT_EQ(style_.Get(), items_[1].Style()); |
| 252 EXPECT_EQ(nullptr, items_[2].Style()); | 342 EXPECT_EQ(nullptr, items_[2].Style()); |
| 343 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 253 } | 344 } |
| 254 | 345 |
| 255 TEST_F(NGInlineItemsBuilderTest, AppendEmptyString) { | 346 TEST_F(NGInlineItemsBuilderTest, AppendEmptyString) { |
| 256 EXPECT_EQ("", TestAppend("")); | 347 EXPECT_EQ("", TestAppend("")); |
| 348 EXPECT_EQ("{}", collapsed_); |
| 257 EXPECT_EQ(0u, items_.size()); | 349 EXPECT_EQ(0u, items_.size()); |
| 258 } | 350 } |
| 259 | 351 |
| 260 TEST_F(NGInlineItemsBuilderTest, NewLines) { | 352 TEST_F(NGInlineItemsBuilderTest, NewLines) { |
| 261 SetWhiteSpace(EWhiteSpace::kPre); | 353 SetWhiteSpace(EWhiteSpace::kPre); |
| 262 EXPECT_EQ("apple\norange\ngrape\n", TestAppend("apple\norange\ngrape\n")); | 354 EXPECT_EQ("apple\norange\ngrape\n", TestAppend("apple\norange\ngrape\n")); |
| 355 EXPECT_EQ("{}", collapsed_); |
| 263 EXPECT_EQ(6u, items_.size()); | 356 EXPECT_EQ(6u, items_.size()); |
| 264 EXPECT_EQ(NGInlineItem::kText, items_[0].Type()); | 357 EXPECT_EQ(NGInlineItem::kText, items_[0].Type()); |
| 265 EXPECT_EQ(NGInlineItem::kControl, items_[1].Type()); | 358 EXPECT_EQ(NGInlineItem::kControl, items_[1].Type()); |
| 266 EXPECT_EQ(NGInlineItem::kText, items_[2].Type()); | 359 EXPECT_EQ(NGInlineItem::kText, items_[2].Type()); |
| 267 EXPECT_EQ(NGInlineItem::kControl, items_[3].Type()); | 360 EXPECT_EQ(NGInlineItem::kControl, items_[3].Type()); |
| 268 EXPECT_EQ(NGInlineItem::kText, items_[4].Type()); | 361 EXPECT_EQ(NGInlineItem::kText, items_[4].Type()); |
| 269 EXPECT_EQ(NGInlineItem::kControl, items_[5].Type()); | 362 EXPECT_EQ(NGInlineItem::kControl, items_[5].Type()); |
| 270 } | 363 } |
| 271 | 364 |
| 272 TEST_F(NGInlineItemsBuilderTest, Empty) { | 365 TEST_F(NGInlineItemsBuilderTest, Empty) { |
| 273 Vector<NGInlineItem> items; | 366 Vector<NGInlineItem> items; |
| 274 NGInlineItemsBuilder builder(&items); | 367 NGInlineItemsBuilderForOffsetMapping builder(&items); |
| 275 RefPtr<ComputedStyle> block_style(ComputedStyle::Create()); | 368 RefPtr<ComputedStyle> block_style(ComputedStyle::Create()); |
| 276 builder.EnterBlock(block_style.Get()); | 369 builder.EnterBlock(block_style.Get()); |
| 277 builder.ExitBlock(); | 370 builder.ExitBlock(); |
| 278 | 371 |
| 279 EXPECT_EQ("", builder.ToString()); | 372 EXPECT_EQ("", builder.ToString()); |
| 373 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 280 } | 374 } |
| 281 | 375 |
| 282 TEST_F(NGInlineItemsBuilderTest, BidiBlockOverride) { | 376 TEST_F(NGInlineItemsBuilderTest, BidiBlockOverride) { |
| 283 Vector<NGInlineItem> items; | 377 Vector<NGInlineItem> items; |
| 284 NGInlineItemsBuilder builder(&items); | 378 NGInlineItemsBuilderForOffsetMapping builder(&items); |
| 285 RefPtr<ComputedStyle> block_style(ComputedStyle::Create()); | 379 RefPtr<ComputedStyle> block_style(ComputedStyle::Create()); |
| 286 block_style->SetUnicodeBidi(UnicodeBidi::kBidiOverride); | 380 block_style->SetUnicodeBidi(UnicodeBidi::kBidiOverride); |
| 287 block_style->SetDirection(TextDirection::kRtl); | 381 block_style->SetDirection(TextDirection::kRtl); |
| 288 builder.EnterBlock(block_style.Get()); | 382 builder.EnterBlock(block_style.Get()); |
| 289 builder.Append("Hello", style_.Get()); | 383 builder.Append("Hello", style_.Get()); |
| 290 builder.ExitBlock(); | 384 builder.ExitBlock(); |
| 291 | 385 |
| 292 // Expected control characters as defined in: | 386 // Expected control characters as defined in: |
| 293 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table | 387 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table |
| 294 EXPECT_EQ(String(u"\u202E" | 388 EXPECT_EQ(String(u"\u202E" |
| 295 u"Hello" | 389 u"Hello" |
| 296 u"\u202C"), | 390 u"\u202C"), |
| 297 builder.ToString()); | 391 builder.ToString()); |
| 392 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 298 } | 393 } |
| 299 | 394 |
| 300 static std::unique_ptr<LayoutInline> CreateLayoutInline( | 395 static std::unique_ptr<LayoutInline> CreateLayoutInline( |
| 301 void (*initialize_style)(ComputedStyle*)) { | 396 void (*initialize_style)(ComputedStyle*)) { |
| 302 RefPtr<ComputedStyle> style(ComputedStyle::Create()); | 397 RefPtr<ComputedStyle> style(ComputedStyle::Create()); |
| 303 initialize_style(style.Get()); | 398 initialize_style(style.Get()); |
| 304 std::unique_ptr<LayoutInline> node = WTF::MakeUnique<LayoutInline>(nullptr); | 399 std::unique_ptr<LayoutInline> node = WTF::MakeUnique<LayoutInline>(nullptr); |
| 305 node->SetStyleInternal(std::move(style)); | 400 node->SetStyleInternal(std::move(style)); |
| 306 return node; | 401 return node; |
| 307 } | 402 } |
| 308 | 403 |
| 309 TEST_F(NGInlineItemsBuilderTest, BidiIsolate) { | 404 TEST_F(NGInlineItemsBuilderTest, BidiIsolate) { |
| 310 Vector<NGInlineItem> items; | 405 Vector<NGInlineItem> items; |
| 311 NGInlineItemsBuilder builder(&items); | 406 NGInlineItemsBuilderForOffsetMapping builder(&items); |
| 312 builder.Append("Hello ", style_.Get()); | 407 builder.Append("Hello ", style_.Get()); |
| 313 std::unique_ptr<LayoutInline> isolate_rtl( | 408 std::unique_ptr<LayoutInline> isolate_rtl( |
| 314 CreateLayoutInline([](ComputedStyle* style) { | 409 CreateLayoutInline([](ComputedStyle* style) { |
| 315 style->SetUnicodeBidi(UnicodeBidi::kIsolate); | 410 style->SetUnicodeBidi(UnicodeBidi::kIsolate); |
| 316 style->SetDirection(TextDirection::kRtl); | 411 style->SetDirection(TextDirection::kRtl); |
| 317 })); | 412 })); |
| 318 builder.EnterInline(isolate_rtl.get()); | 413 builder.EnterInline(isolate_rtl.get()); |
| 319 builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get()); | 414 builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get()); |
| 320 builder.ExitInline(isolate_rtl.get()); | 415 builder.ExitInline(isolate_rtl.get()); |
| 321 builder.Append(" World", style_.Get()); | 416 builder.Append(" World", style_.Get()); |
| 322 | 417 |
| 323 // Expected control characters as defined in: | 418 // Expected control characters as defined in: |
| 324 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table | 419 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table |
| 325 EXPECT_EQ(String(u"Hello " | 420 EXPECT_EQ(String(u"Hello " |
| 326 u"\u2067" | 421 u"\u2067" |
| 327 u"\u05E2\u05D1\u05E8\u05D9\u05EA" | 422 u"\u05E2\u05D1\u05E8\u05D9\u05EA" |
| 328 u"\u2069" | 423 u"\u2069" |
| 329 u" World"), | 424 u" World"), |
| 330 builder.ToString()); | 425 builder.ToString()); |
| 426 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 331 } | 427 } |
| 332 | 428 |
| 333 TEST_F(NGInlineItemsBuilderTest, BidiIsolateOverride) { | 429 TEST_F(NGInlineItemsBuilderTest, BidiIsolateOverride) { |
| 334 Vector<NGInlineItem> items; | 430 Vector<NGInlineItem> items; |
| 335 NGInlineItemsBuilder builder(&items); | 431 NGInlineItemsBuilderForOffsetMapping builder(&items); |
| 336 builder.Append("Hello ", style_.Get()); | 432 builder.Append("Hello ", style_.Get()); |
| 337 std::unique_ptr<LayoutInline> isolate_override_rtl( | 433 std::unique_ptr<LayoutInline> isolate_override_rtl( |
| 338 CreateLayoutInline([](ComputedStyle* style) { | 434 CreateLayoutInline([](ComputedStyle* style) { |
| 339 style->SetUnicodeBidi(UnicodeBidi::kIsolateOverride); | 435 style->SetUnicodeBidi(UnicodeBidi::kIsolateOverride); |
| 340 style->SetDirection(TextDirection::kRtl); | 436 style->SetDirection(TextDirection::kRtl); |
| 341 })); | 437 })); |
| 342 builder.EnterInline(isolate_override_rtl.get()); | 438 builder.EnterInline(isolate_override_rtl.get()); |
| 343 builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get()); | 439 builder.Append(u"\u05E2\u05D1\u05E8\u05D9\u05EA", style_.Get()); |
| 344 builder.ExitInline(isolate_override_rtl.get()); | 440 builder.ExitInline(isolate_override_rtl.get()); |
| 345 builder.Append(" World", style_.Get()); | 441 builder.Append(" World", style_.Get()); |
| 346 | 442 |
| 347 // Expected control characters as defined in: | 443 // Expected control characters as defined in: |
| 348 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table | 444 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table |
| 349 EXPECT_EQ(String(u"Hello " | 445 EXPECT_EQ(String(u"Hello " |
| 350 u"\u2068\u202E" | 446 u"\u2068\u202E" |
| 351 u"\u05E2\u05D1\u05E8\u05D9\u05EA" | 447 u"\u05E2\u05D1\u05E8\u05D9\u05EA" |
| 352 u"\u202C\u2069" | 448 u"\u202C\u2069" |
| 353 u" World"), | 449 u" World"), |
| 354 builder.ToString()); | 450 builder.ToString()); |
| 451 EXPECT_EQ("{}", GetCollapsed(builder.GetOffsetMappingBuilder())); |
| 355 } | 452 } |
| 356 | 453 |
| 357 } // namespace | 454 } // namespace |
| 358 | 455 |
| 359 } // namespace blink | 456 } // namespace blink |
| OLD | NEW |