Flutter Engine
font_collection_unittests.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Google, Inc.
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 "flutter/fml/logging.h"
18 #include "gtest/gtest.h"
19 #include "third_party/skia/include/utils/SkCustomTypeface.h"
20 #include "txt/font_collection.h"
21 #include "txt_test_utils.h"
22 
23 namespace txt {
24 
25 // We don't really need a fixture but a class in a namespace is needed for
26 // the FRIEND_TEST macro.
27 class FontCollectionTest : public ::testing::Test {};
28 
29 namespace {
30 // This function does some boilerplate to fill a builder with enough real
31 // font-like data. Otherwise, detach won't actually build an SkTypeface.
32 void PopulateUserTypefaceBoilerplate(SkCustomTypefaceBuilder* builder) {
33  constexpr float upem = 200;
34 
35  {
36  SkFontMetrics metrics;
37  metrics.fFlags = 0;
38  metrics.fTop = -200;
39  metrics.fAscent = -150;
40  metrics.fDescent = 50;
41  metrics.fBottom = -75;
42  metrics.fLeading = 10;
43  metrics.fAvgCharWidth = 150;
44  metrics.fMaxCharWidth = 300;
45  metrics.fXMin = -20;
46  metrics.fXMax = 290;
47  metrics.fXHeight = -100;
48  metrics.fCapHeight = 0;
49  metrics.fUnderlineThickness = 5;
50  metrics.fUnderlinePosition = 2;
51  metrics.fStrikeoutThickness = 5;
52  metrics.fStrikeoutPosition = -50;
53  builder->setMetrics(metrics, 1.0f / upem);
54  }
55 
56  const SkMatrix scale = SkMatrix::Scale(1.0f / upem, 1.0f / upem);
57  for (SkGlyphID index = 0; index <= 67; ++index) {
58  SkScalar width;
59  width = 100;
60  SkPath path;
61  path.addCircle(50, -50, 75);
62 
63  builder->setGlyph(index, width / upem, path.makeTransform(scale));
64  }
65 }
66 } // namespace
67 
68 TEST(FontCollectionTest, CheckSkTypefacesSorting) {
69  // We have to make a real SkTypeface here. Not all the structs from the
70  // SkTypeface headers are fully declared to be able to gmock.
71  // SkCustomTypefaceBuilder is the simplest way to get a simple SkTypeface.
72  SkCustomTypefaceBuilder typefaceBuilder1;
73  typefaceBuilder1.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight,
74  SkFontStyle::kExpanded_Width,
75  SkFontStyle::kItalic_Slant));
76  // For the purpose of this test, we need to fill this to make the SkTypeface
77  // build but it doesn't matter. We only care about the SkFontStyle.
78  PopulateUserTypefaceBoilerplate(&typefaceBuilder1);
79  sk_sp<SkTypeface> typeface1{typefaceBuilder1.detach()};
80 
81  SkCustomTypefaceBuilder typefaceBuilder2;
82  typefaceBuilder2.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight,
83  SkFontStyle::kNormal_Width,
84  SkFontStyle::kUpright_Slant));
85  PopulateUserTypefaceBoilerplate(&typefaceBuilder2);
86  sk_sp<SkTypeface> typeface2{typefaceBuilder2.detach()};
87 
88  SkCustomTypefaceBuilder typefaceBuilder3;
89  typefaceBuilder3.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
90  SkFontStyle::kNormal_Width,
91  SkFontStyle::kUpright_Slant));
92  PopulateUserTypefaceBoilerplate(&typefaceBuilder3);
93  sk_sp<SkTypeface> typeface3{typefaceBuilder3.detach()};
94 
95  SkCustomTypefaceBuilder typefaceBuilder4;
96  typefaceBuilder4.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight,
97  SkFontStyle::kCondensed_Width,
98  SkFontStyle::kUpright_Slant));
99  PopulateUserTypefaceBoilerplate(&typefaceBuilder4);
100  sk_sp<SkTypeface> typeface4{typefaceBuilder4.detach()};
101 
102  std::vector<sk_sp<SkTypeface>> candidateTypefaces = {typeface1, typeface2,
103  typeface3, typeface4};
104 
105  // This sorts the vector in-place.
106  txt::FontCollection::SortSkTypefaces(candidateTypefaces);
107 
108  // The second one is first because it's both the most normal width font
109  // with the lightest weight.
110  ASSERT_EQ(candidateTypefaces[0].get(), typeface2.get());
111  // Then the most normal width font with normal weight.
112  ASSERT_EQ(candidateTypefaces[1].get(), typeface3.get());
113  // Then a less normal (condensed) width font.
114  ASSERT_EQ(candidateTypefaces[2].get(), typeface4.get());
115  // All things equal, 4 came before 1 because we arbitrarily chose to make the
116  // narrower font come first.
117  ASSERT_EQ(candidateTypefaces[3].get(), typeface1.get());
118 
119  // Double check.
120  ASSERT_EQ(candidateTypefaces[0]->fontStyle().weight(),
121  SkFontStyle::kLight_Weight);
122  ASSERT_EQ(candidateTypefaces[0]->fontStyle().width(),
123  SkFontStyle::kNormal_Width);
124 
125  ASSERT_EQ(candidateTypefaces[1]->fontStyle().weight(),
126  SkFontStyle::kNormal_Weight);
127  ASSERT_EQ(candidateTypefaces[1]->fontStyle().width(),
128  SkFontStyle::kNormal_Width);
129 
130  ASSERT_EQ(candidateTypefaces[2]->fontStyle().weight(),
131  SkFontStyle::kThin_Weight);
132  ASSERT_EQ(candidateTypefaces[2]->fontStyle().width(),
133  SkFontStyle::kCondensed_Width);
134 
135  ASSERT_EQ(candidateTypefaces[3]->fontStyle().weight(),
136  SkFontStyle::kThin_Weight);
137  ASSERT_EQ(candidateTypefaces[3]->fontStyle().width(),
138  SkFontStyle::kExpanded_Width);
139 }
140 
141 #if 0
142 
143 TEST(FontCollection, HasDefaultRegistrations) {
144  std::string defaultFamilyName = txt::FontCollection::GetDefaultFamilyName();
145 
146  auto collection = txt::FontCollection::GetFontCollection(txt::GetFontDir())
147  .GetMinikinFontCollectionForFamily("");
148  ASSERT_EQ(defaultFamilyName,
149  txt::FontCollection::GetFontCollection(txt::GetFontDir())
150  .ProcessFamilyName(""));
151  ASSERT_NE(defaultFamilyName,
152  txt::FontCollection::GetFontCollection(txt::GetFontDir())
153  .ProcessFamilyName("NotARealFont!"));
154  ASSERT_EQ("NotARealFont!",
155  txt::FontCollection::GetFontCollection(txt::GetFontDir())
156  .ProcessFamilyName("NotARealFont!"));
157  ASSERT_NE(collection.get(), nullptr);
158 }
159 
160 TEST(FontCollection, GetMinikinFontCollections) {
161  std::string defaultFamilyName = txt::FontCollection::GetDefaultFamilyName();
162 
163  auto collectionDef = txt::FontCollection::GetFontCollection(txt::GetFontDir())
164  .GetMinikinFontCollectionForFamily("");
165  auto collectionRoboto =
166  txt::FontCollection::GetFontCollection(txt::GetFontDir())
167  .GetMinikinFontCollectionForFamily("Roboto");
168  auto collectionHomemadeApple =
169  txt::FontCollection::GetFontCollection(txt::GetFontDir())
170  .GetMinikinFontCollectionForFamily("Homemade Apple");
171  for (size_t base = 0; base < 50; base++) {
172  for (size_t variation = 0; variation < 50; variation++) {
173  ASSERT_EQ(collectionDef->hasVariationSelector(base, variation),
174  collectionRoboto->hasVariationSelector(base, variation));
175  }
176  }
177 
178  ASSERT_NE(collectionDef, collectionHomemadeApple);
179  ASSERT_NE(collectionHomemadeApple, collectionRoboto);
180  ASSERT_NE(collectionDef.get(), nullptr);
181 }
182 
183 TEST(FontCollection, GetFamilyNames) {
184  std::set<std::string> names =
185  txt::FontCollection::GetFontCollection(txt::GetFontDir())
186  .GetFamilyNames();
187 
188  ASSERT_TRUE(names.size() >= 19ull);
189 
190  ASSERT_EQ(names.count("Roboto"), 1ull);
191  ASSERT_EQ(names.count("Homemade Apple"), 1ull);
192 
193  ASSERT_EQ(names.count("KoreanFont Test"), 1ull);
194  ASSERT_EQ(names.count("JapaneseFont Test"), 1ull);
195  ASSERT_EQ(names.count("EmojiFont Test"), 1ull);
196  ASSERT_EQ(names.count("ItalicFont Test"), 1ull);
197  ASSERT_EQ(names.count("VariationSelector Test"), 1ull);
198  ASSERT_EQ(names.count("ColorEmojiFont Test"), 1ull);
199  ASSERT_EQ(names.count("TraditionalChinese Test"), 1ull);
200  ASSERT_EQ(names.count("Sample Font"), 1ull);
201  ASSERT_EQ(names.count("MultiAxisFont Test"), 1ull);
202  ASSERT_EQ(names.count("TextEmojiFont Test"), 1ull);
203  ASSERT_EQ(names.count("No Cmap Format 14 Subtable Test"), 1ull);
204  ASSERT_EQ(names.count("ColorTextMixedEmojiFont Test"), 1ull);
205  ASSERT_EQ(names.count("BoldFont Test"), 1ull);
206  ASSERT_EQ(names.count("EmptyFont Test"), 1ull);
207  ASSERT_EQ(names.count("SimplifiedChinese Test"), 1ull);
208  ASSERT_EQ(names.count("BoldItalicFont Test"), 1ull);
209  ASSERT_EQ(names.count("RegularFont Test"), 1ull);
210 
211  ASSERT_EQ(names.count("Not a real font!"), 0ull);
212  ASSERT_EQ(names.count(""), 0ull);
213  ASSERT_EQ(names.count("Another Fake Font"), 0ull);
214 }
215 
216 #endif // 0
217 
218 } // namespace txt
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
int32_t width
TEST(FontCollectionTest, CheckSkTypefacesSorting)
const std::string & GetFontDir()