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
36 MeasuredTextBuilder builder;
37
38 MinikinPaint paint1(font);
39 paint1.size = 10.0f; // make 1em = 10px
40 builder.addStyleRun(0, 2, std::move(paint1), false /* is RTL */);
41 builder.addReplacementRun(2, 4, REPLACEMENT_WIDTH, 0 /* locale list id */);
42 MinikinPaint paint2(font);
43 paint2.size = 10.0f; // make 1em = 10px
44 builder.addStyleRun(4, 6, std::move(paint2), false /* is RTL */);
45
46 std::vector<uint16_t> text(CHAR_COUNT, 'a');
47
48 std::unique_ptr<MeasuredText> measuredText =
49 builder.build(text, true /* compute hyphenation */, false /* compute full layout */,
50 nullptr /* no hint */);
51
52 ASSERT_TRUE(measuredText);
53
54 // ReplacementRun assigns all width to the first character and leave zeros others.
55 std::vector<float> expectedWidths = {CHAR_WIDTH, CHAR_WIDTH, REPLACEMENT_WIDTH,
56 0, CHAR_WIDTH, CHAR_WIDTH};
57
58 EXPECT_EQ(expectedWidths, measuredText->widths);
59 }
60
TEST(MeasuredTextTest,getBoundsTest)61 TEST(MeasuredTextTest, getBoundsTest) {
62 auto text = utf8ToUtf16("Hello, World!");
63 auto font = buildFontCollection("Ascii.ttf");
64
65 MeasuredTextBuilder builder;
66 MinikinPaint paint(font);
67 paint.size = 10.0f;
68 builder.addStyleRun(0, text.size(), std::move(paint), false /* is RTL */);
69 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
70 nullptr /* no hint */);
71
72 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
73 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
74 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
75 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
76 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
77 }
78
TEST(MeasuredTextTest,getBoundsTest_LTR)79 TEST(MeasuredTextTest, getBoundsTest_LTR) {
80 auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
81 auto font = buildFontCollection("Bbox.ttf");
82
83 MeasuredTextBuilder builder;
84 MinikinPaint paint(font);
85 paint.size = 10.0f;
86 builder.addStyleRun(0, text.size(), std::move(paint), false /* is RTL */);
87 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
88 nullptr /* no hint */);
89
90 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
91 }
92
TEST(MeasuredTextTest,getBoundsTest_RTL)93 TEST(MeasuredTextTest, getBoundsTest_RTL) {
94 auto text = utf8ToUtf16("\u0028"); // U+0028 has 1em in LTR, 3em in RTL.
95 auto font = buildFontCollection("Bbox.ttf");
96
97 MeasuredTextBuilder builder;
98 MinikinPaint paint(font);
99 paint.size = 10.0f;
100 builder.addStyleRun(0, text.size(), std::move(paint), true /* is RTL */);
101 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
102 nullptr /* no hint */);
103
104 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
105 }
106
TEST(MeasuredTextTest,getBoundsTest_multiStyle)107 TEST(MeasuredTextTest, getBoundsTest_multiStyle) {
108 auto text = utf8ToUtf16("Hello, World!");
109 auto font = buildFontCollection("Ascii.ttf");
110 uint32_t helloLength = 7; // length of "Hello, "
111
112 MeasuredTextBuilder builder;
113 MinikinPaint paint(font);
114 paint.size = 10.0f;
115 builder.addStyleRun(0, helloLength, std::move(paint), false /* is RTL */);
116 MinikinPaint paint2(font);
117 paint2.size = 20.0f;
118 builder.addStyleRun(helloLength, text.size(), std::move(paint2), false /* is RTL */);
119 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
120 nullptr /* no hint */);
121
122 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(0, 0)));
123 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(0, 1)));
124 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), mt->getBounds(text, Range(0, 2)));
125 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), mt->getBounds(text, Range(1, 2)));
126 EXPECT_EQ(MinikinRect(0.0f, 0.0f, 0.0f, 0.0f), mt->getBounds(text, Range(7, 7)));
127 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), mt->getBounds(text, Range(7, 8)));
128 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 30.0f, 0.0f), mt->getBounds(text, Range(6, 8)));
129 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 190.0f, 0.0f), mt->getBounds(text, Range(0, text.size())));
130 }
131
TEST(MeasuredTextTest,getExtentTest)132 TEST(MeasuredTextTest, getExtentTest) {
133 auto text = utf8ToUtf16("Hello, World!");
134 auto font = buildFontCollection("Ascii.ttf");
135
136 MeasuredTextBuilder builder;
137 MinikinPaint paint(font);
138 paint.size = 10.0f;
139 builder.addStyleRun(0, text.size(), std::move(paint), false /* is RTL */);
140 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
141 nullptr /* no hint */);
142
143 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
144 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
145 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
146 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
147 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, text.size())));
148 }
149
TEST(MeasuredTextTest,getExtentTest_multiStyle)150 TEST(MeasuredTextTest, getExtentTest_multiStyle) {
151 auto text = utf8ToUtf16("Hello, World!");
152 auto font = buildFontCollection("Ascii.ttf");
153 uint32_t helloLength = 7; // length of "Hello, "
154
155 MeasuredTextBuilder builder;
156 MinikinPaint paint(font);
157 paint.size = 10.0f;
158 builder.addStyleRun(0, helloLength, std::move(paint), false /* is RTL */);
159 MinikinPaint paint2(font);
160 paint2.size = 20.0f;
161 builder.addStyleRun(helloLength, text.size(), std::move(paint2), false /* is RTL */);
162 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
163 nullptr /* no hint */);
164
165 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(0, 0)));
166 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 1)));
167 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(0, 2)));
168 EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), mt->getExtent(text, Range(1, 2)));
169 EXPECT_EQ(MinikinExtent(0.0f, 0.0f), mt->getExtent(text, Range(7, 7)));
170 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(7, 8)));
171 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(6, 8)));
172 EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), mt->getExtent(text, Range(0, text.size())));
173 }
174
TEST(MeasuredTextTest,buildLayoutTest)175 TEST(MeasuredTextTest, buildLayoutTest) {
176 auto text = utf8ToUtf16("Hello, World!");
177 auto font = buildFontCollection("Ascii.ttf");
178 Range fullContext(0, text.size());
179
180 MeasuredTextBuilder builder;
181 MinikinPaint paint(font);
182 paint.size = 10.0f;
183 builder.addStyleRun(0, text.size(), std::move(paint), false /* is RTL */);
184 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
185 nullptr /* no hint */);
186
187 MinikinRect rect;
188 MinikinPaint samePaint(font);
189 samePaint.size = 10.0f;
190
191 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
192 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
193 EXPECT_EQ(0u, layout.nGlyphs());
194
195 layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
196 EndHyphenEdit::NO_EDIT);
197 ASSERT_EQ(1u, layout.nGlyphs());
198 EXPECT_TRUE(layout.getFont(0));
199 EXPECT_EQ(0.0f, layout.getX(0));
200 EXPECT_EQ(0.0f, layout.getY(0));
201 EXPECT_EQ(10.0f, layout.getAdvance());
202 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
203 EXPECT_EQ(1u, layout.getAdvances().size());
204 getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
205 EndHyphenEdit::NO_EDIT, &rect);
206 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
207
208 layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
209 EndHyphenEdit::NO_EDIT);
210 ASSERT_EQ(2u, layout.nGlyphs());
211 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
212 EXPECT_EQ(0.0f, layout.getX(0));
213 EXPECT_EQ(0.0f, layout.getY(0));
214 EXPECT_EQ(10.0f, layout.getX(1));
215 EXPECT_EQ(0.0f, layout.getY(1));
216 EXPECT_EQ(20.0f, layout.getAdvance());
217 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
218 EXPECT_EQ(10.0f, layout.getCharAdvance(1));
219 EXPECT_EQ(2u, layout.getAdvances().size());
220 getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
221 EndHyphenEdit::NO_EDIT, &rect);
222 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
223
224 layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
225 EndHyphenEdit::NO_EDIT);
226 ASSERT_EQ(1u, layout.nGlyphs());
227 EXPECT_TRUE(layout.getFont(0));
228 EXPECT_EQ(0.0f, layout.getX(0));
229 EXPECT_EQ(0.0f, layout.getY(0));
230 EXPECT_EQ(10.0f, layout.getAdvance());
231 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
232 EXPECT_EQ(1u, layout.getAdvances().size());
233 getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
234 EndHyphenEdit::NO_EDIT, &rect);
235 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
236
237 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, samePaint,
238 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
239 ASSERT_EQ(text.size(), layout.nGlyphs());
240 EXPECT_TRUE(layout.getFont(0));
241 for (uint32_t i = 0; i < text.size(); ++i) {
242 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
243 EXPECT_EQ(10.0f * i, layout.getX(i)) << i;
244 EXPECT_EQ(0.0f, layout.getY(i)) << i;
245 EXPECT_EQ(10.0f, layout.getCharAdvance(i)) << i;
246 }
247 EXPECT_EQ(130.0f, layout.getAdvance());
248 EXPECT_EQ(text.size(), layout.getAdvances().size());
249 getBounds(text, Range(0, text.size()), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
250 EndHyphenEdit::NO_EDIT, &rect);
251 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 130.0f, 0.0f), rect);
252 }
253
TEST(MeasuredTextTest,buildLayoutTest_multiStyle)254 TEST(MeasuredTextTest, buildLayoutTest_multiStyle) {
255 auto text = utf8ToUtf16("Hello, World!");
256 auto font = buildFontCollection("Ascii.ttf");
257 uint32_t helloLength = 7; // length of "Hello, "
258 Range fullContext(0, text.size());
259
260 MeasuredTextBuilder builder;
261 MinikinPaint paint(font);
262 paint.size = 10.0f;
263 builder.addStyleRun(0, helloLength, std::move(paint), false /* is RTL */);
264 MinikinPaint paint2(font);
265 paint2.size = 20.0f;
266 builder.addStyleRun(helloLength, text.size(), std::move(paint2), false /* is RTL */);
267 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
268 nullptr /* no hint */);
269
270 MinikinRect rect;
271 MinikinPaint samePaint(font);
272 samePaint.size = 10.0f;
273
274 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, samePaint,
275 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
276 EXPECT_EQ(0u, layout.nGlyphs());
277
278 layout = mt->buildLayout(text, Range(0, 1), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
279 EndHyphenEdit::NO_EDIT);
280 ASSERT_EQ(1u, layout.nGlyphs());
281 EXPECT_TRUE(layout.getFont(0));
282 EXPECT_EQ(0.0f, layout.getX(0));
283 EXPECT_EQ(0.0f, layout.getY(0));
284 EXPECT_EQ(10.0f, layout.getAdvance());
285 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
286 EXPECT_EQ(1u, layout.getAdvances().size());
287 getBounds(text, Range(0, 1), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
288 EndHyphenEdit::NO_EDIT, &rect);
289 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
290
291 layout = mt->buildLayout(text, Range(0, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
292 EndHyphenEdit::NO_EDIT);
293 ASSERT_EQ(2u, layout.nGlyphs());
294 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
295 EXPECT_EQ(0.0f, layout.getX(0));
296 EXPECT_EQ(0.0f, layout.getY(0));
297 EXPECT_EQ(10.0f, layout.getX(1));
298 EXPECT_EQ(0.0f, layout.getY(1));
299 EXPECT_EQ(20.0f, layout.getAdvance());
300 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
301 EXPECT_EQ(10.0f, layout.getCharAdvance(1));
302 EXPECT_EQ(2u, layout.getAdvances().size());
303 getBounds(text, Range(0, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
304 EndHyphenEdit::NO_EDIT, &rect);
305 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), rect);
306
307 layout = mt->buildLayout(text, Range(1, 2), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
308 EndHyphenEdit::NO_EDIT);
309 ASSERT_EQ(1u, layout.nGlyphs());
310 EXPECT_TRUE(layout.getFont(0));
311 EXPECT_EQ(0.0f, layout.getX(0));
312 EXPECT_EQ(0.0f, layout.getY(0));
313 EXPECT_EQ(10.0f, layout.getAdvance());
314 EXPECT_EQ(10.0f, layout.getCharAdvance(0));
315 EXPECT_EQ(1u, layout.getAdvances().size());
316 getBounds(text, Range(1, 2), Bidi::LTR, samePaint, StartHyphenEdit::NO_EDIT,
317 EndHyphenEdit::NO_EDIT, &rect);
318 EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), rect);
319
320 layout = mt->buildLayout(text, Range(7, 7), fullContext, samePaint, StartHyphenEdit::NO_EDIT,
321 EndHyphenEdit::NO_EDIT);
322 EXPECT_EQ(0u, layout.nGlyphs());
323
324 MinikinPaint samePaint2(font);
325 samePaint2.size = 20.0f;
326 layout = mt->buildLayout(text, Range(7, 8), fullContext, samePaint2, StartHyphenEdit::NO_EDIT,
327 EndHyphenEdit::NO_EDIT);
328 ASSERT_EQ(1u, layout.nGlyphs());
329 EXPECT_TRUE(layout.getFont(0));
330 EXPECT_EQ(0.0f, layout.getX(0));
331 EXPECT_EQ(0.0f, layout.getY(0));
332 EXPECT_EQ(20.0f, layout.getAdvance());
333 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
334 EXPECT_EQ(1u, layout.getAdvances().size());
335 getBounds(text, Range(7, 8), Bidi::LTR, samePaint2, StartHyphenEdit::NO_EDIT,
336 EndHyphenEdit::NO_EDIT, &rect);
337 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
338 }
339
TEST(MeasuredTextTest,buildLayoutTest_differentPaint)340 TEST(MeasuredTextTest, buildLayoutTest_differentPaint) {
341 auto text = utf8ToUtf16("Hello, World!");
342 auto font = buildFontCollection("Ascii.ttf");
343 Range fullContext(0, text.size());
344
345 MeasuredTextBuilder builder;
346 MinikinPaint paint(font);
347 paint.size = 10.0f;
348 builder.addStyleRun(0, text.size(), std::move(paint), false /* is RTL */);
349 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
350 nullptr /* no hint */);
351
352 MinikinRect rect;
353 MinikinPaint differentPaint(font);
354 differentPaint.size = 20.0f;
355
356 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
357 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
358 EXPECT_EQ(0u, layout.nGlyphs());
359
360 layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
361 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
362 ASSERT_EQ(1u, layout.nGlyphs());
363 EXPECT_TRUE(layout.getFont(0));
364 EXPECT_EQ(0.0f, layout.getX(0));
365 EXPECT_EQ(0.0f, layout.getY(0));
366 EXPECT_EQ(20.0f, layout.getAdvance());
367 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
368 EXPECT_EQ(1u, layout.getAdvances().size());
369 getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
370 EndHyphenEdit::NO_EDIT, &rect);
371 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
372
373 layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
374 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
375 ASSERT_EQ(2u, layout.nGlyphs());
376 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
377 EXPECT_EQ(0.0f, layout.getX(0));
378 EXPECT_EQ(0.0f, layout.getY(0));
379 EXPECT_EQ(20.0f, layout.getX(1));
380 EXPECT_EQ(0.0f, layout.getY(1));
381 EXPECT_EQ(40.0f, layout.getAdvance());
382 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
383 EXPECT_EQ(20.0f, layout.getCharAdvance(1));
384 EXPECT_EQ(2u, layout.getAdvances().size());
385 getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
386 EndHyphenEdit::NO_EDIT, &rect);
387 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 40.0f, 0.0f), rect);
388
389 layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
390 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
391 ASSERT_EQ(1u, layout.nGlyphs());
392 EXPECT_TRUE(layout.getFont(0));
393 EXPECT_EQ(0.0f, layout.getX(0));
394 EXPECT_EQ(0.0f, layout.getY(0));
395 EXPECT_EQ(20.0f, layout.getAdvance());
396 EXPECT_EQ(20.0f, layout.getCharAdvance(0));
397 EXPECT_EQ(1u, layout.getAdvances().size());
398 getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
399 EndHyphenEdit::NO_EDIT, &rect);
400 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 20.0f, 0.0f), rect);
401
402 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
403 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
404 ASSERT_EQ(text.size(), layout.nGlyphs());
405 EXPECT_TRUE(layout.getFont(0));
406 for (uint32_t i = 0; i < text.size(); ++i) {
407 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
408 EXPECT_EQ(20.0f * i, layout.getX(i)) << i;
409 EXPECT_EQ(0.0f, layout.getY(i)) << i;
410 EXPECT_EQ(20.0f, layout.getCharAdvance(i)) << i;
411 }
412 EXPECT_EQ(260.0f, layout.getAdvance());
413 EXPECT_EQ(text.size(), layout.getAdvances().size());
414 getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
415 EndHyphenEdit::NO_EDIT, &rect);
416 EXPECT_EQ(MinikinRect(0.0f, 20.0f, 260.0f, 0.0f), rect);
417 }
418
TEST(MeasuredTextTest,buildLayoutTest_multiStyle_differentPaint)419 TEST(MeasuredTextTest, buildLayoutTest_multiStyle_differentPaint) {
420 auto text = utf8ToUtf16("Hello, World!");
421 auto font = buildFontCollection("Ascii.ttf");
422 uint32_t helloLength = 7; // length of "Hello, "
423 Range fullContext(0, text.size());
424
425 MeasuredTextBuilder builder;
426 MinikinPaint paint(font);
427 paint.size = 10.0f;
428 builder.addStyleRun(0, helloLength, std::move(paint), false /* is RTL */);
429 MinikinPaint paint2(font);
430 paint2.size = 20.0f;
431 builder.addStyleRun(helloLength, text.size(), std::move(paint2), false /* is RTL */);
432 auto mt = builder.build(text, true /* hyphenation */, true /* full layout */,
433 nullptr /* no hint */);
434
435 MinikinRect rect;
436 MinikinPaint differentPaint(font);
437 differentPaint.size = 30.0f;
438
439 Layout layout = mt->buildLayout(text, Range(0, 0), fullContext, differentPaint,
440 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
441 EXPECT_EQ(0u, layout.nGlyphs());
442
443 layout = mt->buildLayout(text, Range(0, 1), fullContext, differentPaint,
444 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
445 ASSERT_EQ(1u, layout.nGlyphs());
446 EXPECT_TRUE(layout.getFont(0));
447 EXPECT_EQ(0.0f, layout.getX(0));
448 EXPECT_EQ(0.0f, layout.getY(0));
449 EXPECT_EQ(30.0f, layout.getAdvance());
450 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
451 EXPECT_EQ(1u, layout.getAdvances().size());
452 getBounds(text, Range(0, 1), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
453 EndHyphenEdit::NO_EDIT, &rect);
454 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
455
456 layout = mt->buildLayout(text, Range(0, 2), fullContext, differentPaint,
457 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
458 ASSERT_EQ(2u, layout.nGlyphs());
459 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
460 EXPECT_EQ(0.0f, layout.getX(0));
461 EXPECT_EQ(0.0f, layout.getY(0));
462 EXPECT_EQ(30.0f, layout.getX(1));
463 EXPECT_EQ(0.0f, layout.getY(1));
464 EXPECT_EQ(60.0f, layout.getAdvance());
465 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
466 EXPECT_EQ(30.0f, layout.getCharAdvance(1));
467 EXPECT_EQ(2u, layout.getAdvances().size());
468 getBounds(text, Range(0, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
469 EndHyphenEdit::NO_EDIT, &rect);
470 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
471
472 layout = mt->buildLayout(text, Range(1, 2), fullContext, differentPaint,
473 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
474 ASSERT_EQ(1u, layout.nGlyphs());
475 EXPECT_TRUE(layout.getFont(0));
476 EXPECT_EQ(0.0f, layout.getX(0));
477 EXPECT_EQ(0.0f, layout.getY(0));
478 EXPECT_EQ(30.0f, layout.getAdvance());
479 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
480 EXPECT_EQ(1u, layout.getAdvances().size());
481 getBounds(text, Range(1, 2), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
482 EndHyphenEdit::NO_EDIT, &rect);
483 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
484
485 layout = mt->buildLayout(text, Range(7, 7), fullContext, differentPaint,
486 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
487 EXPECT_EQ(0u, layout.nGlyphs());
488
489 layout = mt->buildLayout(text, Range(7, 8), fullContext, differentPaint,
490 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
491 ASSERT_EQ(1u, layout.nGlyphs());
492 EXPECT_TRUE(layout.getFont(0));
493 EXPECT_EQ(0.0f, layout.getX(0));
494 EXPECT_EQ(0.0f, layout.getY(0));
495 EXPECT_EQ(30.0f, layout.getAdvance());
496 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
497 EXPECT_EQ(1u, layout.getAdvances().size());
498 getBounds(text, Range(7, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
499 EndHyphenEdit::NO_EDIT, &rect);
500 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 30.0f, 0.0f), rect);
501
502 layout = mt->buildLayout(text, Range(6, 8), fullContext, differentPaint,
503 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
504 ASSERT_EQ(2u, layout.nGlyphs());
505 EXPECT_TRUE(layout.getFont(0) && layout.getFont(0) == layout.getFont(1));
506 EXPECT_EQ(0.0f, layout.getX(0));
507 EXPECT_EQ(0.0f, layout.getY(0));
508 EXPECT_EQ(30.0f, layout.getX(1));
509 EXPECT_EQ(0.0f, layout.getY(1));
510 EXPECT_EQ(60.0f, layout.getAdvance());
511 EXPECT_EQ(30.0f, layout.getCharAdvance(0));
512 EXPECT_EQ(30.0f, layout.getCharAdvance(1));
513 EXPECT_EQ(2u, layout.getAdvances().size());
514 getBounds(text, Range(6, 8), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
515 EndHyphenEdit::NO_EDIT, &rect);
516 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 60.0f, 0.0f), rect);
517
518 layout = mt->buildLayout(text, Range(0, text.size()), fullContext, differentPaint,
519 StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
520 ASSERT_EQ(text.size(), layout.nGlyphs());
521 EXPECT_TRUE(layout.getFont(0));
522 for (uint32_t i = 0; i < text.size(); ++i) {
523 EXPECT_EQ(layout.getFont(0), layout.getFont(i)) << i;
524 EXPECT_EQ(30.0f * i, layout.getX(i)) << i;
525 EXPECT_EQ(0.0f, layout.getY(i)) << i;
526 EXPECT_EQ(30.0f, layout.getCharAdvance(i)) << i;
527 }
528 EXPECT_EQ(390.0f, layout.getAdvance());
529 EXPECT_EQ(text.size(), layout.getAdvances().size());
530 getBounds(text, Range(0, text.size()), Bidi::LTR, differentPaint, StartHyphenEdit::NO_EDIT,
531 EndHyphenEdit::NO_EDIT, &rect);
532 EXPECT_EQ(MinikinRect(0.0f, 30.0f, 390.0f, 0.0f), rect);
533 }
534
535 } // namespace minikin
536