diff options
Diffstat (limited to 'include/minikin/FontCollection.h')
-rw-r--r-- | include/minikin/FontCollection.h | 161 |
1 files changed, 155 insertions, 6 deletions
diff --git a/include/minikin/FontCollection.h b/include/minikin/FontCollection.h index f136384..98df571 100644 --- a/include/minikin/FontCollection.h +++ b/include/minikin/FontCollection.h @@ -18,9 +18,14 @@ #define MINIKIN_FONT_COLLECTION_H #include <memory> +#include <unordered_map> #include <unordered_set> #include <vector> +#include <gtest/gtest_prod.h> + +#include "minikin/Buffer.h" +#include "minikin/Font.h" #include "minikin/FontFamily.h" #include "minikin/MinikinFont.h" #include "minikin/U16StringPiece.h" @@ -35,12 +40,134 @@ public: explicit FontCollection(const std::vector<std::shared_ptr<FontFamily>>& typefaces); explicit FontCollection(std::shared_ptr<FontFamily>&& typeface); + template <Font::TypefaceReader typefaceReader> + static std::vector<std::shared_ptr<FontCollection>> readVector(BufferReader* reader) { + uint32_t allFontFamiliesCount = reader->read<uint32_t>(); + std::vector<std::shared_ptr<FontFamily>> allFontFamilies; + allFontFamilies.reserve(allFontFamiliesCount); + for (uint32_t i = 0; i < allFontFamiliesCount; i++) { + allFontFamilies.push_back(FontFamily::readFrom<typefaceReader>(reader)); + } + uint32_t fontCollectionsCount = reader->read<uint32_t>(); + std::vector<std::shared_ptr<FontCollection>> fontCollections; + fontCollections.reserve(fontCollectionsCount); + for (uint32_t i = 0; i < fontCollectionsCount; i++) { + fontCollections.emplace_back(new FontCollection(reader, allFontFamilies)); + } + return fontCollections; + } + + template <Font::TypefaceWriter typefaceWriter> + static void writeVector(BufferWriter* writer, + const std::vector<std::shared_ptr<FontCollection>>& fontCollections) { + std::vector<std::shared_ptr<FontFamily>> allFontFamilies; + // Note: operator== for shared_ptr compares raw pointer values. + std::unordered_map<std::shared_ptr<FontFamily>, uint32_t> fontFamilyToIndexMap; + collectAllFontFamilies(fontCollections, &allFontFamilies, &fontFamilyToIndexMap); + + writer->write<uint32_t>(allFontFamilies.size()); + for (const auto& fontFamily : allFontFamilies) { + fontFamily->writeTo<typefaceWriter>(writer); + } + writer->write<uint32_t>(fontCollections.size()); + for (const auto& fontCollection : fontCollections) { + fontCollection->writeTo(writer, fontFamilyToIndexMap); + } + } + + // Helper class for representing font family match result in packed bits. + struct FamilyMatchResult { + public: + struct Builder { + public: + Builder() : mSize(0), mBits(0) {} + + Builder& add(uint8_t x) { + if (mSize >= 7) [[unlikely]] { + return *this; + } + mBits = mBits | (static_cast<uint64_t>(x) << (8 * mSize)); + mSize++; + return *this; + } + + Builder& reset() { + mSize = 0; + mBits = 0; + return *this; + } + + uint8_t size() const { return mSize; } + + bool empty() const { return size() == 0; } + + FamilyMatchResult build() { + return FamilyMatchResult(mBits | (static_cast<uint64_t>(mSize) << 56)); + } + + private: + uint8_t mSize; + uint64_t mBits; + }; + + // Helper class for iterating FamilyMatchResult + class iterator { + public: + inline bool operator==(const iterator& o) const { + return mOffset == o.mOffset && mResult == o.mResult; + } + + inline bool operator!=(const iterator& o) const { return !(*this == o); } + inline uint8_t operator*() const { return mResult[mOffset]; } + inline iterator& operator++() { + mOffset++; + return *this; + } + + private: + friend struct FamilyMatchResult; + iterator(const FamilyMatchResult& result, uint32_t offset) + : mResult(result), mOffset(offset) {} + const FamilyMatchResult& mResult; + uint32_t mOffset; + }; + + // Create empty FamilyMatchResult. + FamilyMatchResult() : mBits(0) {} + + inline uint8_t size() const { return static_cast<uint8_t>(mBits >> 56); } + + inline uint8_t operator[](uint32_t pos) const { + return static_cast<uint8_t>(mBits >> (pos * 8)); + } + + inline bool empty() const { return size() == 0; } + + inline bool operator==(const FamilyMatchResult& o) const { return mBits == o.mBits; } + + // Returns the common family indices between l and r. + static FamilyMatchResult intersect(FamilyMatchResult l, FamilyMatchResult r); + + // Iterator + inline iterator begin() const { return iterator(*this, 0); } + inline iterator end() const { return iterator(*this, size()); } + + FamilyMatchResult(const FamilyMatchResult& o) = default; + FamilyMatchResult& operator=(const FamilyMatchResult& o) = default; + + private: + explicit FamilyMatchResult(uint64_t bits) : mBits(bits) {} + uint64_t mBits; + }; + struct Run { - FakedFont fakedFont; + FamilyMatchResult familyMatch; int start; int end; }; + FakedFont getBestFont(U16StringPiece textBuf, const Run& run, FontStyle style); + // Perform the itemization until given max runs. std::vector<Run> itemize(U16StringPiece text, FontStyle style, uint32_t localeListId, FamilyVariant familyVariant, uint32_t runMax) const; @@ -68,7 +195,23 @@ public: uint32_t getId() const; + const std::vector<std::shared_ptr<FontFamily>>& getFamilies() const { return mFamilies; } + private: + FRIEND_TEST(FontCollectionTest, bufferTest); + + FontCollection(BufferReader* reader, + const std::vector<std::shared_ptr<FontFamily>>& allFontFamilies); + // Write fields of the instance, using fontFamilyToIndexMap for finding + // indices for FontFamily. + void writeTo(BufferWriter* writer, + const std::unordered_map<std::shared_ptr<FontFamily>, uint32_t>& + fontFamilyToIndexMap) const; + static void collectAllFontFamilies( + const std::vector<std::shared_ptr<FontCollection>>& fontCollections, + std::vector<std::shared_ptr<FontFamily>>* outAllFontFamilies, + std::unordered_map<std::shared_ptr<FontFamily>, uint32_t>* outFontFamilyToIndexMap); + static const int kLogCharsPerPage = 8; static const int kPageMask = (1 << kLogCharsPerPage) - 1; @@ -85,9 +228,8 @@ private: // Initialize the FontCollection. void init(const std::vector<std::shared_ptr<FontFamily>>& typefaces); - const std::shared_ptr<FontFamily>& getFamilyForChar(uint32_t ch, uint32_t vs, - uint32_t localeListId, - FamilyVariant variant) const; + FamilyMatchResult getFamilyForChar(uint32_t ch, uint32_t vs, uint32_t localeListId, + FamilyVariant variant) const; uint32_t calcFamilyScore(uint32_t ch, uint32_t vs, FamilyVariant variant, uint32_t localeListId, const std::shared_ptr<FontFamily>& fontFamily) const; @@ -116,14 +258,21 @@ private: // mFamilyVec[mRange[0xXXYY].end] instead of whole mFamilies. // This vector contains indices into mFamilies. // This vector can't be empty. - std::vector<Range> mRanges; - std::vector<uint8_t> mFamilyVec; + uint32_t mRangesCount; + const Range* mRanges; + uint32_t mFamilyVecCount; + const uint8_t* mFamilyVec; // This vector has pointers to the font family instances which have cmap 14 subtables. std::vector<std::shared_ptr<FontFamily>> mVSFamilyVec; // Set of supported axes in this collection. std::unordered_set<AxisTag> mSupportedAxes; + + // Owns allocated memory if this class is created from font families, otherwise these are + // nullptr. + std::unique_ptr<Range[]> mOwnedRanges; + std::vector<uint8_t> mOwnedFamilyVec; }; } // namespace minikin |