Commit c063974c authored by Yoshifumi Inoue's avatar Yoshifumi Inoue Committed by Commit Bot

Make EndOfWordPosition() to utilize TextSegments class

This patch changes |EndOfWordPosition()| to utilize |TextSegments| class
to make |EndOfWordPosition()| to work with LayoutNG.

This patch also changes |GranularityAdjuster| to handle end of word position in
flat tree mapped before start of word position in DOM tree.

This patch changes following test expectations:
* third_party/WebKit/LayoutTests/fast/text/international/cjk-segmentation.html
|TextSegments| provides more context characters to ICU word breaker.
* VisibleSelectionTest.expandUsingGranularity
* ParameterizedVisibleUnitsWordTest.EndOfWordShadowDOM
Due by |PositionInFlatTree| to |Position| conversion.

Bug: 778507, 810579
Change-Id: Ie888f8b76e00386bc728a5c647aecf8f33ef7b6e
Reviewed-on: https://chromium-review.googlesource.com/1086811Reviewed-by: default avatarYoichi Osato <yoichio@chromium.org>
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564839}
parent 1d22d2c8
......@@ -27,7 +27,7 @@ expand_word_test(
'Case A-0');
expand_word_test(
`\u56FD|\u52A1\u9662${kA1}${kA2}${kA3}${kA4}${kA5}${kA6}${kA7}`,
`\u56FD^\u52A1|\u9662${kA1}${kA2}${kA3}${kA4}${kA5}${kA6}${kA7}`,
`\u56FD^\u52A1\u9662|${kA1}${kA2}${kA3}${kA4}${kA5}${kA6}${kA7}`,
'Case A-1');
expand_word_test(
`\u56FD\u52A1|\u9662${kA1}${kA2}${kA3}${kA4}${kA5}${kA6}${kA7}`,
......
......@@ -299,8 +299,9 @@ class GranularityAdjuster final {
const PositionTemplate<Strategy> expanded_end =
new_end.IsNotNull() ? new_end : end;
const EphemeralRangeTemplate<Strategy> expanded_range(expanded_start,
expanded_end);
const EphemeralRangeTemplate<Strategy> expanded_range =
AdjustStartAndEnd(expanded_start, expanded_end);
return ComputeAdjustedSelection(canonicalized_selection, expanded_range);
}
......@@ -314,6 +315,21 @@ class GranularityAdjuster final {
? kPreviousWordIfOnBoundary
: kNextWordIfOnBoundary;
}
// Because of expansion is done in flat tree, in case of |start| and |end| are
// distributed, |start| can be after |end|.
static EphemeralRange AdjustStartAndEnd(const Position& start,
const Position& end) {
if (start <= end)
return EphemeralRange(start, end);
return EphemeralRange(end, start);
}
static EphemeralRangeInFlatTree AdjustStartAndEnd(
const PositionInFlatTree& start,
const PositionInFlatTree& end) {
return EphemeralRangeInFlatTree(start, end);
}
};
PositionInFlatTree ComputeStartRespectingGranularity(
......
......@@ -101,6 +101,7 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
Node* three = shadow_root->getElementById("three")->firstChild();
Node* four = shadow_root->getElementById("four")->firstChild();
Node* five = shadow_root->getElementById("five")->firstChild();
Node* space = shadow_root->getElementById("space")->firstChild();
VisibleSelection selection;
VisibleSelectionInFlatTree selection_in_flat_tree;
......@@ -118,8 +119,8 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
EXPECT_EQ(selection.Start(), selection.Base());
EXPECT_EQ(selection.End(), selection.Extent());
EXPECT_EQ(Position(one, 0), selection.Start());
EXPECT_EQ(Position(two, 2), selection.End());
EXPECT_EQ(Position(five, 5), selection.Start());
EXPECT_EQ(Position(five, 5), selection.End());
EXPECT_EQ(selection_in_flat_tree.Start(), selection_in_flat_tree.Base());
EXPECT_EQ(selection_in_flat_tree.End(), selection_in_flat_tree.Extent());
......@@ -139,8 +140,8 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
EXPECT_EQ(selection.Start(), selection.Base());
EXPECT_EQ(selection.End(), selection.Extent());
EXPECT_EQ(Position(one, 0), selection.Start());
EXPECT_EQ(Position(two, 2), selection.End());
EXPECT_EQ(Position(space, 0), selection.Start());
EXPECT_EQ(Position(five, 5), selection.End());
EXPECT_EQ(selection_in_flat_tree.Start(), selection_in_flat_tree.Base());
EXPECT_EQ(selection_in_flat_tree.End(), selection_in_flat_tree.Extent());
......
......@@ -126,10 +126,6 @@ StartOfWordPosition(const VisiblePositionInFlatTree&,
CORE_EXPORT VisiblePositionInFlatTree
StartOfWord(const VisiblePositionInFlatTree&,
EWordSide = kNextWordIfOnBoundary);
// TODO(yoichio): Replace |endOfWord| to |endOfWordPosition| because returned
// Position should be canonicalized with |nextBoundary()| by TextItetator.
CORE_EXPORT Position EndOfWordPosition(const VisiblePosition&,
EWordSide = kNextWordIfOnBoundary);
CORE_EXPORT VisiblePosition EndOfWord(const VisiblePosition&,
EWordSide = kNextWordIfOnBoundary);
CORE_EXPORT PositionInFlatTree
......
......@@ -43,41 +43,44 @@ namespace blink {
namespace {
unsigned EndWordBoundary(
const UChar* characters,
unsigned length,
unsigned offset,
BoundarySearchContextAvailability may_have_more_context,
bool& need_more_context) {
DCHECK_LE(offset, length);
if (may_have_more_context &&
EndOfFirstWordBoundaryContext(characters + offset, length - offset) ==
static_cast<int>(length - offset)) {
need_more_context = true;
return length;
}
need_more_context = false;
return FindWordEndBoundary(characters, length, offset);
}
PositionInFlatTree EndOfWordPositionInternal(const PositionInFlatTree& position,
EWordSide side) {
class Finder final : public TextSegments::Finder {
STACK_ALLOCATED();
template <typename Strategy>
PositionTemplate<Strategy> EndOfWordAlgorithm(
const VisiblePositionTemplate<Strategy>& c,
EWordSide side) {
DCHECK(c.IsValid()) << c;
VisiblePositionTemplate<Strategy> p = c;
if (side == kPreviousWordIfOnBoundary) {
if (IsStartOfParagraph(c))
return c.DeepEquivalent();
public:
Finder(EWordSide side) : side_(side) {}
p = PreviousPositionOf(c);
if (p.IsNull())
return c.DeepEquivalent();
} else if (IsEndOfParagraph(c)) {
return c.DeepEquivalent();
}
private:
Position Find(const String text, unsigned offset) final {
DCHECK_LE(offset, text.length());
if (!is_first_time_)
return FindInternal(text, offset);
is_first_time_ = false;
if (side_ == kPreviousWordIfOnBoundary) {
if (offset == 0)
return Position::Before(0);
return FindInternal(text, offset - 1);
}
if (offset == text.length())
return Position::After(offset);
return FindInternal(text, offset);
}
static Position FindInternal(const String text, unsigned offset) {
DCHECK_LE(offset, text.length());
TextBreakIterator* it =
WordBreakIterator(text.Characters16(), text.length());
const int result = it->following(offset);
if (result == kTextBreakDone || result == 0)
return Position();
return Position::After(result - 1);
}
return NextBoundary(p, EndWordBoundary);
const EWordSide side_;
bool is_first_time_ = true;
} finder(side);
return TextSegments::FindBoundaryForward(position, &finder);
}
PositionInFlatTree NextWordPositionInternal(
......@@ -162,24 +165,31 @@ PositionTemplate<Strategy> StartOfWordAlgorithm(
} // namespace
Position EndOfWordPosition(const VisiblePosition& position, EWordSide side) {
return EndOfWordAlgorithm<EditingStrategy>(position, side);
PositionInFlatTree EndOfWordPosition(const PositionInFlatTree& start,
EWordSide side) {
return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
PositionInFlatTreeWithAffinity(
EndOfWordPositionInternal(start, side)),
start)
.GetPosition();
}
VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) {
return CreateVisiblePosition(EndOfWordPosition(position, side),
TextAffinity::kUpstreamIfPossible);
Position EndOfWordPosition(const Position& position, EWordSide side) {
return ToPositionInDOMTree(
EndOfWordPosition(ToPositionInFlatTree(position), side));
}
PositionInFlatTree EndOfWordPosition(const VisiblePositionInFlatTree& position,
EWordSide side) {
return EndOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side);
VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) {
return CreateVisiblePosition(
EndOfWordPosition(position.DeepEquivalent(), side),
TextAffinity::kUpstreamIfPossible);
}
VisiblePositionInFlatTree EndOfWord(const VisiblePositionInFlatTree& position,
EWordSide side) {
return CreateVisiblePosition(EndOfWordPosition(position, side),
TextAffinity::kUpstreamIfPossible);
return CreateVisiblePosition(
EndOfWordPosition(position.DeepEquivalent(), side),
TextAffinity::kUpstreamIfPossible);
}
// ----
......
......@@ -241,7 +241,7 @@ TEST_F(VisibleUnitsWordTest, StartOfWordTextSecurity) {
EXPECT_EQ("|abc<s>foo bar</s>baz", DoStartOfWord("abc<s>foo bar</s>b|az"));
}
TEST_F(VisibleUnitsWordTest, EndOfWordBasic) {
TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordBasic) {
EXPECT_EQ("<p> (|1) abc def</p>", DoEndOfWord("<p>| (1) abc def</p>"));
EXPECT_EQ("<p> (|1) abc def</p>", DoEndOfWord("<p> |(1) abc def</p>"));
EXPECT_EQ("<p> (1|) abc def</p>", DoEndOfWord("<p> (|1) abc def</p>"));
......@@ -258,7 +258,8 @@ TEST_F(VisibleUnitsWordTest, EndOfWordBasic) {
EXPECT_EQ("<p> (1) abc def|</p>", DoEndOfWord("<p> (1) abc def</p>|"));
}
TEST_F(VisibleUnitsWordTest, EndOfWordPreviousWordIfOnBoundaryBasic) {
TEST_P(ParameterizedVisibleUnitsWordTest,
EndOfWordPreviousWordIfOnBoundaryBasic) {
EXPECT_EQ("<p> |(1) abc def</p>",
DoEndOfWord("<p>| (1) abc def</p>",
EWordSide::kPreviousWordIfOnBoundary));
......@@ -303,7 +304,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordPreviousWordIfOnBoundaryBasic) {
EWordSide::kPreviousWordIfOnBoundary));
}
TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordShadowDOM) {
const char* body_content =
"<a id=host><b id=one>1</b> <b id=two>22</b></a><i id=three>333</i>";
const char* shadow_content =
......@@ -319,28 +320,28 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
Node* five = shadow_root->getElementById("five")->firstChild();
EXPECT_EQ(
Position(three, 3),
Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(five, 5),
EndOfWord(CreateVisiblePositionInFlatTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
Position(three, 3),
Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(five, 5),
EndOfWord(CreateVisiblePositionInFlatTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
Position(three, 3),
Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
EndOfWord(CreateVisiblePositionInFlatTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
Position(three, 3),
Position(two, 2),
EndOfWord(CreateVisiblePositionInDOMTree(*two, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
......@@ -354,7 +355,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
EndOfWord(CreateVisiblePositionInFlatTree(*three, 1)).DeepEquivalent());
EXPECT_EQ(
Position(four, 5),
Position(two, 2),
EndOfWord(CreateVisiblePositionInDOMTree(*four, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
......@@ -368,7 +369,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
EndOfWord(CreateVisiblePositionInFlatTree(*five, 1)).DeepEquivalent());
}
TEST_F(VisibleUnitsWordTest, EndOfWordTextSecurity) {
TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordTextSecurity) {
// Note: |EndOfWord()| considers security characters as a sequence "x".
InsertStyleElement("s {-webkit-text-security:disc;}");
EXPECT_EQ("abc<s>foo bar</s>baz|", DoEndOfWord("|abc<s>foo bar</s>baz"));
......
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