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