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