• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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