Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: third_party/WebKit/Source/core/editing/LayoutPositionTest.cpp

Issue 1756763002: 2016-03-02T18:53:01 LayoutPosition Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2016-04-25T19:02:18 Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "core/editing/LayoutPosition.h"
6
7 #include "core/dom/Element.h"
8 #include "core/dom/NodeTraversal.h"
9 #include "core/dom/Text.h"
10 #include "core/editing/EditingTestBase.h"
11 #include "core/editing/VisibleUnits.h"
12 #include "core/layout/LayoutView.h"
13 #include "core/layout/line/InlineTextBox.h"
14 #include "wtf/Noncopyable.h"
15
16 namespace blink {
17
18 class LayoutPositionTest : public EditingTestBase {
19 WTF_MAKE_NONCOPYABLE(LayoutPositionTest);
20
21 public:
22 // |LayoutPosition| constructors
23 LayoutPosition afterAnchorOf(LayoutObject*);
24 LayoutPosition beforeAnchorOf(LayoutObject*);
25 LayoutPosition beforeChildrenOf(LayoutObject*);
26 LayoutPosition textPositionOf(InlineBox*, int offsetInBox);
27
28 // |LayoutPosition| member variable getters
29 static PositionAnchorType anchorTypeOf(const LayoutPosition&);
30 static InlineBox* inlineBoxOf(const LayoutPosition&);
31 static LayoutObject* layoutObjectOf(const LayoutPosition&);
32 static int textOffsetOf(const LayoutPosition&);
33
34 protected:
35 LayoutPositionTest() = default;
36
37 FloatQuad caretQuadOf(const LayoutPosition& position)
38 {
39 return position.computeCaretQuad();
40 }
41
42 // Shortcuts
43 LayoutPosition layoutPositionAfter(Node* node)
44 {
45 return LayoutPosition::create(Position::afterNode(node));
46 }
47
48 LayoutPosition layoutPositionBefore(Node* node)
49 {
50 return LayoutPosition::create(Position::beforeNode(node));
51 }
52
53 LayoutPosition layoutPositionOf(Node* node, int offset)
54 {
55 return LayoutPosition::create(Position(node, offset));
56 }
57 };
58
59 // static
60 LayoutPosition LayoutPositionTest::afterAnchorOf(LayoutObject* layoutObject)
61 {
62 return LayoutPosition::afterAnchorOf(layoutObject);
63 }
64
65 // static
66 LayoutPosition LayoutPositionTest::beforeAnchorOf(LayoutObject* layoutObject)
67 {
68 return LayoutPosition::beforeAnchorOf(layoutObject);
69 }
70
71 // static
72 LayoutPosition LayoutPositionTest::beforeChildrenOf(LayoutObject* layoutObject)
73 {
74 return LayoutPosition::beforeChildrenOf(layoutObject);
75 }
76
77 LayoutPosition LayoutPositionTest::textPositionOf(InlineBox* box, int offsetInBo x)
78 {
79 return LayoutPosition(InlineBoxPosition(box, offsetInBox));
80 }
81
82 // static
83 PositionAnchorType LayoutPositionTest::anchorTypeOf(const LayoutPosition& positi on)
84 {
85 return position.m_anchorType;
86 }
87
88 // static
89 InlineBox* LayoutPositionTest::inlineBoxOf(const LayoutPosition& position)
90 {
91 return position.m_inlineBox;
92 }
93
94 // static
95 LayoutObject* LayoutPositionTest::layoutObjectOf(const LayoutPosition& position)
96 {
97 return position.m_layoutObject;
98 }
99
100 // static
101 int LayoutPositionTest::textOffsetOf(const LayoutPosition& position)
102 {
103 ASSERT(position.isOffsetInAnchor());
104 return position.m_offsetInBox;
105 }
106
107 TEST_F(LayoutPositionTest, canPlaceCaret)
108 {
109 setBodyContent("<div> 234 <br> </div>");
110 updateAllLifecyclePhases();
111
112 // Layout Tree of this test:
113 // +LayoutView {#document} (0,0)+800x600
114 // | +LayoutBlockFlow {HTML} (0,0)+800x600
115 // | | +LayoutBlockFlow {BODY} (8,8)+784x584
116 // | | | +LayoutBlockFlow {DIV} (0,0)+784x2
117 // | | | | | | +-RootInlineBox DIV frameRect=(0,0)+4x2 bidiLevel=0
118 // | | | | | | | +InlineTextBox "234 " start=2 end=5 bidiLevel=0
119 // | | | | +LayoutText {" 234 "}
120 // ------------>LayoutBR {BR}
121 Element* const body = document().body();
122 Node* const div = body->firstChild();
123 Node* const text = div->firstChild();
124 Node* const br = text->nextSibling();
125 Node* const lastText = div->lastChild();
126
127 EXPECT_TRUE(layoutPositionOf(body, 0).canPlaceCaret());
128 EXPECT_TRUE(layoutPositionBefore(div).canPlaceCaret());
129
130 EXPECT_TRUE(layoutPositionOf(div, 0).canPlaceCaret());
131 EXPECT_TRUE(layoutPositionBefore(text).canPlaceCaret());
132 EXPECT_TRUE(layoutPositionAfter(text).canPlaceCaret());
133 EXPECT_TRUE(layoutPositionOf(text, 0).canPlaceCaret());
134 EXPECT_TRUE(layoutPositionOf(text, 1).canPlaceCaret());
135 EXPECT_TRUE(layoutPositionOf(text, 2).canPlaceCaret());
136 EXPECT_TRUE(layoutPositionOf(text, 3).canPlaceCaret());
137 EXPECT_TRUE(layoutPositionOf(text, 4).canPlaceCaret());
138 EXPECT_TRUE(layoutPositionOf(text, 5).canPlaceCaret());
139 EXPECT_TRUE(layoutPositionOf(text, 6).canPlaceCaret());
140 EXPECT_TRUE(layoutPositionOf(text, 6).canPlaceCaret());
141
142 EXPECT_FALSE(layoutPositionBefore(br).canPlaceCaret());
143 EXPECT_FALSE(layoutPositionOf(div, 1).canPlaceCaret());
144 EXPECT_FALSE(layoutPositionAfter(br).canPlaceCaret())
145 << "Since it is hard to compute caret quad for after BR, we don't allow to place caret after BR.";
146
147 EXPECT_FALSE(layoutPositionBefore(lastText).canPlaceCaret())
148 << "We can't place caret before collapsed whitespace.";
149 EXPECT_FALSE(layoutPositionOf(div, 2).canPlaceCaret())
150 << "We can't place caret before collapsed whitespace.";
151 EXPECT_FALSE(layoutPositionAfter(lastText).canPlaceCaret())
152 << "We can't place caret before collapsed whitespace.";
153 EXPECT_FALSE(layoutPositionOf(div, 3).canPlaceCaret())
154 << "We can't place caret before collapsed whitespace.";
155
156 EXPECT_TRUE(layoutPositionAfter(div).canPlaceCaret());
157 EXPECT_TRUE(layoutPositionOf(body, 1).canPlaceCaret());
158 }
159
160 TEST_F(LayoutPositionTest, ctorLeftToRightSimple)
161 {
162 setBodyContent("<div id=one>222</div>");
163 updateAllLifecyclePhases();
164
165 Element* const body = document().body();
166 Element* const one = body->querySelector("#one", ASSERT_NO_EXCEPTION);
167 InlineTextBox* const textBox = toLayoutText(one->firstChild()->layoutObject( ))->firstTextBox();
168
169 EXPECT_EQ(beforeAnchorOf(one->layoutObject()), layoutPositionOf(body, 0));
170 EXPECT_EQ(afterAnchorOf(one->layoutObject()), layoutPositionOf(body, 1));
171
172 EXPECT_EQ(beforeAnchorOf(one->layoutObject()), layoutPositionBefore(one))
173 << "beforeAnchor(one) is a valid position";
174 EXPECT_EQ(textPositionOf(textBox, 0), LayoutPosition::create(Position::first PositionInNode(one)))
175 << "beforeChildren(one) should be text box position";
176 EXPECT_EQ(textPositionOf(textBox, 1), layoutPositionOf(one->firstChild(), 1) )
177 << "offsetInAnchor('222') should be text box position";
178 EXPECT_EQ(textPositionOf(textBox, 3), LayoutPosition::create(Position::lastP ositionInNode(one)))
179 << "afterChildren(one) should be end of text box";
180 EXPECT_EQ(afterAnchorOf(one->layoutObject()), layoutPositionAfter(one))
181 << "afterAnchor(one) is a valid position";
182
183 EXPECT_EQ(layoutPositionOf(body, 0), layoutPositionBefore(one))
184 << "(body, 0) and before(one) should be same.";
185 EXPECT_EQ(layoutPositionOf(body, 1), layoutPositionAfter(one))
186 << "(body, 0) and after(one) should be same.";
187
188 EXPECT_EQ(layoutPositionOf(one, 0), layoutPositionOf(one->firstChild(), 0))
189 << "(one, 0) and (text, 0) should be same.";
190 EXPECT_EQ(layoutPositionOf(one, 1), layoutPositionOf(one->firstChild(), 3))
191 << "(one, 1) and (text, 3) should be same.";
192 }
193
194 // See http://unicode.org/cldr/utility/bidi.jsp for BiDi level and ordering.
195 TEST_F(LayoutPositionTest, ctorRightToLeftMixed)
196 {
197 setBodyContent("<div id=one>mark 3.1% &#x0645;&#x0627;&#x0631;&#x0652;&#x064 3 2.0.</div>");
198 updateAllLifecyclePhases();
199
200 Element* body = document().body();
201 Element* one = body->querySelector("#one", ASSERT_NO_EXCEPTION);
202 Node* text = one->firstChild();
203 // |text| node has four inline boxes based on BiIDi level.
204 // Node: "mark 3.1% "(L0) "ARABIC"(L1) "2.0"(L2) "."(L0)
205 // Layout: "mark 3.1% " "2.0" "ARABIC" "."
206 InlineTextBox* const textBox0 = toLayoutText(text->layoutObject())->firstTex tBox();
207 InlineTextBox* const textBox1 = textBox0->nextTextBox();
208 InlineTextBox* const textBox2 = textBox1->nextTextBox();
209 InlineTextBox* const textBox3 = textBox2->nextTextBox();
210 ASSERT(textBox3 == toLayoutText(text->layoutObject())->lastTextBox());
211
212 EXPECT_EQ(textPositionOf(textBox0, 0), layoutPositionOf(text, 0));
213 EXPECT_EQ(textPositionOf(textBox0, 1), layoutPositionOf(text, 1));
214 EXPECT_EQ(textPositionOf(textBox0, 9), layoutPositionOf(text, 9));
215
216 EXPECT_EQ(textPositionOf(textBox2, 10), layoutPositionOf(text, 10));
217 EXPECT_EQ(textPositionOf(textBox2, 11), layoutPositionOf(text, 11));
218 EXPECT_EQ(textPositionOf(textBox2, 14), layoutPositionOf(text, 14));
219 EXPECT_EQ(textPositionOf(textBox2, 15), layoutPositionOf(text, 15));
220
221 EXPECT_EQ(textPositionOf(textBox1, 16), layoutPositionOf(text, 16));
222 EXPECT_EQ(textPositionOf(textBox1, 17), layoutPositionOf(text, 17));
223 EXPECT_EQ(textPositionOf(textBox1, 18), layoutPositionOf(text, 18));
224
225 EXPECT_EQ(textPositionOf(textBox3, 19), layoutPositionOf(text, 19));
226 }
227
228 TEST_F(LayoutPositionTest, ctorRightToLeftWithBidiOverride)
229 {
230 setBodyContent("<span id=one dir=rtl>abc <bdo id=two dir=rtl>def</bdo> ghi</ span>");
231 updateAllLifecyclePhases();
232
233 Element* body = document().body();
234 Element* one = body->querySelector("#one", ASSERT_NO_EXCEPTION);
235 Element* two = body->querySelector("#two", ASSERT_NO_EXCEPTION);
236
237 Node* firstText = one->firstChild();
238 Node* rtlText = two->firstChild();
239 Node* lastText = one->lastChild();
240
241 InlineTextBox* firstTextBox = toLayoutText(firstText->layoutObject())->lastT extBox();
242 InlineTextBox* rtlTextBox = toLayoutText(rtlText->layoutObject())->firstText Box();
243 InlineTextBox* lastTextBox = toLayoutText(lastText->layoutObject())->firstTe xtBox();
244
245 EXPECT_EQ(textPositionOf(firstTextBox, 0), layoutPositionOf(firstText, 0));
246 EXPECT_EQ(textPositionOf(firstTextBox, 1), layoutPositionOf(firstText, 1));
247 EXPECT_EQ(textPositionOf(firstTextBox, 2), layoutPositionOf(firstText, 2));
248
249 EXPECT_EQ(textPositionOf(rtlTextBox, 0), layoutPositionOf(rtlText, 0));
250 EXPECT_EQ(textPositionOf(rtlTextBox, 1), layoutPositionOf(rtlText, 1));
251 EXPECT_EQ(textPositionOf(rtlTextBox, 2), layoutPositionOf(rtlText, 2));
252
253 EXPECT_EQ(textPositionOf(lastTextBox->nextTextBox(), 0), layoutPositionOf(la stText, 0));
254 EXPECT_EQ(textPositionOf(lastTextBox, 1), layoutPositionOf(lastText, 1));
255 EXPECT_EQ(textPositionOf(lastTextBox, 2), layoutPositionOf(lastText, 2));
256 EXPECT_EQ(textPositionOf(lastTextBox, 3), layoutPositionOf(lastText, 3));
257 }
258
259 TEST_F(LayoutPositionTest, isCaretEquivalentWithBr)
260 {
261 setBodyContent("<div>one<br>two</div>");
262 updateAllLifecyclePhases();
263 Element* div = document().querySelector("div", ASSERT_NO_EXCEPTION);
264 Node* one = div->firstChild();
265 Node* two = div->lastChild();
266 Element* br = document().querySelector("br", ASSERT_NO_EXCEPTION);
267
268 const LayoutPosition& beforeBr = layoutPositionBefore(br);
269 const LayoutPosition& afterBr = layoutPositionAfter(br);
270 const LayoutPosition& one3 = layoutPositionOf(one, 3);
271 const LayoutPosition& two0 = layoutPositionOf(two, 0);
272
273 EXPECT_FALSE(beforeBr.isCaretEquivalent(afterBr));
274 EXPECT_TRUE(one3.isCaretEquivalent(beforeBr))
275 << "End of text and before BR should be equivalent.";
276 EXPECT_FALSE(two0.isCaretEquivalent(afterBr))
277 << "Since we can't place caret after BR, after BR and first position of next line aren't equivalent.";
278 }
279
280 TEST_F(LayoutPositionTest, isCaretEquivalentWithCollapsedWhitespace)
281 {
282 setBodyContent("<div> 234 </div>");
283 updateAllLifecyclePhases();
284 Element* div = document().querySelector("div", ASSERT_NO_EXCEPTION);
285 Node* text = div->firstChild();
286
287 const LayoutPosition& before2 = layoutPositionOf(text, 2);
288 EXPECT_TRUE(before2.isCaretEquivalent(layoutPositionOf(text, 0)));
289 EXPECT_TRUE(before2.isCaretEquivalent(layoutPositionOf(text, 1)));
290 EXPECT_FALSE(before2.isCaretEquivalent(layoutPositionBefore(div)));
291 EXPECT_EQ(Position(div, 0), mostBackwardCaretPosition(Position(text, 2)));
292
293 const LayoutPosition& before5 = layoutPositionOf(text, 5);
294 EXPECT_TRUE(before5.isCaretEquivalent(layoutPositionOf(text, 6)));
295 EXPECT_TRUE(before5.isCaretEquivalent(layoutPositionOf(text, 7)));
296 EXPECT_FALSE(before2.isCaretEquivalent(layoutPositionAfter(div)));
297 }
298
299 TEST_F(LayoutPositionTest, null)
300 {
301 EXPECT_TRUE(LayoutPosition().isNull());
302 EXPECT_FALSE(LayoutPosition().isNotNull());
303 EXPECT_TRUE(LayoutPosition() == LayoutPosition());
304 EXPECT_FALSE(LayoutPosition() != LayoutPosition());
305 }
306
307 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/LayoutPosition.cpp ('k') | third_party/WebKit/Source/core/editing/LayoutTreePrinter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698