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 #include <utils/LruCache.h> 22 23 #include <atomic> 24 #include <functional> 25 #include <map> 26 #include <memory> 27 #include <mutex> 28 #include <unordered_set> 29 30 #include "minikin/Buffer.h" 31 #include "minikin/FVarTable.h" 32 #include "minikin/FontFakery.h" 33 #include "minikin/FontStyle.h" 34 #include "minikin/FontVariation.h" 35 #include "minikin/HbUtils.h" 36 #include "minikin/LocaleList.h" 37 #include "minikin/Macros.h" 38 #include "minikin/MinikinFont.h" 39 40 namespace minikin { 41 42 // Represents a single font file. 43 class Font { 44 public: 45 class Builder { 46 public: Builder(const std::shared_ptr<MinikinFont> & typeface)47 Builder(const std::shared_ptr<MinikinFont>& typeface) : mTypeface(typeface) {} 48 49 // Override the font style. If not called, info from OS/2 table is used. setStyle(FontStyle style)50 Builder& setStyle(FontStyle style) { 51 mWeight = style.weight(); 52 mSlant = style.slant(); 53 mIsWeightSet = mIsSlantSet = true; 54 return *this; 55 } 56 57 // Override the font weight. If not called, info from OS/2 table is used. setWeight(uint16_t weight)58 Builder& setWeight(uint16_t weight) { 59 mWeight = weight; 60 mIsWeightSet = true; 61 return *this; 62 } 63 64 // Override the font slant. If not called, info from OS/2 table is used. setSlant(FontStyle::Slant slant)65 Builder& setSlant(FontStyle::Slant slant) { 66 mSlant = slant; 67 mIsSlantSet = true; 68 return *this; 69 } 70 setLocaleListId(uint32_t id)71 Builder& setLocaleListId(uint32_t id) { 72 mLocaleListId = id; 73 return *this; 74 } 75 76 std::shared_ptr<Font> build(); 77 78 private: 79 std::shared_ptr<MinikinFont> mTypeface; 80 uint16_t mWeight = static_cast<uint16_t>(FontStyle::Weight::NORMAL); 81 FontStyle::Slant mSlant = FontStyle::Slant::UPRIGHT; 82 uint32_t mLocaleListId = kEmptyLocaleListId; 83 bool mIsWeightSet = false; 84 bool mIsSlantSet = false; 85 }; 86 87 explicit Font(BufferReader* reader); 88 void writeTo(BufferWriter* writer) const; 89 90 // Create font instance with axes override. 91 Font(const std::shared_ptr<Font>& parent, const VariationSettings& axes); 92 93 Font(Font&& o) noexcept; 94 Font& operator=(Font&& o) noexcept; 95 ~Font(); 96 // This locale list is just for API compatibility. This is not used in font selection or family 97 // fallback. getLocaleListId()98 uint32_t getLocaleListId() const { return mLocaleListId; } style()99 inline FontStyle style() const { return mStyle; } 100 101 const HbFontUniquePtr& baseFont() const; 102 const std::shared_ptr<MinikinFont>& baseTypeface() const; 103 104 // Returns an adjusted hb_font_t instance and MinikinFont instance. 105 // Passing -1 each means do not override the current variation settings. 106 HbFontUniquePtr getAdjustedFont(int wght, int ital) const; 107 std::shared_ptr<MinikinFont> getAdjustedTypeface(int wght, int ital) const; 108 109 HbFontUniquePtr getAdjustedFont(const VariationSettings& varSettings) const; 110 std::shared_ptr<MinikinFont> getAdjustedTypeface(const VariationSettings& varSettings) const; 111 typefaceMetadataReader()112 BufferReader typefaceMetadataReader() const { return mTypefaceMetadataReader; } 113 getSupportedAxesCount()114 uint16_t getSupportedAxesCount() const { return mSupportedAxesCount; } getSupportedAxes()115 const AxisTag* getSupportedAxes() const { return mSupportedAxes.get(); } 116 bool isAxisSupported(uint32_t tag) const; 117 118 const FVarTable& getFVarTable() const; 119 120 private: 121 // ExternalRefs holds references to objects provided by external libraries. 122 // Because creating these external objects is costly, 123 // ExternalRefs is lazily created if Font was created by readFrom(). 124 class ExternalRefs { 125 public: ExternalRefs(std::shared_ptr<MinikinFont> && typeface,HbFontUniquePtr && baseFont)126 ExternalRefs(std::shared_ptr<MinikinFont>&& typeface, HbFontUniquePtr&& baseFont) 127 : mTypeface(std::move(typeface)), 128 mBaseFont(std::move(baseFont)), 129 mVarTypefaceCache2(16), 130 mVarFontCache2(16) {} 131 132 std::shared_ptr<MinikinFont> mTypeface; 133 HbFontUniquePtr mBaseFont; 134 135 // TODO: remove wght/ital only adjusted typeface pool once redesign typeface flag 136 // is removed. 137 const std::shared_ptr<MinikinFont>& getAdjustedTypeface(int wght, int ital) const; 138 HbFontUniquePtr getAdjustedFont(int wght, int ital) const; 139 mutable std::mutex mMutex; 140 mutable std::map<uint16_t, std::shared_ptr<MinikinFont>> mVarTypefaceCache 141 GUARDED_BY(mMutex); 142 mutable std::map<uint16_t, HbFontUniquePtr> mVarFontCache GUARDED_BY(mMutex); 143 144 std::shared_ptr<MinikinFont> getAdjustedTypeface(const VariationSettings& varSettings, 145 const FVarTable& fvarTable) const; 146 HbFontUniquePtr getAdjustedFont(const VariationSettings& varSettings, 147 const FVarTable& fvarTable) const; 148 mutable android::LruCache<VariationSettings, std::shared_ptr<MinikinFont>> 149 mVarTypefaceCache2 GUARDED_BY(mMutex); 150 mutable android::LruCache<VariationSettings, HbFontUniquePtr*> mVarFontCache2 151 GUARDED_BY(mMutex); 152 }; 153 154 // Use Builder instead. Font(std::shared_ptr<MinikinFont> && typeface,FontStyle style,HbFontUniquePtr && baseFont,uint32_t localeListId)155 Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style, HbFontUniquePtr&& baseFont, 156 uint32_t localeListId) 157 : mExternalRefsHolder(new ExternalRefs(std::move(typeface), std::move(baseFont))), 158 mExternalRefsBuilder(nullptr), 159 mStyle(style), 160 mLocaleListId(localeListId), 161 mTypefaceMetadataReader(nullptr) { 162 calculateSupportedAxes(); 163 } 164 165 void resetExternalRefs(ExternalRefs* refs); 166 167 const ExternalRefs* getExternalRefs() const; 168 std::vector<FontVariation> getAdjustedVariations(int wght, int ital) const; 169 170 static HbFontUniquePtr prepareFont(const std::shared_ptr<MinikinFont>& typeface); 171 static FontStyle analyzeStyle(const HbFontUniquePtr& font); 172 173 // Lazy-initialized if created by readFrom(). 174 mutable std::atomic<ExternalRefs*> mExternalRefsHolder; 175 std::function<ExternalRefs*()> mExternalRefsBuilder; 176 FontStyle mStyle; 177 uint32_t mLocaleListId; 178 std::unique_ptr<AxisTag[]> mSupportedAxes; 179 uint16_t mSupportedAxesCount; 180 181 void calculateSupportedAxes(); 182 183 mutable std::atomic<FVarTable*> mFVarTableHolder; 184 185 // Non-null if created by readFrom(). 186 BufferReader mTypefaceMetadataReader; 187 188 // Stop copying. 189 Font(const Font& o) = delete; 190 Font& operator=(const Font& o) = delete; 191 192 FRIEND_TEST(FontTest, MoveConstructorTest); 193 FRIEND_TEST(FontTest, MoveAssignmentTest); 194 }; 195 196 struct FakedFont { 197 inline bool operator==(const FakedFont& o) const { 198 return font == o.font && fakery == o.fakery; 199 } 200 inline bool operator!=(const FakedFont& o) const { return !(*this == o); } 201 202 HbFontUniquePtr hbFont() const; 203 std::shared_ptr<MinikinFont> typeface() const; 204 205 // ownership is the enclosing FontCollection 206 // FakedFont will be stored in the LayoutCache. It is not a good idea too keep font instance 207 // even if the enclosing FontCollection, i.e. Typeface is GC-ed. The layout cache is only 208 // purged when it is overflown, thus intentionally keep only reference. 209 const std::shared_ptr<Font>& font; 210 FontFakery fakery; 211 }; 212 213 } // namespace minikin 214 215 #endif // MINIKIN_FONT_H 216