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