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_FAMILY_H
18 #define MINIKIN_FONT_FAMILY_H
19 
20 #include <vector>
21 #include <string>
22 #include <hb.h>
23 
24 #include <utils/TypeHelpers.h>
25 
26 #include <minikin/MinikinRefCounted.h>
27 #include <minikin/SparseBitSet.h>
28 
29 namespace android {
30 
31 class MinikinFont;
32 
33 // FontStyle represents all style information needed to select an actual font
34 // from a collection. The implementation is packed into two 32-bit words
35 // so it can be efficiently copied, embedded in other objects, etc.
36 class FontStyle {
37 public:
FontStyle()38     FontStyle() : FontStyle(0 /* variant */, 4 /* weight */, false /* italic */) {}
FontStyle(int weight,bool italic)39     FontStyle(int weight, bool italic) : FontStyle(0 /* variant */, weight, italic) {}
FontStyle(uint32_t langListId)40     FontStyle(uint32_t langListId)
41             : FontStyle(langListId, 0 /* variant */, 4 /* weight */, false /* italic */) {}
42 
43     FontStyle(int variant, int weight, bool italic);
44     FontStyle(uint32_t langListId, int variant, int weight, bool italic);
45 
getWeight()46     int getWeight() const { return bits & kWeightMask; }
getItalic()47     bool getItalic() const { return (bits & kItalicMask) != 0; }
getVariant()48     int getVariant() const { return (bits >> kVariantShift) & kVariantMask; }
getLanguageListId()49     uint32_t getLanguageListId() const { return mLanguageListId; }
50 
51     bool operator==(const FontStyle other) const {
52           return bits == other.bits && mLanguageListId == other.mLanguageListId;
53     }
54 
55     hash_t hash() const;
56 
57     // Looks up a language list from an internal cache and returns its ID.
58     // If the passed language list is not in the cache, registers it and returns newly assigned ID.
59     static uint32_t registerLanguageList(const std::string& languages);
60 private:
61     static const uint32_t kWeightMask = (1 << 4) - 1;
62     static const uint32_t kItalicMask = 1 << 4;
63     static const int kVariantShift = 5;
64     static const uint32_t kVariantMask = (1 << 2) - 1;
65 
66     static uint32_t pack(int variant, int weight, bool italic);
67 
68     uint32_t bits;
69     uint32_t mLanguageListId;
70 };
71 
72 enum FontVariant {
73     VARIANT_DEFAULT = 0,
74     VARIANT_COMPACT = 1,
75     VARIANT_ELEGANT = 2,
76 };
77 
hash_type(const FontStyle & style)78 inline hash_t hash_type(const FontStyle &style) {
79     return style.hash();
80 }
81 
82 // attributes representing transforms (fake bold, fake italic) to match styles
83 class FontFakery {
84 public:
FontFakery()85     FontFakery() : mFakeBold(false), mFakeItalic(false) { }
FontFakery(bool fakeBold,bool fakeItalic)86     FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { }
87     // TODO: want to support graded fake bolding
isFakeBold()88     bool isFakeBold() { return mFakeBold; }
isFakeItalic()89     bool isFakeItalic() { return mFakeItalic; }
90 private:
91     bool mFakeBold;
92     bool mFakeItalic;
93 };
94 
95 struct FakedFont {
96     // ownership is the enclosing FontCollection
97     MinikinFont* font;
98     FontFakery fakery;
99 };
100 
101 class FontFamily : public MinikinRefCounted {
102 public:
103     FontFamily();
104 
105     FontFamily(int variant);
106 
FontFamily(uint32_t langId,int variant)107     FontFamily(uint32_t langId, int variant)
108         : mLangId(langId),
109         mVariant(variant),
110         mHasVSTable(false),
111         mCoverageValid(false) {
112     }
113 
114     ~FontFamily();
115 
116     // Add font to family, extracting style information from the font
117     bool addFont(MinikinFont* typeface);
118 
119     void addFont(MinikinFont* typeface, FontStyle style);
120     FakedFont getClosestMatch(FontStyle style) const;
121 
langId()122     uint32_t langId() const { return mLangId; }
variant()123     int variant() const { return mVariant; }
124 
125     // API's for enumerating the fonts in a family. These don't guarantee any particular order
126     size_t getNumFonts() const;
127     MinikinFont* getFont(size_t index) const;
128     FontStyle getStyle(size_t index) const;
129     bool isColorEmojiFamily() const;
130 
131     // Get Unicode coverage. Lifetime of returned bitset is same as receiver. May return nullptr on
132     // error.
133     const SparseBitSet* getCoverage();
134 
135     // Returns true if the font has a glyph for the code point and variation selector pair.
136     // Caller should acquire a lock before calling the method.
137     bool hasGlyph(uint32_t codepoint, uint32_t variationSelector);
138 
139     // Returns true if this font family has a variaion sequence table (cmap format 14 subtable).
140     bool hasVSTable() const;
141 
142 private:
143     void addFontLocked(MinikinFont* typeface, FontStyle style);
144 
145     class Font {
146     public:
Font(MinikinFont * typeface,FontStyle style)147         Font(MinikinFont* typeface, FontStyle style) :
148             typeface(typeface), style(style) { }
149         MinikinFont* typeface;
150         FontStyle style;
151     };
152     uint32_t mLangId;
153     int mVariant;
154     std::vector<Font> mFonts;
155 
156     SparseBitSet mCoverage;
157     bool mHasVSTable;
158     bool mCoverageValid;
159 };
160 
161 }  // namespace android
162 
163 #endif  // MINIKIN_FONT_FAMILY_H
164