1 /*
2 * Copyright (C) 2024 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
19 #include "FontVariationTestUtils.h"
20 #include "minikin/Constants.h"
21 #include "minikin/FontFakery.h"
22
23 namespace minikin {
24
25 namespace {
26
27 constexpr FontStyle THIN = FontStyle(FontStyle::Weight::THIN, FontStyle::Slant::UPRIGHT);
28 constexpr FontStyle REGULAR = FontStyle(FontStyle::Weight::NORMAL, FontStyle::Slant::UPRIGHT);
29 constexpr FontStyle MEDIUM = FontStyle(FontStyle::Weight::MEDIUM, FontStyle::Slant::UPRIGHT);
30 constexpr FontStyle BOLD = FontStyle(FontStyle::Weight::BOLD, FontStyle::Slant::UPRIGHT);
31 constexpr FontStyle BLACK = FontStyle(FontStyle::Weight::BLACK, FontStyle::Slant::UPRIGHT);
32 constexpr FontStyle ITALIC = FontStyle(FontStyle::Weight::NORMAL, FontStyle::Slant::ITALIC);
33 constexpr FontStyle BOLD_ITALIC = FontStyle(FontStyle::Weight::BOLD, FontStyle::Slant::ITALIC);
34
merge(const FVarTable & fvar,const std::string & base,const std::string & target,FontStyle baseStyle,FontStyle targetStyle)35 FontFakery merge(const FVarTable& fvar, const std::string& base, const std::string& target,
36 FontStyle baseStyle, FontStyle targetStyle) {
37 return merge(fvar, parseVariationSettings(base), parseVariationSettings(target), baseStyle,
38 targetStyle);
39 }
40
41 } // namespace
42
operator ==(const char * expect,const VariationSettings & vs)43 inline bool operator==(const char* expect, const VariationSettings& vs) {
44 VariationSettings expectVarSettings = parseVariationSettings(expect);
45 return expectVarSettings == vs;
46 }
47
TEST(FontFakeryTest,testConstruct)48 TEST(FontFakeryTest, testConstruct) {
49 EXPECT_EQ(FontFakery(), FontFakery(false, false));
50 EXPECT_NE(FontFakery(), FontFakery(true, false));
51 EXPECT_NE(FontFakery(), FontFakery(false, true));
52 EXPECT_NE(FontFakery(), FontFakery(true, true));
53
54 EXPECT_TRUE(FontFakery(true, true).isFakeBold());
55 EXPECT_TRUE(FontFakery(true, true).isFakeItalic());
56 EXPECT_TRUE(FontFakery(true, true).variationSettings().empty());
57
58 EXPECT_FALSE(FontFakery(false, false).isFakeBold());
59 EXPECT_FALSE(FontFakery(false, false).isFakeItalic());
60 EXPECT_TRUE(FontFakery(false, false).variationSettings().empty());
61
62 EXPECT_TRUE(FontFakery(true, false).isFakeBold());
63 EXPECT_FALSE(FontFakery(true, false).isFakeItalic());
64 EXPECT_TRUE(FontFakery(true, false).variationSettings().empty());
65
66 EXPECT_FALSE(FontFakery(false, true).isFakeBold());
67 EXPECT_TRUE(FontFakery(false, true).isFakeItalic());
68 EXPECT_TRUE(FontFakery(false, true).variationSettings().empty());
69 }
70
TEST(FontFakeryTest,testVariationSettings)71 TEST(FontFakeryTest, testVariationSettings) {
72 VariationSettings variationSettings = {FontVariation(TAG_wght, 400),
73 FontVariation(TAG_ital, 1)};
74
75 auto ff = FontFakery(false, false, std::move(variationSettings));
76
77 EXPECT_EQ(2u, ff.variationSettings().size());
78 EXPECT_EQ(TAG_ital, ff.variationSettings()[0].axisTag);
79 EXPECT_EQ(1, ff.variationSettings()[0].value);
80 EXPECT_EQ(TAG_wght, ff.variationSettings()[1].axisTag);
81 EXPECT_EQ(400, ff.variationSettings()[1].value);
82 }
83
TEST(FontFakeryTest,testMerge)84 TEST(FontFakeryTest, testMerge) {
85 FVarTable fvar = {{MakeTag('A', 'B', 'C', 'D'), {0, 100, 50}}};
86
87 // Override should be used.
88 EXPECT_EQ("'ABCD' 100", merge(fvar, "", "'ABCD' 100", REGULAR, REGULAR).variationSettings());
89 // Base should be remains
90 EXPECT_EQ("'ABCD' 0", merge(fvar, "'ABCD' 0", "", REGULAR, REGULAR).variationSettings());
91 // The default value from the target VS should be preserved.
92 EXPECT_EQ("'ABCD' 50", merge(fvar, "", "'ABCD' 50", REGULAR, REGULAR).variationSettings());
93 // Override should override the base settings.
94 EXPECT_EQ("'ABCD' 100",
95 merge(fvar, "'ABCD' 0", "'ABCD' 100", REGULAR, REGULAR).variationSettings());
96 }
97
TEST(FontFakeryTest,testMerge_twoAxes)98 TEST(FontFakeryTest, testMerge_twoAxes) {
99 FVarTable fvar = {{MakeTag('A', 'B', 'C', 'D'), {0, 100, 50}},
100 {MakeTag('E', 'F', 'G', 'H'), {0, 100, 50}}};
101
102 // Different axes should be preserved.
103 EXPECT_EQ("'ABCD' 100, 'EFGH' 100",
104 merge(fvar, "'ABCD' 100", "'EFGH' 100", REGULAR, REGULAR).variationSettings());
105 // Overrides override only matched axis.
106 EXPECT_EQ(
107 "'ABCD' 0, 'EFGH' 100",
108 merge(fvar, "'ABCD' 0, 'EFGH' 0", "'EFGH' 100", REGULAR, REGULAR).variationSettings());
109 }
110
TEST(FontFakeryTest,testMerge_styleWeight)111 TEST(FontFakeryTest, testMerge_styleWeight) {
112 FVarTable fvar = {{TAG_wght, {100, 900, 400}}, {TAG_ital, {0, 1, 0}}};
113
114 // Default FontStyle sets wght 400 and it is dropped.
115 EXPECT_EQ("", merge(fvar, "", "", REGULAR, REGULAR).variationSettings());
116 // Use weight of FontStyle if no override is specified.
117 EXPECT_EQ("'wght' 100", merge(fvar, "", "", REGULAR, THIN).variationSettings());
118 // If override is spseicied, it is used instead of FontStyle.
119 EXPECT_EQ("'wght' 500", merge(fvar, "", "'wght' 500", REGULAR, THIN).variationSettings());
120 }
121
TEST(FontFakeryTest,testMerge_styleItal)122 TEST(FontFakeryTest, testMerge_styleItal) {
123 FVarTable fvar = {{TAG_wght, {100, 900, 400}}, {TAG_ital, {0, 1, 0}}};
124
125 // Use weight of FontStyle if no override is specified.
126 EXPECT_EQ("'ital' 1", merge(fvar, "", "", REGULAR, ITALIC).variationSettings());
127 EXPECT_EQ("'ital' 1", merge(fvar, "'ital' 1", "", REGULAR, REGULAR).variationSettings());
128 EXPECT_EQ("'ital' 0", merge(fvar, "'ital' 0", "", REGULAR, ITALIC).variationSettings());
129 // If override is spseicied, it is used instead of FontStyle.
130 EXPECT_EQ("'ital' 0", merge(fvar, "", "'ital' 0", REGULAR, ITALIC).variationSettings());
131 }
132
TEST(FontFakeryTest,testMerge_styleSlnt)133 TEST(FontFakeryTest, testMerge_styleSlnt) {
134 FVarTable fvar = {{TAG_wght, {100, 900, 400}}, {TAG_slnt, {-10, 0, 0}}};
135
136 // Use weight of FontStyle if no override is specified.
137 EXPECT_EQ("'slnt' -10", merge(fvar, "", "", REGULAR, ITALIC).variationSettings());
138 // If override is spseicied, it is used instead of FontStyle.
139 EXPECT_EQ("'slnt' 0", merge(fvar, "", "'slnt' 0", REGULAR, ITALIC).variationSettings());
140 }
141
TEST(FontFakeryTest,testMerge_complex)142 TEST(FontFakeryTest, testMerge_complex) {
143 FVarTable fvar = {
144 {TAG_wght, {100, 900, 400}},
145 {TAG_slnt, {-10, 0, 0}},
146 {MakeTag('A', 'B', 'C', 'D'), {0, 100, 50}},
147 };
148
149 EXPECT_EQ("'wght' 750, 'slnt' -10, 'ABCD' 75",
150 merge(fvar, "'wght' 650", "'wght' 750, 'ABCD' 75", REGULAR, ITALIC)
151 .variationSettings());
152 }
153
TEST(FontFakeryTest,testMerge_fakeBold_unsupported_font)154 TEST(FontFakeryTest, testMerge_fakeBold_unsupported_font) {
155 FVarTable fvar = {};
156
157 // The same weight won't enable fake bold.
158 EXPECT_FALSE(merge(fvar, "", "", REGULAR, REGULAR).isFakeBold());
159 EXPECT_FALSE(merge(fvar, "", "", BOLD, BOLD).isFakeBold());
160 EXPECT_FALSE(merge(fvar, "", "", THIN, THIN).isFakeBold());
161 EXPECT_FALSE(merge(fvar, "", "", BLACK, BLACK).isFakeBold());
162 EXPECT_FALSE(merge(fvar, "", "", REGULAR, ITALIC).isFakeBold());
163
164 // If the weight diff is more than 200, fake bold is enabled.
165 EXPECT_TRUE(merge(fvar, "", "", REGULAR, BOLD).isFakeBold());
166 EXPECT_TRUE(merge(fvar, "", "", REGULAR, BLACK).isFakeBold());
167 EXPECT_TRUE(merge(fvar, "", "", BOLD, BLACK).isFakeBold());
168
169 // If the requested weight is less than 600, the fake bold is not enabled.
170 EXPECT_FALSE(merge(fvar, "", "", THIN, REGULAR).isFakeBold());
171 EXPECT_FALSE(merge(fvar, "", "", THIN, MEDIUM).isFakeBold());
172 }
173
TEST(FontFakeryTest,testMerge_fakeBold_fullrange_font)174 TEST(FontFakeryTest, testMerge_fakeBold_fullrange_font) {
175 FVarTable fvar = {{TAG_wght, {100, 900, 400}}};
176
177 // If the given font supports full range of weight, the fake bold is never enabled.
178 EXPECT_FALSE(merge(fvar, "", "", REGULAR, THIN).isFakeBold());
179 EXPECT_FALSE(merge(fvar, "", "", REGULAR, REGULAR).isFakeBold());
180 EXPECT_FALSE(merge(fvar, "", "", REGULAR, MEDIUM).isFakeBold());
181 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BOLD).isFakeBold());
182 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BLACK).isFakeBold());
183 EXPECT_FALSE(merge(fvar, "", "", REGULAR, ITALIC).isFakeBold());
184 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BOLD_ITALIC).isFakeBold());
185 }
186
TEST(FontFakeryTest,testMerge_fakeBold_limited_range_font)187 TEST(FontFakeryTest, testMerge_fakeBold_limited_range_font) {
188 FVarTable fvar = {{TAG_wght, {100, 700, 400}}};
189
190 // If the weight diff from the upper limit of the weight is more than 200, fake bold is enabled.
191 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BOLD).isFakeBold());
192 EXPECT_TRUE(merge(fvar, "", "", REGULAR, BLACK).isFakeBold());
193 }
194
TEST(FontFakeryTest,testMerge_fakeItalic_unsupported_font)195 TEST(FontFakeryTest, testMerge_fakeItalic_unsupported_font) {
196 FVarTable fvar = {};
197
198 // The same italic won't enable fake italic.
199 EXPECT_FALSE(merge(fvar, "", "", REGULAR, REGULAR).isFakeItalic());
200 EXPECT_FALSE(merge(fvar, "", "", ITALIC, ITALIC).isFakeItalic());
201 EXPECT_FALSE(merge(fvar, "", "", BOLD_ITALIC, BOLD_ITALIC).isFakeItalic());
202
203 // If the target style is italic but base style is not, fake bold is enabled.
204 EXPECT_TRUE(merge(fvar, "", "", REGULAR, ITALIC).isFakeItalic());
205 EXPECT_TRUE(merge(fvar, "", "", REGULAR, BOLD_ITALIC).isFakeItalic());
206 }
207
TEST(FontFakeryTest,testMerge_fakeItalic_ital_font)208 TEST(FontFakeryTest, testMerge_fakeItalic_ital_font) {
209 FVarTable fvar = {{TAG_ital, {0, 1, 0}}};
210
211 // If the font supports ital tag, the fake italic is never enabled.
212 EXPECT_FALSE(merge(fvar, "", "", REGULAR, ITALIC).isFakeItalic());
213 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BOLD_ITALIC).isFakeItalic());
214 }
215
TEST(FontFakeryTest,testMerge_fakeItalic_slnt_font)216 TEST(FontFakeryTest, testMerge_fakeItalic_slnt_font) {
217 FVarTable fvar = {{TAG_slnt, {-10, 0, 0}}};
218
219 // If the font supports slnt tag, the fake italic is never enabled.
220 EXPECT_FALSE(merge(fvar, "", "", REGULAR, ITALIC).isFakeItalic());
221 EXPECT_FALSE(merge(fvar, "", "", REGULAR, BOLD_ITALIC).isFakeItalic());
222 }
223
224 } // namespace minikin
225