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