1 /* 2 * Copyright (C) 2024 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_FAKERY_H 18 #define MINIKIN_FONT_FAKERY_H 19 20 #include "minikin/FVarTable.h" 21 #include "minikin/FontStyle.h" 22 #include "minikin/FontVariation.h" 23 24 namespace minikin { 25 26 // attributes representing transforms (fake bold, fake italic) to match styles 27 class FontFakery { 28 public: FontFakery()29 FontFakery() : FontFakery(false, false, -1, -1, VariationSettings()) {} FontFakery(bool fakeBold,bool fakeItalic)30 FontFakery(bool fakeBold, bool fakeItalic) 31 : FontFakery(fakeBold, fakeItalic, -1, -1, VariationSettings()) {} FontFakery(bool fakeBold,bool fakeItalic,int16_t wghtAdjustment,int8_t italAdjustment)32 FontFakery(bool fakeBold, bool fakeItalic, int16_t wghtAdjustment, int8_t italAdjustment) 33 : FontFakery(fakeBold, fakeItalic, wghtAdjustment, italAdjustment, 34 VariationSettings()) {} FontFakery(bool fakeBold,bool fakeItalic,VariationSettings && variationSettings)35 FontFakery(bool fakeBold, bool fakeItalic, VariationSettings&& variationSettings) 36 : FontFakery(fakeBold, fakeItalic, -1, -1, std::move(variationSettings)) {} FontFakery(bool fakeBold,bool fakeItalic,int16_t wghtAdjustment,int8_t italAdjustment,VariationSettings && variationSettings)37 FontFakery(bool fakeBold, bool fakeItalic, int16_t wghtAdjustment, int8_t italAdjustment, 38 VariationSettings&& variationSettings) 39 : mBits(pack(fakeBold, fakeItalic, wghtAdjustment, italAdjustment)), 40 mVariationSettings(std::move(variationSettings)) {} 41 42 // TODO: want to support graded fake bolding isFakeBold()43 bool isFakeBold() const { return (mBits & MASK_FAKE_BOLD) != 0; } isFakeItalic()44 bool isFakeItalic() const { return (mBits & MASK_FAKE_ITALIC) != 0; } hasAdjustment()45 bool hasAdjustment() const { return hasWghtAdjustment() || hasItalAdjustment(); } hasWghtAdjustment()46 bool hasWghtAdjustment() const { return (mBits & MASK_HAS_WGHT_ADJUSTMENT) != 0; } hasItalAdjustment()47 bool hasItalAdjustment() const { return (mBits & MASK_HAS_ITAL_ADJUSTMENT) != 0; } wghtAdjustment()48 int16_t wghtAdjustment() const { 49 if (hasWghtAdjustment()) { 50 return (mBits & MASK_WGHT_ADJUSTMENT) >> WGHT_ADJUSTMENT_SHIFT; 51 } else { 52 return -1; 53 } 54 } 55 italAdjustment()56 int8_t italAdjustment() const { 57 if (hasItalAdjustment()) { 58 return (mBits & MASK_ITAL_ADJUSTMENT) != 0 ? 1 : 0; 59 } else { 60 return -1; 61 } 62 } 63 bits()64 uint16_t bits() const { return mBits; } 65 variationSettings()66 const VariationSettings& variationSettings() const { return mVariationSettings; } 67 68 inline bool operator==(const FontFakery& o) const { 69 return mBits == o.mBits && mVariationSettings == o.mVariationSettings; 70 } 71 inline bool operator!=(const FontFakery& o) const { return !(*this == o); } 72 73 private: 74 static constexpr uint16_t MASK_FAKE_BOLD = 1u; 75 static constexpr uint16_t MASK_FAKE_ITALIC = 1u << 1; 76 static constexpr uint16_t MASK_HAS_WGHT_ADJUSTMENT = 1u << 2; 77 static constexpr uint16_t MASK_HAS_ITAL_ADJUSTMENT = 1u << 3; 78 static constexpr uint16_t MASK_ITAL_ADJUSTMENT = 1u << 4; 79 static constexpr uint16_t MASK_WGHT_ADJUSTMENT = 0b1111111111u << 5; 80 static constexpr uint16_t WGHT_ADJUSTMENT_SHIFT = 5; 81 pack(bool isFakeBold,bool isFakeItalic,int16_t wghtAdjustment,int8_t italAdjustment)82 uint16_t pack(bool isFakeBold, bool isFakeItalic, int16_t wghtAdjustment, 83 int8_t italAdjustment) { 84 uint16_t bits = 0u; 85 bits |= isFakeBold ? MASK_FAKE_BOLD : 0; 86 bits |= isFakeItalic ? MASK_FAKE_ITALIC : 0; 87 if (wghtAdjustment != -1) { 88 bits |= MASK_HAS_WGHT_ADJUSTMENT; 89 bits |= (static_cast<uint16_t>(wghtAdjustment) << WGHT_ADJUSTMENT_SHIFT) & 90 MASK_WGHT_ADJUSTMENT; 91 } 92 if (italAdjustment != -1) { 93 bits |= MASK_HAS_ITAL_ADJUSTMENT; 94 bits |= (italAdjustment == 1) ? MASK_ITAL_ADJUSTMENT : 0; 95 } 96 return bits; 97 } 98 99 const uint16_t mBits; 100 const VariationSettings mVariationSettings; 101 }; 102 103 // Merge font variation settings along with font style and returns FontFakery. 104 // 105 // The param baseVS is a base variation settings. It comes from font instance. 106 // The param targetVS is a target variation settings. It is came from Paint settings. 107 // The param baseStyle is a base font style. It is came from font instance. 108 // The param targetStyle is a target font style. It is came from Paint settings. 109 // 110 // The basic concept of the merge strategy is use target variation settings as the first priority, 111 // then use the target style second, then use the base variation settings finally. 112 // 113 // It works like as follows: 114 // Step 1. The target font style is translated to the variation settings based on the axis 115 // availability. For example, if the font support `wght` axis, the 700 of the font weight 116 // in the target font style is translated to `wght` 700. 117 // Step 2. Merge the derived variation settings and target variation settings. If there is a common 118 // tag, the value of the target variation settings is used. 119 // Step 3. Merge the base variation settings and the derived variation settings in Step 2. If there 120 // is a common tag, the value of the target variation settings is used. 121 // 122 // The fake bold and fake italic of the FontFakery is resolved based on the font capabilities. 123 FontFakery merge(const FVarTable& fvar, const VariationSettings& baseVS, 124 const VariationSettings& targetVS, FontStyle baseStyle, FontStyle targetStyle); 125 126 } // namespace minikin 127 128 #endif // MINIKIN_FONT_FAKERY_H 129