• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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_H
18 #define MINIKIN_FONT_H
19 
20 #include <gtest/gtest_prod.h>
21 
22 #include <atomic>
23 #include <functional>
24 #include <map>
25 #include <memory>
26 #include <mutex>
27 #include <unordered_set>
28 
29 #include "minikin/Buffer.h"
30 #include "minikin/FontStyle.h"
31 #include "minikin/FontVariation.h"
32 #include "minikin/HbUtils.h"
33 #include "minikin/LocaleList.h"
34 #include "minikin/Macros.h"
35 #include "minikin/MinikinFont.h"
36 
37 namespace minikin {
38 
39 class Font;
40 
41 // attributes representing transforms (fake bold, fake italic) to match styles
42 class FontFakery {
43 public:
FontFakery()44     FontFakery() : FontFakery(false, false, -1, -1) {}
FontFakery(bool fakeBold,bool fakeItalic)45     FontFakery(bool fakeBold, bool fakeItalic) : FontFakery(fakeBold, fakeItalic, -1, -1) {}
FontFakery(bool fakeBold,bool fakeItalic,int16_t wghtAdjustment,int8_t italAdjustment)46     FontFakery(bool fakeBold, bool fakeItalic, int16_t wghtAdjustment, int8_t italAdjustment)
47             : mBits(pack(fakeBold, fakeItalic, wghtAdjustment, italAdjustment)) {}
48 
49     // TODO: want to support graded fake bolding
isFakeBold()50     bool isFakeBold() { return (mBits & MASK_FAKE_BOLD) != 0; }
isFakeItalic()51     bool isFakeItalic() { return (mBits & MASK_FAKE_ITALIC) != 0; }
hasAdjustment()52     bool hasAdjustment() const { return hasWghtAdjustment() || hasItalAdjustment(); }
hasWghtAdjustment()53     bool hasWghtAdjustment() const { return (mBits & MASK_HAS_WGHT_ADJUSTMENT) != 0; }
hasItalAdjustment()54     bool hasItalAdjustment() const { return (mBits & MASK_HAS_ITAL_ADJUSTMENT) != 0; }
wghtAdjustment()55     int16_t wghtAdjustment() const {
56         if (hasWghtAdjustment()) {
57             return (mBits & MASK_WGHT_ADJUSTMENT) >> WGHT_ADJUSTMENT_SHIFT;
58         } else {
59             return -1;
60         }
61     }
62 
italAdjustment()63     int8_t italAdjustment() const {
64         if (hasItalAdjustment()) {
65             return (mBits & MASK_ITAL_ADJUSTMENT) != 0 ? 1 : 0;
66         } else {
67             return -1;
68         }
69     }
70 
bits()71     uint16_t bits() const { return mBits; }
72 
73     inline bool operator==(const FontFakery& o) const { return mBits == o.mBits; }
74     inline bool operator!=(const FontFakery& o) const { return !(*this == o); }
75 
76 private:
77     static constexpr uint16_t MASK_FAKE_BOLD = 1u;
78     static constexpr uint16_t MASK_FAKE_ITALIC = 1u << 1;
79     static constexpr uint16_t MASK_HAS_WGHT_ADJUSTMENT = 1u << 2;
80     static constexpr uint16_t MASK_HAS_ITAL_ADJUSTMENT = 1u << 3;
81     static constexpr uint16_t MASK_ITAL_ADJUSTMENT = 1u << 4;
82     static constexpr uint16_t MASK_WGHT_ADJUSTMENT = 0b1111111111u << 5;
83     static constexpr uint16_t WGHT_ADJUSTMENT_SHIFT = 5;
84 
pack(bool isFakeBold,bool isFakeItalic,int16_t wghtAdjustment,int8_t italAdjustment)85     uint16_t pack(bool isFakeBold, bool isFakeItalic, int16_t wghtAdjustment,
86                   int8_t italAdjustment) {
87         uint16_t bits = 0u;
88         bits |= isFakeBold ? MASK_FAKE_BOLD : 0;
89         bits |= isFakeItalic ? MASK_FAKE_ITALIC : 0;
90         if (wghtAdjustment != -1) {
91             bits |= MASK_HAS_WGHT_ADJUSTMENT;
92             bits |= (static_cast<uint16_t>(wghtAdjustment) << WGHT_ADJUSTMENT_SHIFT) &
93                     MASK_WGHT_ADJUSTMENT;
94         }
95         if (italAdjustment != -1) {
96             bits |= MASK_HAS_ITAL_ADJUSTMENT;
97             bits |= (italAdjustment == 1) ? MASK_ITAL_ADJUSTMENT : 0;
98         }
99         return bits;
100     }
101 
102     const uint16_t mBits;
103 };
104 
105 // Represents a single font file.
106 class Font {
107 public:
108     class Builder {
109     public:
Builder(const std::shared_ptr<MinikinFont> & typeface)110         Builder(const std::shared_ptr<MinikinFont>& typeface) : mTypeface(typeface) {}
111 
112         // Override the font style. If not called, info from OS/2 table is used.
setStyle(FontStyle style)113         Builder& setStyle(FontStyle style) {
114             mWeight = style.weight();
115             mSlant = style.slant();
116             mIsWeightSet = mIsSlantSet = true;
117             return *this;
118         }
119 
120         // Override the font weight. If not called, info from OS/2 table is used.
setWeight(uint16_t weight)121         Builder& setWeight(uint16_t weight) {
122             mWeight = weight;
123             mIsWeightSet = true;
124             return *this;
125         }
126 
127         // Override the font slant. If not called, info from OS/2 table is used.
setSlant(FontStyle::Slant slant)128         Builder& setSlant(FontStyle::Slant slant) {
129             mSlant = slant;
130             mIsSlantSet = true;
131             return *this;
132         }
133 
setLocaleListId(uint32_t id)134         Builder& setLocaleListId(uint32_t id) {
135             mLocaleListId = id;
136             return *this;
137         }
138 
139         std::shared_ptr<Font> build();
140 
141     private:
142         std::shared_ptr<MinikinFont> mTypeface;
143         uint16_t mWeight = static_cast<uint16_t>(FontStyle::Weight::NORMAL);
144         FontStyle::Slant mSlant = FontStyle::Slant::UPRIGHT;
145         uint32_t mLocaleListId = kEmptyLocaleListId;
146         bool mIsWeightSet = false;
147         bool mIsSlantSet = false;
148     };
149 
150     explicit Font(BufferReader* reader);
151     void writeTo(BufferWriter* writer) const;
152 
153     // Create font instance with axes override.
154     Font(const std::shared_ptr<Font>& parent, const std::vector<FontVariation>& axes);
155 
156     Font(Font&& o) noexcept;
157     Font& operator=(Font&& o) noexcept;
158     ~Font();
159     // This locale list is just for API compatibility. This is not used in font selection or family
160     // fallback.
getLocaleListId()161     uint32_t getLocaleListId() const { return mLocaleListId; }
style()162     inline FontStyle style() const { return mStyle; }
163 
164     const HbFontUniquePtr& baseFont() const;
165     const std::shared_ptr<MinikinFont>& baseTypeface() const;
166 
167     // Returns an adjusted hb_font_t instance and MinikinFont instance.
168     // Passing -1 each means do not override the current variation settings.
169     HbFontUniquePtr getAdjustedFont(int wght, int ital) const;
170     const std::shared_ptr<MinikinFont>& getAdjustedTypeface(int wght, int ital) const;
171 
typefaceMetadataReader()172     BufferReader typefaceMetadataReader() const { return mTypefaceMetadataReader; }
173 
getSupportedAxesCount()174     uint16_t getSupportedAxesCount() const { return mSupportedAxesCount; }
getSupportedAxes()175     const AxisTag* getSupportedAxes() const { return mSupportedAxes.get(); }
176     bool isAxisSupported(uint32_t tag) const;
177 
178 private:
179     // ExternalRefs holds references to objects provided by external libraries.
180     // Because creating these external objects is costly,
181     // ExternalRefs is lazily created if Font was created by readFrom().
182     class ExternalRefs {
183     public:
ExternalRefs(std::shared_ptr<MinikinFont> && typeface,HbFontUniquePtr && baseFont)184         ExternalRefs(std::shared_ptr<MinikinFont>&& typeface, HbFontUniquePtr&& baseFont)
185                 : mTypeface(std::move(typeface)), mBaseFont(std::move(baseFont)) {}
186 
187         std::shared_ptr<MinikinFont> mTypeface;
188         HbFontUniquePtr mBaseFont;
189 
190         const std::shared_ptr<MinikinFont>& getAdjustedTypeface(int wght, int ital) const;
191         HbFontUniquePtr getAdjustedFont(int wght, int ital) const;
192         mutable std::mutex mMutex;
193         mutable std::map<uint16_t, std::shared_ptr<MinikinFont>> mVarTypefaceCache
194                 GUARDED_BY(mMutex);
195         mutable std::map<uint16_t, HbFontUniquePtr> mVarFontCache GUARDED_BY(mMutex);
196     };
197 
198     // Use Builder instead.
Font(std::shared_ptr<MinikinFont> && typeface,FontStyle style,HbFontUniquePtr && baseFont,uint32_t localeListId)199     Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style, HbFontUniquePtr&& baseFont,
200          uint32_t localeListId)
201             : mExternalRefsHolder(new ExternalRefs(std::move(typeface), std::move(baseFont))),
202               mExternalRefsBuilder(nullptr),
203               mStyle(style),
204               mLocaleListId(localeListId),
205               mTypefaceMetadataReader(nullptr) {
206         calculateSupportedAxes();
207     }
208 
209     void resetExternalRefs(ExternalRefs* refs);
210 
211     const ExternalRefs* getExternalRefs() const;
212     std::vector<FontVariation> getAdjustedVariations(int wght, int ital) const;
213 
214     static HbFontUniquePtr prepareFont(const std::shared_ptr<MinikinFont>& typeface);
215     static FontStyle analyzeStyle(const HbFontUniquePtr& font);
216 
217     // Lazy-initialized if created by readFrom().
218     mutable std::atomic<ExternalRefs*> mExternalRefsHolder;
219     std::function<ExternalRefs*()> mExternalRefsBuilder;
220     FontStyle mStyle;
221     uint32_t mLocaleListId;
222     std::unique_ptr<AxisTag[]> mSupportedAxes;
223     uint16_t mSupportedAxesCount;
224 
225     void calculateSupportedAxes();
226 
227     // Non-null if created by readFrom().
228     BufferReader mTypefaceMetadataReader;
229 
230     // Stop copying.
231     Font(const Font& o) = delete;
232     Font& operator=(const Font& o) = delete;
233 
234     FRIEND_TEST(FontTest, MoveConstructorTest);
235     FRIEND_TEST(FontTest, MoveAssignmentTest);
236 };
237 
238 struct FakedFont {
239     inline bool operator==(const FakedFont& o) const {
240         return font == o.font && fakery == o.fakery;
241     }
242     inline bool operator!=(const FakedFont& o) const { return !(*this == o); }
243 
hbFontFakedFont244     HbFontUniquePtr hbFont() const {
245         return font->getAdjustedFont(fakery.wghtAdjustment(), fakery.italAdjustment());
246     }
247 
typefaceFakedFont248     const std::shared_ptr<MinikinFont>& typeface() const {
249         return font->getAdjustedTypeface(fakery.wghtAdjustment(), fakery.italAdjustment());
250     }
251 
252     // ownership is the enclosing FontCollection
253     // FakedFont will be stored in the LayoutCache. It is not a good idea too keep font instance
254     // even if the enclosing FontCollection, i.e. Typeface is GC-ed. The layout cache is only
255     // purged when it is overflown, thus intentionally keep only reference.
256     const std::shared_ptr<Font>& font;
257     FontFakery fakery;
258 };
259 
260 }  // namespace minikin
261 
262 #endif  // MINIKIN_FONT_H
263