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