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