Add sub-pixel glyph positioning support.
This commit is contained in:
parent
d3a6b6daaa
commit
29199579f7
27 changed files with 496 additions and 84 deletions
|
@ -600,5 +600,8 @@
|
|||
<member name="style_name" type="String" setter="set_font_style_name" getter="get_font_style_name" default="""">
|
||||
Font style name.
|
||||
</member>
|
||||
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
|
||||
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
||||
|
|
|
@ -564,6 +564,15 @@
|
|||
<member name="gui/theme/custom_font" type="String" setter="" getter="" default="""">
|
||||
Path to a custom [Font] resource to use as default for all GUI elements of the project.
|
||||
</member>
|
||||
<member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true">
|
||||
If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontData.antialiased].
|
||||
</member>
|
||||
<member name="gui/theme/default_font_hinting" type="int" setter="" getter="" default="1">
|
||||
Default font hinting mode. See [member FontData.hinting].
|
||||
</member>
|
||||
<member name="gui/theme/default_font_subpixel_positioning" type="int" setter="" getter="" default="1">
|
||||
Default font glyph sub-pixel positioning mode. See [member FontData.subpixel_positioning].
|
||||
</member>
|
||||
<member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0">
|
||||
</member>
|
||||
<member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000">
|
||||
|
|
|
@ -328,6 +328,13 @@
|
|||
Returns font style name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="font_get_subpixel_positioning" qualifiers="const">
|
||||
<return type="int" enum="TextServer.SubpixelPositioning" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
<description>
|
||||
Returns font sub-pixel glyph positioning mode.
|
||||
</description>
|
||||
</method>
|
||||
<method name="font_get_supported_chars" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
|
@ -613,7 +620,7 @@
|
|||
<method name="font_set_hinting">
|
||||
<return type="void" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
<argument index="1" name="_hinting" type="int" enum="TextServer.Hinting" />
|
||||
<argument index="1" name="hinting" type="int" enum="TextServer.Hinting" />
|
||||
<description>
|
||||
Sets font hinting mode. Used by dynamic fonts only.
|
||||
</description>
|
||||
|
@ -727,7 +734,15 @@
|
|||
<argument index="0" name="font_rid" type="RID" />
|
||||
<argument index="1" name="name" type="String" />
|
||||
<description>
|
||||
Set the font style name.
|
||||
Sets the font style name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="font_set_subpixel_positioning">
|
||||
<return type="void" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
<argument index="1" name="subpixel_positioning" type="int" enum="TextServer.SubpixelPositioning" />
|
||||
<description>
|
||||
Sets font sub-pixel glyph positioning mode.
|
||||
</description>
|
||||
</method>
|
||||
<method name="font_set_texture_image">
|
||||
|
@ -1493,6 +1508,21 @@
|
|||
<constant name="HINTING_NORMAL" value="2" enum="Hinting">
|
||||
Use the default font hinting mode (crisper but less smooth).
|
||||
</constant>
|
||||
<constant name="SUBPIXEL_POSITIONING_DISABLED" value="0" enum="SubpixelPositioning">
|
||||
Glyph horizontal position is rounded to the whole pixel size, each glyph is rasterized once.
|
||||
</constant>
|
||||
<constant name="SUBPIXEL_POSITIONING_AUTO" value="1" enum="SubpixelPositioning">
|
||||
Glyph horizontal position is rounded based on font size.
|
||||
- To one quarter of the pixel size if font size is smaller or equal to [code]16[/code].
|
||||
- To one half of the pixel size if font size is smaller or equal to [code]20[/code].
|
||||
- To the whole pixel size for larger fonts.
|
||||
</constant>
|
||||
<constant name="SUBPIXEL_POSITIONING_ONE_HALF" value="2" enum="SubpixelPositioning">
|
||||
Glyph horizontal position is rounded to one half of the pixel size, each glyph is rasterized up to two times.
|
||||
</constant>
|
||||
<constant name="SUBPIXEL_POSITIONING_ONE_QUARTER" value="3" enum="SubpixelPositioning">
|
||||
Glyph horizontal position is rounded to one quarter of the pixel size, each glyph is rasterized up to four times.
|
||||
</constant>
|
||||
<constant name="FEATURE_BIDI_LAYOUT" value="1" enum="Feature">
|
||||
TextServer supports bidirectional layouts.
|
||||
</constant>
|
||||
|
|
|
@ -328,6 +328,13 @@
|
|||
Returns font style name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_font_get_subpixel_positioning" qualifiers="virtual const">
|
||||
<return type="int" enum="TextServer.SubpixelPositioning" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
<description>
|
||||
Returns font sub-pixel glyph positioning mode.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_font_get_supported_chars" qualifiers="virtual const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
|
@ -738,6 +745,14 @@
|
|||
Sets the font style name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_font_set_subpixel_positioning" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
<argument index="1" name="subpixel_positioning" type="int" enum="TextServer.SubpixelPositioning" />
|
||||
<description>
|
||||
Sets font sub-pixel glyph positioning mode.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_font_set_texture_image" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="font_rid" type="RID" />
|
||||
|
|
|
@ -1576,10 +1576,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
|
|||
int decimals = 2;
|
||||
bool step_found = false;
|
||||
|
||||
const int period_width = font->get_char_size('.', 0, font_size).width;
|
||||
int max_digit_width = font->get_char_size('0', 0, font_size).width;
|
||||
const float period_width = font->get_char_size('.', 0, font_size).width;
|
||||
float max_digit_width = font->get_char_size('0', 0, font_size).width;
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
const int digit_width = font->get_char_size('0' + i, 0, font_size).width;
|
||||
const float digit_width = font->get_char_size('0' + i, 0, font_size).width;
|
||||
max_digit_width = MAX(digit_width, max_digit_width);
|
||||
}
|
||||
const int max_sc = int(Math::ceil(zoomw / scale));
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
|
||||
MAKE_FALLBACKS(m_name);
|
||||
|
||||
Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint) {
|
||||
Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning) {
|
||||
Ref<FontData> font;
|
||||
font.instantiate();
|
||||
|
||||
|
@ -155,11 +155,12 @@ Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hintin
|
|||
font->set_antialiased(p_aa);
|
||||
font->set_hinting(p_hinting);
|
||||
font->set_force_autohinter(p_autohint);
|
||||
font->set_subpixel_positioning(p_font_subpixel_positioning);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint) {
|
||||
Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning) {
|
||||
Ref<FontData> font;
|
||||
font.instantiate();
|
||||
|
||||
|
@ -167,6 +168,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
|
|||
font->set_antialiased(p_aa);
|
||||
font->set_hinting(p_hinting);
|
||||
font->set_force_autohinter(p_autohint);
|
||||
font->set_subpixel_positioning(p_font_subpixel_positioning);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -178,6 +180,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
|
|||
|
||||
bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased");
|
||||
int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting");
|
||||
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning");
|
||||
|
||||
TextServer::Hinting font_hinting;
|
||||
switch (font_hinting_setting) {
|
||||
|
@ -208,7 +211,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
|
|||
String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font");
|
||||
Ref<FontData> CustomFont;
|
||||
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
|
||||
CustomFont = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true);
|
||||
CustomFont = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
} else {
|
||||
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
|
||||
}
|
||||
|
@ -218,7 +221,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
|
|||
String custom_font_path_bold = EditorSettings::get_singleton()->get("interface/editor/main_font_bold");
|
||||
Ref<FontData> CustomFontBold;
|
||||
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
|
||||
CustomFontBold = load_cached_external_font(custom_font_path_bold, font_hinting, font_antialiased, true);
|
||||
CustomFontBold = load_cached_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
} else {
|
||||
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
|
||||
}
|
||||
|
@ -228,7 +231,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
|
|||
String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
|
||||
Ref<FontData> CustomFontSource;
|
||||
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
|
||||
CustomFontSource = load_cached_external_font(custom_font_path_source, font_hinting, font_antialiased, true);
|
||||
CustomFontSource = load_cached_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
} else {
|
||||
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
|
||||
}
|
||||
|
@ -237,39 +240,39 @@ void editor_register_fonts(Ref<Theme> p_theme) {
|
|||
|
||||
/* Noto Sans */
|
||||
|
||||
Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> DefaultFontBold = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontArabic = load_cached_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontArabicBold = load_cached_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontBengali = load_cached_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontBengaliBold = load_cached_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontDevanagari = load_cached_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontDevanagariBold = load_cached_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontGeorgian = load_cached_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontGeorgianBold = load_cached_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontHebrew = load_cached_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontHebrewBold = load_cached_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontMalayalam = load_cached_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontMalayalamBold = load_cached_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontOriya = load_cached_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontOriyaBold = load_cached_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontSinhala = load_cached_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontSinhalaBold = load_cached_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontTamil = load_cached_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontTamilBold = load_cached_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontTelugu = load_cached_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontTeluguBold = load_cached_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontThai = load_cached_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontThaiBold = load_cached_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> DefaultFontBold = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontArabic = load_cached_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontArabicBold = load_cached_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontBengali = load_cached_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontBengaliBold = load_cached_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontDevanagari = load_cached_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontDevanagariBold = load_cached_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontGeorgian = load_cached_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontGeorgianBold = load_cached_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontHebrew = load_cached_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontHebrewBold = load_cached_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontMalayalam = load_cached_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontMalayalamBold = load_cached_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontOriya = load_cached_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontOriyaBold = load_cached_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontSinhala = load_cached_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontSinhalaBold = load_cached_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontTamil = load_cached_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontTamilBold = load_cached_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontTelugu = load_cached_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontTeluguBold = load_cached_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontThai = load_cached_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontThaiBold = load_cached_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
|
||||
/* Droid Sans */
|
||||
|
||||
Ref<FontData> FontFallback = load_cached_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontJapanese = load_cached_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> FontFallback = load_cached_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Ref<FontData> FontJapanese = load_cached_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
|
||||
/* Hack */
|
||||
|
||||
Ref<FontData> dfmono = load_cached_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true);
|
||||
Ref<FontData> dfmono = load_cached_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
|
||||
Dictionary opentype_features;
|
||||
opentype_features["calt"] = 0;
|
||||
dfmono->set_opentype_feature_overrides(opentype_features); // Disable contextual alternates (coding ligatures).
|
||||
|
|
|
@ -415,6 +415,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||
#else
|
||||
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (Light),None,Light,Normal")
|
||||
#endif
|
||||
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_subpixel_positioning", 1, "Disabled,Auto,One half of a pixel,One quarter of a pixel")
|
||||
|
||||
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf")
|
||||
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf")
|
||||
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/code_font", "", "*.ttf,*.otf")
|
||||
|
|
|
@ -480,6 +480,10 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
|
|||
if (font_preview->get_data_count() > 0) {
|
||||
font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
|
||||
}
|
||||
} else if (p_edited_property == "subpixel_positioning") {
|
||||
if (font_preview->get_data_count() > 0) {
|
||||
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
|
||||
}
|
||||
} else if (p_edited_property == "oversampling") {
|
||||
if (font_preview->get_data_count() > 0) {
|
||||
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
|
||||
|
@ -915,6 +919,7 @@ void DynamicFontImportSettings::_re_import() {
|
|||
main_settings["msdf_size"] = import_settings_data->get("msdf_size");
|
||||
main_settings["force_autohinter"] = import_settings_data->get("force_autohinter");
|
||||
main_settings["hinting"] = import_settings_data->get("hinting");
|
||||
main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning");
|
||||
main_settings["oversampling"] = import_settings_data->get("oversampling");
|
||||
main_settings["compress"] = import_settings_data->get("compress");
|
||||
|
||||
|
@ -1265,6 +1270,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
|
|||
font_preview->get_data(0)->set_msdf_size(import_settings_data->get("msdf_size"));
|
||||
font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
|
||||
font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
|
||||
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
|
||||
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
|
||||
}
|
||||
font_preview_label->add_theme_font_override("font", font_preview);
|
||||
|
@ -1323,6 +1329,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
|
|||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48));
|
||||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
|
||||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
|
||||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
|
||||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
|
||||
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));
|
||||
|
||||
|
|
|
@ -76,6 +76,9 @@ bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, co
|
|||
if (p_option == "oversampling" && bool(p_options["multichannel_signed_distance_field"])) {
|
||||
return false;
|
||||
}
|
||||
if (p_option == "subpixel_positioning" && bool(p_options["multichannel_signed_distance_field"])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -104,6 +107,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
|
|||
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
|
||||
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
|
||||
|
@ -179,6 +183,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
|
|||
|
||||
bool autohinter = p_options["force_autohinter"];
|
||||
int hinting = p_options["hinting"];
|
||||
int subpixel_positioning = p_options["subpixel_positioning"];
|
||||
real_t oversampling = p_options["oversampling"];
|
||||
|
||||
// Load base font data.
|
||||
|
@ -195,6 +200,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
|
|||
font->set_opentype_feature_overrides(ot_ov);
|
||||
font->set_fixed_size(0);
|
||||
font->set_force_autohinter(autohinter);
|
||||
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
|
||||
font->set_hinting((TextServer::Hinting)hinting);
|
||||
font->set_oversampling(oversampling);
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
|
|||
font->set_antialiased(false);
|
||||
font->set_multichannel_signed_distance_field(false);
|
||||
font->set_fixed_size(base_size);
|
||||
font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED);
|
||||
font->set_force_autohinter(false);
|
||||
font->set_hinting(TextServer::HINTING_NONE);
|
||||
font->set_oversampling(1.0f);
|
||||
|
|
|
@ -1097,12 +1097,14 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
|
|||
_FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
|
||||
ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false);
|
||||
|
||||
int32_t glyph_index = p_glyph & 0xFFFFFF; // Remove subpixel shifts.
|
||||
|
||||
FontDataForSizeAdvanced *fd = p_font_data->cache[p_size];
|
||||
if (fd->glyph_map.has(p_glyph)) {
|
||||
return fd->glyph_map[p_glyph].found;
|
||||
}
|
||||
|
||||
if (p_glyph == 0) { // Non graphical or invalid glyph, do not render.
|
||||
if (glyph_index == 0) { // Non graphical or invalid glyph, do not render.
|
||||
fd->glyph_map[p_glyph] = FontGlyph();
|
||||
return true;
|
||||
}
|
||||
|
@ -1134,15 +1136,25 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
|
|||
}
|
||||
|
||||
FT_Fixed v, h;
|
||||
FT_Get_Advance(fd->face, p_glyph, flags, &h);
|
||||
FT_Get_Advance(fd->face, p_glyph, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
|
||||
FT_Get_Advance(fd->face, glyph_index, flags, &h);
|
||||
FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
|
||||
|
||||
int error = FT_Load_Glyph(fd->face, p_glyph, flags);
|
||||
int error = FT_Load_Glyph(fd->face, glyph_index, flags);
|
||||
if (error) {
|
||||
fd->glyph_map[p_glyph] = FontGlyph();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p_font_data->msdf) {
|
||||
if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
FT_Pos xshift = (int)((p_glyph >> 27) & 3) << 4;
|
||||
FT_Outline_Translate(&fd->face->glyph->outline, xshift, 0);
|
||||
} else if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
FT_Pos xshift = (int)((p_glyph >> 27) & 3) << 5;
|
||||
FT_Outline_Translate(&fd->face->glyph->outline, xshift, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!outline) {
|
||||
if (!p_font_data->msdf) {
|
||||
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
|
||||
|
@ -1844,6 +1856,24 @@ TextServer::Hinting TextServerAdvanced::font_get_hinting(RID p_font_rid) const {
|
|||
return fd->hinting;
|
||||
}
|
||||
|
||||
void TextServerAdvanced::font_set_subpixel_positioning(RID p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
|
||||
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND(!fd);
|
||||
|
||||
MutexLock lock(fd->mutex);
|
||||
if (fd->subpixel_positioning != p_subpixel) {
|
||||
fd->subpixel_positioning = p_subpixel;
|
||||
}
|
||||
}
|
||||
|
||||
TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positioning(RID p_font_rid) const {
|
||||
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED);
|
||||
|
||||
MutexLock lock(fd->mutex);
|
||||
return fd->subpixel_positioning;
|
||||
}
|
||||
|
||||
void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
|
||||
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND(!fd);
|
||||
|
@ -2261,6 +2291,8 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, i
|
|||
|
||||
if (fd->msdf) {
|
||||
return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
return gl[p_glyph].advance.round();
|
||||
} else {
|
||||
return gl[p_glyph].advance;
|
||||
}
|
||||
|
@ -2628,12 +2660,25 @@ void TextServerAdvanced::font_render_range(RID p_font_rid, const Vector2i &p_siz
|
|||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
for (char32_t i = p_start; i <= p_end; i++) {
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
int32_t idx = FT_Get_Char_Index(fd->cache[size]->face, i);
|
||||
if (fd->cache[size]->face) {
|
||||
_ensure_glyph(fd, size, FT_Get_Char_Index(fd->cache[size]->face, i));
|
||||
continue;
|
||||
if (fd->msdf) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
} else {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
} else {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_ensure_glyph(fd, size, (int32_t)i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2644,7 +2689,26 @@ void TextServerAdvanced::font_render_glyph(RID p_font_rid, const Vector2i &p_siz
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size_outline(fd, p_size);
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
ERR_FAIL_COND(!_ensure_glyph(fd, size, p_index));
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
int32_t idx = p_index;
|
||||
if (fd->cache[size]->face) {
|
||||
if (fd->msdf) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
} else {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
} else {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
|
||||
|
@ -2654,11 +2718,26 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size(fd, p_size);
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
if (!_ensure_glyph(fd, size, p_index)) {
|
||||
|
||||
int32_t index = p_index;
|
||||
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
if (!fd->msdf && fd->cache[size]->face) {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
|
||||
index = index | (xshift << 27);
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(2 * (p_pos.x + 0.25)) - 2 * Math::floor(p_pos.x + 0.25));
|
||||
index = index | (xshift << 27);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_ensure_glyph(fd, size, index)) {
|
||||
return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
|
||||
}
|
||||
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[index];
|
||||
if (gl.found) {
|
||||
ERR_FAIL_COND(gl.texture_idx < -1 || gl.texture_idx >= fd->cache[size]->textures.size());
|
||||
|
||||
|
@ -2677,7 +2756,15 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
|
|||
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
|
||||
} else {
|
||||
Point2 cpos = p_pos.floor();
|
||||
Point2 cpos = p_pos;
|
||||
cpos.y = Math::floor(cpos.y);
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.125));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.25));
|
||||
} else {
|
||||
cpos.x = Math::floor(cpos.x);
|
||||
}
|
||||
cpos += gl.rect.position;
|
||||
Size2 csize = gl.rect.size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
|
||||
|
@ -2694,11 +2781,26 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size_outline(fd, Vector2i(p_size, p_outline_size));
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
if (!_ensure_glyph(fd, size, p_index)) {
|
||||
|
||||
int32_t index = p_index;
|
||||
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
if (!fd->msdf && fd->cache[size]->face) {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
|
||||
index = index | (xshift << 27);
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(2 * (p_pos.x + 0.25)) - 2 * Math::floor(p_pos.x + 0.25));
|
||||
index = index | (xshift << 27);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_ensure_glyph(fd, size, index)) {
|
||||
return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
|
||||
}
|
||||
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[index];
|
||||
if (gl.found) {
|
||||
ERR_FAIL_COND(gl.texture_idx < -1 || gl.texture_idx >= fd->cache[size]->textures.size());
|
||||
|
||||
|
@ -2717,7 +2819,15 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
|
|||
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
|
||||
} else {
|
||||
Point2 cpos = p_pos.floor();
|
||||
Point2 cpos = p_pos;
|
||||
cpos.y = Math::floor(cpos.y);
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.125));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.25));
|
||||
} else {
|
||||
cpos.x = Math::floor(cpos.x);
|
||||
}
|
||||
cpos += gl.rect.position;
|
||||
Size2 csize = gl.rect.size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
|
||||
|
@ -3559,7 +3669,7 @@ float TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, float p_width,
|
|||
}
|
||||
justification_width = sd->width_trimmed;
|
||||
} else {
|
||||
return sd->width;
|
||||
return Math::ceil(sd->width);
|
||||
}
|
||||
} else {
|
||||
justification_width = sd->width;
|
||||
|
@ -3662,7 +3772,7 @@ float TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, float p_width,
|
|||
sd->width = justification_width;
|
||||
}
|
||||
|
||||
return justification_width;
|
||||
return Math::ceil(justification_width);
|
||||
}
|
||||
|
||||
float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
|
||||
|
@ -4281,6 +4391,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
|
|||
|
||||
Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size) {
|
||||
hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size);
|
||||
bool subpos = (font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_AUTO && p_font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
|
||||
ERR_FAIL_COND_V(hb_font == nullptr, Glyph());
|
||||
|
||||
hb_buffer_clear_contents(p_sd->hb_buffer);
|
||||
|
@ -4308,14 +4419,22 @@ Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char
|
|||
if (glyph_count > 0) {
|
||||
float scale = font_get_scale(p_font, p_font_size);
|
||||
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale));
|
||||
if (subpos) {
|
||||
gl.advance = glyph_pos[0].x_advance / (64.0 / scale);
|
||||
} else {
|
||||
gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale));
|
||||
}
|
||||
} else {
|
||||
gl.advance = -Math::round(glyph_pos[0].y_advance / (64.0 / scale));
|
||||
}
|
||||
gl.count = 1;
|
||||
|
||||
gl.index = glyph_info[0].codepoint;
|
||||
gl.x_off = Math::round(glyph_pos[0].x_offset / (64.0 / scale));
|
||||
if (subpos) {
|
||||
gl.x_off = glyph_pos[0].x_offset / (64.0 / scale);
|
||||
} else {
|
||||
gl.x_off = Math::round(glyph_pos[0].x_offset / (64.0 / scale));
|
||||
}
|
||||
gl.y_off = -Math::round(glyph_pos[0].y_offset / (64.0 / scale));
|
||||
|
||||
if ((glyph_info[0].codepoint != 0) || !u_isgraph(p_char)) {
|
||||
|
@ -4380,6 +4499,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
|
|||
float scale = font_get_scale(f, fs);
|
||||
float sp_sp = font_get_spacing(f, fs, SPACING_SPACE);
|
||||
float sp_gl = font_get_spacing(f, fs, SPACING_GLYPH);
|
||||
bool subpos = (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
|
||||
ERR_FAIL_COND(hb_font == nullptr);
|
||||
|
||||
hb_buffer_clear_contents(p_sd->hb_buffer);
|
||||
|
@ -4456,11 +4576,19 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
|
|||
gl.index = glyph_info[i].codepoint;
|
||||
if (gl.index != 0) {
|
||||
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
|
||||
if (subpos) {
|
||||
gl.advance = glyph_pos[i].x_advance / (64.0 / scale);
|
||||
} else {
|
||||
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
|
||||
}
|
||||
} else {
|
||||
gl.advance = -Math::round(glyph_pos[i].y_advance / (64.0 / scale));
|
||||
}
|
||||
gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / scale));
|
||||
if (subpos) {
|
||||
gl.x_off = glyph_pos[i].x_offset / (64.0 / scale);
|
||||
} else {
|
||||
gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / scale));
|
||||
}
|
||||
gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale));
|
||||
}
|
||||
if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
|
||||
|
@ -4797,9 +4925,9 @@ Size2 TextServerAdvanced::shaped_text_get_size(RID p_shaped) const {
|
|||
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
|
||||
}
|
||||
if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) {
|
||||
return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent);
|
||||
return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent).ceil();
|
||||
} else {
|
||||
return Size2(sd->ascent + sd->descent, (sd->text_trimmed ? sd->width_trimmed : sd->width));
|
||||
return Size2(sd->ascent + sd->descent, (sd->text_trimmed ? sd->width_trimmed : sd->width)).ceil();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4833,7 +4961,7 @@ float TextServerAdvanced::shaped_text_get_width(RID p_shaped) const {
|
|||
if (!sd->valid) {
|
||||
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
|
||||
}
|
||||
return (sd->text_trimmed ? sd->width_trimmed : sd->width);
|
||||
return Math::ceil(sd->text_trimmed ? sd->width_trimmed : sd->width);
|
||||
}
|
||||
|
||||
float TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) const {
|
||||
|
|
|
@ -174,6 +174,7 @@ class TextServerAdvanced : public TextServer {
|
|||
int fixed_size = 0;
|
||||
bool force_autohinter = false;
|
||||
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
|
||||
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
|
||||
Dictionary variation_coordinates;
|
||||
float oversampling = 0.f;
|
||||
|
||||
|
@ -379,6 +380,9 @@ public:
|
|||
virtual void font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) override;
|
||||
virtual TextServer::Hinting font_get_hinting(RID p_font_rid) const override;
|
||||
|
||||
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
|
||||
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
|
||||
|
||||
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
|
||||
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
|
||||
|
||||
|
|
|
@ -548,12 +548,14 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
|
|||
_FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
|
||||
ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false);
|
||||
|
||||
int32_t glyph_index = p_glyph & 0xFFFFFF; // Remove subpixel shifts.
|
||||
|
||||
FontDataForSizeFallback *fd = p_font_data->cache[p_size];
|
||||
if (fd->glyph_map.has(p_glyph)) {
|
||||
return fd->glyph_map[p_glyph].found;
|
||||
}
|
||||
|
||||
if (p_glyph == 0) { // Non graphical or invalid glyph, do not render.
|
||||
if (glyph_index == 0) { // Non graphical or invalid glyph, do not render.
|
||||
fd->glyph_map[p_glyph] = FontGlyph();
|
||||
return true;
|
||||
}
|
||||
|
@ -584,8 +586,6 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
|
|||
flags |= FT_LOAD_COLOR;
|
||||
}
|
||||
|
||||
int32_t glyph_index = FT_Get_Char_Index(fd->face, p_glyph);
|
||||
|
||||
FT_Fixed v, h;
|
||||
FT_Get_Advance(fd->face, glyph_index, flags, &h);
|
||||
FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
|
||||
|
@ -596,6 +596,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!p_font_data->msdf) {
|
||||
if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
FT_Pos xshift = (int)((p_glyph >> 27) & 3) << 4;
|
||||
FT_Outline_Translate(&fd->face->glyph->outline, xshift, 0);
|
||||
} else if ((p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (p_font_data->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && p_size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
FT_Pos xshift = (int)((p_glyph >> 27) & 3) << 5;
|
||||
FT_Outline_Translate(&fd->face->glyph->outline, xshift, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!outline) {
|
||||
if (!p_font_data->msdf) {
|
||||
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
|
||||
|
@ -1016,6 +1026,24 @@ TextServer::Hinting TextServerFallback::font_get_hinting(RID p_font_rid) const {
|
|||
return fd->hinting;
|
||||
}
|
||||
|
||||
void TextServerFallback::font_set_subpixel_positioning(RID p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
|
||||
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND(!fd);
|
||||
|
||||
MutexLock lock(fd->mutex);
|
||||
if (fd->subpixel_positioning != p_subpixel) {
|
||||
fd->subpixel_positioning = p_subpixel;
|
||||
}
|
||||
}
|
||||
|
||||
TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positioning(RID p_font_rid) const {
|
||||
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED);
|
||||
|
||||
MutexLock lock(fd->mutex);
|
||||
return fd->subpixel_positioning;
|
||||
}
|
||||
|
||||
void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
|
||||
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
|
||||
ERR_FAIL_COND(!fd);
|
||||
|
@ -1433,6 +1461,8 @@ Vector2 TextServerFallback::font_get_glyph_advance(RID p_font_rid, int p_size, i
|
|||
|
||||
if (fd->msdf) {
|
||||
return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
return gl[p_glyph].advance.round();
|
||||
} else {
|
||||
return gl[p_glyph].advance;
|
||||
}
|
||||
|
@ -1781,7 +1811,26 @@ void TextServerFallback::font_render_range(RID p_font_rid, const Vector2i &p_siz
|
|||
Vector2i size = _get_size_outline(fd, p_size);
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
for (char32_t i = p_start; i <= p_end; i++) {
|
||||
_ensure_glyph(fd, size, (int32_t)i);
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
int32_t idx = i;
|
||||
if (fd->cache[size]->face) {
|
||||
if (fd->msdf) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
} else {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
} else {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1792,7 +1841,26 @@ void TextServerFallback::font_render_glyph(RID p_font_rid, const Vector2i &p_siz
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size_outline(fd, p_size);
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
ERR_FAIL_COND(!_ensure_glyph(fd, size, p_index));
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
int32_t idx = p_index;
|
||||
if (fd->cache[size]->face) {
|
||||
if (fd->msdf) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
} else {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
|
||||
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
|
||||
} else {
|
||||
_ensure_glyph(fd, size, (int32_t)idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
|
||||
|
@ -1802,11 +1870,26 @@ void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size(fd, p_size);
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
if (!_ensure_glyph(fd, size, p_index)) {
|
||||
|
||||
int32_t index = p_index;
|
||||
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
if (!fd->msdf && fd->cache[size]->face) {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
|
||||
index = index | (xshift << 27);
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(2 * (p_pos.x + 0.25)) - 2 * Math::floor(p_pos.x + 0.25));
|
||||
index = index | (xshift << 27);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_ensure_glyph(fd, size, index)) {
|
||||
return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
|
||||
}
|
||||
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[index];
|
||||
if (gl.found) {
|
||||
ERR_FAIL_COND(gl.texture_idx < -1 || gl.texture_idx >= fd->cache[size]->textures.size());
|
||||
|
||||
|
@ -1825,7 +1908,15 @@ void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
|
|||
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
|
||||
} else {
|
||||
Point2 cpos = p_pos.floor();
|
||||
Point2 cpos = p_pos;
|
||||
cpos.y = Math::floor(cpos.y);
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.125));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.25));
|
||||
} else {
|
||||
cpos.x = Math::floor(cpos.x);
|
||||
}
|
||||
cpos += gl.rect.position;
|
||||
Size2 csize = gl.rect.size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
|
||||
|
@ -1842,11 +1933,26 @@ void TextServerFallback::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
|
|||
MutexLock lock(fd->mutex);
|
||||
Vector2i size = _get_size_outline(fd, Vector2i(p_size, p_outline_size));
|
||||
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
|
||||
if (!_ensure_glyph(fd, size, p_index)) {
|
||||
|
||||
int32_t index = p_index;
|
||||
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
if (!fd->msdf && fd->cache[size]->face) {
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
|
||||
index = index | (xshift << 27);
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
int xshift = (int)(Math::floor(2 * (p_pos.x + 0.25)) - 2 * Math::floor(p_pos.x + 0.25));
|
||||
index = index | (xshift << 27);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_ensure_glyph(fd, size, index)) {
|
||||
return; // Invalid or non-graphical glyph, do not display errors, nothing to draw.
|
||||
}
|
||||
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[p_index];
|
||||
const FontGlyph &gl = fd->cache[size]->glyph_map[index];
|
||||
if (gl.found) {
|
||||
ERR_FAIL_COND(gl.texture_idx < -1 || gl.texture_idx >= fd->cache[size]->textures.size());
|
||||
|
||||
|
@ -1865,7 +1971,15 @@ void TextServerFallback::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
|
|||
Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
|
||||
} else {
|
||||
Point2 cpos = p_pos.floor();
|
||||
Point2 cpos = p_pos;
|
||||
cpos.y = Math::floor(cpos.y);
|
||||
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.125));
|
||||
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
|
||||
cpos.x = ((int)Math::floor(cpos.x + 0.25));
|
||||
} else {
|
||||
cpos.x = Math::floor(cpos.x);
|
||||
}
|
||||
cpos += gl.rect.position;
|
||||
Size2 csize = gl.rect.size;
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
|
||||
|
@ -2660,7 +2774,7 @@ float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width,
|
|||
end_pos = sd->overrun_trim_data.trim_pos;
|
||||
justification_width = sd->width_trimmed;
|
||||
} else {
|
||||
return sd->width;
|
||||
return Math::ceil(sd->width);
|
||||
}
|
||||
} else {
|
||||
justification_width = sd->width;
|
||||
|
@ -2720,7 +2834,7 @@ float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width,
|
|||
sd->width = justification_width;
|
||||
}
|
||||
|
||||
return justification_width;
|
||||
return Math::ceil(justification_width);
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
|
||||
|
@ -3109,6 +3223,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
|||
}
|
||||
|
||||
if (gl.font_rid.is_valid()) {
|
||||
bool subpos = (font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_AUTO && gl.font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
|
||||
if (sd->text[j - sd->start] != 0 && !is_linebreak(sd->text[j - sd->start])) {
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
gl.advance = Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x);
|
||||
|
@ -3143,6 +3258,9 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL && !subpos) {
|
||||
gl.advance = Math::round(gl.advance);
|
||||
}
|
||||
} else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) {
|
||||
// Glyph not found, replace with hex code box.
|
||||
if (sd->orientation == ORIENTATION_HORIZONTAL) {
|
||||
|
@ -3312,9 +3430,9 @@ Size2 TextServerFallback::shaped_text_get_size(RID p_shaped) const {
|
|||
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
|
||||
}
|
||||
if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) {
|
||||
return Size2(sd->width, sd->ascent + sd->descent);
|
||||
return Size2(sd->width, sd->ascent + sd->descent).ceil();
|
||||
} else {
|
||||
return Size2(sd->ascent + sd->descent, sd->width);
|
||||
return Size2(sd->ascent + sd->descent, sd->width).ceil();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3348,7 +3466,7 @@ float TextServerFallback::shaped_text_get_width(RID p_shaped) const {
|
|||
if (!sd->valid) {
|
||||
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
|
||||
}
|
||||
return sd->width;
|
||||
return Math::ceil(sd->width);
|
||||
}
|
||||
|
||||
float TextServerFallback::shaped_text_get_underline_position(RID p_shaped) const {
|
||||
|
|
|
@ -139,6 +139,7 @@ class TextServerFallback : public TextServer {
|
|||
int fixed_size = 0;
|
||||
bool force_autohinter = false;
|
||||
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
|
||||
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
|
||||
Dictionary variation_coordinates;
|
||||
float oversampling = 0.f;
|
||||
|
||||
|
@ -290,6 +291,9 @@ public:
|
|||
virtual void font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) override;
|
||||
virtual TextServer::Hinting font_get_hinting(RID p_font_rid) const override;
|
||||
|
||||
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
|
||||
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
|
||||
|
||||
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
|
||||
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void CodeEdit::_notification(int p_what) {
|
|||
if (line_length_guideline_columns.size() > 0) {
|
||||
const int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
|
||||
const int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
|
||||
const int char_size = Math::round(font->get_char_size('0', 0, font_size).width);
|
||||
const float char_size = font->get_char_size('0', 0, font_size).width;
|
||||
|
||||
for (int i = 0; i < line_length_guideline_columns.size(); i++) {
|
||||
const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll();
|
||||
|
|
|
@ -1606,7 +1606,7 @@ Size2 LineEdit::get_minimum_size() const {
|
|||
Size2 min_size;
|
||||
|
||||
// Minimum size of text.
|
||||
int em_space_size = font->get_char_size('M', 0, font_size).x;
|
||||
float em_space_size = font->get_char_size('M', 0, font_size).x;
|
||||
min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
|
||||
|
||||
if (expand_to_text_length) {
|
||||
|
|
|
@ -961,7 +961,7 @@ void TextEdit::_notification(int p_what) {
|
|||
|
||||
// Give visual indication of empty selected line.
|
||||
if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) {
|
||||
int char_w = font->get_char_size(' ', 0, font_size).width;
|
||||
float char_w = font->get_char_size(' ', 0, font_size).width;
|
||||
if (rtl) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), selection_color);
|
||||
} else {
|
||||
|
|
|
@ -1075,11 +1075,22 @@ void initialize_theme() {
|
|||
// Allow creating the default theme at a different scale to suit higher/lower base resolutions.
|
||||
float default_theme_scale = GLOBAL_DEF("gui/theme/default_theme_scale", 1.0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_theme_scale", PropertyInfo(Variant::FLOAT, "gui/theme/default_theme_scale", PROPERTY_HINT_RANGE, "0.5,8,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
String theme_path = GLOBAL_DEF_RST("gui/theme/custom", "");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", "");
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
|
||||
|
||||
Ref<Font> font;
|
||||
if (!font_path.is_empty()) {
|
||||
font = ResourceLoader::load(font_path);
|
||||
|
@ -1090,7 +1101,7 @@ void initialize_theme() {
|
|||
|
||||
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
|
||||
if (RenderingServer::get_singleton()) {
|
||||
make_default_theme(default_theme_scale, font);
|
||||
make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased);
|
||||
}
|
||||
|
||||
if (!theme_path.is_empty()) {
|
||||
|
|
|
@ -1019,7 +1019,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
|
|||
default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2);
|
||||
}
|
||||
|
||||
void make_default_theme(float p_scale, Ref<Font> p_font) {
|
||||
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa) {
|
||||
Ref<Theme> t;
|
||||
t.instantiate();
|
||||
|
||||
|
@ -1041,6 +1041,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font) {
|
|||
Ref<FontData> dynamic_font_data;
|
||||
dynamic_font_data.instantiate();
|
||||
dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
|
||||
dynamic_font_data->set_subpixel_positioning(p_subpixel);
|
||||
dynamic_font_data->set_hinting(p_hinting);
|
||||
dynamic_font_data->set_antialiased(p_aa);
|
||||
dynamic_font->add_data(dynamic_font_data);
|
||||
|
||||
default_font = dynamic_font;
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
const int default_font_size = 16;
|
||||
|
||||
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
|
||||
void make_default_theme(float p_scale, Ref<Font> p_font);
|
||||
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa);
|
||||
void clear_default_theme();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,6 +60,7 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
|
|||
TS->font_set_fixed_size(cache[p_cache_index], fixed_size);
|
||||
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
|
||||
TS->font_set_hinting(cache[p_cache_index], hinting);
|
||||
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
|
||||
TS->font_set_oversampling(cache[p_cache_index], oversampling);
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +102,9 @@ void FontData::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &FontData::set_hinting);
|
||||
ClassDB::bind_method(D_METHOD("get_hinting"), &FontData::get_hinting);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
|
||||
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
|
||||
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
|
||||
|
||||
|
@ -204,6 +208,7 @@ void FontData::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
|
||||
|
@ -430,6 +435,7 @@ void FontData::reset_state() {
|
|||
msdf = false;
|
||||
force_autohinter = false;
|
||||
hinting = TextServer::HINTING_LIGHT;
|
||||
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
|
||||
msdf_pixel_range = 14;
|
||||
msdf_size = 128;
|
||||
fixed_size = 0;
|
||||
|
@ -1364,6 +1370,21 @@ TextServer::Hinting FontData::get_hinting() const {
|
|||
return hinting;
|
||||
}
|
||||
|
||||
void FontData::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
|
||||
if (subpixel_positioning != p_subpixel) {
|
||||
subpixel_positioning = p_subpixel;
|
||||
for (int i = 0; i < cache.size(); i++) {
|
||||
_ensure_rid(i);
|
||||
TS->font_set_subpixel_positioning(cache[i], subpixel_positioning);
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
|
||||
return subpixel_positioning;
|
||||
}
|
||||
|
||||
void FontData::set_oversampling(real_t p_oversampling) {
|
||||
if (oversampling != p_oversampling) {
|
||||
oversampling = p_oversampling;
|
||||
|
|
|
@ -55,6 +55,7 @@ class FontData : public Resource {
|
|||
int fixed_size = 0;
|
||||
bool force_autohinter = false;
|
||||
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
|
||||
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
|
||||
real_t oversampling = 0.f;
|
||||
|
||||
// Cache.
|
||||
|
@ -118,6 +119,9 @@ public:
|
|||
virtual void set_hinting(TextServer::Hinting p_hinting);
|
||||
virtual TextServer::Hinting get_hinting() const;
|
||||
|
||||
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
|
||||
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
|
||||
|
||||
virtual void set_oversampling(real_t p_oversampling);
|
||||
virtual real_t get_oversampling() const;
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ void TextServerExtension::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
|
||||
GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
|
||||
|
||||
GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
|
||||
GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
|
||||
|
||||
GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
|
||||
GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
|
||||
|
||||
|
@ -512,6 +515,18 @@ TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const
|
|||
return TextServer::Hinting::HINTING_NONE;
|
||||
}
|
||||
|
||||
void TextServerExtension::font_set_subpixel_positioning(RID p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
|
||||
GDVIRTUAL_CALL(_font_set_subpixel_positioning, p_font_rid, p_subpixel);
|
||||
}
|
||||
|
||||
TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(RID p_font_rid) const {
|
||||
TextServer::SubpixelPositioning ret;
|
||||
if (GDVIRTUAL_CALL(_font_get_subpixel_positioning, p_font_rid, ret)) {
|
||||
return (TextServer::SubpixelPositioning)ret;
|
||||
}
|
||||
return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
|
||||
}
|
||||
|
||||
void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
|
||||
GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
|
||||
}
|
||||
|
|
|
@ -134,6 +134,11 @@ public:
|
|||
GDVIRTUAL2(_font_set_hinting, RID, Hinting);
|
||||
GDVIRTUAL1RC(Hinting, _font_get_hinting, RID);
|
||||
|
||||
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
|
||||
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
|
||||
GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
|
||||
GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
|
||||
|
||||
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
|
||||
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
|
||||
GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
|
||||
|
|
|
@ -235,9 +235,12 @@ void TextServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter);
|
||||
ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("font_set_hinting", "font_rid", "_hinting"), &TextServer::font_set_hinting);
|
||||
ClassDB::bind_method(D_METHOD("font_set_hinting", "font_rid", "hinting"), &TextServer::font_set_hinting);
|
||||
ClassDB::bind_method(D_METHOD("font_get_hinting", "font_rid"), &TextServer::font_get_hinting);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning);
|
||||
ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
|
||||
ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);
|
||||
|
||||
|
@ -479,6 +482,12 @@ void TextServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(HINTING_LIGHT);
|
||||
BIND_ENUM_CONSTANT(HINTING_NORMAL);
|
||||
|
||||
/* SubpixelPositioning */
|
||||
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_DISABLED);
|
||||
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_AUTO);
|
||||
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_HALF);
|
||||
BIND_ENUM_CONSTANT(SUBPIXEL_POSITIONING_ONE_QUARTER);
|
||||
|
||||
/* Feature */
|
||||
BIND_ENUM_CONSTANT(FEATURE_BIDI_LAYOUT);
|
||||
BIND_ENUM_CONSTANT(FEATURE_VERTICAL_LAYOUT);
|
||||
|
|
|
@ -101,6 +101,16 @@ public:
|
|||
HINTING_NORMAL
|
||||
};
|
||||
|
||||
enum SubpixelPositioning {
|
||||
SUBPIXEL_POSITIONING_DISABLED,
|
||||
SUBPIXEL_POSITIONING_AUTO,
|
||||
SUBPIXEL_POSITIONING_ONE_HALF,
|
||||
SUBPIXEL_POSITIONING_ONE_QUARTER,
|
||||
};
|
||||
|
||||
const int SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE = 20;
|
||||
const int SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE = 16;
|
||||
|
||||
enum Feature {
|
||||
FEATURE_BIDI_LAYOUT = 1 << 0,
|
||||
FEATURE_VERTICAL_LAYOUT = 1 << 1,
|
||||
|
@ -248,6 +258,9 @@ public:
|
|||
virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0;
|
||||
virtual Hinting font_get_hinting(RID p_font_rid) const = 0;
|
||||
|
||||
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0;
|
||||
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0;
|
||||
|
||||
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
|
||||
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;
|
||||
|
||||
|
@ -551,6 +564,7 @@ VARIANT_ENUM_CAST(TextServer::LineBreakFlag);
|
|||
VARIANT_ENUM_CAST(TextServer::TextOverrunFlag);
|
||||
VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
|
||||
VARIANT_ENUM_CAST(TextServer::Hinting);
|
||||
VARIANT_ENUM_CAST(TextServer::SubpixelPositioning);
|
||||
VARIANT_ENUM_CAST(TextServer::Feature);
|
||||
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
|
||||
VARIANT_ENUM_CAST(TextServer::SpacingType);
|
||||
|
|
|
@ -206,7 +206,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
|
|||
memnew(InputMap);
|
||||
InputMap::get_singleton()->load_default();
|
||||
|
||||
make_default_theme(1.0, Ref<Font>());
|
||||
make_default_theme(1.0, Ref<Font>(), TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::HINTING_LIGHT, true);
|
||||
|
||||
memnew(SceneTree);
|
||||
SceneTree::get_singleton()->initialize();
|
||||
|
|
Loading…
Reference in a new issue