1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "minikin/MeasuredText.h"
18
19 #include <gtest/gtest.h>
20
21 #include "minikin/LineBreaker.h"
22 #include "minikin/Measurement.h"
23
24 #include "FontTestUtils.h"
25 #include "UnicodeUtils.h"
26
27 namespace minikin {
28
29 constexpr float CHAR_WIDTH = 10.0; // Mock implementation always returns 10.0 for advance.
30
TEST(MeasuredTextTest,RunTests)31 TEST(MeasuredTextTest, RunTests) {
32 constexpr uint32_t CHAR_COUNT = 6;
33 constexpr float REPLACEMENT_WIDTH = 20.0f;
34 auto font = buildFontCollection("Ascii.ttf");
35 int lbStyle = (int)LineBreakStyle::None;
36 int lbWordStyle = (int)LineBreakWordStyle::None;
37
38 MeasuredTextBuilder builder;
39
40 MinikinPaint paint1(font);
41 paint1.size = 10.0f; // make 1em = 10px
42 builder.addStyleRun(0, 2, std::move(paint1), lbStyle, lbWordStyle, false /* is RTL */);
43 builder.addReplacementRun(2, 4, REPLACEMENT_WIDTH, 0 /* locale list id */);
44 MinikinPaint paint2(font);
45 paint2.size = 10.0f; // make 1em = 10px
46 builder.addStyleRun(4, 6, std::move(paint2), lbStyle, lbWordStyle, false /* is RTL */);
47
48 std::vector<uint16_t> text(CHAR_COUNT, 'a');
49
50 std::unique_ptr<MeasuredText> measuredText =
51 builder.build(text, true /* compute hyphenation */, false /* compute full layout */,
52 false /* ignore kerning */, nullptr /* no hint */);
53
54 ASSERT_TRUE(measuredText);
55
56 // ReplacementRun assigns all width to the first character and leave zeros others.
57 std::vector<float> expectedWidths = {CHAR_WIDTH, CHAR_WIDTH, REPLACEMENT_WIDTH,
58 0, CHAR_WIDTH, CHAR_WIDTH};
59
60 EXPECT_EQ(expectedWidths, measuredText->widths);
61 }
62
TEST(MeasuredTextTest,getBoundsTest)63 TEST(MeasuredTextTest, getBoundsTest) {
64 auto text = utf8ToUtf16("Hello, World!");
65 auto font = buildFontCollection("Ascii.ttf");
66 int lbStyle = (int)LineBreakStyle::None;
67 int lbWordStyle = (int)LineBreakWordStyle::None;
68
69 MeasuredTextBuilder builder;
70 MinikinPaint paint(font);
71 paint.size = 10.0f;
72 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
73 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
74 false /* ignore kerning */, nullptr /* no hint */);
75
76 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
77 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
78 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
79 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
80 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
81 }
82
TEST(MeasuredTextTest,getBoundsTest_LTR)83 TEST(MeasuredTextTest, getBoundsTest_LTR) {
84 auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
85 auto font = buildFontCollection("Bbox.ttf");
86 int lbStyle = (int)LineBreakStyle::None;
87 int lbWordStyle = (int)LineBreakWordStyle::None;
88
89 MeasuredTextBuilder builder;
90 MinikinPaint paint(font);
91 paint.size = 10.0f;
92 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
93 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
94 false /* ignore kerning */, nullptr /* no hint */);
95
96 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
97 }
98
TEST(MeasuredTextTest,getBoundsTest_RTL)99 TEST(MeasuredTextTest, getBoundsTest_RTL) {
100 auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
101 auto font = buildFontCollection("Bbox.ttf");
102 int lbStyle = (int)LineBreakStyle::None;
103 int lbWordStyle = (int)LineBreakWordStyle::None;
104
105 MeasuredTextBuilder builder;
106 MinikinPaint paint(font);
107 paint.size = 10.0f;
108 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, true /* is RTL */);
109 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
110 false /* ignore kerning */, nullptr /* no hint */);
111
112 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
113 }
114
TEST(MeasuredTextTest,getBoundsTest_multiStyle)115 TEST(MeasuredTextTest, getBoundsTest_multiStyle) {
116 auto text = utf8ToUtf16("Hello, World!");
117 auto font = buildFontCollection("Ascii.ttf");
118 uint32_t helloLength = 7; // length of "Hello, "
119 int lbStyle = (int)LineBreakStyle::None;
120 int lbWordStyle = (int)LineBreakWordStyle::None;
121
122 MeasuredTextBuilder builder;
123 MinikinPaint paint(font);
124 paint.size = 10.0f;
125 builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
126 MinikinPaint paint2(font);
127 paint2.size = 20.0f;
128 builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
129 false /* is RTL */);
130 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
131 false /* ignore kerning */, nullptr /* no hint */);
132
133 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
134 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
135 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
136 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
137 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(7, 7)));
138 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), mt->getBounds(text, Range(7, 8)));
139 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 30.0f, 0.0f), mt->getBounds(text, Range(6, 8)));
140 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 190.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
141 }
142
TEST(MeasuredTextTest,getExtentTest)143 TEST(MeasuredTextTest, getExtentTest) {
144 auto text = utf8ToUtf16("Hello, World!");
145 auto font = buildFontCollection("Ascii.ttf");
146 int lbStyle = (int)LineBreakStyle::None;
147 int lbWordStyle = (int)LineBreakWordStyle::None;
148
149 MeasuredTextBuilder builder;
150 MinikinPaint paint(font);
151 paint.size = 10.0f;
152 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
153 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
154 false /* ignore kernign */, nullptr /* no hint */);
155
156 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
157 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
158 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
159 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
160 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, text.size())));
161 }
162
TEST(MeasuredTextTest,getExtentTest_multiStyle)163 TEST(MeasuredTextTest, getExtentTest_multiStyle) {
164 auto text = utf8ToUtf16("Hello, World!");
165 auto font = buildFontCollection("Ascii.ttf");
166 uint32_t helloLength = 7; // length of "Hello, "
167 int lbStyle = (int)LineBreakStyle::None;
168 int lbWordStyle = (int)LineBreakWordStyle::None;
169
170 MeasuredTextBuilder builder;
171 MinikinPaint paint(font);
172 paint.size = 10.0f;
173 builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
174 MinikinPaint paint2(font);
175 paint2.size = 20.0f;
176 builder.addStyleRun(helloLength, text.size(), std::move(paint2), 0 /* no line break */,
177 0 /* no line break word style */, false /* is RTL */);
178 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
179 false /* ignore kerning */, nullptr /* no hint */);
180
181 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
182 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
183 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
184 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
185 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(7, 7)));
186 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(7, 8)));
187 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(6, 8)));
188 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(0, text.size())));
189 }
190
TEST(MeasuredTextTest,buildLayoutTest)191 TEST(MeasuredTextTest, buildLayoutTest) {
192 auto text = utf8ToUtf16("Hello, World!");
193 auto font = buildFontCollection("Ascii.ttf");
194 Range fullContext(0, text.size());
195 int lbStyle = (int)LineBreakStyle::None;
196 int lbWordStyle = (int)LineBreakWordStyle::None;
197
198 MeasuredTextBuilder builder;
199 MinikinPaint paint(font);
200 paint.size = 10.0f;
201 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
202 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
203 false /* ignore kerning */, nullptr /* no hint */);
204
205 MinikinRect rect;
206 MinikinPaint samePaint(font);
207 samePaint.size = 10.0f;
208
209 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
210 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
211 EXPECT_EQ(0u, layout.nGlyphs());
212
213 layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
214 EndHyphenEdit::NO_EDIT);
215 ASSERT_EQ(1u, layout.nGlyphs());
216 EXPECT_TRUE(layout.getFont(0));
217 EXPECT_EQ(0.0f, layout.getX(0));
218 EXPECT_EQ(0.0f, layout.getY(0));
219 EXPECT_EQ(10.0f, layout.getAdvance());
220 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
221 EXPECT_EQ(1u, layout.getAdvances().size());
222 getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
223 EndHyphenEdit::NO_EDIT, &rect);
224 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
225
226 layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
227 EndHyphenEdit::NO_EDIT);
228 ASSERT_EQ(2u, layout.nGlyphs());
229 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
230 EXPECT_EQ(0.0f, layout.getX(0));
231 EXPECT_EQ(0.0f, layout.getY(0));
232 EXPECT_EQ(10.0f, layout.getX(1));
233 EXPECT_EQ(0.0f, layout.getY(1));
234 EXPECT_EQ(20.0f, layout.getAdvance());
235 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
236 EXPECT_EQ(10.0f, layout.getCharAdvance(1));
237 EXPECT_EQ(2u, layout.getAdvances().size());
238 getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
239 EndHyphenEdit::NO_EDIT, &rect);
240 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
241
242 layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
243 EndHyphenEdit::NO_EDIT);
244 ASSERT_EQ(1u, layout.nGlyphs());
245 EXPECT_TRUE(layout.getFont(0));
246 EXPECT_EQ(0.0f, layout.getX(0));
247 EXPECT_EQ(0.0f, layout.getY(0));
248 EXPECT_EQ(10.0f, layout.getAdvance());
249 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
250 EXPECT_EQ(1u, layout.getAdvances().size());
251 getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
252 EndHyphenEdit::NO_EDIT, &rect);
253 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
254
255 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, samePaint,
256 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
257 ASSERT_EQ(text.size(), layout.nGlyphs());
258 EXPECT_TRUE(layout.getFont(0));
259 for (uint32_t i = 0; i < text.size(); ++i) {
260 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
261 EXPECT_EQ(10.0f * i, layout.getX(i)) << i;
262 EXPECT_EQ(0.0f, layout.getY(i)) << i;
263 EXPECT_EQ(10.0f, layout.getCharAdvance(i)) << i;
264 }
265 EXPECT_EQ(130.0f, layout.getAdvance());
266 EXPECT_EQ(text.size(), layout.getAdvances().size());
267 getBounds(text, Range(0, text.size()), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
268 EndHyphenEdit::NO_EDIT, &rect);
269 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), rect);
270 }
271
TEST(MeasuredTextTest,buildLayoutTest_multiStyle)272 TEST(MeasuredTextTest, buildLayoutTest_multiStyle) {
273 auto text = utf8ToUtf16("Hello, World!");
274 auto font = buildFontCollection("Ascii.ttf");
275 uint32_t helloLength = 7; // length of "Hello, "
276 Range fullContext(0, text.size());
277 int lbStyle = (int)LineBreakStyle::None;
278 int lbWordStyle = (int)LineBreakWordStyle::None;
279
280 MeasuredTextBuilder builder;
281 MinikinPaint paint(font);
282 paint.size = 10.0f;
283 builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
284 MinikinPaint paint2(font);
285 paint2.size = 20.0f;
286 builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
287 false /* is RTL */);
288 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
289 false /* ignore kerning */, nullptr /* no hint */);
290
291 MinikinRect rect;
292 MinikinPaint samePaint(font);
293 samePaint.size = 10.0f;
294
295 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
296 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
297 EXPECT_EQ(0u, layout.nGlyphs());
298
299 layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
300 EndHyphenEdit::NO_EDIT);
301 ASSERT_EQ(1u, layout.nGlyphs());
302 EXPECT_TRUE(layout.getFont(0));
303 EXPECT_EQ(0.0f, layout.getX(0));
304 EXPECT_EQ(0.0f, layout.getY(0));
305 EXPECT_EQ(10.0f, layout.getAdvance());
306 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
307 EXPECT_EQ(1u, layout.getAdvances().size());
308 getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
309 EndHyphenEdit::NO_EDIT, &rect);
310 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
311
312 layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
313 EndHyphenEdit::NO_EDIT);
314 ASSERT_EQ(2u, layout.nGlyphs());
315 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
316 EXPECT_EQ(0.0f, layout.getX(0));
317 EXPECT_EQ(0.0f, layout.getY(0));
318 EXPECT_EQ(10.0f, layout.getX(1));
319 EXPECT_EQ(0.0f, layout.getY(1));
320 EXPECT_EQ(20.0f, layout.getAdvance());
321 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
322 EXPECT_EQ(10.0f, layout.getCharAdvance(1));
323 EXPECT_EQ(2u, layout.getAdvances().size());
324 getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
325 EndHyphenEdit::NO_EDIT, &rect);
326 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
327
328 layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
329 EndHyphenEdit::NO_EDIT);
330 ASSERT_EQ(1u, layout.nGlyphs());
331 EXPECT_TRUE(layout.getFont(0));
332 EXPECT_EQ(0.0f, layout.getX(0));
333 EXPECT_EQ(0.0f, layout.getY(0));
334 EXPECT_EQ(10.0f, layout.getAdvance());
335 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
336 EXPECT_EQ(1u, layout.getAdvances().size());
337 getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
338 EndHyphenEdit::NO_EDIT, &rect);
339 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
340
341 layout = mt->buildLayout(text, Range(7, 7), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
342 EndHyphenEdit::NO_EDIT);
343 EXPECT_EQ(0u, layout.nGlyphs());
344
345 MinikinPaint samePaint2(font);
346 samePaint2.size = 20.0f;
347 layout = mt->buildLayout(text, Range(7, 8), fullContext, samePaint2, StartHyphenEdit::NO_EDIT,
348 EndHyphenEdit::NO_EDIT);
349 ASSERT_EQ(1u, layout.nGlyphs());
350 EXPECT_TRUE(layout.getFont(0));
351 EXPECT_EQ(0.0f, layout.getX(0));
352 EXPECT_EQ(0.0f, layout.getY(0));
353 EXPECT_EQ(20.0f, layout.getAdvance());
354 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
355 EXPECT_EQ(1u, layout.getAdvances().size());
356 getBounds(text, Range(7, 8), Bidi::LTR, samePaint2, StartHyphenEdit::NO_EDIT,
357 EndHyphenEdit::NO_EDIT, &rect);
358 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
359 }
360
TEST(MeasuredTextTest,buildLayoutTest_differentPaint)361 TEST(MeasuredTextTest, buildLayoutTest_differentPaint) {
362 auto text = utf8ToUtf16("Hello, World!");
363 auto font = buildFontCollection("Ascii.ttf");
364 Range fullContext(0, text.size());
365 int lbStyle = (int)LineBreakStyle::None;
366 int lbWordStyle = (int)LineBreakWordStyle::None;
367
368 MeasuredTextBuilder builder;
369 MinikinPaint paint(font);
370 paint.size = 10.0f;
371 builder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
372 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
373 false /* ignore kerning */, nullptr /* no hint */);
374
375 MinikinRect rect;
376 MinikinPaint differentPaint(font);
377 differentPaint.size = 20.0f;
378
379 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
380 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
381 EXPECT_EQ(0u, layout.nGlyphs());
382
383 layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
384 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
385 ASSERT_EQ(1u, layout.nGlyphs());
386 EXPECT_TRUE(layout.getFont(0));
387 EXPECT_EQ(0.0f, layout.getX(0));
388 EXPECT_EQ(0.0f, layout.getY(0));
389 EXPECT_EQ(20.0f, layout.getAdvance());
390 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
391 EXPECT_EQ(1u, layout.getAdvances().size());
392 getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
393 EndHyphenEdit::NO_EDIT, &rect);
394 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
395
396 layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
397 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
398 ASSERT_EQ(2u, layout.nGlyphs());
399 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
400 EXPECT_EQ(0.0f, layout.getX(0));
401 EXPECT_EQ(0.0f, layout.getY(0));
402 EXPECT_EQ(20.0f, layout.getX(1));
403 EXPECT_EQ(0.0f, layout.getY(1));
404 EXPECT_EQ(40.0f, layout.getAdvance());
405 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
406 EXPECT_EQ(20.0f, layout.getCharAdvance(1));
407 EXPECT_EQ(2u, layout.getAdvances().size());
408 getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
409 EndHyphenEdit::NO_EDIT, &rect);
410 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 40.0f, 0.0f), rect);
411
412 layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
413 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
414 ASSERT_EQ(1u, layout.nGlyphs());
415 EXPECT_TRUE(layout.getFont(0));
416 EXPECT_EQ(0.0f, layout.getX(0));
417 EXPECT_EQ(0.0f, layout.getY(0));
418 EXPECT_EQ(20.0f, layout.getAdvance());
419 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
420 EXPECT_EQ(1u, layout.getAdvances().size());
421 getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
422 EndHyphenEdit::NO_EDIT, &rect);
423 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
424
425 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
426 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
427 ASSERT_EQ(text.size(), layout.nGlyphs());
428 EXPECT_TRUE(layout.getFont(0));
429 for (uint32_t i = 0; i < text.size(); ++i) {
430 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
431 EXPECT_EQ(20.0f * i, layout.getX(i)) << i;
432 EXPECT_EQ(0.0f, layout.getY(i)) << i;
433 EXPECT_EQ(20.0f, layout.getCharAdvance(i)) << i;
434 }
435 EXPECT_EQ(260.0f, layout.getAdvance());
436 EXPECT_EQ(text.size(), layout.getAdvances().size());
437 getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
438 EndHyphenEdit::NO_EDIT, &rect);
439 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 260.0f, 0.0f), rect);
440 }
441
TEST(MeasuredTextTest,buildLayoutTest_multiStyle_differentPaint)442 TEST(MeasuredTextTest, buildLayoutTest_multiStyle_differentPaint) {
443 auto text = utf8ToUtf16("Hello, World!");
444 auto font = buildFontCollection("Ascii.ttf");
445 uint32_t helloLength = 7; // length of "Hello, "
446 Range fullContext(0, text.size());
447 int lbStyle = (int)LineBreakStyle::None;
448 int lbWordStyle = (int)LineBreakWordStyle::None;
449
450 MeasuredTextBuilder builder;
451 MinikinPaint paint(font);
452 paint.size = 10.0f;
453 builder.addStyleRun(0, helloLength, std::move(paint), lbStyle, lbWordStyle, false /* is RTL */);
454 MinikinPaint paint2(font);
455 paint2.size = 20.0f;
456 builder.addStyleRun(helloLength, text.size(), std::move(paint2), lbStyle, lbWordStyle,
457 false /* is RTL */);
458 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
459 false /* ignore kerning */, nullptr /* no hint */);
460
461 MinikinRect rect;
462 MinikinPaint differentPaint(font);
463 differentPaint.size = 30.0f;
464
465 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
466 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
467 EXPECT_EQ(0u, layout.nGlyphs());
468
469 layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
470 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
471 ASSERT_EQ(1u, layout.nGlyphs());
472 EXPECT_TRUE(layout.getFont(0));
473 EXPECT_EQ(0.0f, layout.getX(0));
474 EXPECT_EQ(0.0f, layout.getY(0));
475 EXPECT_EQ(30.0f, layout.getAdvance());
476 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
477 EXPECT_EQ(1u, layout.getAdvances().size());
478 getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
479 EndHyphenEdit::NO_EDIT, &rect);
480 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
481
482 layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
483 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
484 ASSERT_EQ(2u, layout.nGlyphs());
485 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
486 EXPECT_EQ(0.0f, layout.getX(0));
487 EXPECT_EQ(0.0f, layout.getY(0));
488 EXPECT_EQ(30.0f, layout.getX(1));
489 EXPECT_EQ(0.0f, layout.getY(1));
490 EXPECT_EQ(60.0f, layout.getAdvance());
491 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
492 EXPECT_EQ(30.0f, layout.getCharAdvance(1));
493 EXPECT_EQ(2u, layout.getAdvances().size());
494 getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
495 EndHyphenEdit::NO_EDIT, &rect);
496 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
497
498 layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
499 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
500 ASSERT_EQ(1u, layout.nGlyphs());
501 EXPECT_TRUE(layout.getFont(0));
502 EXPECT_EQ(0.0f, layout.getX(0));
503 EXPECT_EQ(0.0f, layout.getY(0));
504 EXPECT_EQ(30.0f, layout.getAdvance());
505 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
506 EXPECT_EQ(1u, layout.getAdvances().size());
507 getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
508 EndHyphenEdit::NO_EDIT, &rect);
509 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
510
511 layout = mt->buildLayout(text, Range(7, 7), fullContext, differentPaint,
512 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
513 EXPECT_EQ(0u, layout.nGlyphs());
514
515 layout = mt->buildLayout(text, Range(7, 8), fullContext, differentPaint,
516 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
517 ASSERT_EQ(1u, layout.nGlyphs());
518 EXPECT_TRUE(layout.getFont(0));
519 EXPECT_EQ(0.0f, layout.getX(0));
520 EXPECT_EQ(0.0f, layout.getY(0));
521 EXPECT_EQ(30.0f, layout.getAdvance());
522 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
523 EXPECT_EQ(1u, layout.getAdvances().size());
524 getBounds(text, Range(7, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
525 EndHyphenEdit::NO_EDIT, &rect);
526 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
527
528 layout = mt->buildLayout(text, Range(6, 8), fullContext, differentPaint,
529 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
530 ASSERT_EQ(2u, layout.nGlyphs());
531 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
532 EXPECT_EQ(0.0f, layout.getX(0));
533 EXPECT_EQ(0.0f, layout.getY(0));
534 EXPECT_EQ(30.0f, layout.getX(1));
535 EXPECT_EQ(0.0f, layout.getY(1));
536 EXPECT_EQ(60.0f, layout.getAdvance());
537 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
538 EXPECT_EQ(30.0f, layout.getCharAdvance(1));
539 EXPECT_EQ(2u, layout.getAdvances().size());
540 getBounds(text, Range(6, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
541 EndHyphenEdit::NO_EDIT, &rect);
542 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
543
544 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
545 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
546 ASSERT_EQ(text.size(), layout.nGlyphs());
547 EXPECT_TRUE(layout.getFont(0));
548 for (uint32_t i = 0; i < text.size(); ++i) {
549 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
550 EXPECT_EQ(30.0f * i, layout.getX(i)) << i;
551 EXPECT_EQ(0.0f, layout.getY(i)) << i;
552 EXPECT_EQ(30.0f, layout.getCharAdvance(i)) << i;
553 }
554 EXPECT_EQ(390.0f, layout.getAdvance());
555 EXPECT_EQ(text.size(), layout.getAdvances().size());
556 getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
557 EndHyphenEdit::NO_EDIT, &rect);
558 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 390.0f, 0.0f), rect);
559 }
560
TEST(MeasuredTextTest,testLineBreakStyle_from_builder)561 TEST(MeasuredTextTest, testLineBreakStyle_from_builder) {
562 auto text = utf8ToUtf16("Hello, World!");
563 auto font = buildFontCollection("Ascii.ttf");
564 int lbStyle = (int)LineBreakStyle::Loose; // loose
565 int lbWordStyle = (int)LineBreakWordStyle::Phrase; // phrase
566
567 MeasuredTextBuilder looseStyleBuilder;
568 MinikinPaint paint(font);
569 looseStyleBuilder.addStyleRun(0, text.size(), std::move(paint), lbStyle, lbWordStyle, false);
570 auto mt = looseStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
571 false /* ignore kerning */, nullptr /* no hint */);
572
573 EXPECT_EQ((size_t)1, mt->runs.size());
574 EXPECT_EQ(LineBreakStyle::Loose, mt->runs[0]->lineBreakStyle());
575 EXPECT_EQ(LineBreakWordStyle::Phrase, mt->runs[0]->lineBreakWordStyle());
576
577 lbStyle = (int)LineBreakStyle::Normal; // normal
578 MeasuredTextBuilder normalStyleBuilder;
579 MinikinPaint normalStylePaint(font);
580 normalStyleBuilder.addStyleRun(0, text.size(), std::move(normalStylePaint), lbStyle,
581 lbWordStyle, false);
582 mt = normalStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
583 false /* ignore kerning */, nullptr /* no hint */);
584
585 EXPECT_EQ((size_t)1, mt->runs.size());
586 EXPECT_EQ(LineBreakStyle::Normal, mt->runs[0]->lineBreakStyle());
587 EXPECT_EQ(LineBreakWordStyle::Phrase, mt->runs[0]->lineBreakWordStyle());
588
589 lbStyle = (int)LineBreakStyle::Strict; // strict
590 lbWordStyle = (int)LineBreakWordStyle::None; // no word style
591 MeasuredTextBuilder strictStyleBuilder;
592 MinikinPaint strictStylePaint(font);
593 strictStyleBuilder.addStyleRun(0, text.size(), std::move(strictStylePaint), lbStyle,
594 lbWordStyle, false);
595 mt = strictStyleBuilder.build(text, true /* hyphenation */, true /* full layout */,
596 false /* ignore kerning */, nullptr /* no hint */);
597
598 EXPECT_EQ((size_t)1, mt->runs.size());
599 EXPECT_EQ(LineBreakStyle::Strict, mt->runs[0]->lineBreakStyle());
600 EXPECT_EQ(LineBreakWordStyle::None, mt->runs[0]->lineBreakWordStyle());
601 }
602
TEST(MeasuredTextTest,testLineBreakStyle_from_run)603 TEST(MeasuredTextTest, testLineBreakStyle_from_run) {
604 auto text = utf8ToUtf16("Hello, World!");
605 auto font = buildFontCollection("Ascii.ttf");
606 int lbStyle = (int)LineBreakStyle::Strict;
607 int lbWordStyle = (int)LineBreakWordStyle::Phrase;
608 Range range(0, text.size());
609 MinikinPaint paint(font);
610
611 StyleRun styleRun(range, std::move(paint), lbStyle, lbWordStyle, false /* isRtl */);
612 EXPECT_EQ(LineBreakStyle::Strict, styleRun.lineBreakStyle());
613 EXPECT_EQ(LineBreakWordStyle::Phrase, styleRun.lineBreakWordStyle());
614
615 ReplacementRun replacementRun(range, 10.0f /* width */, 0 /* locale list id */);
616 EXPECT_EQ(LineBreakStyle::None, replacementRun.lineBreakStyle());
617 EXPECT_EQ(LineBreakWordStyle::None, replacementRun.lineBreakWordStyle());
618 }
619
620 } // namespace minikin
621