1 /*
2 * Copyright (C) 2013 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/FontFamily.h"
18
19 #include <log/log.h>
20
21 #include <algorithm>
22 #include <unordered_set>
23 #include <vector>
24
25 #include "FeatureFlags.h"
26 #include "FontUtils.h"
27 #include "Locale.h"
28 #include "LocaleListCache.h"
29 #include "MinikinInternal.h"
30 #include "minikin/CmapCoverage.h"
31 #include "minikin/Constants.h"
32 #include "minikin/FamilyVariant.h"
33 #include "minikin/HbUtils.h"
34 #include "minikin/MinikinFont.h"
35
36 namespace minikin {
37
38 namespace {
getAncestor(const std::shared_ptr<FontFamily> & family)39 const std::shared_ptr<FontFamily>& getAncestor(const std::shared_ptr<FontFamily>& family) {
40 return !family->getParent() ? family : getAncestor(family->getParent());
41 }
42 } // namespace
43
44 // static
create(std::vector<std::shared_ptr<Font>> && fonts)45 std::shared_ptr<FontFamily> FontFamily::create(std::vector<std::shared_ptr<Font>>&& fonts) {
46 return create(FamilyVariant::DEFAULT, std::move(fonts));
47 }
48
49 // static
create(FamilyVariant variant,std::vector<std::shared_ptr<Font>> && fonts)50 std::shared_ptr<FontFamily> FontFamily::create(FamilyVariant variant,
51 std::vector<std::shared_ptr<Font>>&& fonts) {
52 return create(kEmptyLocaleListId, variant, std::move(fonts), false /* isCustomFallback */,
53 false /* isDefaultFallback */, VariationFamilyType::None);
54 }
55
56 // static
create(uint32_t localeListId,FamilyVariant variant,std::vector<std::shared_ptr<Font>> && fonts,bool isCustomFallback,bool isDefaultFallback,VariationFamilyType varFamilyType)57 std::shared_ptr<FontFamily> FontFamily::create(uint32_t localeListId, FamilyVariant variant,
58 std::vector<std::shared_ptr<Font>>&& fonts,
59 bool isCustomFallback, bool isDefaultFallback,
60 VariationFamilyType varFamilyType) {
61 // TODO(b/174672300): Revert back to make_shared.
62 return std::shared_ptr<FontFamily>(new FontFamily(localeListId, variant, std::move(fonts),
63 isCustomFallback, isDefaultFallback,
64 varFamilyType));
65 }
66
create(const std::shared_ptr<FontFamily> & parent,const VariationSettings & axes)67 std::shared_ptr<FontFamily> FontFamily::create(const std::shared_ptr<FontFamily>& parent,
68 const VariationSettings& axes) {
69 if (axes.empty() || parent->getSupportedAxesCount() == 0) {
70 return nullptr;
71 }
72
73 bool hasSupportedAxis = false;
74 for (const auto& axis : axes) {
75 for (uint32_t i = 0; i < parent->getSupportedAxesCount(); ++i) {
76 if (axis.axisTag == parent->getSupportedAxisAt(i)) {
77 hasSupportedAxis = true;
78 break;
79 }
80 }
81 }
82 if (!hasSupportedAxis) {
83 // None of variation axes are suppored by this family.
84 return nullptr;
85 }
86
87 return std::shared_ptr<FontFamily>(new FontFamily(parent, axes));
88 }
89
FontFamily(const std::shared_ptr<FontFamily> & parent,const VariationSettings & axesOverride)90 FontFamily::FontFamily(const std::shared_ptr<FontFamily>& parent,
91 const VariationSettings& axesOverride)
92 : mFonts(),
93 mSupportedAxes(std::make_unique<AxisTag[]>(parent->getSupportedAxesCount())),
94 mCoverage(),
95 mCmapFmt14Coverage(nullptr),
96 mParent(getAncestor(parent)), // Use ancestor as parent.
97 mVarOverride(axesOverride),
98 mLocaleListId(parent->mLocaleListId),
99 mFontsCount(parent->mFontsCount),
100 mSupportedAxesCount(parent->mSupportedAxesCount),
101 mCmapFmt14CoverageCount(parent->mCmapFmt14CoverageCount),
102 mVariant(parent->mVariant),
103 mIsColorEmoji(parent->mIsColorEmoji),
104 mIsCustomFallback(parent->mIsCustomFallback),
105 mIsDefaultFallback(parent->mIsDefaultFallback),
106 mVarFamilyType(VariationFamilyType::None),
107 mIsVariationFamily(true) {
108 // Filter only the axis supported font.
109 std::vector<std::shared_ptr<Font>> overriddenFonts;
110 for (uint16_t i = 0; i < mFontsCount; ++i) {
111 const auto& font = parent->mFonts[i];
112 bool isSupported = false;
113 for (const auto& axis : axesOverride) {
114 if (font->isAxisSupported(axis.axisTag)) {
115 isSupported = true;
116 break;
117 }
118 }
119 if (isSupported) {
120 overriddenFonts.emplace_back(std::make_shared<Font>(font, axesOverride));
121 }
122 }
123 mFonts = std::make_unique<std::shared_ptr<Font>[]>(overriddenFonts.size());
124 for (uint16_t i = 0; i < overriddenFonts.size(); ++i) {
125 mFonts[i] = std::move(overriddenFonts[i]);
126 }
127
128 // Copy the supported axes
129 const AxisTag* src = parent->mSupportedAxes.get();
130 std::copy(src, src + mSupportedAxesCount, mSupportedAxes.get());
131 }
132
FontFamily(uint32_t localeListId,FamilyVariant variant,std::vector<std::shared_ptr<Font>> && fonts,bool isCustomFallback,bool isDefaultFallback,VariationFamilyType varFamilyType)133 FontFamily::FontFamily(uint32_t localeListId, FamilyVariant variant,
134 std::vector<std::shared_ptr<Font>>&& fonts, bool isCustomFallback,
135 bool isDefaultFallback, VariationFamilyType varFamilyType)
136 : mFonts(std::make_unique<std::shared_ptr<Font>[]>(fonts.size())),
137 // computeCoverage may update supported axes and coverages later.
138 mSupportedAxes(nullptr),
139 mCoverage(),
140 mCmapFmt14Coverage(nullptr),
141 mParent(nullptr),
142 mVarOverride(),
143 mLocaleListId(localeListId),
144 mFontsCount(static_cast<uint32_t>(fonts.size())),
145 mSupportedAxesCount(0),
146 mCmapFmt14CoverageCount(0),
147 mVariant(variant),
148 mIsColorEmoji(LocaleListCache::getById(localeListId).getEmojiStyle() ==
149 EmojiStyle::EMOJI),
150 mIsCustomFallback(isCustomFallback),
151 mIsDefaultFallback(isDefaultFallback),
152 mVarFamilyType(varFamilyType),
153 mIsVariationFamily(false) {
154 MINIKIN_ASSERT(!fonts.empty(), "FontFamily must contain at least one font.");
155 MINIKIN_ASSERT(fonts.size() <= std::numeric_limits<uint32_t>::max(),
156 "Number of fonts must be less than 2^32.");
157 for (size_t i = 0; i < mFontsCount; i++) {
158 mFonts[i] = std::move(fonts[i]);
159 }
160 computeCoverage();
161 }
162
FontFamily(BufferReader * reader,const std::shared_ptr<std::vector<Font>> & allFonts)163 FontFamily::FontFamily(BufferReader* reader, const std::shared_ptr<std::vector<Font>>& allFonts)
164 : mSupportedAxes(nullptr), mCmapFmt14Coverage(nullptr), mParent(nullptr), mVarOverride() {
165 mLocaleListId = LocaleListCache::readFrom(reader);
166 mFontsCount = reader->read<uint32_t>();
167 mFonts = std::make_unique<std::shared_ptr<Font>[]>(mFontsCount);
168 for (size_t i = 0; i < mFontsCount; i++) {
169 uint32_t fontIndex = reader->read<uint32_t>();
170 // Use aliasing constructor to save memory.
171 // See the comments on FontFamily::readVector for details.
172 mFonts[i] = std::shared_ptr<Font>(allFonts, &(*allFonts)[fontIndex]);
173 }
174 // FamilyVariant is uint8_t
175 static_assert(sizeof(FamilyVariant) == 1);
176 mVariant = reader->read<FamilyVariant>();
177 // AxisTag is uint32_t
178 static_assert(sizeof(AxisTag) == 4);
179 const auto& [axesPtr, axesCount] = reader->readArray<AxisTag>();
180 mSupportedAxesCount = axesCount;
181 if (axesCount > 0) {
182 mSupportedAxes = std::unique_ptr<AxisTag[]>(new AxisTag[axesCount]);
183 std::copy(axesPtr, axesPtr + axesCount, mSupportedAxes.get());
184 }
185 mIsColorEmoji = static_cast<bool>(reader->read<uint8_t>());
186 mIsCustomFallback = static_cast<bool>(reader->read<uint8_t>());
187 mIsDefaultFallback = static_cast<bool>(reader->read<uint8_t>());
188 mVarFamilyType = reader->read<VariationFamilyType>();
189 mIsVariationFamily = false;
190 mCoverage = SparseBitSet(reader);
191 // Read mCmapFmt14Coverage. As it can have null entries, it is stored in the buffer as a sparse
192 // array (size, non-null entry count, array of (index, entry)).
193 mCmapFmt14CoverageCount = reader->read<uint32_t>();
194 if (mCmapFmt14CoverageCount > 0) {
195 mCmapFmt14Coverage = std::make_unique<SparseBitSet[]>(mCmapFmt14CoverageCount);
196 uint32_t cmapFmt14CoverageEntryCount = reader->read<uint32_t>();
197 for (uint32_t i = 0; i < cmapFmt14CoverageEntryCount; i++) {
198 uint32_t index = reader->read<uint32_t>();
199 mCmapFmt14Coverage[index] = SparseBitSet(reader);
200 }
201 }
202 }
203
writeTo(BufferWriter * writer,uint32_t * fontIndex) const204 void FontFamily::writeTo(BufferWriter* writer, uint32_t* fontIndex) const {
205 MINIKIN_ASSERT(mParent == nullptr, "Do not serialize variation overridden font families.");
206 LocaleListCache::writeTo(writer, mLocaleListId);
207 writer->write<uint32_t>(mFontsCount);
208 for (size_t i = 0; i < mFontsCount; i++) {
209 writer->write<uint32_t>(*fontIndex);
210 (*fontIndex)++;
211 }
212 writer->write<FamilyVariant>(mVariant);
213 writer->writeArray<AxisTag>(mSupportedAxes.get(), mSupportedAxesCount);
214 writer->write<uint8_t>(mIsColorEmoji);
215 writer->write<uint8_t>(mIsCustomFallback);
216 writer->write<uint8_t>(mIsDefaultFallback);
217 writer->write<VariationFamilyType>(mVarFamilyType);
218 mCoverage.writeTo(writer);
219 // Write mCmapFmt14Coverage as a sparse array (size, non-null entry count,
220 // array of (index, entry))
221 writer->write<uint32_t>(mCmapFmt14CoverageCount);
222 // Skip writing the sparse entries if the size is zero
223 if (mCmapFmt14CoverageCount > 0) {
224 uint32_t cmapFmt14CoverageEntryCount = 0;
225 for (size_t i = 0; i < mCmapFmt14CoverageCount; i++) {
226 if (!mCmapFmt14Coverage[i].empty()) cmapFmt14CoverageEntryCount++;
227 }
228 writer->write<uint32_t>(cmapFmt14CoverageEntryCount);
229 for (size_t i = 0; i < mCmapFmt14CoverageCount; i++) {
230 if (!mCmapFmt14Coverage[i].empty()) {
231 writer->write<uint32_t>(i);
232 mCmapFmt14Coverage[i].writeTo(writer);
233 }
234 }
235 }
236 }
237
238 // static
readVector(BufferReader * reader)239 std::vector<std::shared_ptr<FontFamily>> FontFamily::readVector(BufferReader* reader) {
240 // To save memory used for reference counting objects, we store
241 // Font / FontFamily in shared_ptr<vector<Font / FontFamily>>, and use
242 // shared_ptr's aliasing constructor to create shared_ptr<Font / FontFamily>
243 // that share the reference counting objects with
244 // the shared_ptr<vector<Font / FontFamily>>.
245 // We can do this because we know that all Font and FontFamily
246 // instances based on the same BufferReader share the same life span.
247 uint32_t fontsCount = reader->read<uint32_t>();
248 std::shared_ptr<std::vector<Font>> fonts = std::make_shared<std::vector<Font>>();
249 fonts->reserve(fontsCount);
250 for (uint32_t i = 0; i < fontsCount; i++) {
251 fonts->emplace_back(reader);
252 }
253 uint32_t count = reader->read<uint32_t>();
254 std::shared_ptr<std::vector<FontFamily>> families = std::make_shared<std::vector<FontFamily>>();
255 families->reserve(count);
256 std::vector<std::shared_ptr<FontFamily>> pointers;
257 pointers.reserve(count);
258 for (uint32_t i = 0; i < count; i++) {
259 // TODO(b/174672300): Revert back to emplace_back.
260 families->push_back(FontFamily(reader, fonts));
261 // Use aliasing constructor.
262 pointers.emplace_back(families, &families->back());
263 }
264 return pointers;
265 }
266
267 // static
writeVector(BufferWriter * writer,const std::vector<std::shared_ptr<FontFamily>> & families)268 void FontFamily::writeVector(BufferWriter* writer,
269 const std::vector<std::shared_ptr<FontFamily>>& families) {
270 std::vector<std::shared_ptr<Font>> fonts;
271 for (const auto& fontFamily : families) {
272 for (uint32_t i = 0; i < fontFamily->getNumFonts(); i++) {
273 fonts.emplace_back(fontFamily->getFontRef(i));
274 }
275 }
276 writer->write<uint32_t>(fonts.size());
277 for (const auto& font : fonts) {
278 font->writeTo(writer);
279 }
280 uint32_t fontIndex = 0;
281 writer->write<uint32_t>(families.size());
282 for (const auto& fontFamily : families) {
283 fontFamily->writeTo(writer, &fontIndex);
284 }
285 }
286
287 // Compute a matching metric between two styles - 0 is an exact match
computeMatch(FontStyle style1,FontStyle style2)288 static int computeMatch(FontStyle style1, FontStyle style2) {
289 if (style1 == style2) return 0;
290 int score = abs(style1.weight() / 100 - style2.weight() / 100);
291 if (style1.slant() != style2.slant()) {
292 score += 2;
293 }
294 return score;
295 }
296
computeFakery(FontStyle wanted,FontStyle actual)297 static FontFakery computeFakery(FontStyle wanted, FontStyle actual) {
298 // If desired weight is semibold or darker, and 2 or more grades
299 // higher than actual (for example, medium 500 -> bold 700), then
300 // select fake bold.
301 bool isFakeBold = wanted.weight() >= 600 && (wanted.weight() - actual.weight()) >= 200;
302 bool isFakeItalic = wanted.slant() == FontStyle::Slant::ITALIC &&
303 actual.slant() == FontStyle::Slant::UPRIGHT;
304 return FontFakery(isFakeBold, isFakeItalic);
305 }
306
getClosestMatch(FontStyle style,const VariationSettings & axes) const307 FakedFont FontFamily::getClosestMatch(FontStyle style, const VariationSettings& axes) const {
308 if (features::typeface_redesign_readonly()) {
309 int bestIndex = 0;
310 Font* bestFont = mFonts[bestIndex].get();
311 int bestMatch = computeMatch(bestFont->style(), style);
312 for (size_t i = 1; i < mFontsCount; i++) {
313 Font* font = mFonts[i].get();
314 int match = computeMatch(font->style(), style);
315 if (i == 0 || match < bestMatch) {
316 bestFont = font;
317 bestIndex = i;
318 bestMatch = match;
319 }
320 }
321
322 if (mIsVariationFamily) {
323 // For backward compatibility reasons, we don't merge the variation settings because it
324 // is developer provided configuration.
325 return FakedFont{mFonts[bestIndex], computeFakery(style, bestFont->style())};
326 }
327
328 if (axes.empty() && style == bestFont->style()) {
329 // Easy case, no merge is necessary.
330 return FakedFont{mFonts[bestIndex], FontFakery(false, false)};
331 }
332 FontFakery fakery = merge(bestFont->getFVarTable(), bestFont->baseTypeface()->GetAxes(),
333 axes, bestFont->style(), style);
334 return FakedFont(mFonts[bestIndex], fakery);
335 }
336
337 if (mVarFamilyType != VariationFamilyType::None) {
338 return getVariationFamilyAdjustment(style);
339 }
340 int bestIndex = 0;
341 Font* bestFont = mFonts[bestIndex].get();
342 int bestMatch = computeMatch(bestFont->style(), style);
343 for (size_t i = 1; i < mFontsCount; i++) {
344 Font* font = mFonts[i].get();
345 int match = computeMatch(font->style(), style);
346 if (i == 0 || match < bestMatch) {
347 bestFont = font;
348 bestIndex = i;
349 bestMatch = match;
350 }
351 }
352 return FakedFont{mFonts[bestIndex], computeFakery(style, bestFont->style())};
353 }
354
getVariationFamilyAdjustment(FontStyle style) const355 FakedFont FontFamily::getVariationFamilyAdjustment(FontStyle style) const {
356 const bool italic = style.slant() == FontStyle::Slant::ITALIC;
357 switch (mVarFamilyType) {
358 case VariationFamilyType::SingleFont_wghtOnly:
359 return FakedFont{mFonts[0], FontFakery(false, italic, style.weight(), -1)};
360 case VariationFamilyType::SingleFont_wght_ital:
361 return FakedFont{mFonts[0], FontFakery(false, false, style.weight(), italic ? 1 : 0)};
362 case VariationFamilyType::TwoFont_wght:
363 return FakedFont{mFonts[italic ? 1 : 0], FontFakery(false, false, style.weight(), -1)};
364 case VariationFamilyType::None:
365 return FakedFont{mFonts[0], FontFakery()};
366 }
367 }
368
computeCoverage()369 void FontFamily::computeCoverage() {
370 const std::shared_ptr<Font>& font = getClosestMatch(FontStyle(), VariationSettings()).font;
371 HbBlob cmapTable(font->baseFont(), MakeTag('c', 'm', 'a', 'p'));
372 if (cmapTable.get() == nullptr) {
373 ALOGE("Could not get cmap table size!\n");
374 return;
375 }
376
377 std::vector<SparseBitSet> cmapFmt14Coverage;
378 mCoverage = CmapCoverage::getCoverage(cmapTable.get(), cmapTable.size(), &cmapFmt14Coverage);
379 static_assert(INVALID_VS_INDEX <= std::numeric_limits<uint16_t>::max());
380 // cmapFmt14Coverage maps VS index to coverage.
381 // cmapFmt14Coverage's size cannot exceed INVALID_VS_INDEX.
382 MINIKIN_ASSERT(cmapFmt14Coverage.size() <= INVALID_VS_INDEX,
383 "cmapFmt14Coverage's size must not exceed INVALID_VS_INDEX.");
384 mCmapFmt14CoverageCount = static_cast<uint16_t>(cmapFmt14Coverage.size());
385 if (mCmapFmt14CoverageCount > 0) {
386 mCmapFmt14Coverage = std::make_unique<SparseBitSet[]>(mCmapFmt14CoverageCount);
387 for (size_t i = 0; i < mCmapFmt14CoverageCount; i++) {
388 mCmapFmt14Coverage[i] = std::move(cmapFmt14Coverage[i]);
389 }
390 }
391
392 std::unordered_set<AxisTag> supportedAxesSet;
393 for (size_t i = 0; i < mFontsCount; ++i) {
394 const uint16_t axesCount = mFonts[i]->getSupportedAxesCount();
395 if (axesCount != 0) {
396 const AxisTag* axesPtr = mFonts[i]->getSupportedAxes();
397 supportedAxesSet.insert(axesPtr, axesPtr + axesCount);
398 }
399 }
400 MINIKIN_ASSERT(supportedAxesSet.size() <= std::numeric_limits<uint32_t>::max(),
401 "Number of supported axes must be less than 2^16.");
402 mSupportedAxesCount = static_cast<uint16_t>(supportedAxesSet.size());
403 if (mSupportedAxesCount > 0) {
404 mSupportedAxes = sortedArrayFromSet(supportedAxesSet);
405 }
406 }
407
hasGlyph(uint32_t codepoint,uint32_t variationSelector) const408 bool FontFamily::hasGlyph(uint32_t codepoint, uint32_t variationSelector) const {
409 if (variationSelector == 0) {
410 return getCoverage().get(codepoint);
411 }
412
413 if (mCmapFmt14CoverageCount == 0) {
414 return false;
415 }
416
417 const uint16_t vsIndex = getVsIndex(variationSelector);
418
419 if (vsIndex >= mCmapFmt14CoverageCount) {
420 // Even if vsIndex is INVALID_VS_INDEX, we reach here since INVALID_VS_INDEX is defined to
421 // be at the maximum end of the range.
422 return false;
423 }
424
425 const SparseBitSet& bitset = getCmap14Coverage(vsIndex);
426 if (bitset.empty()) {
427 return false;
428 }
429
430 return bitset.get(codepoint);
431 }
432
createFamilyWithVariation(const VariationSettings & variations) const433 std::shared_ptr<FontFamily> FontFamily::createFamilyWithVariation(
434 const VariationSettings& variations) const {
435 if (variations.empty() || mSupportedAxesCount == 0) {
436 return nullptr;
437 }
438
439 bool hasSupportedAxis = false;
440 for (const FontVariation& variation : variations) {
441 if (std::binary_search(mSupportedAxes.get(), mSupportedAxes.get() + mSupportedAxesCount,
442 variation.axisTag)) {
443 hasSupportedAxis = true;
444 break;
445 }
446 }
447 if (!hasSupportedAxis) {
448 // None of variation axes are suppored by this family.
449 return nullptr;
450 }
451
452 std::vector<std::shared_ptr<Font>> fonts;
453 for (size_t i = 0; i < mFontsCount; i++) {
454 const std::shared_ptr<Font>& font = mFonts[i];
455 bool supportedVariations = false;
456 if (font->getSupportedAxesCount() != 0) {
457 for (const FontVariation& variation : variations) {
458 if (font->isAxisSupported(variation.axisTag)) {
459 supportedVariations = true;
460 break;
461 }
462 }
463 }
464 std::shared_ptr<MinikinFont> minikinFont;
465 if (supportedVariations) {
466 minikinFont = font->baseTypeface()->createFontWithVariation(variations);
467 }
468 if (minikinFont == nullptr) {
469 fonts.push_back(font);
470 } else {
471 fonts.push_back(Font::Builder(minikinFont).setStyle(font->style()).build());
472 }
473 }
474
475 return create(mLocaleListId, mVariant, std::move(fonts), mIsCustomFallback, mIsDefaultFallback,
476 VariationFamilyType::None);
477 }
478
479 } // namespace minikin
480