FontFamily.h revision 13f1aae02bacd475722bc8ea3fc2cf6abc1a82e3
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
28namespace android {
29
30class 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.
35class FontLanguage {
36    friend class FontStyle;
37public:
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
51private:
52    explicit FontLanguage(uint32_t bits) : mBits(bits) { }
53
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.
66class FontStyle {
67public:
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    }
75    int getWeight() const { return bits & kWeightMask; }
76    bool getItalic() const { return (bits & kItalicMask) != 0; }
77    int getVariant() const { return (bits >> kVariantShift) & kVariantMask; }
78    FontLanguage getLanguage() const { return FontLanguage(bits >> kLangShift); }
79
80    bool operator==(const FontStyle other) const { return bits == other.bits; }
81
82    hash_t hash() const { return bits; }
83private:
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
92enum FontVariant {
93    VARIANT_DEFAULT = 0,
94    VARIANT_COMPACT = 1,
95    VARIANT_ELEGANT = 2,
96};
97
98inline hash_t hash_type(const FontStyle &style) {
99    return style.hash();
100}
101
102// attributes representing transforms (fake bold, fake italic) to match styles
103class FontFakery {
104public:
105    FontFakery() : mFakeBold(false), mFakeItalic(false) { }
106    FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { }
107    // TODO: want to support graded fake bolding
108    bool isFakeBold() { return mFakeBold; }
109    bool isFakeItalic() { return mFakeItalic; }
110private:
111    bool mFakeBold;
112    bool mFakeItalic;
113};
114
115struct FakedFont {
116    // ownership is the enclosing FontCollection
117    MinikinFont* font;
118    FontFakery fakery;
119};
120
121class FontFamily : public MinikinRefCounted {
122public:
123    FontFamily() { }
124
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
136    FontLanguage lang() const { return mLang; }
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();
146private:
147    void addFontLocked(MinikinFont* typeface, FontStyle style);
148
149    class Font {
150    public:
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