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
23 #include <utils/TypeHelpers.h>
24
25 #include <minikin/MinikinRefCounted.h>
26 #include <minikin/SparseBitSet.h>
27
28 namespace android {
29
30 class MinikinFont;
31
32 // FontLanguage is a compact representation of a bcp-47 language tag. It
33 // does not capture all possible information, only what directly affects
34 // font rendering.
35 class FontLanguage {
36 friend class FontStyle;
37 public:
FontLanguage()38 FontLanguage() : mBits(0) { }
39
40 // Parse from string
41 FontLanguage(const char* buf, size_t size);
42
43 bool operator==(const FontLanguage other) const { return mBits == other.mBits; }
44 operator bool() const { return mBits != 0; }
45
46 std::string getString() const;
47
48 // 0 = no match, 1 = language matches, 2 = language and script match
49 int match(const FontLanguage other) const;
50
51 private:
FontLanguage(uint32_t bits)52 explicit FontLanguage(uint32_t bits) : mBits(bits) { }
53
bits()54 uint32_t bits() const { return mBits; }
55
56 static const uint32_t kBaseLangMask = 0xffff;
57 static const uint32_t kScriptMask = (1 << 18) - (1 << 16);
58 static const uint32_t kHansFlag = 1 << 16;
59 static const uint32_t kHantFlag = 1 << 17;
60 uint32_t mBits;
61 };
62
63 // FontStyle represents all style information needed to select an actual font
64 // from a collection. The implementation is packed into a single 32-bit word
65 // so it can be efficiently copied, embedded in other objects, etc.
66 class FontStyle {
67 public:
68 FontStyle(int weight = 4, bool italic = false) {
69 bits = (weight & kWeightMask) | (italic ? kItalicMask : 0);
70 }
71 FontStyle(FontLanguage lang, int variant = 0, int weight = 4, bool italic = false) {
72 bits = (weight & kWeightMask) | (italic ? kItalicMask : 0)
73 | (variant << kVariantShift) | (lang.bits() << kLangShift);
74 }
getWeight()75 int getWeight() const { return bits & kWeightMask; }
getItalic()76 bool getItalic() const { return (bits & kItalicMask) != 0; }
getVariant()77 int getVariant() const { return (bits >> kVariantShift) & kVariantMask; }
getLanguage()78 FontLanguage getLanguage() const { return FontLanguage(bits >> kLangShift); }
79
80 bool operator==(const FontStyle other) const { return bits == other.bits; }
81
hash()82 hash_t hash() const { return bits; }
83 private:
84 static const uint32_t kWeightMask = (1 << 4) - 1;
85 static const uint32_t kItalicMask = 1 << 4;
86 static const int kVariantShift = 5;
87 static const uint32_t kVariantMask = (1 << 2) - 1;
88 static const int kLangShift = 7;
89 uint32_t bits;
90 };
91
92 enum FontVariant {
93 VARIANT_DEFAULT = 0,
94 VARIANT_COMPACT = 1,
95 VARIANT_ELEGANT = 2,
96 };
97
hash_type(const FontStyle & style)98 inline hash_t hash_type(const FontStyle &style) {
99 return style.hash();
100 }
101
102 // attributes representing transforms (fake bold, fake italic) to match styles
103 class FontFakery {
104 public:
FontFakery()105 FontFakery() : mFakeBold(false), mFakeItalic(false) { }
FontFakery(bool fakeBold,bool fakeItalic)106 FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { }
107 // TODO: want to support graded fake bolding
isFakeBold()108 bool isFakeBold() { return mFakeBold; }
isFakeItalic()109 bool isFakeItalic() { return mFakeItalic; }
110 private:
111 bool mFakeBold;
112 bool mFakeItalic;
113 };
114
115 struct FakedFont {
116 // ownership is the enclosing FontCollection
117 MinikinFont* font;
118 FontFakery fakery;
119 };
120
121 class FontFamily : public MinikinRefCounted {
122 public:
FontFamily()123 FontFamily() { }
124
FontFamily(FontLanguage lang,int variant)125 FontFamily(FontLanguage lang, int variant) : mLang(lang), mVariant(variant) {
126 }
127
128 ~FontFamily();
129
130 // Add font to family, extracting style information from the font
131 bool addFont(MinikinFont* typeface);
132
133 void addFont(MinikinFont* typeface, FontStyle style);
134 FakedFont getClosestMatch(FontStyle style) const;
135
lang()136 FontLanguage lang() const { return mLang; }
variant()137 int variant() const { return mVariant; }
138
139 // API's for enumerating the fonts in a family. These don't guarantee any particular order
140 size_t getNumFonts() const;
141 MinikinFont* getFont(size_t index) const;
142 FontStyle getStyle(size_t index) const;
143
144 // Get Unicode coverage. Lifetime of returned bitset is same as receiver.
145 const SparseBitSet* getCoverage();
146 private:
147 void addFontLocked(MinikinFont* typeface, FontStyle style);
148
149 class Font {
150 public:
Font(MinikinFont * typeface,FontStyle style)151 Font(MinikinFont* typeface, FontStyle style) :
152 typeface(typeface), style(style) { }
153 MinikinFont* typeface;
154 FontStyle style;
155 };
156 FontLanguage mLang;
157 int mVariant;
158 std::vector<Font> mFonts;
159
160 SparseBitSet mCoverage;
161 bool mCoverageValid;
162 };
163
164 } // namespace android
165
166 #endif // MINIKIN_FONT_FAMILY_H
167