xref: /aosp_15_r20/frameworks/minikin/include/minikin/FontFakery.h (revision 834a2baab5fdfc28e9a428ee87c7ea8f6a06a53d)
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