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