[Complex Text Layouts] Add variable fonts support.
This commit is contained in:
parent
bbf7bb3838
commit
c1d261fdb0
16 changed files with 279 additions and 4 deletions
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include FT_STROKER_H
|
||||
#include FT_ADVANCES_H
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(int p_size, int p_outline_size) {
|
||||
ERR_FAIL_COND_V(!valid, nullptr);
|
||||
|
|
@ -134,14 +135,89 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
|
|||
memdelete(fds);
|
||||
ERR_FAIL_V_MSG(nullptr, "Error loading HB font.");
|
||||
}
|
||||
|
||||
if (p_outline_size != 0) {
|
||||
size_cache_outline[id] = fds;
|
||||
} else {
|
||||
size_cache[id] = fds;
|
||||
}
|
||||
|
||||
// Write variations.
|
||||
if (fds->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
FT_MM_Var *amaster;
|
||||
|
||||
FT_Get_MM_Var(fds->face, &amaster);
|
||||
|
||||
Vector<hb_variation_t> hb_vars;
|
||||
Vector<FT_Fixed> coords;
|
||||
coords.resize(amaster->num_axis);
|
||||
|
||||
FT_Get_Var_Design_Coordinates(fds->face, coords.size(), coords.ptrw());
|
||||
|
||||
for (FT_UInt i = 0; i < amaster->num_axis; i++) {
|
||||
hb_variation_t var;
|
||||
|
||||
// Reset to default.
|
||||
var.tag = amaster->axis[i].tag;
|
||||
var.value = (double)amaster->axis[i].def / 65536.f;
|
||||
coords.write[i] = amaster->axis[i].def;
|
||||
|
||||
if (variations.has(var.tag)) {
|
||||
var.value = variations[var.tag];
|
||||
coords.write[i] = CLAMP(variations[var.tag] * 65536.f, amaster->axis[i].minimum, amaster->axis[i].maximum);
|
||||
}
|
||||
|
||||
hb_vars.push_back(var);
|
||||
}
|
||||
|
||||
FT_Set_Var_Design_Coordinates(fds->face, coords.size(), coords.ptrw());
|
||||
hb_font_set_variations(fds->hb_handle, hb_vars.empty() ? nullptr : &hb_vars[0], hb_vars.size());
|
||||
|
||||
FT_Done_MM_Var(library, amaster);
|
||||
}
|
||||
}
|
||||
return fds;
|
||||
}
|
||||
|
||||
Dictionary DynamicFontDataAdvanced::get_variation_list() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size);
|
||||
if (fds == nullptr) {
|
||||
return Dictionary();
|
||||
}
|
||||
|
||||
return fds;
|
||||
Dictionary ret;
|
||||
// Read variations.
|
||||
if (fds->face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
FT_MM_Var *amaster;
|
||||
|
||||
FT_Get_MM_Var(fds->face, &amaster);
|
||||
|
||||
for (FT_UInt i = 0; i < amaster->num_axis; i++) {
|
||||
ret[(int32_t)amaster->axis[i].tag] = Vector3i(amaster->axis[i].minimum / 65536, amaster->axis[i].maximum / 65536, amaster->axis[i].def / 65536);
|
||||
}
|
||||
|
||||
FT_Done_MM_Var(library, amaster);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DynamicFontDataAdvanced::set_variation(const String &p_name, double p_value) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
int32_t tag = TS->name_to_tag(p_name);
|
||||
if (!variations.has(tag) || (variations[tag] != p_value)) {
|
||||
variations[tag] = p_value;
|
||||
clear_cache();
|
||||
}
|
||||
}
|
||||
|
||||
double DynamicFontDataAdvanced::get_variation(const String &p_name) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
int32_t tag = TS->name_to_tag(p_name);
|
||||
if (!variations.has(tag)) {
|
||||
return 0.f;
|
||||
}
|
||||
return variations[tag];
|
||||
}
|
||||
|
||||
Dictionary DynamicFontDataAdvanced::get_feature_list() const {
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ private:
|
|||
String font_path;
|
||||
Vector<uint8_t> font_mem_cache;
|
||||
|
||||
Map<int32_t, double> variations;
|
||||
|
||||
float rect_margin = 1.f;
|
||||
int base_size = 16;
|
||||
float oversampling = 1.f;
|
||||
|
|
@ -146,6 +148,10 @@ public:
|
|||
virtual float get_descent(int p_size) const override;
|
||||
|
||||
virtual Dictionary get_feature_list() const override;
|
||||
virtual Dictionary get_variation_list() const override;
|
||||
|
||||
virtual void set_variation(const String &p_name, double p_value) override;
|
||||
virtual double get_variation(const String &p_name) const override;
|
||||
|
||||
virtual float get_underline_position(int p_size) const override;
|
||||
virtual float get_underline_thickness(int p_size) const override;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ struct FontDataAdvanced {
|
|||
virtual float get_descent(int p_size) const = 0;
|
||||
|
||||
virtual Dictionary get_feature_list() const { return Dictionary(); };
|
||||
virtual Dictionary get_variation_list() const { return Dictionary(); };
|
||||
|
||||
virtual void set_variation(const String &p_name, double p_value){};
|
||||
virtual double get_variation(const String &p_name) const { return 0; };
|
||||
|
||||
virtual float get_underline_position(int p_size) const = 0;
|
||||
virtual float get_underline_thickness(int p_size) const = 0;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ _FORCE_INLINE_ bool is_linebreak(char32_t p_char) {
|
|||
/*************************************************************************/
|
||||
|
||||
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
|
||||
uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA;
|
||||
uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE;
|
||||
|
||||
bool TextServerAdvanced::has_feature(Feature p_feature) {
|
||||
return (interface_features & p_feature) == p_feature;
|
||||
|
|
@ -622,6 +622,27 @@ bool TextServerAdvanced::font_get_antialiased(RID p_font) const {
|
|||
return fd->get_antialiased();
|
||||
}
|
||||
|
||||
Dictionary TextServerAdvanced::font_get_variation_list(RID p_font) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
const FontDataAdvanced *fd = font_owner.getornull(p_font);
|
||||
ERR_FAIL_COND_V(!fd, Dictionary());
|
||||
return fd->get_variation_list();
|
||||
}
|
||||
|
||||
void TextServerAdvanced::font_set_variation(RID p_font, const String &p_name, double p_value) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
FontDataAdvanced *fd = font_owner.getornull(p_font);
|
||||
ERR_FAIL_COND(!fd);
|
||||
fd->set_variation(p_name, p_value);
|
||||
}
|
||||
|
||||
double TextServerAdvanced::font_get_variation(RID p_font, const String &p_name) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
const FontDataAdvanced *fd = font_owner.getornull(p_font);
|
||||
ERR_FAIL_COND_V(!fd, 0);
|
||||
return fd->get_variation(p_name);
|
||||
}
|
||||
|
||||
void TextServerAdvanced::font_set_distance_field_hint(RID p_font, bool p_distance_field) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
FontDataAdvanced *fd = font_owner.getornull(p_font);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ public:
|
|||
virtual bool font_get_antialiased(RID p_font) const override;
|
||||
|
||||
virtual Dictionary font_get_feature_list(RID p_font) const override;
|
||||
virtual Dictionary font_get_variation_list(RID p_font) const override;
|
||||
|
||||
virtual void font_set_variation(RID p_font, const String &p_name, double p_value) override;
|
||||
virtual double font_get_variation(RID p_font, const String &p_name) const override;
|
||||
|
||||
virtual void font_set_hinting(RID p_font, Hinting p_hinting) override;
|
||||
virtual Hinting font_get_hinting(RID p_font) const override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue