|
32 | 32 |
|
33 | 33 | #include FT_STROKER_H
|
34 | 34 | #include FT_ADVANCES_H
|
| 35 | +#include FT_MULTIPLE_MASTERS_H |
35 | 36 |
|
36 | 37 | DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(int p_size, int p_outline_size) {
|
37 | 38 | ERR_FAIL_COND_V(!valid, nullptr);
|
@@ -134,16 +135,91 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
|
134 | 135 | memdelete(fds);
|
135 | 136 | ERR_FAIL_V_MSG(nullptr, "Error loading HB font.");
|
136 | 137 | }
|
| 138 | + |
137 | 139 | if (p_outline_size != 0) {
|
138 | 140 | size_cache_outline[id] = fds;
|
139 | 141 | } else {
|
140 | 142 | size_cache[id] = fds;
|
141 | 143 | }
|
142 |
| - } |
143 | 144 |
|
| 145 | + // Write variations. |
| 146 | + if (fds->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { |
| 147 | + FT_MM_Var *amaster; |
| 148 | + |
| 149 | + FT_Get_MM_Var(fds->face, &amaster); |
| 150 | + |
| 151 | + Vector<hb_variation_t> hb_vars; |
| 152 | + Vector<FT_Fixed> coords; |
| 153 | + coords.resize(amaster->num_axis); |
| 154 | + |
| 155 | + FT_Get_Var_Design_Coordinates(fds->face, coords.size(), coords.ptrw()); |
| 156 | + |
| 157 | + for (FT_UInt i = 0; i < amaster->num_axis; i++) { |
| 158 | + hb_variation_t var; |
| 159 | + |
| 160 | + // Reset to default. |
| 161 | + var.tag = amaster->axis[i].tag; |
| 162 | + var.value = (double)amaster->axis[i].def / 65536.f; |
| 163 | + coords.write[i] = amaster->axis[i].def; |
| 164 | + |
| 165 | + if (variations.has(var.tag)) { |
| 166 | + var.value = variations[var.tag]; |
| 167 | + coords.write[i] = CLAMP(variations[var.tag] * 65536.f, amaster->axis[i].minimum, amaster->axis[i].maximum); |
| 168 | + } |
| 169 | + |
| 170 | + hb_vars.push_back(var); |
| 171 | + } |
| 172 | + |
| 173 | + FT_Set_Var_Design_Coordinates(fds->face, coords.size(), coords.ptrw()); |
| 174 | + hb_font_set_variations(fds->hb_handle, hb_vars.empty() ? nullptr : &hb_vars[0], hb_vars.size()); |
| 175 | + |
| 176 | + FT_Done_MM_Var(library, amaster); |
| 177 | + } |
| 178 | + } |
144 | 179 | return fds;
|
145 | 180 | }
|
146 | 181 |
|
| 182 | +Dictionary DynamicFontDataAdvanced::get_variation_list() const { |
| 183 | + _THREAD_SAFE_METHOD_ |
| 184 | + DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size); |
| 185 | + if (fds == nullptr) { |
| 186 | + return Dictionary(); |
| 187 | + } |
| 188 | + |
| 189 | + Dictionary ret; |
| 190 | + // Read variations. |
| 191 | + if (fds->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { |
| 192 | + FT_MM_Var *amaster; |
| 193 | + |
| 194 | + FT_Get_MM_Var(fds->face, &amaster); |
| 195 | + |
| 196 | + for (FT_UInt i = 0; i < amaster->num_axis; i++) { |
| 197 | + ret[(int32_t)amaster->axis[i].tag] = Vector3i(amaster->axis[i].minimum / 65536, amaster->axis[i].maximum / 65536, amaster->axis[i].def / 65536); |
| 198 | + } |
| 199 | + |
| 200 | + FT_Done_MM_Var(library, amaster); |
| 201 | + } |
| 202 | + return ret; |
| 203 | +} |
| 204 | + |
| 205 | +void DynamicFontDataAdvanced::set_variation(const String &p_name, double p_value) { |
| 206 | + _THREAD_SAFE_METHOD_ |
| 207 | + int32_t tag = TS->name_to_tag(p_name); |
| 208 | + if (!variations.has(tag) || (variations[tag] != p_value)) { |
| 209 | + variations[tag] = p_value; |
| 210 | + clear_cache(); |
| 211 | + } |
| 212 | +} |
| 213 | + |
| 214 | +double DynamicFontDataAdvanced::get_variation(const String &p_name) const { |
| 215 | + _THREAD_SAFE_METHOD_ |
| 216 | + int32_t tag = TS->name_to_tag(p_name); |
| 217 | + if (!variations.has(tag)) { |
| 218 | + return 0.f; |
| 219 | + } |
| 220 | + return variations[tag]; |
| 221 | +} |
| 222 | + |
147 | 223 | Dictionary DynamicFontDataAdvanced::get_feature_list() const {
|
148 | 224 | _THREAD_SAFE_METHOD_
|
149 | 225 | DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size);
|
|
0 commit comments