• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef MINIKIN_FONT_COLLECTION_H
18 #define MINIKIN_FONT_COLLECTION_H
19 
20 #include <memory>
21 #include <unordered_map>
22 #include <unordered_set>
23 #include <vector>
24 
25 #include <gtest/gtest_prod.h>
26 
27 #include "minikin/Buffer.h"
28 #include "minikin/Font.h"
29 #include "minikin/FontFamily.h"
30 #include "minikin/MinikinFont.h"
31 #include "minikin/U16StringPiece.h"
32 
33 namespace minikin {
34 
35 // The maximum number of font families.
36 constexpr uint32_t MAX_FAMILY_COUNT = 254;
37 
38 class FontCollection {
39 public:
40     explicit FontCollection(const std::vector<std::shared_ptr<FontFamily>>& typefaces);
41     explicit FontCollection(std::shared_ptr<FontFamily>&& typeface);
42 
43     template <Font::TypefaceReader typefaceReader>
readVector(BufferReader * reader)44     static std::vector<std::shared_ptr<FontCollection>> readVector(BufferReader* reader) {
45         uint32_t allFontFamiliesCount = reader->read<uint32_t>();
46         std::vector<std::shared_ptr<FontFamily>> allFontFamilies;
47         allFontFamilies.reserve(allFontFamiliesCount);
48         for (uint32_t i = 0; i < allFontFamiliesCount; i++) {
49             allFontFamilies.push_back(FontFamily::readFrom<typefaceReader>(reader));
50         }
51         uint32_t fontCollectionsCount = reader->read<uint32_t>();
52         std::vector<std::shared_ptr<FontCollection>> fontCollections;
53         fontCollections.reserve(fontCollectionsCount);
54         for (uint32_t i = 0; i < fontCollectionsCount; i++) {
55             fontCollections.emplace_back(new FontCollection(reader, allFontFamilies));
56         }
57         return fontCollections;
58     }
59 
60     template <Font::TypefaceWriter typefaceWriter>
writeVector(BufferWriter * writer,const std::vector<std::shared_ptr<FontCollection>> & fontCollections)61     static void writeVector(BufferWriter* writer,
62                             const std::vector<std::shared_ptr<FontCollection>>& fontCollections) {
63         std::vector<std::shared_ptr<FontFamily>> allFontFamilies;
64         // Note: operator== for shared_ptr compares raw pointer values.
65         std::unordered_map<std::shared_ptr<FontFamily>, uint32_t> fontFamilyToIndexMap;
66         collectAllFontFamilies(fontCollections, &allFontFamilies, &fontFamilyToIndexMap);
67 
68         writer->write<uint32_t>(allFontFamilies.size());
69         for (const auto& fontFamily : allFontFamilies) {
70             fontFamily->writeTo<typefaceWriter>(writer);
71         }
72         writer->write<uint32_t>(fontCollections.size());
73         for (const auto& fontCollection : fontCollections) {
74             fontCollection->writeTo(writer, fontFamilyToIndexMap);
75         }
76     }
77 
78     // Helper class for representing font family match result in packed bits.
79     struct FamilyMatchResult {
80     public:
81         struct Builder {
82         public:
BuilderFamilyMatchResult::Builder83             Builder() : mSize(0), mBits(0) {}
84 
addFamilyMatchResult::Builder85             Builder& add(uint8_t x) {
86                 if (mSize >= 7) [[unlikely]] {
87                         return *this;
88                     }
89                 mBits = mBits | (static_cast<uint64_t>(x) << (8 * mSize));
90                 mSize++;
91                 return *this;
92             }
93 
resetFamilyMatchResult::Builder94             Builder& reset() {
95                 mSize = 0;
96                 mBits = 0;
97                 return *this;
98             }
99 
sizeFamilyMatchResult::Builder100             uint8_t size() const { return mSize; }
101 
emptyFamilyMatchResult::Builder102             bool empty() const { return size() == 0; }
103 
buildFamilyMatchResult::Builder104             FamilyMatchResult build() {
105                 return FamilyMatchResult(mBits | (static_cast<uint64_t>(mSize) << 56));
106             }
107 
108         private:
109             uint8_t mSize;
110             uint64_t mBits;
111         };
112 
113         // Helper class for iterating FamilyMatchResult
114         class iterator {
115         public:
116             inline bool operator==(const iterator& o) const {
117                 return mOffset == o.mOffset && mResult == o.mResult;
118             }
119 
120             inline bool operator!=(const iterator& o) const { return !(*this == o); }
121             inline uint8_t operator*() const { return mResult[mOffset]; }
122             inline iterator& operator++() {
123                 mOffset++;
124                 return *this;
125             }
126 
127         private:
128             friend struct FamilyMatchResult;
iteratorFamilyMatchResult129             iterator(const FamilyMatchResult& result, uint32_t offset)
130                     : mResult(result), mOffset(offset) {}
131             const FamilyMatchResult& mResult;
132             uint32_t mOffset;
133         };
134 
135         // Create empty FamilyMatchResult.
FamilyMatchResultFamilyMatchResult136         FamilyMatchResult() : mBits(0) {}
137 
sizeFamilyMatchResult138         inline uint8_t size() const { return static_cast<uint8_t>(mBits >> 56); }
139 
140         inline uint8_t operator[](uint32_t pos) const {
141             return static_cast<uint8_t>(mBits >> (pos * 8));
142         }
143 
emptyFamilyMatchResult144         inline bool empty() const { return size() == 0; }
145 
146         inline bool operator==(const FamilyMatchResult& o) const { return mBits == o.mBits; }
147 
148         // Returns the common family indices between l and r.
149         static FamilyMatchResult intersect(FamilyMatchResult l, FamilyMatchResult r);
150 
151         // Iterator
beginFamilyMatchResult152         inline iterator begin() const { return iterator(*this, 0); }
endFamilyMatchResult153         inline iterator end() const { return iterator(*this, size()); }
154 
155         FamilyMatchResult(const FamilyMatchResult& o) = default;
156         FamilyMatchResult& operator=(const FamilyMatchResult& o) = default;
157 
158     private:
FamilyMatchResultFamilyMatchResult159         explicit FamilyMatchResult(uint64_t bits) : mBits(bits) {}
160         uint64_t mBits;
161     };
162 
163     struct Run {
164         FamilyMatchResult familyMatch;
165         int start;
166         int end;
167     };
168 
169     FakedFont getBestFont(U16StringPiece textBuf, const Run& run, FontStyle style);
170 
171     // Perform the itemization until given max runs.
172     std::vector<Run> itemize(U16StringPiece text, FontStyle style, uint32_t localeListId,
173                              FamilyVariant familyVariant, uint32_t runMax) const;
174 
175     // Perform the itemization until end of the text.
itemize(U16StringPiece text,FontStyle style,uint32_t localeListId,FamilyVariant familyVariant)176     std::vector<Run> itemize(U16StringPiece text, FontStyle style, uint32_t localeListId,
177                              FamilyVariant familyVariant) const {
178         return itemize(text, style, localeListId, familyVariant, text.size());
179     }
180 
181     // Returns true if there is a glyph for the code point and variation selector pair.
182     // Returns false if no fonts have a glyph for the code point and variation
183     // selector pair, or invalid variation selector is passed.
184     bool hasVariationSelector(uint32_t baseCodepoint, uint32_t variationSelector) const;
185 
186     // Get base font with fakery information (fake bold could affect metrics)
187     FakedFont baseFontFaked(FontStyle style);
188 
189     // Creates new FontCollection based on this collection while applying font variations. Returns
190     // nullptr if none of variations apply to this collection.
191     std::shared_ptr<FontCollection> createCollectionWithVariation(
192             const std::vector<FontVariation>& variations);
193 
getSupportedTags()194     const std::unordered_set<AxisTag>& getSupportedTags() const { return mSupportedAxes; }
195 
196     uint32_t getId() const;
197 
getFamilies()198     const std::vector<std::shared_ptr<FontFamily>>& getFamilies() const { return mFamilies; }
199 
200 private:
201     FRIEND_TEST(FontCollectionTest, bufferTest);
202 
203     FontCollection(BufferReader* reader,
204                    const std::vector<std::shared_ptr<FontFamily>>& allFontFamilies);
205     // Write fields of the instance, using fontFamilyToIndexMap for finding
206     // indices for FontFamily.
207     void writeTo(BufferWriter* writer,
208                  const std::unordered_map<std::shared_ptr<FontFamily>, uint32_t>&
209                          fontFamilyToIndexMap) const;
210     static void collectAllFontFamilies(
211             const std::vector<std::shared_ptr<FontCollection>>& fontCollections,
212             std::vector<std::shared_ptr<FontFamily>>* outAllFontFamilies,
213             std::unordered_map<std::shared_ptr<FontFamily>, uint32_t>* outFontFamilyToIndexMap);
214 
215     static const int kLogCharsPerPage = 8;
216     static const int kPageMask = (1 << kLogCharsPerPage) - 1;
217 
218     // mFamilyVec holds the indices of the mFamilies and mRanges holds the range of indices of
219     // mFamilyVec. The maximum number of pages is 0x10FF (U+10FFFF >> 8). The maximum number of
220     // the fonts is 0xFF. Thus, technically the maximum length of mFamilyVec is 0x10EE01
221     // (0x10FF * 0xFF). However, in practice, 16-bit integers are enough since most fonts supports
222     // only limited range of code points.
223     struct Range {
224         uint16_t start;
225         uint16_t end;
226     };
227 
228     // Initialize the FontCollection.
229     void init(const std::vector<std::shared_ptr<FontFamily>>& typefaces);
230 
231     FamilyMatchResult getFamilyForChar(uint32_t ch, uint32_t vs, uint32_t localeListId,
232                                        FamilyVariant variant) const;
233 
234     uint32_t calcFamilyScore(uint32_t ch, uint32_t vs, FamilyVariant variant, uint32_t localeListId,
235                              const std::shared_ptr<FontFamily>& fontFamily) const;
236 
237     uint32_t calcCoverageScore(uint32_t ch, uint32_t vs, uint32_t localeListId,
238                                const std::shared_ptr<FontFamily>& fontFamily) const;
239 
240     static uint32_t calcLocaleMatchingScore(uint32_t userLocaleListId,
241                                             const FontFamily& fontFamily);
242 
243     static uint32_t calcVariantMatchingScore(FamilyVariant variant, const FontFamily& fontFamily);
244 
245     // unique id for this font collection (suitable for cache key)
246     uint32_t mId;
247 
248     // Highest UTF-32 code point that can be mapped
249     uint32_t mMaxChar;
250 
251     // This vector has pointers to the all font family instances in this collection.
252     // This vector can't be empty.
253     std::vector<std::shared_ptr<FontFamily>> mFamilies;
254 
255     // Following two vectors are pre-calculated tables for resolving coverage faster.
256     // For example, to iterate over all fonts which support Unicode code point U+XXYYZZ,
257     // iterate font families index from mFamilyVec[mRanges[0xXXYY].start] to
258     // mFamilyVec[mRange[0xXXYY].end] instead of whole mFamilies.
259     // This vector contains indices into mFamilies.
260     // This vector can't be empty.
261     uint32_t mRangesCount;
262     const Range* mRanges;
263     uint32_t mFamilyVecCount;
264     const uint8_t* mFamilyVec;
265 
266     // This vector has pointers to the font family instances which have cmap 14 subtables.
267     std::vector<std::shared_ptr<FontFamily>> mVSFamilyVec;
268 
269     // Set of supported axes in this collection.
270     std::unordered_set<AxisTag> mSupportedAxes;
271 
272     // Owns allocated memory if this class is created from font families, otherwise these are
273     // nullptr.
274     std::unique_ptr<Range[]> mOwnedRanges;
275     std::vector<uint8_t> mOwnedFamilyVec;
276 };
277 
278 }  // namespace minikin
279 
280 #endif  // MINIKIN_FONT_COLLECTION_H
281