19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/*
29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project
39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License");
59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License.
69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at
79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *      http://www.apache.org/licenses/LICENSE-2.0
99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software
119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS,
129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and
149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License.
159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */
169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifndef MINIKIN_FONT_FAMILY_H
189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#define MINIKIN_FONT_FAMILY_H
199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
20dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka#include <memory>
21a5bb91190edbea0be0e78a8511b3c920b6e99c4eBehdad Esfahbod#include <string>
22065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka#include <unordered_set>
23dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka#include <vector>
24dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka
250f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka#include <hb.h>
269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
274d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien#include <utils/TypeHelpers.h>
284d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien
2913f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien#include <minikin/SparseBitSet.h>
30b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
3114e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin {
329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
337b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienclass MinikinFont;
347b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien
359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// FontStyle represents all style information needed to select an actual font
366d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka// from a collection. The implementation is packed into two 32-bit words
379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// so it can be efficiently copied, embedded in other objects, etc.
389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienclass FontStyle {
399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienpublic:
406d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    FontStyle() : FontStyle(0 /* variant */, 4 /* weight */, false /* italic */) {}
416d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    FontStyle(int weight, bool italic) : FontStyle(0 /* variant */, weight, italic) {}
4247b905f6840ea6776d6f6778915e7408a1ff8be4Chih-Hung Hsieh    FontStyle(uint32_t langListId)  // NOLINT(implicit)
436d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka            : FontStyle(langListId, 0 /* variant */, 4 /* weight */, false /* italic */) {}
446d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka
456d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    FontStyle(int variant, int weight, bool italic);
466d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    FontStyle(uint32_t langListId, int variant, int weight, bool italic);
476d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka
484d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    int getWeight() const { return bits & kWeightMask; }
494d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    bool getItalic() const { return (bits & kItalicMask) != 0; }
507b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    int getVariant() const { return (bits >> kVariantShift) & kVariantMask; }
516d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    uint32_t getLanguageListId() const { return mLanguageListId; }
527b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien
536d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    bool operator==(const FontStyle other) const {
546d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka          return bits == other.bits && mLanguageListId == other.mLanguageListId;
556d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    }
566d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka
5714e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka    android::hash_t hash() const;
584d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien
596d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    // Looks up a language list from an internal cache and returns its ID.
606d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    // If the passed language list is not in the cache, registers it and returns newly assigned ID.
616d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    static uint32_t registerLanguageList(const std::string& languages);
629cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienprivate:
637b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    static const uint32_t kWeightMask = (1 << 4) - 1;
647b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    static const uint32_t kItalicMask = 1 << 4;
657b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    static const int kVariantShift = 5;
667b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    static const uint32_t kVariantMask = (1 << 2) - 1;
676d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka
686d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    static uint32_t pack(int variant, int weight, bool italic);
696d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka
709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    uint32_t bits;
716d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    uint32_t mLanguageListId;
729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien};
739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
747b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levienenum FontVariant {
757b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    VARIANT_DEFAULT = 0,
767b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    VARIANT_COMPACT = 1,
777b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    VARIANT_ELEGANT = 2,
787b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien};
797b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien
8014e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakainline android::hash_t hash_type(const FontStyle &style) {
814d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    return style.hash();
824d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien}
834d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien
849a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien// attributes representing transforms (fake bold, fake italic) to match styles
859a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienclass FontFakery {
869a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienpublic:
879a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    FontFakery() : mFakeBold(false), mFakeItalic(false) { }
889a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { }
899a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    // TODO: want to support graded fake bolding
909a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    bool isFakeBold() { return mFakeBold; }
919a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    bool isFakeItalic() { return mFakeItalic; }
929a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienprivate:
939a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    bool mFakeBold;
949a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    bool mFakeItalic;
959a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien};
969a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien
979a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienstruct FakedFont {
989a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    // ownership is the enclosing FontCollection
999a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    MinikinFont* font;
1009a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    FontFakery fakery;
1019a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien};
1029a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien
103065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonakatypedef uint32_t AxisTag;
104065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka
10541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonakastruct Font {
106dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    Font(const std::shared_ptr<MinikinFont>& typeface, FontStyle style);
107dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style);
10841718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    Font(Font&& o);
10941718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    Font(const Font& o);
11041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka
111dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    std::shared_ptr<MinikinFont> typeface;
11241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    FontStyle style;
11341718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka
1141adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka    std::unordered_set<AxisTag> getSupportedAxesLocked() const;
11541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka};
11641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka
117065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonakastruct FontVariation {
118065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    FontVariation(AxisTag axisTag, float value) : axisTag(axisTag), value(value) {}
119065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    AxisTag axisTag;
120065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    float value;
121065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka};
122065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka
123dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonakaclass FontFamily {
1249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienpublic:
12541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    explicit FontFamily(std::vector<Font>&& fonts);
12641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    FontFamily(int variant, std::vector<Font>&& fonts);
12741718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    FontFamily(uint32_t langId, int variant, std::vector<Font>&& fonts);
1287b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien
12941718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    // TODO: Good to expose FontUtil.h.
130dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    static bool analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight,
131dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka            bool* italic);
1329a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    FakedFont getClosestMatch(FontStyle style) const;
1339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
134198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    uint32_t langId() const { return mLangId; }
1357b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    int variant() const { return mVariant; }
1367b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien
1379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    // API's for enumerating the fonts in a family. These don't guarantee any particular order
13841718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    size_t getNumFonts() const { return mFonts.size(); }
139dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    const std::shared_ptr<MinikinFont>& getFont(size_t index) const {
140dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka        return mFonts[index].typeface;
141dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    }
14241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    FontStyle getStyle(size_t index) const { return mFonts[index].style; }
143994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    bool isColorEmojiFamily() const;
144065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; }
14513f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien
14641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    // Get Unicode coverage.
14741718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    const SparseBitSet& getCoverage() const { return mCoverage; }
1480f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka
1490f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka    // Returns true if the font has a glyph for the code point and variation selector pair.
1500f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka    // Caller should acquire a lock before calling the method.
15141718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    bool hasGlyph(uint32_t codepoint, uint32_t variationSelector) const;
1520f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka
1536b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    // Returns true if this font family has a variaion sequence table (cmap format 14 subtable).
1549196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    bool hasVSTable() const { return !mCmapFmt14Coverage.empty(); }
1556b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka
156065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    // Creates new FontFamily based on this family while applying font variations. Returns nullptr
157065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    // if none of variations apply to this family.
158dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka    std::shared_ptr<FontFamily> createFamilyWithVariation(
159dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka            const std::vector<FontVariation>& variations) const;
160065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka
1619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienprivate:
16241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    void computeCoverage();
1631adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka
164198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    uint32_t mLangId;
1657b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    int mVariant;
1669cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    std::vector<Font> mFonts;
167065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka    std::unordered_set<AxisTag> mSupportedAxes;
16813f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien
16913f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    SparseBitSet mCoverage;
1709196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka    std::vector<std::unique_ptr<SparseBitSet>> mCmapFmt14Coverage;
17141718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka
17241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    // Forbid copying and assignment.
17341718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    FontFamily(const FontFamily&) = delete;
17441718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka    void operator=(const FontFamily&) = delete;
1759cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien};
1769cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
17714e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka}  // namespace minikin
1789cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif  // MINIKIN_FONT_FAMILY_H
180