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 "minikin/FontStyle.h"
26 #include "minikin/HbUtils.h"
27 #include "minikin/Macros.h"
28 #include "minikin/SparseBitSet.h"
29 
30 namespace minikin {
31 
32 class Font;
33 class MinikinFont;
34 
35 // attributes representing transforms (fake bold, fake italic) to match styles
36 class FontFakery {
37 public:
FontFakery()38     FontFakery() : mFakeBold(false), mFakeItalic(false) {}
FontFakery(bool fakeBold,bool fakeItalic)39     FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) {}
40     // TODO: want to support graded fake bolding
isFakeBold()41     bool isFakeBold() { return mFakeBold; }
isFakeItalic()42     bool isFakeItalic() { return mFakeItalic; }
43 
44 private:
45     bool mFakeBold;
46     bool mFakeItalic;
47 };
48 
49 struct FakedFont {
50     // ownership is the enclosing FontCollection
51     const Font* font;
52     FontFakery fakery;
53 };
54 
55 typedef uint32_t AxisTag;
56 
57 // Represents a single font file.
58 class Font {
59 public:
60     class Builder {
61     public:
Builder(const std::shared_ptr<MinikinFont> & typeface)62         Builder(const std::shared_ptr<MinikinFont>& typeface) : mTypeface(typeface) {}
63 
64         // Override the font style. If not called, info from OS/2 table is used.
setStyle(FontStyle style)65         Builder& setStyle(FontStyle style) {
66             mWeight = style.weight();
67             mSlant = style.slant();
68             mIsWeightSet = mIsSlantSet = true;
69             return *this;
70         }
71 
72         // Override the font weight. If not called, info from OS/2 table is used.
setWeight(uint16_t weight)73         Builder& setWeight(uint16_t weight) {
74             mWeight = weight;
75             mIsWeightSet = true;
76             return *this;
77         }
78 
79         // Override the font slant. If not called, info from OS/2 table is used.
setSlant(FontStyle::Slant slant)80         Builder& setSlant(FontStyle::Slant slant) {
81             mSlant = slant;
82             mIsSlantSet = true;
83             return *this;
84         }
85 
86         Font build();
87 
88     private:
89         std::shared_ptr<MinikinFont> mTypeface;
90         uint16_t mWeight = static_cast<uint16_t>(FontStyle::Weight::NORMAL);
91         FontStyle::Slant mSlant = FontStyle::Slant::UPRIGHT;
92         bool mIsWeightSet = false;
93         bool mIsSlantSet = false;
94     };
95 
96     Font(Font&& o) = default;
97     Font& operator=(Font&& o) = default;
98 
typeface()99     inline const std::shared_ptr<MinikinFont>& typeface() const { return mTypeface; }
style()100     inline FontStyle style() const { return mStyle; }
baseFont()101     inline const HbFontUniquePtr& baseFont() const { return mBaseFont; }
102 
103     std::unordered_set<AxisTag> getSupportedAxes() const;
104 
105 private:
106     // Use Builder instead.
Font(std::shared_ptr<MinikinFont> && typeface,FontStyle style,HbFontUniquePtr && baseFont)107     Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style, HbFontUniquePtr&& baseFont)
108             : mTypeface(std::move(typeface)), mStyle(style), mBaseFont(std::move(baseFont)) {}
109 
110     static HbFontUniquePtr prepareFont(const std::shared_ptr<MinikinFont>& typeface);
111     static FontStyle analyzeStyle(const HbFontUniquePtr& font);
112 
113     std::shared_ptr<MinikinFont> mTypeface;
114     FontStyle mStyle;
115     HbFontUniquePtr mBaseFont;
116 
117     MINIKIN_PREVENT_COPY_AND_ASSIGN(Font);
118 };
119 
120 struct FontVariation {
FontVariationFontVariation121     FontVariation(AxisTag axisTag, float value) : axisTag(axisTag), value(value) {}
122     AxisTag axisTag;
123     float value;
124 };
125 
126 class FontFamily {
127 public:
128     // Must be the same value as FontConfig.java
129     enum class Variant : uint8_t {
130         DEFAULT = 0,  // Must be the same as FontConfig.VARIANT_DEFAULT
131         COMPACT = 1,  // Must be the same as FontConfig.VARIANT_COMPACT
132         ELEGANT = 2,  // Must be the same as FontConfig.VARIANT_ELEGANT
133     };
134 
135     explicit FontFamily(std::vector<Font>&& fonts);
136     FontFamily(Variant variant, std::vector<Font>&& fonts);
137     FontFamily(uint32_t localeListId, Variant variant, std::vector<Font>&& fonts);
138 
139     FakedFont getClosestMatch(FontStyle style) const;
140 
localeListId()141     uint32_t localeListId() const { return mLocaleListId; }
variant()142     Variant variant() const { return mVariant; }
143 
144     // API's for enumerating the fonts in a family. These don't guarantee any particular order
getNumFonts()145     size_t getNumFonts() const { return mFonts.size(); }
getFont(size_t index)146     const Font* getFont(size_t index) const { return &mFonts[index]; }
getStyle(size_t index)147     FontStyle getStyle(size_t index) const { return mFonts[index].style(); }
isColorEmojiFamily()148     bool isColorEmojiFamily() const { return mIsColorEmoji; }
supportedAxes()149     const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; }
150 
151     // Get Unicode coverage.
getCoverage()152     const SparseBitSet& getCoverage() const { return mCoverage; }
153 
154     // Returns true if the font has a glyph for the code point and variation selector pair.
155     // Caller should acquire a lock before calling the method.
156     bool hasGlyph(uint32_t codepoint, uint32_t variationSelector) const;
157 
158     // Returns true if this font family has a variaion sequence table (cmap format 14 subtable).
hasVSTable()159     bool hasVSTable() const { return !mCmapFmt14Coverage.empty(); }
160 
161     // Creates new FontFamily based on this family while applying font variations. Returns nullptr
162     // if none of variations apply to this family.
163     std::shared_ptr<FontFamily> createFamilyWithVariation(
164             const std::vector<FontVariation>& variations) const;
165 
166 private:
167     void computeCoverage();
168 
169     uint32_t mLocaleListId;
170     Variant mVariant;
171     std::vector<Font> mFonts;
172     std::unordered_set<AxisTag> mSupportedAxes;
173     bool mIsColorEmoji;
174 
175     SparseBitSet mCoverage;
176     std::vector<std::unique_ptr<SparseBitSet>> mCmapFmt14Coverage;
177 
178     MINIKIN_PREVENT_COPY_AND_ASSIGN(FontFamily);
179 };
180 
181 }  // namespace minikin
182 
183 #endif  // MINIKIN_FONT_FAMILY_H
184