| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/editing/EditingUtilities.h" | 5 #include "core/editing/EditingUtilities.h" |
| 6 | 6 |
| 7 #include "core/dom/StaticNodeList.h" | 7 #include "core/dom/StaticNodeList.h" |
| 8 #include "core/editing/EditingTestBase.h" | 8 #include "core/editing/EditingTestBase.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 EXPECT_FALSE(areIdenticalElements(*items->item(0), *items->item(1))) | 197 EXPECT_FALSE(areIdenticalElements(*items->item(0), *items->item(1))) |
| 198 << "Can't merge non-editable nodes."; | 198 << "Can't merge non-editable nodes."; |
| 199 | 199 |
| 200 EXPECT_TRUE(areIdenticalElements(*items->item(1), *items->item(3))); | 200 EXPECT_TRUE(areIdenticalElements(*items->item(1), *items->item(3))); |
| 201 } | 201 } |
| 202 | 202 |
| 203 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset_FirstLetter) | 203 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset_FirstLetter) |
| 204 { | 204 { |
| 205 setBodyContent("<style>p::first-letter {color:red;}</style><p id='target'>ab
c</p>"); | 205 setBodyContent("<style>p::first-letter {color:red;}</style><p id='target'>ab
c</p>"); |
| 206 Node* node = document().getElementById("target")->firstChild(); | 206 Node* node = document().getElementById("target")->firstChild(); |
| 207 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 207 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 208 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 208 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 209 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 209 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 210 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 210 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 211 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 211 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 212 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 212 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 213 | 213 |
| 214 updateLayoutAndStyleForPainting(); | 214 updateLayoutAndStyleForPainting(); |
| 215 EXPECT_NE(nullptr, node->layoutObject()); | 215 EXPECT_NE(nullptr, node->layoutObject()); |
| 216 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 216 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 217 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 217 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 218 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 218 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 219 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 219 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 220 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 220 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 221 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 221 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 222 } | 222 } |
| 223 | 223 |
| 224 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset_textTransform) | 224 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset_textTransform) |
| 225 { | 225 { |
| 226 setBodyContent("<style>p {text-transform:uppercase}</style><p id='target'>ab
c</p>"); | 226 setBodyContent("<style>p {text-transform:uppercase}</style><p id='target'>ab
c</p>"); |
| 227 Node* node = document().getElementById("target")->firstChild(); | 227 Node* node = document().getElementById("target")->firstChild(); |
| 228 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 228 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 229 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 229 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 230 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 230 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 231 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 231 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 232 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 232 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 233 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 233 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 234 | 234 |
| 235 updateLayoutAndStyleForPainting(); | 235 updateLayoutAndStyleForPainting(); |
| 236 EXPECT_NE(nullptr, node->layoutObject()); | 236 EXPECT_NE(nullptr, node->layoutObject()); |
| 237 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 237 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 238 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 238 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 239 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 239 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 240 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 240 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 241 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 241 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 242 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 242 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 243 } | 243 } |
| 244 | 244 |
| 245 // Following breaking rules come from http://unicode.org/reports/tr29/ | 245 // Following breaking rules come from http://unicode.org/reports/tr29/ |
| 246 // Note that some of rules are in draft. Also see | 246 // Note that some of rules are in draft. Also see |
| 247 // http://www.unicode.org/reports/tr29/proposed.html | 247 // http://www.unicode.org/reports/tr29/proposed.html |
| 248 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) | 248 TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) |
| 249 { | 249 { |
| 250 // GB1: Break at the start of text. | 250 // GB1: Break at the start of text. |
| 251 setBodyContent("<p id='target'>a</p>"); | 251 setBodyContent("<p id='target'>a</p>"); |
| 252 Node* node = document().getElementById("target")->firstChild(); | 252 Node* node = document().getElementById("target")->firstChild(); |
| 253 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 253 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 254 | 254 |
| 255 // GB2: Break at the end of text. | 255 // GB2: Break at the end of text. |
| 256 setBodyContent("<p id='target'>a</p>"); | 256 setBodyContent("<p id='target'>a</p>"); |
| 257 node = document().getElementById("target")->firstChild(); | 257 node = document().getElementById("target")->firstChild(); |
| 258 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 258 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 259 | 259 |
| 260 // GB3: Do not break between CR and LF. | 260 // GB3: Do not break between CR and LF. |
| 261 setBodyContent("<p id='target'>a
b</p>"); | 261 setBodyContent("<p id='target'>a
b</p>"); |
| 262 node = document().getElementById("target")->firstChild(); | 262 node = document().getElementById("target")->firstChild(); |
| 263 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 263 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 264 // TODO(nona) : Enable following expectation. | 264 // TODO(nona) : Enable following expectation. |
| 265 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 265 // EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 266 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 266 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 267 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 267 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 268 // TODO(nona) : Enable following expectation. | 268 // TODO(nona) : Enable following expectation. |
| 269 // EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 269 // EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 270 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 270 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 271 | 271 |
| 272 // GB4,GB5: Break before and after CR/LF/Control. | 272 // GB4,GB5: Break before and after CR/LF/Control. |
| 273 setBodyContent("<p id='target'>a
b</p>"); // CR | 273 setBodyContent("<p id='target'>a
b</p>"); // CR |
| 274 node = document().getElementById("target")->firstChild(); | 274 node = document().getElementById("target")->firstChild(); |
| 275 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 275 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 276 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 276 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 277 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 277 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 278 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 278 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 279 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 279 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 280 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 280 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 281 setBodyContent("<p id='target'>a
b</p>"); // LF | 281 setBodyContent("<p id='target'>a
b</p>"); // LF |
| 282 node = document().getElementById("target")->firstChild(); | 282 node = document().getElementById("target")->firstChild(); |
| 283 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 283 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 284 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 284 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 285 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 285 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 286 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 286 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 287 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 287 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 288 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 288 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 289 setBodyContent("<p id='target'>a­b</p>"); // U+00AD(SOFT HYPHEN) has Co
ntrol property. | 289 setBodyContent("<p id='target'>a­b</p>"); // U+00AD(SOFT HYPHEN) has Co
ntrol property. |
| 290 node = document().getElementById("target")->firstChild(); | 290 node = document().getElementById("target")->firstChild(); |
| 291 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 291 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 292 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 292 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 293 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 293 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 294 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 294 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 295 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 295 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 296 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 296 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 297 | 297 |
| 298 // GB6: Don't break Hangul sequence. | 298 // GB6: Don't break Hangul sequence. |
| 299 const std::string L = "ᄀ"; // U+1100 (HANGUL CHOSEONG KIYEOK) has L p
roperty. | 299 const std::string L = "ᄀ"; // U+1100 (HANGUL CHOSEONG KIYEOK) has L p
roperty. |
| 300 const std::string V = "ᅠ"; // U+1160 (HANGUL JUNGSEONG FILLER) has V
property. | 300 const std::string V = "ᅠ"; // U+1160 (HANGUL JUNGSEONG FILLER) has V
property. |
| 301 const std::string LV = "가"; // U+AC00 (HANGUL SYLLABLE GA) has LV pro
perty. | 301 const std::string LV = "가"; // U+AC00 (HANGUL SYLLABLE GA) has LV pro
perty. |
| 302 const std::string LVT = "각"; // U+AC01 (HANGUL SYLLABLE GAG) has LVT
property. | 302 const std::string LVT = "각"; // U+AC01 (HANGUL SYLLABLE GAG) has LVT
property. |
| 303 const std::string T = "ᆨ"; // U+11A8 (HANGUL JONGSEONG KIYEOK) has T
property. | 303 const std::string T = "ᆨ"; // U+11A8 (HANGUL JONGSEONG KIYEOK) has T
property. |
| 304 setBodyContent("<p id='target'>a" + L + L + "b</p>"); // L x L | 304 setBodyContent("<p id='target'>a" + L + L + "b</p>"); // L x L |
| 305 node = document().getElementById("target")->firstChild(); | 305 node = document().getElementById("target")->firstChild(); |
| 306 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 306 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 307 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 307 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 308 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 308 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 309 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 309 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 310 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 310 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 311 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 311 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 312 setBodyContent("<p id='target'>a" + L + V +"b</p>"); // L x V | 312 setBodyContent("<p id='target'>a" + L + V +"b</p>"); // L x V |
| 313 node = document().getElementById("target")->firstChild(); | 313 node = document().getElementById("target")->firstChild(); |
| 314 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 314 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 315 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 315 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 316 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 316 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 317 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 317 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 318 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 318 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 319 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 319 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 320 setBodyContent("<p id='target'>a" + L + LV + "b</p>"); // L x LV | 320 setBodyContent("<p id='target'>a" + L + LV + "b</p>"); // L x LV |
| 321 node = document().getElementById("target")->firstChild(); | 321 node = document().getElementById("target")->firstChild(); |
| 322 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 322 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 323 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 323 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 324 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 324 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 325 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 325 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 326 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 326 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 327 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 327 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 328 setBodyContent("<p id='target'>a" + L + LVT + "b</p>"); // L x LVT | 328 setBodyContent("<p id='target'>a" + L + LVT + "b</p>"); // L x LVT |
| 329 node = document().getElementById("target")->firstChild(); | 329 node = document().getElementById("target")->firstChild(); |
| 330 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 330 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 331 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 331 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 332 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 332 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 333 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 333 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 334 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 334 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 335 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 335 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 336 | 336 |
| 337 // GB7: Don't break Hangul sequence. | 337 // GB7: Don't break Hangul sequence. |
| 338 setBodyContent("<p id='target'>a" + LV + V + "b</p>"); // LV x V | 338 setBodyContent("<p id='target'>a" + LV + V + "b</p>"); // LV x V |
| 339 node = document().getElementById("target")->firstChild(); | 339 node = document().getElementById("target")->firstChild(); |
| 340 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 340 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 341 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 341 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 342 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 342 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 343 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 343 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 344 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 344 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 345 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 345 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 346 setBodyContent("<p id='target'>a" + LV + T + "b</p>"); // LV x T | 346 setBodyContent("<p id='target'>a" + LV + T + "b</p>"); // LV x T |
| 347 node = document().getElementById("target")->firstChild(); | 347 node = document().getElementById("target")->firstChild(); |
| 348 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 348 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 349 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 349 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 350 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 350 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 351 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 351 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 352 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 352 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 353 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 353 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 354 setBodyContent("<p id='target'>a" + V + V + "b</p>"); // V x V | 354 setBodyContent("<p id='target'>a" + V + V + "b</p>"); // V x V |
| 355 node = document().getElementById("target")->firstChild(); | 355 node = document().getElementById("target")->firstChild(); |
| 356 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 356 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 357 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 357 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 358 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 358 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 359 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 359 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 360 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 360 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 361 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 361 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 362 setBodyContent("<p id='target'>a" + V + T + "b</p>"); // V x T | 362 setBodyContent("<p id='target'>a" + V + T + "b</p>"); // V x T |
| 363 node = document().getElementById("target")->firstChild(); | 363 node = document().getElementById("target")->firstChild(); |
| 364 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 364 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 365 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 365 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 366 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 366 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 367 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 367 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 368 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 368 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 369 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 369 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 370 | 370 |
| 371 // GB8: Don't break Hangul sequence. | 371 // GB8: Don't break Hangul sequence. |
| 372 setBodyContent("<p id='target'>a" + LVT + T + "b</p>"); // LVT x T | 372 setBodyContent("<p id='target'>a" + LVT + T + "b</p>"); // LVT x T |
| 373 node = document().getElementById("target")->firstChild(); | 373 node = document().getElementById("target")->firstChild(); |
| 374 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 374 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 375 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 375 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 376 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 376 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 377 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 377 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 378 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 378 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 379 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 379 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 380 setBodyContent("<p id='target'>a" + T + T + "b</p>"); // T x T | 380 setBodyContent("<p id='target'>a" + T + T + "b</p>"); // T x T |
| 381 node = document().getElementById("target")->firstChild(); | 381 node = document().getElementById("target")->firstChild(); |
| 382 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 382 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 383 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 383 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 384 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 384 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 385 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 385 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 386 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 386 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 387 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 387 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 388 | 388 |
| 389 // Break other Hangul syllable combination. See test of GB999. | 389 // Break other Hangul syllable combination. See test of GB999. |
| 390 | 390 |
| 391 // GB8a: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. | 391 // GB8a: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. |
| 392 // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U. | 392 // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U. |
| 393 // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S. | 393 // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S. |
| 394 const std::string flag = "🇺🇸"; // US flag. | 394 const std::string flag = "🇺🇸"; // US flag. |
| 395 setBodyContent("<p id='target'>" + flag + flag + flag + flag + "a</p>"); //
^(RI RI)* RI x RI | 395 setBodyContent("<p id='target'>" + flag + flag + flag + flag + "a</p>"); //
^(RI RI)* RI x RI |
| 396 node = document().getElementById("target")->firstChild(); | 396 node = document().getElementById("target")->firstChild(); |
| 397 EXPECT_EQ(16, uncheckedPreviousOffset(node, 17)); | 397 EXPECT_EQ(16, previousGraphemeBoundaryOf(node, 17)); |
| 398 EXPECT_EQ(12, uncheckedPreviousOffset(node, 16)); | 398 EXPECT_EQ(12, previousGraphemeBoundaryOf(node, 16)); |
| 399 // TODO(nona): Enable following expectations. | 399 // TODO(nona): Enable following expectations. |
| 400 // EXPECT_EQ(8, uncheckedPreviousOffset(node, 12)); | 400 // EXPECT_EQ(8, previousGraphemeBoundaryOf(node, 12)); |
| 401 // EXPECT_EQ(4, uncheckedPreviousOffset(node, 8)); | 401 // EXPECT_EQ(4, previousGraphemeBoundaryOf(node, 8)); |
| 402 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 4)); | 402 // EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 4)); |
| 403 // EXPECT_EQ(4, uncheckedNextOffset(node, 0)); | 403 // EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 0)); |
| 404 // EXPECT_EQ(8, uncheckedNextOffset(node, 4)); | 404 // EXPECT_EQ(8, nextGraphemeBoundaryOf(node, 4)); |
| 405 EXPECT_EQ(12, uncheckedNextOffset(node, 8)); | 405 EXPECT_EQ(12, nextGraphemeBoundaryOf(node, 8)); |
| 406 EXPECT_EQ(16, uncheckedNextOffset(node, 12)); | 406 EXPECT_EQ(16, nextGraphemeBoundaryOf(node, 12)); |
| 407 EXPECT_EQ(17, uncheckedNextOffset(node, 16)); | 407 EXPECT_EQ(17, nextGraphemeBoundaryOf(node, 16)); |
| 408 | 408 |
| 409 // GB8c: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. | 409 // GB8c: Don't break between regional indicator if there are even numbered r
egional indicator symbols before. |
| 410 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "b</p>"); //
[^RI] (RI RI)* RI x RI | 410 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "b</p>"); //
[^RI] (RI RI)* RI x RI |
| 411 node = document().getElementById("target")->firstChild(); | 411 node = document().getElementById("target")->firstChild(); |
| 412 EXPECT_EQ(17, uncheckedPreviousOffset(node, 18)); | 412 EXPECT_EQ(17, previousGraphemeBoundaryOf(node, 18)); |
| 413 EXPECT_EQ(13, uncheckedPreviousOffset(node, 17)); | 413 EXPECT_EQ(13, previousGraphemeBoundaryOf(node, 17)); |
| 414 // TODO(nona): Enable following expectations. | 414 // TODO(nona): Enable following expectations. |
| 415 // EXPECT_EQ(9, uncheckedPreviousOffset(node, 13)); | 415 // EXPECT_EQ(9, previousGraphemeBoundaryOf(node, 13)); |
| 416 // EXPECT_EQ(5, uncheckedPreviousOffset(node, 9)); | 416 // EXPECT_EQ(5, previousGraphemeBoundaryOf(node, 9)); |
| 417 EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); | 417 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 5)); |
| 418 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 418 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 419 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 419 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 420 // TODO(nona): Enable following expectations. | 420 // TODO(nona): Enable following expectations. |
| 421 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); | 421 // EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 1)); |
| 422 // EXPECT_EQ(9, uncheckedNextOffset(node, 5)); | 422 // EXPECT_EQ(9, nextGraphemeBoundaryOf(node, 5)); |
| 423 EXPECT_EQ(13, uncheckedNextOffset(node, 9)); | 423 EXPECT_EQ(13, nextGraphemeBoundaryOf(node, 9)); |
| 424 EXPECT_EQ(17, uncheckedNextOffset(node, 13)); | 424 EXPECT_EQ(17, nextGraphemeBoundaryOf(node, 13)); |
| 425 EXPECT_EQ(18, uncheckedNextOffset(node, 17)); | 425 EXPECT_EQ(18, nextGraphemeBoundaryOf(node, 17)); |
| 426 | 426 |
| 427 // GB8c: Break if there is an odd number of regional indicator symbols befor
e. | 427 // GB8c: Break if there is an odd number of regional indicator symbols befor
e. |
| 428 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "🇸b<
/p>"); // RI ÷ RI | 428 setBodyContent("<p id='target'>a" + flag + flag + flag + flag + "🇸b<
/p>"); // RI ÷ RI |
| 429 node = document().getElementById("target")->firstChild(); | 429 node = document().getElementById("target")->firstChild(); |
| 430 EXPECT_EQ(19, uncheckedPreviousOffset(node, 20)); | 430 EXPECT_EQ(19, previousGraphemeBoundaryOf(node, 20)); |
| 431 // TODO(nona): Enable following expectations. | 431 // TODO(nona): Enable following expectations. |
| 432 // EXPECT_EQ(17, uncheckedPreviousOffset(node, 19)); | 432 // EXPECT_EQ(17, previousGraphemeBoundaryOf(node, 19)); |
| 433 // EXPECT_EQ(13, uncheckedPreviousOffset(node, 17)); | 433 // EXPECT_EQ(13, previousGraphemeBoundaryOf(node, 17)); |
| 434 // EXPECT_EQ(9, uncheckedPreviousOffset(node, 13)); | 434 // EXPECT_EQ(9, previousGraphemeBoundaryOf(node, 13)); |
| 435 // EXPECT_EQ(5, uncheckedPreviousOffset(node, 9)); | 435 // EXPECT_EQ(5, previousGraphemeBoundaryOf(node, 9)); |
| 436 EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); | 436 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 5)); |
| 437 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 437 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 438 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 438 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 439 // TODO(nona): Enable following expectations. | 439 // TODO(nona): Enable following expectations. |
| 440 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); | 440 // EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 1)); |
| 441 // EXPECT_EQ(9, uncheckedNextOffset(node, 5)); | 441 // EXPECT_EQ(9, nextGraphemeBoundaryOf(node, 5)); |
| 442 // EXPECT_EQ(13, uncheckedNextOffset(node, 9)); | 442 // EXPECT_EQ(13, nextGraphemeBoundaryOf(node, 9)); |
| 443 EXPECT_EQ(17, uncheckedNextOffset(node, 13)); | 443 EXPECT_EQ(17, nextGraphemeBoundaryOf(node, 13)); |
| 444 EXPECT_EQ(19, uncheckedNextOffset(node, 17)); | 444 EXPECT_EQ(19, nextGraphemeBoundaryOf(node, 17)); |
| 445 EXPECT_EQ(20, uncheckedNextOffset(node, 19)); | 445 EXPECT_EQ(20, nextGraphemeBoundaryOf(node, 19)); |
| 446 | 446 |
| 447 // GB9: Do not break before extending characters or ZWJ. | 447 // GB9: Do not break before extending characters or ZWJ. |
| 448 // U+0300(COMBINING GRAVE ACCENT) has Extend property. | 448 // U+0300(COMBINING GRAVE ACCENT) has Extend property. |
| 449 setBodyContent("<p id='target'>àb</p>"); // x Extend | 449 setBodyContent("<p id='target'>àb</p>"); // x Extend |
| 450 node = document().getElementById("target")->firstChild(); | 450 node = document().getElementById("target")->firstChild(); |
| 451 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 451 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 452 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); | 452 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 2)); |
| 453 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); | 453 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 0)); |
| 454 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 454 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 455 // U+200D is ZERO WIDTH JOINER. | 455 // U+200D is ZERO WIDTH JOINER. |
| 456 setBodyContent("<p id='target'>a‍b</p>"); // x ZWJ | 456 setBodyContent("<p id='target'>a‍b</p>"); // x ZWJ |
| 457 node = document().getElementById("target")->firstChild(); | 457 node = document().getElementById("target")->firstChild(); |
| 458 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 458 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 459 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); | 459 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 2)); |
| 460 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); | 460 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 0)); |
| 461 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 461 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 462 | 462 |
| 463 // GB9a: Do not break before SpacingMarks. | 463 // GB9a: Do not break before SpacingMarks. |
| 464 // U+0903(DEVANAGARI SIGN VISARGA) has SpacingMark property. | 464 // U+0903(DEVANAGARI SIGN VISARGA) has SpacingMark property. |
| 465 setBodyContent("<p id='target'>aःb</p>"); // x SpacingMark | 465 setBodyContent("<p id='target'>aःb</p>"); // x SpacingMark |
| 466 node = document().getElementById("target")->firstChild(); | 466 node = document().getElementById("target")->firstChild(); |
| 467 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 467 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 468 EXPECT_EQ(0, uncheckedPreviousOffset(node, 2)); | 468 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 2)); |
| 469 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); | 469 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 0)); |
| 470 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 470 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 471 | 471 |
| 472 // GB9b: Do not break after Prepend but Blink breaks after Prepend char to a
ddress Bug 24342. | 472 // GB9b: Do not break after Prepend but Blink breaks after Prepend char to a
ddress Bug 24342. |
| 473 // U+0600(ARABIC NUMBER SIGN) has Prepend property. | 473 // U+0600(ARABIC NUMBER SIGN) has Prepend property. |
| 474 setBodyContent("<p id='target'>a؀b</p>"); // Prepend x | 474 setBodyContent("<p id='target'>a؀b</p>"); // Prepend x |
| 475 node = document().getElementById("target")->firstChild(); | 475 node = document().getElementById("target")->firstChild(); |
| 476 EXPECT_EQ(2, uncheckedPreviousOffset(node, 3)); | 476 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 3)); |
| 477 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 477 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 478 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 478 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 479 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 479 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 480 EXPECT_EQ(2, uncheckedNextOffset(node, 1)); | 480 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 1)); |
| 481 EXPECT_EQ(3, uncheckedNextOffset(node, 2)); | 481 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 2)); |
| 482 | 482 |
| 483 // Blink customization: Don't break before Japanese half-width katakana voic
ed marks. | 483 // Blink customization: Don't break before Japanese half-width katakana voic
ed marks. |
| 484 setBodyContent("<p id='target'>aガb</p>"); | 484 setBodyContent("<p id='target'>aガb</p>"); |
| 485 node = document().getElementById("target")->firstChild(); | 485 node = document().getElementById("target")->firstChild(); |
| 486 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 486 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 487 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 487 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 488 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 488 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 489 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 489 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 490 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 490 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 491 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 491 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 492 | 492 |
| 493 // Additional rule for Virama: Do not break after Virama except for Tamil. | 493 // Additional rule for Virama: Do not break after Virama except for Tamil. |
| 494 // See http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory-9.0.0d2
.txt | 494 // See http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory-9.0.0d2
.txt |
| 495 // U+0905 is DEVANAGARI LETTER A. This has Extend property. | 495 // U+0905 is DEVANAGARI LETTER A. This has Extend property. |
| 496 // U+094D is DEVANAGARI SIGN VIRAMA. This has Virama property. | 496 // U+094D is DEVANAGARI SIGN VIRAMA. This has Virama property. |
| 497 // U+0915 is DEVANAGARI LETTER KA. | 497 // U+0915 is DEVANAGARI LETTER KA. |
| 498 setBodyContent("<p id='target'>aअ्कb</p>"); | 498 setBodyContent("<p id='target'>aअ्कb</p>"); |
| 499 node = document().getElementById("target")->firstChild(); | 499 node = document().getElementById("target")->firstChild(); |
| 500 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); | 500 EXPECT_EQ(4, previousGraphemeBoundaryOf(node, 5)); |
| 501 EXPECT_EQ(1, uncheckedPreviousOffset(node, 4)); | 501 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 4)); |
| 502 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 502 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 503 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 503 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 504 EXPECT_EQ(4, uncheckedNextOffset(node, 1)); | 504 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 1)); |
| 505 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); | 505 EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 4)); |
| 506 // U+0B85 is TAMIL LETTER A. This has Extend property. | 506 // U+0B85 is TAMIL LETTER A. This has Extend property. |
| 507 // U+0BCD is TAMIL SIGN VIRAMA. This has Virama property. | 507 // U+0BCD is TAMIL SIGN VIRAMA. This has Virama property. |
| 508 // U+0B95 is TAMIL LETTER KA. | 508 // U+0B95 is TAMIL LETTER KA. |
| 509 setBodyContent("<p id='target'>aஅ்கb</p>"); | 509 setBodyContent("<p id='target'>aஅ்கb</p>"); |
| 510 node = document().getElementById("target")->firstChild(); | 510 node = document().getElementById("target")->firstChild(); |
| 511 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); | 511 EXPECT_EQ(4, previousGraphemeBoundaryOf(node, 5)); |
| 512 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 512 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 513 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 513 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 514 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 514 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 515 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 515 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 516 EXPECT_EQ(3, uncheckedNextOffset(node, 1)); | 516 EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 1)); |
| 517 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 517 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 518 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); | 518 EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 4)); |
| 519 // TODO(nona): Consider to add Sinhala, Balinese, etc. | 519 // TODO(nona): Consider to add Sinhala, Balinese, etc. |
| 520 | 520 |
| 521 // GB10: Do not break within emoji modifier. | 521 // GB10: Do not break within emoji modifier. |
| 522 // U+1F385(FATHER CHRISTMAS) has E_Base property. | 522 // U+1F385(FATHER CHRISTMAS) has E_Base property. |
| 523 // U+1F3FB(EMOJI MODIFIER FITZPATRICK TYPE-1-2) has E_Modifier property. | 523 // U+1F3FB(EMOJI MODIFIER FITZPATRICK TYPE-1-2) has E_Modifier property. |
| 524 setBodyContent("<p id='target'>a🎅🏻b</p>"); // E_Base x E_Mod
ifier | 524 setBodyContent("<p id='target'>a🎅🏻b</p>"); // E_Base x E_Mod
ifier |
| 525 node = document().getElementById("target")->firstChild(); | 525 node = document().getElementById("target")->firstChild(); |
| 526 EXPECT_EQ(5, uncheckedPreviousOffset(node, 6)); | 526 EXPECT_EQ(5, previousGraphemeBoundaryOf(node, 6)); |
| 527 // TODO(nona): Enable following expectation. | 527 // TODO(nona): Enable following expectation. |
| 528 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); | 528 // EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 5)); |
| 529 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 529 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 530 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 530 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 531 // TODO(nona): Enable following expectation. | 531 // TODO(nona): Enable following expectation. |
| 532 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); | 532 // EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 1)); |
| 533 EXPECT_EQ(6, uncheckedNextOffset(node, 5)); | 533 EXPECT_EQ(6, nextGraphemeBoundaryOf(node, 5)); |
| 534 // U+1F466(BOY) has EBG property. | 534 // U+1F466(BOY) has EBG property. |
| 535 setBodyContent("<p id='target'>a👦🏻b</p>"); // EBG x E_Modifi
er | 535 setBodyContent("<p id='target'>a👦🏻b</p>"); // EBG x E_Modifi
er |
| 536 node = document().getElementById("target")->firstChild(); | 536 node = document().getElementById("target")->firstChild(); |
| 537 EXPECT_EQ(5, uncheckedPreviousOffset(node, 6)); | 537 EXPECT_EQ(5, previousGraphemeBoundaryOf(node, 6)); |
| 538 // TODO(nona): Enable following expectation. | 538 // TODO(nona): Enable following expectation. |
| 539 // EXPECT_EQ(1, uncheckedPreviousOffset(node, 5)); | 539 // EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 5)); |
| 540 EXPECT_EQ(0, uncheckedPreviousOffset(node, 1)); | 540 EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 1)); |
| 541 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 541 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 542 // TODO(nona): Enable following expectation. | 542 // TODO(nona): Enable following expectation. |
| 543 // EXPECT_EQ(5, uncheckedNextOffset(node, 1)); | 543 // EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 1)); |
| 544 EXPECT_EQ(6, uncheckedNextOffset(node, 5)); | 544 EXPECT_EQ(6, nextGraphemeBoundaryOf(node, 5)); |
| 545 | 545 |
| 546 // GB11: Do not break within ZWJ emoji sequence. | 546 // GB11: Do not break within ZWJ emoji sequence. |
| 547 // U+2764(HEAVY BLACK HEART) has Glue_After_Zwj property. | 547 // U+2764(HEAVY BLACK HEART) has Glue_After_Zwj property. |
| 548 setBodyContent("<p id='target'>a‍❤b</p>"); // ZWJ x Glue_After
_Zwj | 548 setBodyContent("<p id='target'>a‍❤b</p>"); // ZWJ x Glue_After
_Zwj |
| 549 node = document().getElementById("target")->firstChild(); | 549 node = document().getElementById("target")->firstChild(); |
| 550 EXPECT_EQ(3, uncheckedPreviousOffset(node, 4)); | 550 EXPECT_EQ(3, previousGraphemeBoundaryOf(node, 4)); |
| 551 // TODO(nona): Enable following expectation. | 551 // TODO(nona): Enable following expectation. |
| 552 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 3)); | 552 // EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 3)); |
| 553 // EXPECT_EQ(3, uncheckedNextOffset(node, 0)); | 553 // EXPECT_EQ(3, nextGraphemeBoundaryOf(node, 0)); |
| 554 EXPECT_EQ(4, uncheckedNextOffset(node, 3)); | 554 EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 3)); |
| 555 setBodyContent("<p id='target'>a‍👦b</p>"); // ZWJ x EBG | 555 setBodyContent("<p id='target'>a‍👦b</p>"); // ZWJ x EBG |
| 556 node = document().getElementById("target")->firstChild(); | 556 node = document().getElementById("target")->firstChild(); |
| 557 EXPECT_EQ(4, uncheckedPreviousOffset(node, 5)); | 557 EXPECT_EQ(4, previousGraphemeBoundaryOf(node, 5)); |
| 558 // TODO(nona): Enable following expectation. | 558 // TODO(nona): Enable following expectation. |
| 559 // EXPECT_EQ(0, uncheckedPreviousOffset(node, 4)); | 559 // EXPECT_EQ(0, previousGraphemeBoundaryOf(node, 4)); |
| 560 // EXPECT_EQ(4, uncheckedNextOffset(node, 0)); | 560 // EXPECT_EQ(4, nextGraphemeBoundaryOf(node, 0)); |
| 561 EXPECT_EQ(5, uncheckedNextOffset(node, 4)); | 561 EXPECT_EQ(5, nextGraphemeBoundaryOf(node, 4)); |
| 562 | 562 |
| 563 // GB999: Otherwise break everywhere. | 563 // GB999: Otherwise break everywhere. |
| 564 // Breaks between Hangul syllable except for GB6, GB7, GB8. | 564 // Breaks between Hangul syllable except for GB6, GB7, GB8. |
| 565 setBodyContent("<p id='target'>" + L + T + "</p>"); | 565 setBodyContent("<p id='target'>" + L + T + "</p>"); |
| 566 node = document().getElementById("target")->firstChild(); | 566 node = document().getElementById("target")->firstChild(); |
| 567 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 567 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 568 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 568 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 569 setBodyContent("<p id='target'>" + V + L + "</p>"); | 569 setBodyContent("<p id='target'>" + V + L + "</p>"); |
| 570 node = document().getElementById("target")->firstChild(); | 570 node = document().getElementById("target")->firstChild(); |
| 571 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 571 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 572 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 572 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 573 setBodyContent("<p id='target'>" + V + LV + "</p>"); | 573 setBodyContent("<p id='target'>" + V + LV + "</p>"); |
| 574 node = document().getElementById("target")->firstChild(); | 574 node = document().getElementById("target")->firstChild(); |
| 575 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 575 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 576 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 576 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 577 setBodyContent("<p id='target'>" + V + LVT + "</p>"); | 577 setBodyContent("<p id='target'>" + V + LVT + "</p>"); |
| 578 node = document().getElementById("target")->firstChild(); | 578 node = document().getElementById("target")->firstChild(); |
| 579 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 579 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 580 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 580 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 581 setBodyContent("<p id='target'>" + LV + L + "</p>"); | 581 setBodyContent("<p id='target'>" + LV + L + "</p>"); |
| 582 node = document().getElementById("target")->firstChild(); | 582 node = document().getElementById("target")->firstChild(); |
| 583 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 583 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 584 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 584 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 585 setBodyContent("<p id='target'>" + LV + LV + "</p>"); | 585 setBodyContent("<p id='target'>" + LV + LV + "</p>"); |
| 586 node = document().getElementById("target")->firstChild(); | 586 node = document().getElementById("target")->firstChild(); |
| 587 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 587 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 588 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 588 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 589 setBodyContent("<p id='target'>" + LV + LVT + "</p>"); | 589 setBodyContent("<p id='target'>" + LV + LVT + "</p>"); |
| 590 node = document().getElementById("target")->firstChild(); | 590 node = document().getElementById("target")->firstChild(); |
| 591 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 591 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 592 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 592 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 593 setBodyContent("<p id='target'>" + LVT + L + "</p>"); | 593 setBodyContent("<p id='target'>" + LVT + L + "</p>"); |
| 594 node = document().getElementById("target")->firstChild(); | 594 node = document().getElementById("target")->firstChild(); |
| 595 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 595 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 596 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 596 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 597 setBodyContent("<p id='target'>" + LVT + V + "</p>"); | 597 setBodyContent("<p id='target'>" + LVT + V + "</p>"); |
| 598 node = document().getElementById("target")->firstChild(); | 598 node = document().getElementById("target")->firstChild(); |
| 599 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 599 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 600 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 600 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 601 setBodyContent("<p id='target'>" + LVT + LV + "</p>"); | 601 setBodyContent("<p id='target'>" + LVT + LV + "</p>"); |
| 602 node = document().getElementById("target")->firstChild(); | 602 node = document().getElementById("target")->firstChild(); |
| 603 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 603 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 604 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 604 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 605 setBodyContent("<p id='target'>" + LVT + LVT + "</p>"); | 605 setBodyContent("<p id='target'>" + LVT + LVT + "</p>"); |
| 606 node = document().getElementById("target")->firstChild(); | 606 node = document().getElementById("target")->firstChild(); |
| 607 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 607 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 608 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 608 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 609 setBodyContent("<p id='target'>" + T + L + "</p>"); | 609 setBodyContent("<p id='target'>" + T + L + "</p>"); |
| 610 node = document().getElementById("target")->firstChild(); | 610 node = document().getElementById("target")->firstChild(); |
| 611 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 611 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 612 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 612 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 613 setBodyContent("<p id='target'>" + T + V + "</p>"); | 613 setBodyContent("<p id='target'>" + T + V + "</p>"); |
| 614 node = document().getElementById("target")->firstChild(); | 614 node = document().getElementById("target")->firstChild(); |
| 615 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 615 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 616 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 616 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 617 setBodyContent("<p id='target'>" + T + LV + "</p>"); | 617 setBodyContent("<p id='target'>" + T + LV + "</p>"); |
| 618 node = document().getElementById("target")->firstChild(); | 618 node = document().getElementById("target")->firstChild(); |
| 619 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 619 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 620 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 620 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 621 setBodyContent("<p id='target'>" + T + LVT + "</p>"); | 621 setBodyContent("<p id='target'>" + T + LVT + "</p>"); |
| 622 node = document().getElementById("target")->firstChild(); | 622 node = document().getElementById("target")->firstChild(); |
| 623 EXPECT_EQ(1, uncheckedPreviousOffset(node, 2)); | 623 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 2)); |
| 624 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 624 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 625 | 625 |
| 626 // For GB10, if base emoji character is not E_Base or EBG, break happens bef
ore E_Modifier. | 626 // For GB10, if base emoji character is not E_Base or EBG, break happens bef
ore E_Modifier. |
| 627 setBodyContent("<p id='target'>a🏻</p>"); | 627 setBodyContent("<p id='target'>a🏻</p>"); |
| 628 node = document().getElementById("target")->firstChild(); | 628 node = document().getElementById("target")->firstChild(); |
| 629 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 629 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 630 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 630 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 631 // U+1F5FA(WORLD MAP) doesn't have either E_Base or EBG property. | 631 // U+1F5FA(WORLD MAP) doesn't have either E_Base or EBG property. |
| 632 setBodyContent("<p id='target'>🗺🏻</p>"); | 632 setBodyContent("<p id='target'>🗺🏻</p>"); |
| 633 node = document().getElementById("target")->firstChild(); | 633 node = document().getElementById("target")->firstChild(); |
| 634 EXPECT_EQ(2, uncheckedPreviousOffset(node, 4)); | 634 EXPECT_EQ(2, previousGraphemeBoundaryOf(node, 4)); |
| 635 EXPECT_EQ(2, uncheckedNextOffset(node, 0)); | 635 EXPECT_EQ(2, nextGraphemeBoundaryOf(node, 0)); |
| 636 | 636 |
| 637 // For GB11, if trailing character is not Glue_After_Zwj or EBG, break happe
ns after ZWJ. | 637 // For GB11, if trailing character is not Glue_After_Zwj or EBG, break happe
ns after ZWJ. |
| 638 // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG. | 638 // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG. |
| 639 setBodyContent("<p id='target'>‍🗺</p>"); | 639 setBodyContent("<p id='target'>‍🗺</p>"); |
| 640 node = document().getElementById("target")->firstChild(); | 640 node = document().getElementById("target")->firstChild(); |
| 641 EXPECT_EQ(1, uncheckedPreviousOffset(node, 3)); | 641 EXPECT_EQ(1, previousGraphemeBoundaryOf(node, 3)); |
| 642 EXPECT_EQ(1, uncheckedNextOffset(node, 0)); | 642 EXPECT_EQ(1, nextGraphemeBoundaryOf(node, 0)); |
| 643 } | 643 } |
| 644 | 644 |
| 645 TEST_F(EditingUtilitiesTest, previousPositionOf_Backspace) | 645 TEST_F(EditingUtilitiesTest, previousPositionOf_Backspace) |
| 646 { | 646 { |
| 647 // BMP characters. Only one code point should be deleted. | 647 // BMP characters. Only one code point should be deleted. |
| 648 setBodyContent("<p id='target'>abc</p>"); | 648 setBodyContent("<p id='target'>abc</p>"); |
| 649 Node* node = document().getElementById("target")->firstChild(); | 649 Node* node = document().getElementById("target")->firstChild(); |
| 650 EXPECT_EQ(Position(node, 2), previousPositionOf(Position(node, 3), PositionM
oveType::BackwardDeletion)); | 650 EXPECT_EQ(Position(node, 2), previousPositionOf(Position(node, 3), PositionM
oveType::BackwardDeletion)); |
| 651 EXPECT_EQ(Position(node, 1), previousPositionOf(Position(node, 2), PositionM
oveType::BackwardDeletion)); | 651 EXPECT_EQ(Position(node, 1), previousPositionOf(Position(node, 2), PositionM
oveType::BackwardDeletion)); |
| 652 EXPECT_EQ(Position(node, 0), previousPositionOf(Position(node, 1), PositionM
oveType::BackwardDeletion)); | 652 EXPECT_EQ(Position(node, 0), previousPositionOf(Position(node, 1), PositionM
oveType::BackwardDeletion)); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 | 734 |
| 735 // Edge case: specify middle of surrogate pairs. | 735 // Edge case: specify middle of surrogate pairs. |
| 736 setBodyContent("<p id='target'>👁👁👁</p>"); | 736 setBodyContent("<p id='target'>👁👁👁</p>"); |
| 737 node = document().getElementById("target")->firstChild(); | 737 node = document().getElementById("target")->firstChild(); |
| 738 EXPECT_EQ(Position(node, 4), previousPositionOf(Position(node, 5), PositionM
oveType::BackwardDeletion)); | 738 EXPECT_EQ(Position(node, 4), previousPositionOf(Position(node, 5), PositionM
oveType::BackwardDeletion)); |
| 739 EXPECT_EQ(Position(node, 2), previousPositionOf(Position(node, 3), PositionM
oveType::BackwardDeletion)); | 739 EXPECT_EQ(Position(node, 2), previousPositionOf(Position(node, 3), PositionM
oveType::BackwardDeletion)); |
| 740 EXPECT_EQ(Position(node, 0), previousPositionOf(Position(node, 1), PositionM
oveType::BackwardDeletion)); | 740 EXPECT_EQ(Position(node, 0), previousPositionOf(Position(node, 1), PositionM
oveType::BackwardDeletion)); |
| 741 } | 741 } |
| 742 | 742 |
| 743 } // namespace blink | 743 } // namespace blink |
| OLD | NEW |