1 /*
2 * Copyright (C) 2018 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 <gtest/gtest.h>
18 #include <minikin/Constants.h>
19
20 #include "BufferUtils.h"
21 #include "FontTestUtils.h"
22 #include "FreeTypeMinikinFontForTest.h"
23 #include "minikin/Font.h"
24
25 namespace minikin {
26
27 namespace {
28
getHeapSize()29 size_t getHeapSize() {
30 struct mallinfo info = mallinfo();
31 return info.uordblks;
32 }
33
34 } // namespace
35
TEST(FontTest,BufferTest)36 TEST(FontTest, BufferTest) {
37 FreeTypeMinikinFontForTestFactory::init();
38 auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("Ascii.ttf"));
39 std::shared_ptr<Font> original = Font::Builder(minikinFont).build();
40 std::vector<uint8_t> buffer = writeToBuffer<Font>(*original);
41
42 BufferReader reader(buffer.data());
43 Font font(&reader);
44 EXPECT_EQ(minikinFont->GetFontPath(), font.baseTypeface()->GetFontPath());
45 EXPECT_EQ(original->style(), font.style());
46 EXPECT_EQ(original->getLocaleListId(), font.getLocaleListId());
47 // baseFont() should return the same non-null instance when called twice.
48 const auto& baseFont = font.baseFont();
49 EXPECT_NE(nullptr, baseFont);
50 EXPECT_EQ(baseFont, font.baseFont());
51 // baseTypeface() should return the same non-null instance when called twice.
52 const auto& typeface = font.baseTypeface();
53 EXPECT_NE(nullptr, typeface);
54 EXPECT_EQ(typeface, font.baseTypeface());
55 std::vector<uint8_t> newBuffer = writeToBuffer<Font>(font);
56 EXPECT_EQ(buffer, newBuffer);
57 }
58
TEST(FontTest,MoveConstructorTest)59 TEST(FontTest, MoveConstructorTest) {
60 FreeTypeMinikinFontForTestFactory::init();
61 // Note: by definition, only BufferReader-based Font can be moved.
62 auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("Ascii.ttf"));
63 std::shared_ptr<Font> original = Font::Builder(minikinFont).build();
64 std::vector<uint8_t> buffer = writeToBuffer<Font>(*original);
65
66 size_t baseHeapSize = getHeapSize();
67 {
68 BufferReader reader(buffer.data());
69 Font moveFrom(&reader);
70 Font moveTo(std::move(moveFrom));
71 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
72 EXPECT_EQ(nullptr, moveTo.mExternalRefsHolder.load());
73 }
74 EXPECT_EQ(baseHeapSize, getHeapSize());
75 {
76 BufferReader reader(buffer.data());
77 Font moveFrom(&reader);
78 std::shared_ptr<MinikinFont> typeface = moveFrom.baseTypeface();
79 Font moveTo(std::move(moveFrom));
80 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
81 EXPECT_EQ(typeface, moveTo.baseTypeface());
82 }
83 EXPECT_EQ(baseHeapSize, getHeapSize());
84 }
85
TEST(FontTest,MoveAssignmentTest)86 TEST(FontTest, MoveAssignmentTest) {
87 FreeTypeMinikinFontForTestFactory::init();
88 // Note: by definition, only BufferReader-based Font can be moved.
89 auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("Ascii.ttf"));
90 std::shared_ptr<Font> original = Font::Builder(minikinFont).build();
91 std::vector<uint8_t> buffer = writeToBuffer<Font>(*original);
92
93 size_t baseHeapSize = getHeapSize();
94 {
95 // mExternalRefsHolder: null -> null
96 BufferReader reader(buffer.data());
97 Font moveFrom(&reader);
98 BufferReader reader2(buffer.data());
99 Font moveTo(&reader2);
100 moveTo = std::move(moveFrom);
101 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
102 EXPECT_EQ(nullptr, moveTo.mExternalRefsHolder.load());
103 }
104 EXPECT_EQ(baseHeapSize, getHeapSize());
105 {
106 // mExternalRefsHolder: non-null -> null
107 BufferReader reader(buffer.data());
108 Font moveFrom(&reader);
109 std::shared_ptr<MinikinFont> typeface = moveFrom.baseTypeface();
110 BufferReader reader2(buffer.data());
111 Font moveTo(&reader2);
112 moveTo = std::move(moveFrom);
113 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
114 EXPECT_EQ(typeface, moveTo.baseTypeface());
115 }
116 EXPECT_EQ(baseHeapSize, getHeapSize());
117 {
118 // mExternalRefsHolder: null -> non-null
119 BufferReader reader(buffer.data());
120 Font moveFrom(&reader);
121 BufferReader reader2(buffer.data());
122 Font moveTo(&reader2);
123 moveTo.baseTypeface();
124 moveTo = std::move(moveFrom);
125 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
126 EXPECT_EQ(nullptr, moveTo.mExternalRefsHolder.load());
127 }
128 EXPECT_EQ(baseHeapSize, getHeapSize());
129 {
130 // mExternalRefsHolder: non-null -> non-null
131 BufferReader reader(buffer.data());
132 Font moveFrom(&reader);
133 std::shared_ptr<MinikinFont> typeface = moveFrom.baseTypeface();
134 BufferReader reader2(buffer.data());
135 Font moveTo(&reader2);
136 moveTo.baseTypeface();
137 moveTo = std::move(moveFrom);
138 EXPECT_EQ(nullptr, moveFrom.mExternalRefsHolder.load());
139 EXPECT_EQ(typeface, moveTo.baseTypeface());
140 }
141 EXPECT_EQ(baseHeapSize, getHeapSize());
142 }
143
TEST(FontTest,getAdjustedFontTest)144 TEST(FontTest, getAdjustedFontTest) {
145 FreeTypeMinikinFontForTestFactory::init();
146 auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(
147 getTestFontPath("WeightEqualsEmVariableFont.ttf"));
148 std::shared_ptr<Font> font = Font::Builder(minikinFont).build();
149
150 {
151 auto hbFont = font->getAdjustedFont(-1, -1);
152 EXPECT_EQ(hbFont.get(), font->baseFont().get());
153 }
154 {
155 // Set correct wight axis value.
156 auto hbFont = font->getAdjustedFont(400, -1);
157 EXPECT_EQ(hb_font_get_parent(hbFont.get()), font->baseFont().get());
158 EXPECT_NE(hbFont.get(), font->baseFont().get());
159 unsigned int length;
160 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
161 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
162 EXPECT_EQ(400, coords[0]);
163 EXPECT_EQ(0, coords[1]);
164 }
165 {
166 // Override existing wght axis.
167 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(700, -1)).build();
168 auto hbFont = newFont->getAdjustedFont(500, -1);
169 EXPECT_EQ(hb_font_get_parent(hbFont.get()), newFont->baseFont().get());
170 EXPECT_NE(hbFont.get(), newFont->baseFont().get());
171 unsigned int length;
172 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
173 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
174 EXPECT_EQ(500, coords[0]);
175 EXPECT_EQ(0, coords[1]);
176 }
177 {
178 // Set correct wight axis value.
179 auto hbFont = font->getAdjustedFont(-1, 1);
180 EXPECT_EQ(hb_font_get_parent(hbFont.get()), font->baseFont().get());
181 EXPECT_NE(hbFont.get(), font->baseFont().get());
182 unsigned int length;
183 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
184 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
185 EXPECT_EQ(400, coords[0]); // 400 is a default value of `wght` axis
186 EXPECT_EQ(1, coords[1]);
187 }
188 {
189 // Override existing wght axis.
190 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(-1, 0)).build();
191 auto hbFont = newFont->getAdjustedFont(-1, 1);
192 EXPECT_EQ(hb_font_get_parent(hbFont.get()), newFont->baseFont().get());
193 EXPECT_NE(hbFont.get(), newFont->baseFont().get());
194 unsigned int length;
195 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
196 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
197 EXPECT_EQ(400, coords[0]); // 400 is a default value of `wght` axis
198 EXPECT_EQ(1, coords[1]);
199 }
200 {
201 // Set correct wight axis value.
202 auto hbFont = font->getAdjustedFont(500, 1);
203 EXPECT_EQ(hb_font_get_parent(hbFont.get()), font->baseFont().get());
204 EXPECT_NE(hbFont.get(), font->baseFont().get());
205 unsigned int length;
206 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
207 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
208 EXPECT_EQ(500, coords[0]);
209 EXPECT_EQ(1, coords[1]);
210 }
211 {
212 // Override existing wght axis.
213 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(500, 1)).build();
214 auto hbFont = newFont->getAdjustedFont(700, 0);
215 EXPECT_EQ(hb_font_get_parent(hbFont.get()), newFont->baseFont().get());
216 EXPECT_NE(hbFont.get(), newFont->baseFont().get());
217 unsigned int length;
218 const float* coords = hb_font_get_var_coords_design(hbFont.get(), &length);
219 ASSERT_EQ(2u, length); // The test font has 'wght', 'ital' axes in this order
220 EXPECT_EQ(700, coords[0]);
221 EXPECT_EQ(0, coords[1]);
222 }
223 }
224
TEST(FontTest,getAdjustedTypefaceTest)225 TEST(FontTest, getAdjustedTypefaceTest) {
226 FreeTypeMinikinFontForTestFactory::init();
227 auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(
228 getTestFontPath("WeightEqualsEmVariableFont.ttf"));
229 std::shared_ptr<Font> font = Font::Builder(minikinFont).build();
230
231 {
232 auto minikinFontBase = font->getAdjustedTypeface(-1, -1);
233 EXPECT_EQ(minikinFontBase.get(), font->baseTypeface().get());
234 }
235 {
236 // Set correct wght axis value.
237 auto minikinFontBase = font->getAdjustedTypeface(400, -1);
238 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
239 auto axes = minikinFontBase->GetAxes();
240 ASSERT_EQ(1u, axes.size());
241 EXPECT_EQ(TAG_wght, axes[0].axisTag);
242 EXPECT_EQ(400, axes[0].value);
243 }
244 {
245 // Override existing wght axis.
246 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(700, -1)).build();
247 auto minikinFontBase = newFont->getAdjustedTypeface(500, -1);
248 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
249 auto axes = minikinFontBase->GetAxes();
250 ASSERT_EQ(1u, axes.size());
251 EXPECT_EQ(TAG_wght, axes[0].axisTag);
252 EXPECT_EQ(500, axes[0].value);
253 }
254 {
255 // Set correct wght axis value.
256 auto minikinFontBase = font->getAdjustedTypeface(-1, 1);
257 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
258 auto axes = minikinFontBase->GetAxes();
259 ASSERT_EQ(1u, axes.size());
260 EXPECT_EQ(TAG_ital, axes[0].axisTag);
261 EXPECT_EQ(1, axes[0].value);
262 }
263 {
264 // Override existing wght axis.
265 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(-1, 1)).build();
266 auto minikinFontBase = newFont->getAdjustedTypeface(-1, 0);
267 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
268 auto axes = minikinFontBase->GetAxes();
269 ASSERT_EQ(1u, axes.size());
270 EXPECT_EQ(TAG_ital, axes[0].axisTag);
271 EXPECT_EQ(0, axes[0].value);
272 }
273 {
274 // Set correct ital axis value.
275 auto minikinFontBase = font->getAdjustedTypeface(400, 1);
276 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
277 auto axes = minikinFontBase->GetAxes();
278 ASSERT_EQ(2u, axes.size());
279 EXPECT_EQ(TAG_wght, axes[0].axisTag);
280 EXPECT_EQ(TAG_ital, axes[1].axisTag);
281 EXPECT_EQ(400, axes[0].value);
282 EXPECT_EQ(1, axes[1].value);
283 }
284 {
285 // Override existing ital axis.
286 std::shared_ptr<Font> newFont = Font::Builder(font->getAdjustedTypeface(500, 0)).build();
287 auto minikinFontBase = newFont->getAdjustedTypeface(700, 1);
288 EXPECT_NE(minikinFontBase.get(), font->baseTypeface().get());
289 auto axes = minikinFontBase->GetAxes();
290 ASSERT_EQ(2u, axes.size());
291 EXPECT_EQ(TAG_wght, axes[0].axisTag);
292 EXPECT_EQ(TAG_ital, axes[1].axisTag);
293 EXPECT_EQ(700, axes[0].value);
294 EXPECT_EQ(1, axes[1].value);
295 }
296 }
297
TEST(FontTest,ChildLazyCreationTest)298 TEST(FontTest, ChildLazyCreationTest) {
299 FreeTypeMinikinFontForTestFactory::init();
300 // Note: by definition, only BufferReader-based Font can be moved.
301 auto minikinFont =
302 std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("MultiAxis.ttf"));
303 std::shared_ptr<Font> original = Font::Builder(minikinFont).build();
304
305 // The original font doesn't axes settings.
306 EXPECT_TRUE(original->baseTypeface()->GetAxes().empty());
307
308 std::shared_ptr<Font> overridden = std::make_shared<Font>(
309 original, std::vector<FontVariation>{FontVariation(MakeTag('w', 'g', 'h', 't'), 0)});
310
311 EXPECT_EQ(1u, overridden->baseTypeface()->GetAxes().size());
312 EXPECT_EQ(MakeTag('w', 'g', 'h', 't'), overridden->baseTypeface()->GetAxes()[0].axisTag);
313 }
314
315 } // namespace minikin
316