1
0
mirror of https://github.com/godotengine/godot synced 2024-07-05 16:43:46 +00:00

Refactor Font configuration and import UI, and Font resources.

This commit is contained in:
bruvzg 2022-05-09 12:47:10 +03:00
parent cf19484746
commit 344ba0ffaf
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
113 changed files with 5041 additions and 6485 deletions

View File

@ -102,6 +102,7 @@ public:
}
_FORCE_INLINE_ size_t get_capacity() const { return capacity; }
_FORCE_INLINE_ size_t get_size() const { return _map.size(); }
void set_capacity(size_t p_capacity) {
if (capacity > 0) {

View File

@ -40,29 +40,6 @@
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
<methods>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" enum="HorizontalAlignment" default="1">
Text alignment policy for the button's text, use one of the [enum @GlobalScope.HorizontalAlignment] constants.

View File

@ -48,17 +48,26 @@
</description>
</method>
<method name="draw_char" qualifiers="const">
<return type="float" />
<return type="void" />
<argument index="0" name="font" type="Font" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="String" />
<argument index="3" name="next" type="String" default="&quot;&quot;" />
<argument index="4" name="size" type="int" default="16" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="6" name="outline_size" type="int" default="0" />
<argument index="7" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="3" name="font_size" type="int" default="16" />
<argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<description>
Draws a string character using a custom font. Returns the advance, depending on the character width and kerning with an optional next character.
Draws a string first character using a custom font.
</description>
</method>
<method name="draw_char_outline" qualifiers="const">
<return type="void" />
<argument index="0" name="font" type="Font" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="String" />
<argument index="3" name="font_size" type="int" default="16" />
<argument index="4" name="size" type="int" default="-1" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<description>
Draws a string first character outline using a custom font.
</description>
</method>
<method name="draw_circle">
@ -127,7 +136,7 @@
<argument index="4" name="outline" type="float" default="0.0" />
<argument index="5" name="pixel_range" type="float" default="4.0" />
<description>
Draws a textured rectangle region of the multi-channel signed distance field texture at a given position, optionally modulated by a color. See [member FontData.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
Draws a textured rectangle region of the multi-channel signed distance field texture at a given position, optionally modulated by a color. See [member FontFile.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
If [code]outline[/code] is positive, each alpha channel value of pixel in region is set to maximum value of true distance in the [code]outline[/code] radius.
Value of the [code]pixel_range[/code] should the same that was used during distance field texture generation.
</description>
@ -157,16 +166,34 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="max_lines" type="int" default="-1" />
<argument index="6" name="size" type="int" default="16" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="max_lines" type="int" default="-1" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="10" name="flags" type="int" default="99" />
<argument index="8" name="flags" type="int" default="99" />
<argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines and draws it using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
</description>
</method>
<method name="draw_multiline_string_outline" qualifiers="const">
<return type="void" />
<argument index="0" name="font" type="Font" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="max_lines" type="int" default="-1" />
<argument index="7" name="size" type="int" default="1" />
<argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="9" name="flags" type="int" default="99" />
<argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines and draws text outline using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
</description>
</method>
<method name="draw_multimesh">
<return type="void" />
<argument index="0" name="multimesh" type="MultiMesh" />
@ -250,11 +277,11 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="size" type="int" default="16" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="7" name="outline_size" type="int" default="0" />
<argument index="8" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="9" name="flags" type="int" default="3" />
<argument index="7" name="flags" type="int" default="3" />
<argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draws [code]text[/code] using the specified [code]font[/code] at the [code]position[/code] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
[b]Example using the default project font:[/b]
@ -279,6 +306,23 @@
See also [method Font.draw_string].
</description>
</method>
<method name="draw_string_outline" qualifiers="const">
<return type="void" />
<argument index="0" name="font" type="Font" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="size" type="int" default="1" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="flags" type="int" default="3" />
<argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draws [code]text[/code] outline using the specified [code]font[/code] at the [code]position[/code] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
</description>
</method>
<method name="draw_style_box">
<return type="void" />
<argument index="0" name="style_box" type="StyleBox" />

View File

@ -1,93 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Font" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Font class is set of font data sources used to draw text.
Base class for fonts and font variations.
</brief_description>
<description>
Font contains a set of glyphs to represent Unicode characters, as well as the ability to draw it with variable width, ascent, descent and kerning.
[b]Note:[/b] A character is a symbol that represents an item (letter, digit etc.) in an abstract way.
[b]Note:[/b] A glyph is a bitmap or shape used to draw a one or more characters in a context-dependent manner. Glyph indices are bound to the specific font data source.
[b]Note:[/b] If a non of the font data sources contain glyphs for a character used in a string, the character in question will be replaced with a box displaying its hexadecimal code.
[codeblocks]
[gdscript]
var font = Font.new()
font.add_data(load("res://BarlowCondensed-Bold.ttf"))
$"Label".set("custom_fonts/font", font)
$"Label".set("custom_fonts/font_size", 64)
[/gdscript]
[csharp]
var font = new Font();
font.AddData(ResourceLoader.Load&lt;FontData&gt;("res://BarlowCondensed-Bold.ttf"));
GetNode("Label").Set("custom_fonts/font", font);
GetNode("Label").Set("custom_font_sizes/font_size", 64);
[/csharp]
[/codeblocks]
To control font substitution priority use [FontData] language and script support.
Use language overrides to use same [Font] stack for multiple languages:
[codeblocks]
[gdscript]
# Use Naskh font for Persian and Nastaʼlīq font for Urdu text.
var font_data_fa = load("res://NotoNaskhArabicUI_Regular.ttf");
font_data_fa.set_language_support_override("fa", true);
font_data_fa.set_language_support_override("ur", false);
var font_data_ur = load("res://NotoNastaliqUrdu_Regular.ttf");
font_data_ur.set_language_support_override("fa", false);
font_data_ur.set_language_support_override("ur", true);
[/gdscript]
[csharp]
// Use Naskh font for Persian and Nastaʼlīq font for Urdu text.
var fontDataFA = ResourceLoader.Load&lt;FontData&gt;("res://NotoNaskhArabicUI_Regular.ttf");
fontDataFA.SetLanguageSupportOverride("fa", true);
fontDataFA.SetLanguageSupportOverride("ur", false);
var fontDataUR = ResourceLoader.Load&lt;FontData&gt;("res://NotoNastaliqUrdu_Regular.ttf");
fontDataUR.SetLanguageSupportOverride("fa", false);
fontDataUR.SetLanguageSupportOverride("ur", true);
[/csharp]
[/codeblocks]
Use script overrides to specify supported scripts for bitmap font or for less common scripts not directly supported by TrueType format:
[codeblocks]
[gdscript]
# Use specified font for Egyptian hieroglyphs.
var font_data = load("res://unifont.ttf");
font_data.set_script_support_override("Egyp", true);
[/gdscript]
[csharp]
// Use specified font for Egyptian hieroglyphs.
var fontData = ResourceLoader.Load&lt;FontData&gt;("res://unifont.ttf");
fontData.SetScriptSupportOverride("Egyp", true);
[/csharp]
[/codeblocks]
Font is the abstract base class for font, so it shouldn't be used directly. Other types of fonts inherit from it.
</description>
<tutorials>
</tutorials>
<methods>
<method name="add_data">
<return type="void" />
<argument index="0" name="data" type="FontData" />
<description>
Add font data source to the set.
</description>
</method>
<method name="clear_data">
<return type="void" />
<description>
Removes all font data sourcers for the set.
</description>
</method>
<method name="draw_char" qualifiers="const">
<return type="float" />
<argument index="0" name="canvas_item" type="RID" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="int" />
<argument index="3" name="next" type="int" default="0" />
<argument index="4" name="size" type="int" default="16" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="6" name="outline_size" type="int" default="0" />
<argument index="7" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="3" name="modulate" type="int" />
<argument index="4" name="arg4" type="Color" default="Color(1, 1, 1, 1)" />
<description>
Draw a single Unicode character [code]char[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color, and optionally kerning if [code]next[/code] is passed. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
Draw a single Unicode character [code]char[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
[b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead.
</description>
</method>
<method name="draw_char_outline" qualifiers="const">
<return type="float" />
<argument index="0" name="canvas_item" type="RID" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="int" />
<argument index="3" name="size" type="int" />
<argument index="4" name="modulate" type="int" default="-1" />
<argument index="5" name="arg5" type="Color" default="Color(1, 1, 1, 1)" />
<description>
Draw a single Unicode character [code]char[/code] outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
[b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead.
</description>
</method>
@ -98,17 +41,36 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="max_lines" type="int" default="-1" />
<argument index="6" name="size" type="int" default="16" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="max_lines" type="int" default="-1" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="10" name="flags" type="int" default="99" />
<argument index="8" name="flags" type="int" default="99" />
<argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws it into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_multiline_string].
</description>
</method>
<method name="draw_multiline_string_outline" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="max_lines" type="int" default="-1" />
<argument index="7" name="size" type="int" default="1" />
<argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="9" name="flags" type="int" default="99" />
<argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws text outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_multiline_string_outline].
</description>
</method>
<method name="draw_string" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
@ -116,19 +78,47 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="size" type="int" default="16" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="7" name="outline_size" type="int" default="0" />
<argument index="8" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="9" name="flags" type="int" default="3" />
<argument index="7" name="flags" type="int" default="3" />
<argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draw [code]text[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_string].
</description>
</method>
<method name="draw_string_outline" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="font_size" type="int" default="16" />
<argument index="6" name="size" type="int" default="1" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="flags" type="int" default="3" />
<argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draw [code]text[/code] outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_string_outline].
</description>
</method>
<method name="find_variation" qualifiers="const">
<return type="RID" />
<argument index="0" name="variation_coordinates" type="Dictionary" />
<argument index="1" name="face_index" type="int" default="0" />
<argument index="2" name="strength" type="float" default="0.0" />
<argument index="3" name="transform" type="Transform2D" default="Transform2D(1, 0, 0, 1, 0, 0)" />
<description>
Returns [TextServer] RID of the font cache for specific variation.
</description>
</method>
<method name="get_ascent" qualifiers="const">
<return type="float" />
<argument index="0" name="size" type="int" default="16" />
<argument index="0" name="font_size" type="int" default="16" />
<description>
Returns the average font ascent (number of pixels above the baseline).
[b]Note:[/b] Real ascent of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the ascent of empty line).
@ -137,44 +127,53 @@
<method name="get_char_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="size" type="int" default="16" />
<argument index="1" name="arg1" type="int" />
<description>
Returns the size of a character, optionally taking kerning into account if the next character is provided.
[b]Note:[/b] Do not use this function to calculate width of the string character by character, use [method get_string_size] or [TextLine] instead. The height returned is the font height (see also [method get_height]) and has no relation to the glyph height.
</description>
</method>
<method name="get_data" qualifiers="const">
<return type="FontData" />
<argument index="0" name="idx" type="int" />
<description>
Returns the font data source at index [code]idx[/code]. If the index does not exist, returns [code]null[/code].
</description>
</method>
<method name="get_data_count" qualifiers="const">
<return type="int" />
<description>
Returns the number of font data sources.
</description>
</method>
<method name="get_data_rid" qualifiers="const">
<return type="RID" />
<argument index="0" name="idx" type="int" />
<description>
Returns TextServer RID of the font data resources.
</description>
</method>
<method name="get_descent" qualifiers="const">
<return type="float" />
<argument index="0" name="size" type="int" default="16" />
<argument index="0" name="font_size" type="int" default="16" />
<description>
Returns the average font descent (number of pixels below the baseline).
[b]Note:[/b] Real descent of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the descent of empty line).
</description>
</method>
<method name="get_face_count" qualifiers="const">
<return type="int" />
<description>
Returns number of faces in the TrueType / OpenType collection.
</description>
</method>
<method name="get_fallbacks" qualifiers="const">
<return type="Font[]" />
<description>
Returns array of fallback [Font]s.
</description>
</method>
<method name="get_font_name" qualifiers="const">
<return type="String" />
<description>
Returns font family name.
</description>
</method>
<method name="get_font_style" qualifiers="const">
<return type="int" />
<description>
Returns font style flags, see [enum TextServer.FontStyle].
</description>
</method>
<method name="get_font_style_name" qualifiers="const">
<return type="String" />
<description>
Returns font style name.
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="float" />
<argument index="0" name="size" type="int" default="16" />
<argument index="0" name="font_size" type="int" default="16" />
<description>
Returns the total average font height (ascent plus descent) in pixels.
[b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the height of empty line).
@ -183,18 +182,28 @@
<method name="get_multiline_string_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="text" type="String" />
<argument index="1" name="width" type="float" default="-1" />
<argument index="2" name="size" type="int" default="16" />
<argument index="3" name="flags" type="int" default="96" />
<argument index="1" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="2" name="width" type="float" default="-1" />
<argument index="3" name="font_size" type="int" default="16" />
<argument index="4" name="max_lines" type="int" default="-1" />
<argument index="5" name="flags" type="int" default="96" />
<argument index="6" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="7" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Returns the size of a bounding box of a string broken into the lines, taking kerning and advance into account.
See also [method draw_multiline_string].
</description>
</method>
<method name="get_rids" qualifiers="const">
<return type="Array" />
<method name="get_opentype_features" qualifiers="const">
<return type="Dictionary" />
<description>
Returns [Array] of valid [FontData] [RID]s, which can be passed to the [TextServer] methods.
Returns a set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="get_rids" qualifiers="const">
<return type="RID[]" />
<description>
Returns [Array] of valid [Font] [RID]s, which can be passed to the [TextServer] methods.
</description>
</method>
<method name="get_spacing" qualifiers="const">
@ -207,10 +216,12 @@
<method name="get_string_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="text" type="String" />
<argument index="1" name="size" type="int" default="16" />
<argument index="2" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="3" name="width" type="float" default="-1" />
<argument index="1" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="2" name="width" type="float" default="-1" />
<argument index="3" name="font_size" type="int" default="16" />
<argument index="4" name="flags" type="int" default="3" />
<argument index="5" name="direction" type="int" enum="TextServer.Direction" default="0" />
<argument index="6" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Returns the size of a bounding box of a string, taking kerning and advance into account.
[b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by [method get_height].
@ -224,9 +235,22 @@
If a given character is included in more than one font data source, it appears only once in the returned string.
</description>
</method>
<method name="get_supported_feature_list" qualifiers="const">
<return type="Dictionary" />
<description>
Returns list of OpenType features supported by font.
</description>
</method>
<method name="get_supported_variation_list" qualifiers="const">
<return type="Dictionary" />
<description>
Returns list of supported [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url], each coordinate is returned as [code]tag: Vector3i(min_value,max_value,default_value)[/code].
Font variations allow for continuous change of glyph characteristics along some given design axis, such as weight, width or slant.
</description>
</method>
<method name="get_underline_position" qualifiers="const">
<return type="float" />
<argument index="0" name="size" type="int" default="16" />
<argument index="0" name="font_size" type="int" default="16" />
<description>
Returns average pixel offset of the underline below the baseline.
[b]Note:[/b] Real underline position of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate.
@ -234,7 +258,7 @@
</method>
<method name="get_underline_thickness" qualifiers="const">
<return type="float" />
<argument index="0" name="size" type="int" default="16" />
<argument index="0" name="font_size" type="int" default="16" />
<description>
Returns average thickness of the underline.
[b]Note:[/b] Real underline thickness of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate.
@ -247,45 +271,34 @@
Returns [code]true[/code] if a Unicode [code]char[/code] is available in the font.
</description>
</method>
<method name="remove_data">
<return type="void" />
<argument index="0" name="idx" type="int" />
<method name="is_language_supported" qualifiers="const">
<return type="bool" />
<argument index="0" name="language" type="String" />
<description>
Removes the font data source at index [code]idx[/code]. If the index does not exist, nothing happens.
Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code).
</description>
</method>
<method name="set_data">
<return type="void" />
<argument index="0" name="idx" type="int" />
<argument index="1" name="data" type="FontData" />
<method name="is_script_supported" qualifiers="const">
<return type="bool" />
<argument index="0" name="script" type="String" />
<description>
Sets the font data source at index [code]idx[/code]. If the index does not exist, nothing happens.
Returns [code]true[/code], if font supports given script ([url=https://en.wikipedia.org/wiki/ISO_15924]ISO 15924[/url] code).
</description>
</method>
<method name="set_spacing">
<method name="set_cache_capacity">
<return type="void" />
<argument index="0" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="1" name="value" type="int" />
<argument index="0" name="single_line" type="int" />
<argument index="1" name="multi_line" type="int" />
<description>
Sets the spacing for [code]type[/code] (see [enum TextServer.SpacingType]) to [code]value[/code] in pixels (not relative to the font size).
Sets LRU cache capacity for [code]draw_*[/code] methods.
</description>
</method>
<method name="update_changes">
<method name="set_fallbacks">
<return type="void" />
<argument index="0" name="fallbacks" type="Font[]" />
<description>
After editing a font (changing data sources, etc.). Call this function to propagate changes to controls that might use it.
Sets array of fallback [Font]s.
</description>
</method>
</methods>
<members>
<member name="spacing_bottom" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the bottom of the line in pixels.
</member>
<member name="spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the top of the line in pixels.
</member>
<member name="variation_coordinates" type="Dictionary" setter="set_variation_coordinates" getter="get_variation_coordinates" default="{}">
Default font [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url].
</member>
</members>
</class>

View File

@ -1,13 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="FontData" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<class name="FontFile" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Font source data and prerendered glyph cache, imported from dynamic or bitmap font.
FontFile source data and prerendered glyph cache, imported from dynamic or bitmap font.
</brief_description>
<description>
[FontFile] contains a set of glyphs to represent Unicode characters imported from a font file, as well as a cache of rasterized glyphs, and a set of fallback [Font]s to use.
Use [FontVariation] to access specific OpenType variation of the font, create simulated bold / slanted version, and draw lines of text.
For more complex text processing, use [FontVariation] in conjunction with [TextLine] or [TextParagraph].
Supported font formats:
- Dynamic font importer: TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2), Type 1 (.pfb, .pfm).
- Bitmap font importer: AngelCode BMFont (.fnt, .font), text and binary (version 3) format variants.
- Monospace image font importer: All supported image formats.
</brief_description>
<description>
[b]Note:[/b] A character is a symbol that represents an item (letter, digit etc.) in an abstract way.
[b]Note:[/b] A glyph is a bitmap or shape used to draw a one or more characters in a context-dependent manner. Glyph indices are bound to the specific font data source.
[b]Note:[/b] If a none of the font data sources contain glyphs for a character used in a string, the character in question will be replaced with a box displaying its hexadecimal code.
[codeblocks]
[gdscript]
var f = load("res://BarlowCondensed-Bold.ttf")
$"Label".set("custom_fonts/font", f)
$"Label".set("custom_fonts/font_size", 64)
[/gdscript]
[csharp]
var f = ResourceLoader.Load&lt;FontFile&gt;("res://BarlowCondensed-Bold.ttf");
GetNode("Label").Set("custom_fonts/font", f);
GetNode("Label").Set("custom_font_sizes/font_size", 64);
[/csharp]
[/codeblocks]
</description>
<tutorials>
</tutorials>
@ -51,14 +70,7 @@
[b]Note:[/b] This function will not remove glyphs associated with the texture, use [method remove_glyph] to remove them manually.
</description>
</method>
<method name="find_cache" qualifiers="const">
<return type="RID" />
<argument index="0" name="variation_coordinates" type="Dictionary" />
<description>
Returns existing or creates a new font cache entry for the specified variation coordinates.
</description>
</method>
<method name="get_ascent" qualifiers="const">
<method name="get_cache_ascent" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
@ -72,25 +84,46 @@
Returns number of the font cache entries.
</description>
</method>
<method name="get_cache_rid" qualifiers="const">
<return type="RID" />
<argument index="0" name="cache_index" type="int" />
<description>
Returns text server font cache entry resource id.
</description>
</method>
<method name="get_descent" qualifiers="const">
<method name="get_cache_descent" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
Returns font descent (number of pixels below the baseline).
</description>
</method>
<method name="get_face_count" qualifiers="const">
<return type="int" />
<method name="get_cache_scale" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
Returns number of faces in the TrueType / OpenType collection.
</description>
</method>
<method name="get_cache_underline_position" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
</description>
</method>
<method name="get_cache_underline_thickness" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
</description>
</method>
<method name="get_embolden" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<description>
Returns embolden strength, if is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
<method name="get_face_index" qualifiers="const">
<return type="int" />
<argument index="0" name="cache_index" type="int" />
<description>
Recturns an active face index in the TrueType / OpenType collection.
</description>
</method>
<method name="get_glyph_advance" qualifiers="const">
@ -186,14 +219,6 @@
Returns list of language support overrides.
</description>
</method>
<method name="get_scale" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
Returns scaling factor of the color bitmap font.
</description>
</method>
<method name="get_script_support_override" qualifiers="const">
<return type="bool" />
<argument index="0" name="script" type="String" />
@ -214,34 +239,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
<method name="get_spacing" qualifiers="const">
<return type="int" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing_type" type="int" enum="TextServer.SpacingType" />
<description>
Returns extra spacing added between glyphs in pixels.
</description>
</method>
<method name="get_supported_chars" qualifiers="const">
<return type="String" />
<description>
Returns a string containing all the characters available in the font.
</description>
</method>
<method name="get_supported_feature_list" qualifiers="const">
<return type="Dictionary" />
<description>
Returns list of OpenType features supported by font.
</description>
</method>
<method name="get_supported_variation_list" qualifiers="const">
<return type="Dictionary" />
<description>
Returns list of supported [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url], each coordinate is returned as [code]tag: Vector3i(min_value,max_value,default_value)[/code].
Font variations allow for continuous change of glyph characteristics along some given design axis, such as weight, width or slant.
</description>
</method>
<method name="get_texture_count" qualifiers="const">
<return type="int" />
<argument index="0" name="cache_index" type="int" />
@ -268,48 +265,18 @@
Returns a copy of the array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
<method name="get_underline_position" qualifiers="const">
<return type="float" />
<method name="get_transform" qualifiers="const">
<return type="Transform2D" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
Returns pixel offset of the underline below the baseline.
</description>
</method>
<method name="get_underline_thickness" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
Returns thickness of the underline in pixels.
Returns 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
</description>
</method>
<method name="get_variation_coordinates" qualifiers="const">
<return type="Dictionary" />
<argument index="0" name="cache_index" type="int" />
<description>
Returns variation coordinates for the specified font cache entry. See [method get_supported_variation_list] for more info.
</description>
</method>
<method name="has_char" qualifiers="const">
<return type="bool" />
<argument index="0" name="char" type="int" />
<description>
Returns [code]true[/code] if a Unicode [code]char[/code] is available in the font.
</description>
</method>
<method name="is_language_supported" qualifiers="const">
<return type="bool" />
<argument index="0" name="language" type="String" />
<description>
Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code).
</description>
</method>
<method name="is_script_supported" qualifiers="const">
<return type="bool" />
<argument index="0" name="script" type="String" />
<description>
Returns [code]true[/code], if font supports given script ([url=https://en.wikipedia.org/wiki/ISO_15924]ISO 15924[/url] code).
Returns variation coordinates for the specified font cache entry. See [method Font.get_supported_variation_list] for more info.
</description>
</method>
<method name="load_bitmap_font">
@ -324,8 +291,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
Loads a TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
[b]Note:[/b] Use [member face_index] to select specific face from the collection file.
Loads a TrueType (.ttf), OpenType (.otf), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
[b]Warning:[/b] This method should only be used in the editor or in cases when you need to load external fonts at run-time, such as fonts located at the [code]user://[/code] directory.
</description>
</method>
@ -383,8 +349,8 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
Removes specified texture from font cache entry.
[b]Note:[/b] This function will not remove glyphs associated with the texture, remove them manually, using [method remove_glyph].
Removes specified texture from the cache entry.
[b]Note:[/b] This function will not remove glyphs associated with the texture. Remove them manually using [method remove_glyph].
</description>
</method>
<method name="render_glyph">
@ -393,7 +359,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="index" type="int" />
<description>
Renders specified glyph the the font cache texture.
Renders specified glyph to the font cache texture.
</description>
</method>
<method name="render_range">
@ -406,22 +372,60 @@
Renders the range of characters to the font cache texture.
</description>
</method>
<method name="set_ascent">
<method name="set_cache_ascent">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="ascent" type="float" />
<description>
Sets the font ascent (number of pixels above the baseline).
</description>
</method>
<method name="set_descent">
<method name="set_cache_descent">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="descent" type="float" />
<description>
Sets the font descent (number of pixels below the baseline).
</description>
</method>
<method name="set_cache_scale">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="scale" type="float" />
<description>
</description>
</method>
<method name="set_cache_underline_position">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="underline_position" type="float" />
<description>
</description>
</method>
<method name="set_cache_underline_thickness">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="underline_thickness" type="float" />
<description>
</description>
</method>
<method name="set_embolden">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="strength" type="float" />
<description>
Sets embolden strength, if is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
<method name="set_face_index">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="face_index" type="int" />
<description>
Sets an active face index in the TrueType / OpenType collection.
</description>
</method>
<method name="set_glyph_advance">
@ -490,16 +494,7 @@
<argument index="0" name="language" type="String" />
<argument index="1" name="supported" type="bool" />
<description>
Adds override for [method is_language_supported].
</description>
</method>
<method name="set_scale">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="scale" type="float" />
<description>
Sets scaling factor of the color bitmap font.
Adds override for [method Font.is_language_supported].
</description>
</method>
<method name="set_script_support_override">
@ -507,17 +502,7 @@
<argument index="0" name="script" type="String" />
<argument index="1" name="supported" type="bool" />
<description>
Adds override for [method is_script_supported].
</description>
</method>
<method name="set_spacing">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing_type" type="int" enum="TextServer.SpacingType" />
<argument index="3" name="value" type="int" />
<description>
Sets extra spacing added between glyphs in pixels.
Adds override for [method Font.is_script_supported].
</description>
</method>
<method name="set_texture_image">
@ -540,22 +525,12 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty (for the fonts without dynamic glyph generation support).
</description>
</method>
<method name="set_underline_position">
<method name="set_transform">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="underline_position" type="float" />
<argument index="1" name="transform" type="Transform2D" />
<description>
Sets pixel offset of the underline below the baseline.
</description>
</method>
<method name="set_underline_thickness">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="underline_thickness" type="float" />
<description>
Sets thickness of the underline in pixels.
Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
</description>
</method>
<method name="set_variation_coordinates">
@ -563,7 +538,7 @@
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="variation_coordinates" type="Dictionary" />
<description>
Sets variation coordinates for the specified font cache entry. See [method get_supported_variation_list] for more info.
Sets variation coordinates for the specified font cache entry. See [method Font.get_supported_variation_list] for more info.
</description>
</method>
</methods>
@ -574,11 +549,8 @@
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file.
</member>
<member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</member>
<member name="face_index" type="int" setter="set_face_index" getter="get_face_index" default="0">
Active face index in the TrueType / OpenType collection file.
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
Array of fallback [Font]s.
</member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts.
@ -619,9 +591,5 @@
<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>
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
</member>
</members>
</class>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="FontVariation" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Variation of the [Font].
</brief_description>
<description>
OpenType variations, simulated bold / slant, and additional font settings like OpenType features and extra spacing.
To use simulated bold font variant:
[codeblocks]
[gdscript]
var fv = FontVariation.new()
fv.set_base_font(load("res://BarlowCondensed-Regular.ttf"))
fv.set_variation_embolden(1.2);
$"Label".set("custom_fonts/font", fv)
$"Label".set("custom_fonts/font_size", 64)
[/gdscript]
[csharp]
var fv = new FontVariation();
fv.SetBaseFont(ResourceLoader.Load&lt;FontFile&gt;("res://BarlowCondensed-Regular.ttf"));
fv.SetVariationEmbolden(1.2);
GetNode("Label").Set("custom_fonts/font", fv);
GetNode("Label").Set("custom_font_sizes/font_size", 64);
[/csharp]
[/codeblocks]
</description>
<tutorials>
</tutorials>
<methods>
<method name="set_spacing">
<return type="void" />
<argument index="0" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="1" name="value" type="int" />
<description>
Sets the spacing for [code]type[/code] (see [enum TextServer.SpacingType]) to [code]value[/code] in pixels (not relative to the font size).
</description>
</method>
</methods>
<members>
<member name="base_font" type="Font" setter="set_base_font" getter="get_base_font">
Base font used to create a variation. If not set, default [Theme] font is used.
</member>
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
Array of fallback [Font]s. If not set [member base_font] fallback are ussed.
</member>
<member name="opentype_features" type="Dictionary" setter="set_opentype_features" getter="get_opentype_features" default="{}">
A set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</member>
<member name="spacing_bottom" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the bottom of the line in pixels.
</member>
<member name="spacing_glyph" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing between graphical glyphs
</member>
<member name="spacing_space" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra width of the space glyphs.
</member>
<member name="spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the top of the line in pixels.
</member>
<member name="variation_embolden" type="float" setter="set_variation_embolden" getter="get_variation_embolden" default="0.0">
If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
[b]Note:[/b] Emboldened fonts might have self-intersecting outlines, which will prevent MSDF fonts and [TextMesh] from working correctly.
</member>
<member name="variation_face_index" type="int" setter="set_variation_face_index" getter="get_variation_face_index" default="0">
Active face index in the TrueType / OpenType collection file.
</member>
<member name="variation_opentype" type="Dictionary" setter="set_variation_opentype" getter="get_variation_opentype" default="{}">
Font OpenType variation coordinates. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]OpenType variation tags[/url].
</member>
<member name="variation_transform" type="Transform2D" setter="set_variation_transform" getter="get_variation_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
</member>
</members>
</class>

View File

@ -17,12 +17,6 @@
Disables all input and output slots of the GraphNode.
</description>
</method>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="clear_slot">
<return type="void" />
<argument index="0" name="idx" type="int" />
@ -98,13 +92,6 @@
Returns the type of the output connection [code]idx[/code].
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="get_slot_color_left" qualifiers="const">
<return type="Color" />
<argument index="0" name="idx" type="int" />
@ -154,14 +141,6 @@
Returns [code]true[/code] if right (output) side of the slot [code]idx[/code] is enabled.
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="set_slot">
<return type="void" />
<argument index="0" name="idx" type="int" />

View File

@ -38,13 +38,6 @@
Removes all items from the list.
</description>
</method>
<method name="clear_item_opentype_features">
<return type="void" />
<argument index="0" name="idx" type="int" />
<description>
Removes all OpenType features from the item's text.
</description>
</method>
<method name="deselect">
<return type="void" />
<argument index="0" name="idx" type="int" />
@ -122,14 +115,6 @@
Returns the metadata value of the specified index.
</description>
</method>
<method name="get_item_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="idx" type="int" />
<argument index="1" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code] of the item's text.
</description>
</method>
<method name="get_item_text" qualifiers="const">
<return type="String" />
<argument index="0" name="idx" type="int" />
@ -302,15 +287,6 @@
Sets a value (of any type) to be stored with the item associated with the specified index.
</description>
</method>
<method name="set_item_opentype_feature">
<return type="void" />
<argument index="0" name="idx" type="int" />
<argument index="1" name="tag" type="String" />
<argument index="2" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code] for the item's text. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="set_item_selectable">
<return type="void" />
<argument index="0" name="idx" type="int" />

View File

@ -11,12 +11,6 @@
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
</tutorials>
<methods>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="get_line_count" qualifiers="const">
<return type="int" />
<description>
@ -32,13 +26,6 @@
If there're no lines returns font size in pixels.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="get_total_character_count" qualifiers="const">
<return type="int" />
<description>
@ -51,14 +38,6 @@
Returns the number of lines shown. Useful if the [Label]'s height cannot currently display all lines.
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="TextServer.AutowrapMode" default="0">
@ -119,7 +98,7 @@
Default text [Color] of the [Label].
</theme_item>
<theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
The tint of [Font]'s outline.
The tint of text outline.
</theme_item>
<theme_item name="font_shadow_color" data_type="color" type="Color" default="Color(0, 0, 0, 0)">
[Color] of the text's shadow effect.

View File

@ -9,12 +9,6 @@
<tutorials>
</tutorials>
<methods>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="generate_triangle_mesh" qualifiers="const">
<return type="TriangleMesh" />
<description>
@ -28,13 +22,6 @@
Returns the value of the specified flag.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="set_draw_flag">
<return type="void" />
<argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
@ -43,14 +30,6 @@
If [code]true[/code], the specified flag will be enabled. See [enum Label3D.DrawFlags] for a list of flags.
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0">
@ -72,7 +51,7 @@
If [code]true[/code], the label is rendered at the same size regardless of distance.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
[Font] used for the [Label3D]'s text.
Font configuration used to display text.
</member>
<member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
Font size of the [Label3D]'s text.
@ -96,7 +75,7 @@
The text drawing offset (in pixels).
</member>
<member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color(0, 0, 0, 1)">
The tint of [Font]'s outline.
The tint of text outline.
</member>
<member name="outline_render_priority" type="int" setter="set_outline_render_priority" getter="get_outline_render_priority" default="-1">
Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects.

View File

@ -37,12 +37,6 @@
Erases the [LineEdit]'s [member text].
</description>
</method>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="delete_char_at_caret">
<return type="void" />
<description>
@ -70,13 +64,6 @@
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member Window.visible] property.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="get_scroll_offset" qualifiers="const">
<return type="int" />
<description>
@ -149,14 +136,6 @@
Selects the whole [String].
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">

View File

@ -9,29 +9,6 @@
</description>
<tutorials>
</tutorials>
<methods>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.

View File

@ -182,13 +182,6 @@
Removes all items from the [PopupMenu].
</description>
</method>
<method name="clear_item_opentype_features">
<return type="void" />
<argument index="0" name="index" type="int" />
<description>
Removes all OpenType features form the item's text.
</description>
</method>
<method name="get_current_index" qualifiers="const">
<return type="int" />
<description>
@ -244,14 +237,6 @@
Returns the metadata of the specified item, which might be of any type. You can set it with [method set_item_metadata], which provides a simple way of assigning context data to items.
</description>
</method>
<method name="get_item_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="index" type="int" />
<argument index="1" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code] of the item's text.
</description>
</method>
<method name="get_item_shortcut" qualifiers="const">
<return type="Shortcut" />
<argument index="0" name="index" type="int" />
@ -452,15 +437,6 @@
Sets the state of a multistate item. See [method add_multistate_item] for details.
</description>
</method>
<method name="set_item_opentype_feature">
<return type="void" />
<argument index="0" name="index" type="int" />
<argument index="1" name="tag" type="String" />
<argument index="2" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code] for the item's text. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="set_item_shortcut">
<return type="void" />
<argument index="0" name="index" type="int" />

View File

@ -628,7 +628,7 @@
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].
If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontFile.antialiased].
</member>
<member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false">
If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps).
@ -636,7 +636,7 @@
[b]Note:[/b] This setting does not affect custom [Font]s used within the project.
</member>
<member name="gui/theme/default_font_hinting" type="int" setter="" getter="" default="1">
Default font hinting mode. See [member FontData.hinting].
Default font hinting mode. See [member FontFile.hinting].
</member>
<member name="gui/theme/default_font_multichannel_signed_distance_field" type="bool" setter="" getter="" default="false">
If set to [code]true[/code], the default font will use multichannel signed distance field (MSDF) for crisp rendering at any size. Since this approach does not rely on rasterizing the font every time its size changes, this allows for resizing the font in real-time without any performance penalty. Text will also not look grainy for [Control]s that are scaled down (or for [Label3D]s viewed from a long distance).
@ -644,7 +644,7 @@
[b]Note:[/b] This setting does not affect custom [Font]s used within the project.
</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].
Default font glyph sub-pixel positioning mode. See [member FontFile.subpixel_positioning].
</member>
<member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0">
</member>

View File

@ -276,18 +276,10 @@
Adds a [code][font][/code] tag to the tag stack. Overrides default fonts for its duration.
</description>
</method>
<method name="push_font_features">
<return type="void" />
<argument index="0" name="opentype_features" type="Dictionary" />
<description>
Adds a [code][ot_feature][/code] tag to the tag stack. Overrides default OpenType font feature for its duration.
</description>
</method>
<method name="push_font_size">
<return type="void" />
<argument index="0" name="font_size" type="int" />
<description>
Adds a [code][font_size][/code] tag to the tag stack. Overrides default font size for its duration.
</description>
</method>
<method name="push_hint">

View File

@ -17,13 +17,6 @@
Adds a new tab.
</description>
</method>
<method name="clear_tab_opentype_features">
<return type="void" />
<argument index="0" name="tab_idx" type="int" />
<description>
Removes all OpenType features from the tab title.
</description>
</method>
<method name="ensure_tab_visible">
<return type="void" />
<argument index="0" name="idx" type="int" />
@ -77,14 +70,6 @@
Returns the number of hidden tabs offsetted to the left.
</description>
</method>
<method name="get_tab_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tab_idx" type="int" />
<argument index="1" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code] of the tab title.
</description>
</method>
<method name="get_tab_rect" qualifiers="const">
<return type="Rect2" />
<argument index="0" name="tab_idx" type="int" />
@ -175,15 +160,6 @@
Sets language code of tab title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</description>
</method>
<method name="set_tab_opentype_feature">
<return type="void" />
<argument index="0" name="tab_idx" type="int" />
<argument index="1" name="tag" type="String" />
<argument index="2" name="values" type="int" />
<description>
Sets OpenType feature [code]tag[/code] for the tab title. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="set_tab_text_direction">
<return type="void" />
<argument index="0" name="tab_idx" type="int" />

View File

@ -85,12 +85,6 @@
Performs a full reset of [TextEdit], including undo history.
</description>
</method>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="clear_undo_history">
<return type="void" />
<description>
@ -355,13 +349,6 @@
Returns the count to the next visible line from [code]line[/code] to [code]line + visible_amount[/code]. Can also count backwards. For example if a [TextEdit] has 5 lines with lines 2 and 3 hidden, calling this with [code]line = 1, visible_amount = 1[/code] would return 3.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="get_pos_at_line_column" qualifiers="const">
<return type="Vector2i" />
<argument index="0" name="line" type="int" />
@ -859,14 +846,6 @@
Sets the text for [code]gutter[/code] on [code]line[/code].
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
<method name="set_overtype_mode_enabled">
<return type="void" />
<argument index="0" name="enabled" type="bool" />

View File

@ -22,11 +22,10 @@
<method name="add_string">
<return type="bool" />
<argument index="0" name="text" type="String" />
<argument index="1" name="fonts" type="Font" />
<argument index="2" name="size" type="int" />
<argument index="3" name="opentype_features" type="Dictionary" default="{}" />
<argument index="4" name="language" type="String" default="&quot;&quot;" />
<argument index="5" name="meta" type="Variant" default="null" />
<argument index="1" name="font" type="Font" />
<argument index="2" name="font_size" type="int" />
<argument index="3" name="language" type="String" default="&quot;&quot;" />
<argument index="4" name="meta" type="Variant" default="null" />
<description>
Adds text span and font to draw it.
</description>

View File

@ -10,29 +10,6 @@
</description>
<tutorials>
</tutorials>
<methods>
<method name="clear_opentype_features">
<return type="void" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code].
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="tag" type="String" />
<argument index="1" name="value" type="int" />
<description>
Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
</description>
</method>
</methods>
<members>
<member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5">
Step (in pixels) used to approximate Bézier curves.
@ -41,7 +18,7 @@
Depths of the mesh, if set to [code]0.0[/code] only front surface, is generated, and UV layout is changed to use full texture for the front face only.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
[Font] used for the [TextMesh]'s text.
Font configuration used to display text.
</member>
<member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
Font size of the [TextMesh]'s text.

View File

@ -22,11 +22,10 @@
<method name="add_string">
<return type="bool" />
<argument index="0" name="text" type="String" />
<argument index="1" name="fonts" type="Font" />
<argument index="2" name="size" type="int" />
<argument index="3" name="opentype_features" type="Dictionary" default="{}" />
<argument index="4" name="language" type="String" default="&quot;&quot;" />
<argument index="5" name="meta" type="Variant" default="null" />
<argument index="1" name="font" type="Font" />
<argument index="2" name="font_size" type="int" />
<argument index="3" name="language" type="String" default="&quot;&quot;" />
<argument index="4" name="meta" type="Variant" default="null" />
<description>
Adds text span and font to draw it.
</description>
@ -217,18 +216,6 @@
Returns the size of the bounding box of the paragraph.
</description>
</method>
<method name="get_spacing_bottom" qualifiers="const">
<return type="int" />
<description>
Returns extra spacing at the bottom of the line. See [member Font.spacing_bottom].
</description>
</method>
<method name="get_spacing_top" qualifiers="const">
<return type="int" />
<description>
Returns extra spacing at the top of the line. See [member Font.spacing_top].
</description>
</method>
<method name="hit_test" qualifiers="const">
<return type="int" />
<argument index="0" name="coords" type="Vector2" />
@ -256,11 +243,10 @@
<method name="set_dropcap">
<return type="bool" />
<argument index="0" name="text" type="String" />
<argument index="1" name="fonts" type="Font" />
<argument index="2" name="size" type="int" />
<argument index="1" name="font" type="Font" />
<argument index="2" name="font_size" type="int" />
<argument index="3" name="dropcap_margins" type="Rect2" default="Rect2(0, 0, 0, 0)" />
<argument index="4" name="opentype_features" type="Dictionary" default="{}" />
<argument index="5" name="language" type="String" default="&quot;&quot;" />
<argument index="4" name="language" type="String" default="&quot;&quot;" />
<description>
Sets drop cap, overrides previously set drop cap. Drop cap (dropped capital) is a decorative element at the beginning of a paragraph that is larger than the rest of the text.
</description>

View File

@ -355,15 +355,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
<method name="font_get_spacing" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
<description>
Returns extra spacing added between glyphs in pixels.
</description>
</method>
<method name="font_get_style" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@ -542,7 +533,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
Removes specified texture from font cache entry.
Removes specified texture from the cache entry.
[b]Note:[/b] This function will not remove glyphs associated with the texture, remove them manually, using [method font_remove_glyph].
</description>
</method>
@ -792,16 +783,6 @@
Adds override for [method font_is_script_supported].
</description>
</method>
<method name="font_set_spacing">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="3" name="value" type="int" />
<description>
Sets extra spacing added between glyphs in pixels.
</description>
</method>
<method name="font_set_style">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@ -1286,6 +1267,14 @@
Returns size of the text.
</description>
</method>
<method name="shaped_text_get_spacing" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
<description>
Returns extra spacing added between glyphs or lines in pixels.
</description>
</method>
<method name="shaped_text_get_trim_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
@ -1431,6 +1420,15 @@
If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed.
</description>
</method>
<method name="shaped_text_set_spacing">
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="2" name="value" type="int" />
<description>
Sets extra spacing added between glyphs or lines in pixels.
</description>
</method>
<method name="shaped_text_shape">
<return type="bool" />
<argument index="0" name="shaped" type="RID" />

View File

@ -345,15 +345,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
<method name="font_get_spacing" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
<description>
Returns extra spacing added between glyphs in pixels.
</description>
</method>
<method name="font_get_style" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@ -531,7 +522,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
Removes specified texture from font cache entry.
Removes specified texture from the cache entry.
</description>
</method>
<method name="font_render_glyph" qualifiers="virtual">
@ -788,16 +779,6 @@
Adds override for [method font_is_script_supported].
</description>
</method>
<method name="font_set_spacing" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="size" type="int" />
<argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="3" name="value" type="int" />
<description>
Sets extra spacing added between glyphs in pixels.
</description>
</method>
<method name="font_set_style" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@ -1288,6 +1269,14 @@
Returns size of the text.
</description>
</method>
<method name="shaped_text_get_spacing" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
<description>
Returns extra spacing added between glyphs or lines in pixels.
</description>
</method>
<method name="shaped_text_get_trim_pos" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
@ -1436,6 +1425,15 @@
If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed.
</description>
</method>
<method name="shaped_text_set_spacing" qualifiers="virtual">
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
<argument index="2" name="value" type="int" />
<description>
Sets extra spacing added between glyphs or lines in pixels.
</description>
</method>
<method name="shaped_text_shape" qualifiers="virtual">
<return type="bool" />
<argument index="0" name="shaped" type="RID" />

View File

@ -334,8 +334,8 @@
<argument index="0" name="name" type="StringName" />
<argument index="1" name="theme_type" type="StringName" />
<description>
Returns [code]true[/code] if the font size property defined by [code]name[/code] and [code]theme_type[/code] exists, or if the default theme font size is set up (see [method has_default_font_size]).
Returns [code]false[/code] if neither exist. Use [method set_font_size] to define the property.
Returns [code]true[/code] if [member default_font_size] has a valid value.
Returns [code]false[/code] if it doesn't. The value must be greater than [code]0[/code] to be considered valid.
</description>
</method>
<method name="has_icon" qualifiers="const">
@ -426,8 +426,8 @@
<argument index="1" name="name" type="StringName" />
<argument index="2" name="theme_type" type="StringName" />
<description>
Renames the font size property defined by [code]old_name[/code] and [code]theme_type[/code] to [code]name[/code], if it exists.
Fails if it doesn't exist, or if a similar property with the new name already exists. Use [method has_font_size] to check for existence, and [method clear_font_size] to remove the existing property.
Returns [code]true[/code] if the font size property defined by [code]name[/code] and [code]theme_type[/code] exists, or if the default theme font size is set up (see [method has_default_font_size]).
Returns [code]false[/code] if neither exist. Use [method set_font_size] to define the property.
</description>
</method>
<method name="rename_icon">
@ -495,7 +495,8 @@
<argument index="1" name="theme_type" type="StringName" />
<argument index="2" name="font_size" type="int" />
<description>
Creates or changes the value of the font size property defined by [code]name[/code] and [code]theme_type[/code]. Use [method clear_font_size] to remove the property.
Renames the font size property defined by [code]old_name[/code] and [code]theme_type[/code] to [code]name[/code], if it exists.
Fails if it doesn't exist, or if a similar property with the new name already exists. Use [method has_font_size] to check for existence, and [method clear_font_size] to remove the existing property.
</description>
</method>
<method name="set_icon">

View File

@ -42,13 +42,6 @@
Clears the tree. This removes all items.
</description>
</method>
<method name="clear_column_title_opentype_features">
<return type="void" />
<argument index="0" name="column" type="int" />
<description>
Removes all OpenType features from the item's text.
</description>
</method>
<method name="create_item">
<return type="TreeItem" />
<argument index="0" name="parent" type="TreeItem" default="null" />
@ -114,14 +107,6 @@
Returns column title language code.
</description>
</method>
<method name="get_column_title_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="column" type="int" />
<argument index="1" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code] of the column title.
</description>
</method>
<method name="get_column_width" qualifiers="const">
<return type="int" />
<argument index="0" name="column" type="int" />
@ -308,15 +293,6 @@
Sets language code of column title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</description>
</method>
<method name="set_column_title_opentype_feature">
<return type="void" />
<argument index="0" name="column" type="int" />
<argument index="1" name="tag" type="String" />
<argument index="2" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code] for the column title.
</description>
</method>
</methods>
<members>
<member name="allow_reselect" type="bool" setter="set_allow_reselect" getter="get_allow_reselect" default="false">

View File

@ -42,13 +42,6 @@
Resets the color for the given column to default.
</description>
</method>
<method name="clear_opentype_features">
<return type="void" />
<argument index="0" name="column" type="int" />
<description>
Removes all OpenType features.
</description>
</method>
<method name="create_child">
<return type="TreeItem" />
<argument index="0" name="idx" type="int" default="-1" />
@ -241,14 +234,6 @@
If [code]wrap[/code] is enabled, the method will wrap around to the first visible element in the tree when called on the last visible element, otherwise it returns [code]null[/code].
</description>
</method>
<method name="get_opentype_feature" qualifiers="const">
<return type="int" />
<argument index="0" name="column" type="int" />
<argument index="1" name="tag" type="String" />
<description>
Returns OpenType feature [code]tag[/code] of the item's text.
</description>
</method>
<method name="get_parent" qualifiers="const">
<return type="TreeItem" />
<description>
@ -580,15 +565,6 @@
Sets the metadata value for the given column, which can be retrieved later using [method get_metadata]. This can be used, for example, to store a reference to the original data.
</description>
</method>
<method name="set_opentype_feature">
<return type="void" />
<argument index="0" name="column" type="int" />
<argument index="1" name="tag" type="String" />
<argument index="2" name="value" type="int" />
<description>
Sets OpenType feature [code]tag[/code] for the item's text.
</description>
</method>
<method name="set_range">
<return type="void" />
<argument index="0" name="column" type="int" />

View File

@ -1577,10 +1577,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
int decimals = 2;
bool step_found = false;
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;
const float period_width = font->get_char_size('.', font_size).width;
float max_digit_width = font->get_char_size('0', font_size).width;
for (int i = 1; i <= 9; i++) {
const float digit_width = font->get_char_size('0' + i, 0, font_size).width;
const float digit_width = font->get_char_size('0' + i, font_size).width;
max_digit_width = MAX(digit_width, max_digit_width);
}
const int max_sc = int(Math::ceil(zoomw / scale));
@ -1628,7 +1628,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
prev_frame_ofs = i + font->get_string_size(itos(frame), font_size).x + 5 * EDSCALE;
prev_frame_ofs = i + font->get_string_size(itos(frame), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + 5 * EDSCALE;
}
}
}

View File

@ -1636,31 +1636,39 @@ void CodeTextEditor::_apply_settings_change() {
_update_text_editor_theme();
font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
int ot_mode = EditorSettings::get_singleton()->get("interface/editor/code_font_contextual_ligatures");
Ref<Font> fb = text_editor->get_theme_font(SNAME("font"));
Ref<FontVariation> fc = fb;
if (fc.is_null()) {
fc.instantiate();
fc->set_base_font(fb);
}
switch (ot_mode) {
case 1: { // Disable ligatures.
text_editor->clear_opentype_features();
text_editor->set_opentype_feature("calt", 0);
fc->set_opentype_features(Dictionary());
} break;
case 2: { // Custom.
text_editor->clear_opentype_features();
Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
Dictionary ftrs;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
text_editor->set_opentype_feature(subtag_a[0], subtag_a[1].to_int());
ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
} else if (subtag_a.size() == 1) {
text_editor->set_opentype_feature(subtag_a[0], 1);
ftrs[TS->name_to_tag(subtag_a[0])] = 1;
}
}
fc->set_opentype_features(ftrs);
} break;
default: { // Default.
text_editor->clear_opentype_features();
text_editor->set_opentype_feature("calt", 1);
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
} break;
}
text_editor->add_theme_font_override("font", fc);
text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
@ -1862,29 +1870,36 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
int ot_mode = EditorSettings::get_singleton()->get("interface/editor/code_font_contextual_ligatures");
Ref<Font> fb = text_editor->get_theme_font(SNAME("font"));
Ref<FontVariation> fc = fb;
if (fc.is_null()) {
fc.instantiate();
fc->set_base_font(fb);
}
switch (ot_mode) {
case 1: { // Disable ligatures.
text_editor->clear_opentype_features();
text_editor->set_opentype_feature("calt", 0);
fc->set_opentype_features(Dictionary());
} break;
case 2: { // Custom.
text_editor->clear_opentype_features();
Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
Dictionary ftrs;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
text_editor->set_opentype_feature(subtag_a[0], subtag_a[1].to_int());
ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
} else if (subtag_a.size() == 1) {
text_editor->set_opentype_feature(subtag_a[0], 1);
ftrs[TS->name_to_tag(subtag_a[0])] = 1;
}
}
fc->set_opentype_features(ftrs);
} break;
default: { // Default.
text_editor->clear_opentype_features();
text_editor->set_opentype_feature("calt", 1);
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
} break;
}
text_editor->add_theme_font_override("font", fc);
text_editor->set_draw_line_numbers(true);
text_editor->set_highlight_matching_braces_enabled(true);

View File

@ -136,7 +136,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent(font_size)), current.item->get_text(0), HORIZONTAL_ALIGNMENT_LEFT, rect.size.x, font_size, draw_color);
draw_color.a = 0.9f;
float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1), font_size).width;
float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
if (value_position < 0) {
value_position = 0;
}
@ -184,7 +184,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE));
String label = _create_label(e->get(), current.type);
Size2 size = graph_font->get_string_size(label, font_size);
Size2 size = graph_font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN));
if (text_top_left_position.x < 0) {
text_top_left_position.x = from + MARKER_MARGIN;

View File

@ -469,7 +469,7 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), color * Color(1, 1, 1, 0.5));
const String limit_str = String::num(graph_limit, 2) + " ms";
graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
if (graph_height_gpu > 0) {
@ -480,11 +480,11 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), color * Color(1, 1, 1, 0.5));
const String limit_str = String::num(graph_limit, 2) + " ms";
graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
}
void EditorVisualProfiler::_graph_tex_mouse_exit() {

View File

@ -1394,7 +1394,7 @@ Size2 EditorAudioMeterNotches::get_minimum_size() const {
for (int i = 0; i < notches.size(); i++) {
if (notches[i].render_db_value) {
width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB", font_size).x);
width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x);
height += font_height;
}
}

View File

@ -37,212 +37,8 @@
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/font.h"
#define MAKE_FALLBACKS(m_name) \
m_name->add_data(FontArabic); \
m_name->add_data(FontBengali); \
m_name->add_data(FontDevanagari); \
m_name->add_data(FontGeorgian); \
m_name->add_data(FontHebrew); \
m_name->add_data(FontMalayalam); \
m_name->add_data(FontOriya); \
m_name->add_data(FontSinhala); \
m_name->add_data(FontTamil); \
m_name->add_data(FontTelugu); \
m_name->add_data(FontThai); \
m_name->add_data(FontJapanese); \
m_name->add_data(FontFallback);
// Note: In some languages, the use of italic/slanted fonts is controversial. Therefore, we are limiting simulated slant to the main font (Latin, Cyrillic, and Greek) and using bold fonts for the rest.
#define MAKE_FALLBACKS_SLANTED(m_name) \
m_name->add_data(FontArabicBold); \
m_name->add_data(FontBengaliBold); \
m_name->add_data(FontDevanagariBold); \
m_name->add_data(FontGeorgianBold); \
m_name->add_data(FontHebrewBold); \
m_name->add_data(FontMalayalamBold); \
m_name->add_data(FontOriyaBold); \
m_name->add_data(FontSinhalaBold); \
m_name->add_data(FontTamilBold); \
m_name->add_data(FontTeluguBold); \
m_name->add_data(FontThaiBold); \
m_name->add_data(FontJapaneseBold); \
m_name->add_data(FontFallbackBold);
#define MAKE_FALLBACKS_BOLD(m_name) \
m_name->add_data(FontArabicBold); \
m_name->add_data(FontBengaliBold); \
m_name->add_data(FontDevanagariBold); \
m_name->add_data(FontGeorgianBold); \
m_name->add_data(FontHebrewBold); \
m_name->add_data(FontMalayalamBold); \
m_name->add_data(FontOriyaBold); \
m_name->add_data(FontSinhalaBold); \
m_name->add_data(FontTamilBold); \
m_name->add_data(FontTeluguBold); \
m_name->add_data(FontThaiBold); \
m_name->add_data(FontJapaneseBold); \
m_name->add_data(FontFallbackBold);
#define MAKE_DEFAULT_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFont.is_valid()) { \
m_name->add_data(CustomFont); \
m_name->add_data(DefaultFont); \
} else { \
m_name->add_data(DefaultFont); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
#define MAKE_DEFAULT_FONT_MSDF(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFont.is_valid()) { \
m_name->add_data(CustomFontMSDF); \
m_name->add_data(DefaultFontMSDF); \
} else { \
m_name->add_data(DefaultFontMSDF); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
#define MAKE_SLANTED_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
m_name.instantiate(); \
if (CustomFontSlanted.is_valid()) { \
m_name->add_data(CustomFontSlanted); \
m_name->add_data(DefaultFontSlanted); \
} else { \
m_name->add_data(DefaultFontSlanted); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS_SLANTED(m_name);
#define MAKE_BOLD_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFontBold.is_valid()) { \
m_name->add_data(CustomFontBold); \
m_name->add_data(DefaultFontBold); \
} else { \
m_name->add_data(DefaultFontBold); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS_BOLD(m_name);
#define MAKE_BOLD_FONT_MSDF(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFontBold.is_valid()) { \
m_name->add_data(CustomFontBoldMSDF); \
m_name->add_data(DefaultFontBoldMSDF); \
} else { \
m_name->add_data(DefaultFontBoldMSDF); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS_BOLD(m_name);
#define MAKE_SOURCE_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFontSource.is_valid()) { \
m_name->add_data(CustomFontSource); \
m_name->add_data(dfmono); \
} else { \
m_name->add_data(dfmono); \
} \
{ \
Dictionary variations; \
if (!m_variations.is_empty()) { \
Vector<String> variation_tags = m_variations.split(","); \
for (int i = 0; i < variation_tags.size(); i++) { \
Vector<String> tokens = variation_tags[i].split("="); \
if (tokens.size() == 2) { \
variations[tokens[0]] = tokens[1].to_float(); \
} \
} \
} \
m_name->set_variation_coordinates(variations); \
} \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
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, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) {
Ref<FontData> font;
Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
Ref<FontFile> font;
font.instantiate();
Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
@ -254,11 +50,15 @@ Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hintin
font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning);
if (r_fallbacks != nullptr) {
r_fallbacks->push_back(font);
}
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, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) {
Ref<FontData> font;
Ref<FontFile> load_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, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
Ref<FontFile> font;
font.instantiate();
font->set_data_ptr(p_data, p_size);
@ -268,14 +68,29 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning);
if (r_fallbacks != nullptr) {
r_fallbacks->push_back(font);
}
return font;
}
Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, TypedArray<Font> *r_fallbacks = nullptr) {
Ref<FontVariation> font_var;
font_var.instantiate();
font_var->set_base_font(p_font);
font_var->set_variation_embolden(p_embolden);
if (r_fallbacks != nullptr) {
r_fallbacks->push_back(font_var);
}
return font_var;
}
void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
/* Custom font */
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");
@ -304,184 +119,251 @@ void editor_register_fonts(Ref<Theme> p_theme) {
break;
}
// Load built-in fonts.
const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
const float embolden_strength = 0.6;
Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false);
Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
TypedArray<Font> fallbacks;
Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
default_font->set_fallbacks(fallbacks);
default_font_msdf->set_fallbacks(fallbacks);
Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false);
Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
TypedArray<Font> fallbacks_bold;
Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold);
Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold);
default_font_bold->set_fallbacks(fallbacks_bold);
default_font_bold_msdf->set_fallbacks(fallbacks_bold);
Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
Dictionary opentype_features_mono;
opentype_features_mono["calt"] = 0;
default_font_mono->set_opentype_feature_overrides(opentype_features_mono); // Disable contextual alternates (coding ligatures).
}
default_font_mono->set_fallbacks(fallbacks);
// Init base font configs and load custom fonts.
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, font_subpixel_positioning);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
}
Ref<FontData> CustomFontMSDF;
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
CustomFontMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
}
Ref<FontData> CustomFontSlanted;
if (CustomFont.is_valid()) {
CustomFontSlanted = CustomFont->duplicate();
CustomFontSlanted->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
}
/* Custom Bold font */
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, font_subpixel_positioning);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
}
if (CustomFont.is_valid() && !CustomFontBold.is_valid()) {
CustomFontBold = CustomFont->duplicate();
CustomFontBold->set_embolden(embolden_strength);
}
Ref<FontData> CustomFontBoldMSDF;
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
CustomFontBoldMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
}
/* Custom source code font */
String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
Ref<FontData> CustomFontSource;
Ref<FontVariation> default_fc;
default_fc.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font);
custom_font->set_fallbacks(fallback_custom);
}
default_fc->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
default_fc->set_base_font(default_font);
}
default_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
default_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
Ref<FontVariation> default_fc_msdf;
default_fc_msdf.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_msdf);
custom_font->set_fallbacks(fallback_custom);
}
default_fc_msdf->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
default_fc_msdf->set_base_font(default_font_msdf);
}
default_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
default_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
Ref<FontVariation> bold_fc;
bold_fc.instantiate();
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold);
custom_font->set_fallbacks(fallback_custom);
}
bold_fc->set_base_font(custom_font);
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold);
custom_font->set_fallbacks(fallback_custom);
}
bold_fc->set_base_font(custom_font);
bold_fc->set_variation_embolden(embolden_strength);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
bold_fc->set_base_font(default_font_bold);
}
bold_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
bold_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
Ref<FontVariation> bold_fc_msdf;
bold_fc_msdf.instantiate();
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold_msdf);
custom_font->set_fallbacks(fallback_custom);
}
bold_fc_msdf->set_base_font(custom_font);
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold_msdf);
custom_font->set_fallbacks(fallback_custom);
}
bold_fc_msdf->set_base_font(custom_font);
bold_fc_msdf->set_variation_embolden(embolden_strength);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
bold_fc_msdf->set_base_font(default_font_bold_msdf);
}
bold_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
bold_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
Ref<FontVariation> mono_fc;
mono_fc.instantiate();
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, font_subpixel_positioning);
Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning);
{
TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_mono);
custom_font->set_fallbacks(fallback_custom);
}
mono_fc->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
mono_fc->set_base_font(default_font_mono);
}
/* Noto Sans */
String code_font_custom_variations = EditorSettings::get_singleton()->get("interface/editor/code_font_custom_variations");
Dictionary variations_mono;
if (!code_font_custom_variations.is_empty()) {
Vector<String> variation_tags = code_font_custom_variations.split(",");
for (int i = 0; i < variation_tags.size(); i++) {
Vector<String> subtag_a = variation_tags[i].split("=");
if (subtag_a.size() == 2) {
variations_mono[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_float();
} else if (subtag_a.size() == 1) {
variations_mono[TS->name_to_tag(subtag_a[0])] = 1;
}
}
mono_fc->set_variation_opentype(variations_mono);
}
mono_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
mono_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
Ref<FontData> DefaultFontMSDF = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
Ref<FontData> DefaultFontBold = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
Ref<FontData> DefaultFontBoldMSDF = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
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);
Ref<FontVariation> italic_fc = default_fc->duplicate();
italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
Ref<FontData> DefaultFontSlanted = DefaultFont->duplicate();
DefaultFontSlanted->set_transform(Transform2D(1.0, 0.3, 0.0, 1.0, 0.0, 0.0));
// Setup theme.
/* Droid Sans */
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);
Ref<FontData> FontFallbackBold = FontFallback->duplicate();
FontFallbackBold->set_embolden(embolden_strength);
Ref<FontData> FontJapaneseBold = FontJapanese->duplicate();
FontJapaneseBold->set_embolden(embolden_strength);
/* Hack */
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).
// Default font
MAKE_DEFAULT_FONT(df, String());
p_theme->set_default_font(df); // Default theme font
p_theme->set_default_font(default_fc); // Default theme font config.
p_theme->set_default_font_size(default_font_size);
// Main font.
p_theme->set_font("main", "EditorFonts", default_fc);
p_theme->set_font("main_msdf", "EditorFonts", default_fc_msdf);
p_theme->set_font_size("main_size", "EditorFonts", default_font_size);
p_theme->set_font("main", "EditorFonts", df);
MAKE_DEFAULT_FONT_MSDF(df_msdf, String());
p_theme->set_font("main_msdf", "EditorFonts", df_msdf);
// Bold font
MAKE_BOLD_FONT(df_bold, String());
MAKE_SLANTED_FONT(df_italic, String());
p_theme->set_font("bold", "EditorFonts", bold_fc);
p_theme->set_font("main_bold_msdf", "EditorFonts", bold_fc_msdf);
p_theme->set_font_size("bold_size", "EditorFonts", default_font_size);
p_theme->set_font("bold", "EditorFonts", df_bold);
MAKE_BOLD_FONT_MSDF(df_bold_msdf, String());
p_theme->set_font("main_bold_msdf", "EditorFonts", df_bold_msdf);
// Title font.
// Title font
p_theme->set_font("title", "EditorFonts", bold_fc);
p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 1 * EDSCALE);
p_theme->set_font("title", "EditorFonts", df_bold);
p_theme->set_font("main_button_font", "EditorFonts", bold_fc);
p_theme->set_font_size("main_button_font_size", "EditorFonts", default_font_size + 1 * EDSCALE);
p_theme->set_font("main_button_font", "EditorFonts", df_bold);
p_theme->set_font("font", "Label", df);
p_theme->set_font("font", "Label", default_fc);
p_theme->set_type_variation("HeaderSmall", "Label");
p_theme->set_font("font", "HeaderSmall", df_bold);
p_theme->set_font("font", "HeaderSmall", bold_fc);
p_theme->set_font_size("font_size", "HeaderSmall", default_font_size);
p_theme->set_type_variation("HeaderMedium", "Label");
p_theme->set_font("font", "HeaderMedium", df_bold);
p_theme->set_font("font", "HeaderMedium", bold_fc);
p_theme->set_font_size("font_size", "HeaderMedium", default_font_size + 1 * EDSCALE);
p_theme->set_type_variation("HeaderLarge", "Label");
p_theme->set_font("font", "HeaderLarge", df_bold);
p_theme->set_font("font", "HeaderLarge", bold_fc);
p_theme->set_font_size("font_size", "HeaderLarge", default_font_size + 3 * EDSCALE);
// Documentation fonts
String code_font_custom_variations = EditorSettings::get_singleton()->get("interface/editor/code_font_custom_variations");
MAKE_SOURCE_FONT(df_code, code_font_custom_variations);
p_theme->set_font_size("doc_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df);
p_theme->set_font("doc_bold", "EditorFonts", df_bold);
p_theme->set_font("doc_italic", "EditorFonts", df_italic);
p_theme->set_font("doc", "EditorFonts", default_fc);
p_theme->set_font("doc_bold", "EditorFonts", bold_fc);
p_theme->set_font("doc_italic", "EditorFonts", italic_fc);
p_theme->set_font_size("doc_title_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE);
p_theme->set_font("doc_title", "EditorFonts", df_bold);
p_theme->set_font("doc_title", "EditorFonts", bold_fc);
p_theme->set_font_size("doc_source_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE);
p_theme->set_font("doc_source", "EditorFonts", df_code);
p_theme->set_font("doc_source", "EditorFonts", mono_fc);
p_theme->set_font_size("doc_keyboard_size", "EditorFonts", (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE);
p_theme->set_font("doc_keyboard", "EditorFonts", df_code);
p_theme->set_font("doc_keyboard", "EditorFonts", mono_fc);
// Ruler font
p_theme->set_font_size("rulers_size", "EditorFonts", 8 * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df);
p_theme->set_font("rulers", "EditorFonts", default_fc);
// Rotation widget font
p_theme->set_font_size("rotation_control_size", "EditorFonts", 14 * EDSCALE);
p_theme->set_font("rotation_control", "EditorFonts", df);
p_theme->set_font("rotation_control", "EditorFonts", default_fc);
// Code font
p_theme->set_font_size("source_size", "EditorFonts", int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE);
p_theme->set_font("source", "EditorFonts", df_code);
p_theme->set_font("source", "EditorFonts", mono_fc);
p_theme->set_font_size("expression_size", "EditorFonts", (int(EDITOR_GET("interface/editor/code_font_size")) - 1) * EDSCALE);
p_theme->set_font("expression", "EditorFonts", df_code);
p_theme->set_font("expression", "EditorFonts", mono_fc);
p_theme->set_font_size("output_source_size", "EditorFonts", int(EDITOR_GET("run/output/font_size")) * EDSCALE);
p_theme->set_font("output_source", "EditorFonts", df_code);
p_theme->set_font("output_source", "EditorFonts", mono_fc);
p_theme->set_font_size("status_source_size", "EditorFonts", default_font_size);
p_theme->set_font("status_source", "EditorFonts", df_code);
p_theme->set_font("status_source", "EditorFonts", mono_fc);
}

View File

@ -183,7 +183,7 @@ void EditorHelp::_class_desc_resized(bool p_force_update_theme) {
// The margins increase as the width of the editor help container increases.
Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("doc_source_size"), SNAME("EditorFonts"));
real_t char_width = doc_code_font->get_char_size('x', 0, font_size).width;
real_t char_width = doc_code_font->get_char_size('x', font_size).width;
const int new_display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5;
if (display_margin != new_display_margin || p_force_update_theme) {
display_margin = new_display_margin;

View File

@ -322,7 +322,7 @@ void EditorProperty::_notification(int p_what) {
Ref<Texture2D> pinned_icon = get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"));
int margin_w = get_theme_constant(SNAME("hseparator"), SNAME("Tree")) * 2;
int total_icon_w = margin_w + pinned_icon->get_width();
int text_w = font->get_string_size(label, font_size, rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT, text_limit - total_icon_w).x;
int text_w = font->get_string_size(label, rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT, text_limit - total_icon_w, font_size).x;
int y = (size.height - pinned_icon->get_height()) / 2;
if (rtl) {
draw_texture(pinned_icon, Vector2(size.width - ofs - text_w - total_icon_w, y), color);
@ -1087,7 +1087,7 @@ void EditorInspectorCategory::_notification(int p_what) {
int hs = get_theme_constant(SNAME("h_separation"), SNAME("Tree"));
int w = font->get_string_size(label, font_size).width;
int w = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
if (icon.is_valid()) {
w += hs + icon->get_width();
}
@ -3429,6 +3429,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
if (editor_property_map.has(p_path)) {
for (EditorProperty *E : editor_property_map[p_path]) {
E->set_checked(p_checked);
E->update_property();
E->update_revert_and_pin_status();
E->update_cache();

View File

@ -146,7 +146,7 @@
#include "editor/plugins/debugger_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/font_editor_plugin.h"
#include "editor/plugins/font_config_plugin.h"
#include "editor/plugins/gdextension_export_plugin.h"
#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
@ -165,7 +165,6 @@
#include "editor/plugins/navigation_polygon_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/occluder_instance_3d_editor_plugin.h"
#include "editor/plugins/ot_features_plugin.h"
#include "editor/plugins/packed_scene_translation_parser_plugin.h"
#include "editor/plugins/path_2d_editor_plugin.h"
#include "editor/plugins/path_3d_editor_plugin.h"
@ -187,7 +186,6 @@
#include "editor/plugins/sprite_frames_editor_plugin.h"
#include "editor/plugins/style_box_editor_plugin.h"
#include "editor/plugins/sub_viewport_preview_editor_plugin.h"
#include "editor/plugins/text_control_editor_plugin.h"
#include "editor/plugins/text_editor.h"
#include "editor/plugins/texture_3d_editor_plugin.h"
#include "editor/plugins/texture_editor_plugin.h"
@ -7125,7 +7123,6 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(CollisionShape2DEditorPlugin));
add_editor_plugin(memnew(CurveEditorPlugin));
add_editor_plugin(memnew(FontEditorPlugin));
add_editor_plugin(memnew(OpenTypeFeaturesEditorPlugin));
add_editor_plugin(memnew(TextureEditorPlugin));
add_editor_plugin(memnew(TextureLayeredEditorPlugin));
add_editor_plugin(memnew(Texture3DEditorPlugin));
@ -7140,7 +7137,6 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin));
add_editor_plugin(memnew(InputEventEditorPlugin));
add_editor_plugin(memnew(SubViewportPreviewEditorPlugin));
add_editor_plugin(memnew(TextControlEditorPlugin));
add_editor_plugin(memnew(ControlEditorPlugin));
add_editor_plugin(memnew(GradientTexture2DEditorPlugin));
add_editor_plugin(memnew(BitMapEditorPlugin));

View File

@ -534,8 +534,6 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin
p_vector->insert("Texture2D");
} else if (base == "ShaderMaterial") {
p_vector->insert("Shader");
} else if (base == "Font") {
p_vector->insert("FontData");
} else if (base == "Texture2D") {
p_vector->insert("Image");
}
@ -675,16 +673,6 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_
break;
}
if (at == "Font" && Ref<FontData>(dropped_resource).is_valid()) {
Ref<Font> font = edited_resource;
if (!font.is_valid()) {
font.instantiate();
}
font->add_data(dropped_resource);
dropped_resource = font;
break;
}
if (at == "Texture2D" && Ref<Image>(dropped_resource).is_valid()) {
Ref<ImageTexture> texture = edited_resource;
if (!texture.is_valid()) {

View File

@ -444,6 +444,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Inspector
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/inspector/max_array_dictionary_items_per_page", 20, "10,100,1")
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/inspector/show_low_level_opentype_features", false, "")
// Theme
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Custom")

View File

@ -286,7 +286,7 @@ void EditorSpinSlider::_draw_spin_slider() {
int sep_base = 4 * EDSCALE;
int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
int label_width = font->get_string_size(label, font_size).width;
int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
int number_width = size.width - sb->get_minimum_size().width - label_width - sep;
Ref<Texture2D> updown = get_theme_icon(is_read_only() ? SNAME("updown_disabled") : SNAME("updown"), SNAME("SpinBox"));
@ -324,7 +324,10 @@ void EditorSpinSlider::_draw_spin_slider() {
int suffix_start = numstr.length();
RID num_rid = TS->create_shaped_text();
TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size);
TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size, font->get_opentype_features());
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(num_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep);
Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);

View File

@ -764,8 +764,8 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
int font_size = _results_display->get_theme_font_size(SNAME("font_size"));
Rect2 match_rect = rect;
match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), font_size).x;
match_rect.size.x = font->get_string_size(_search_text_label->get_text(), font_size).x;
match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
match_rect.size.x = font->get_string_size(_search_text_label->get_text(), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
match_rect.position.y += 1 * EDSCALE;
match_rect.size.y -= 2 * EDSCALE;

View File

@ -1 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m1 1037.4h14v2h-14z"/><path d="m7 1037.4h2v14h-2z"/><path d="m5 1050.4h6v1h-6z"/><path d="m1037.4-2h4v1h-4z" transform="rotate(90)"/><path d="m1037.4-15h4v1h-4z" transform="rotate(90)"/><path d="m2 3v2a2 2 0 0 1 2-2z" transform="translate(0 1036.4)"/><path d="m12 3a2 2 0 0 1 2 2v-2z" transform="translate(0 1036.4)"/><path d="m5 1050.4a2 2 0 0 0 2-2v2z"/><path d="m11 1050.4a2 2 0 0 1 -2-2v2z"/></g></svg>
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="M1 1h14v2H1z"/><path d="M7 1h2v14H7z"/><path d="M5 14h6v1H5zM2 1v4H1V1zm13 0v4h-1V1zM2 3v2a2 2 0 0 1 2-2zm10 0a2 2 0 0 1 2 2V3zM5 14a2 2 0 0 0 2-2v2zm6 0a2 2 0 0 1-2-2v2z"/></g></svg>

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 274 B

View File

@ -1 +0,0 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2zm0 5v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2zm3 0v2h2v-2z" fill="#e0e0e0"/><path d="m4 5v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#ff5f5f"/></svg>

Before

Width:  |  Height:  |  Size: 394 B

View File

@ -0,0 +1 @@
<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V3h2a1 1 0 0 1 1 1h1V1h-6Z" fill="#e0e0e0"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6Z" fill="#ff5f5f"/></svg>

After

Width:  |  Height:  |  Size: 302 B

View File

@ -0,0 +1 @@
<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M2.437 1 1.379 4h1A.84 1.192 50 0 1 3.73 3h2L3.615 9a.84 1.192 50 0 1-1.352 1l-.353 1h4l.353-1a.84 1.192 50 0 1-.648-1l2.116-6h2a.84 1.192 50 0 1 .648 1h1l1.058-3h-6Z" fill="#e0e0e0"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6Z" fill="#ff5f5f"/></svg>

After

Width:  |  Height:  |  Size: 505 B

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,30 @@
#include "scene/resources/font.h"
#include "servers/text_server.h"
class DynamicFontImportSettingsData;
class DynamicFontImportSettings;
class DynamicFontImportSettingsData : public RefCounted {
GDCLASS(DynamicFontImportSettingsData, RefCounted)
friend class DynamicFontImportSettings;
HashMap<StringName, Variant> settings;
HashMap<StringName, Variant> defaults;
List<ResourceImporter::ImportOption> options;
DynamicFontImportSettings *owner = nullptr;
HashSet<char32_t> selected_chars;
HashSet<int32_t> selected_glyphs;
Ref<FontFile> fd;
public:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
Ref<FontFile> get_font() const;
};
class EditorFileDialog;
class EditorInspector;
class EditorLocaleDialog;
@ -67,21 +90,19 @@ class DynamicFontImportSettings : public ConfirmationDialog {
List<ResourceImporter::ImportOption> options_variations;
List<ResourceImporter::ImportOption> options_general;
EditorLocaleDialog *locale_select = nullptr;
Vector<String> script_codes;
// Root layout
Label *label_warn = nullptr;
TabContainer *main_pages = nullptr;
// Page 1 layout: Rendering Options
Label *page1_description = nullptr;
Label *font_name_label = nullptr;
Label *font_preview_label = nullptr;
EditorInspector *inspector_general = nullptr;
void _main_prop_changed(const String &p_edited_property);
// Page 2 layout: Configurations
// Page 2 layout: Preload Configurations
Label *page2_description = nullptr;
Label *label_vars = nullptr;
Button *add_var = nullptr;
@ -95,19 +116,23 @@ class DynamicFontImportSettings : public ConfirmationDialog {
void _variation_changed(const String &p_edited_property);
void _variations_validate();
// Page 3 layout: Text to select glyphs
Label *page3_description = nullptr;
TabContainer *preload_pages = nullptr;
// Page 2.1 layout: Text to select glyphs
Label *page2_1_description = nullptr;
Label *label_glyphs = nullptr;
TextEdit *text_edit = nullptr;
LineEdit *ftr_edit = nullptr;
LineEdit *lang_edit = nullptr;
EditorInspector *inspector_text = nullptr;
List<ResourceImporter::ImportOption> options_text;
Ref<DynamicFontImportSettingsData> text_settings_data;
void _change_text_opts();
void _glyph_text_selected();
void _glyph_clear();
// Page 4 layout: Character map
Label *page4_description = nullptr;
// Page 2.2 layout: Character map
Label *page2_2_description = nullptr;
Tree *glyph_table = nullptr;
Tree *glyph_tree = nullptr;
TreeItem *glyph_root = nullptr;
@ -119,51 +144,12 @@ class DynamicFontImportSettings : public ConfirmationDialog {
bool _char_update(int32_t p_char);
void _range_update(int32_t p_start, int32_t p_end);
// Page 5 layout: Metadata override
Label *page5_description = nullptr;
Button *add_lang = nullptr;
Button *add_script = nullptr;
Button *add_ot = nullptr;
PopupMenu *menu_scripts = nullptr;
PopupMenu *menu_ot = nullptr;
PopupMenu *menu_ot_ss = nullptr;
PopupMenu *menu_ot_cv = nullptr;
PopupMenu *menu_ot_cu = nullptr;
Tree *lang_list = nullptr;
TreeItem *lang_list_root = nullptr;
Label *label_langs = nullptr;
Tree *script_list = nullptr;
TreeItem *script_list_root = nullptr;
Label *label_script = nullptr;
Tree *ot_list = nullptr;
TreeItem *ot_list_root = nullptr;
Label *label_ot = nullptr;
void _lang_add();
void _lang_add_item(const String &p_locale);
void _lang_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _script_add();
void _script_add_item(int p_option);
void _script_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _ot_add();
void _ot_add_item(int p_option);
void _ot_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
// Common
void _add_glyph_range_item(int32_t p_start, int32_t p_end, const String &p_name);
Ref<Font> font_preview;
Ref<Font> font_main;
RBSet<char32_t> selected_chars;
RBSet<int32_t> selected_glyphs;
Ref<FontFile> font_preview;
Ref<FontFile> font_main;
void _re_import();

View File

@ -52,7 +52,7 @@ String ResourceImporterBMFont::get_save_extension() const {
}
String ResourceImporterBMFont::get_resource_type() const {
return "FontData";
return "FontFile";
}
bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@ -60,19 +60,25 @@ bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const S
}
void ResourceImporterBMFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing BMFont font from: " + p_source_file);
Ref<FontData> font;
Array fallbacks = p_options["fallbacks"];
Ref<FontFile> font;
font.instantiate();
Error err = font->load_bitmap_font(p_source_file);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load font to file \"" + p_source_file + "\".");
int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
font->set_fallbacks(fallbacks);
int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}

View File

@ -66,7 +66,7 @@ String ResourceImporterDynamicFont::get_save_extension() const {
}
String ResourceImporterDynamicFont::get_resource_type() const {
return "FontData";
return "FontFile";
}
bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@ -103,7 +103,7 @@ String ResourceImporterDynamicFont::get_preset_name(int p_idx) const {
void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
bool msdf = p_preset == PRESET_MSDF;
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "face_index"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
@ -114,63 +114,19 @@ 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, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
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::NIL, "Fallbacks", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides"), Dictionary()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/char_ranges"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/glyph_ranges"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/configurations"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/language_enabled"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/language_disabled"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/script_enabled"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/script_disabled"), Vector<String>()));
}
bool ResourceImporterDynamicFont::_decode_variation(const String &p_token, Dictionary &r_variations, Vector2i &r_size, String &r_name, Vector2i &r_spacing) {
Vector<String> tokens = p_token.split("=");
if (tokens.size() == 2) {
if (tokens[0] == "name") {
r_name = tokens[1];
} else if (tokens[0] == "size") {
r_size.x = tokens[1].to_int();
} else if (tokens[0] == "outline_size") {
r_size.y = tokens[1].to_int();
} else if (tokens[0] == "spacing_space") {
r_spacing.x = tokens[1].to_int();
} else if (tokens[0] == "spacing_glyph") {
r_spacing.y = tokens[1].to_int();
} else {
r_variations[tokens[0]] = tokens[1].to_float();
}
return true;
} else {
WARN_PRINT("Invalid variation: '" + p_token + "'.");
return false;
}
}
bool ResourceImporterDynamicFont::_decode_range(const String &p_token, int32_t &r_pos) {
if (p_token.begins_with("U+") || p_token.begins_with("u+") || p_token.begins_with("0x")) {
// Unicode character hex index.
r_pos = p_token.substr(2).hex_to_int();
return true;
} else if (p_token.length() == 3 && p_token[0] == '\'' && p_token[2] == '\'') {
// Unicode character.
r_pos = p_token.unicode_at(1);
return true;
} else if (p_token.is_numeric()) {
// Unicode character decimal index.
r_pos = p_token.to_int();
return true;
} else {
return false;
}
// Hide from the main UI, only for advanced import dialog.
r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "preload", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "language_support", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "script_support", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_features", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
}
bool ResourceImporterDynamicFont::has_advanced_options() const {
@ -183,30 +139,26 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) {
Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing dynamic font from: " + p_source_file);
int face_index = p_options["face_index"];
bool antialiased = p_options["antialiased"];
bool generate_mipmaps = p_options["generate_mipmaps"];
bool msdf = p_options["multichannel_signed_distance_field"];
int px_range = p_options["msdf_pixel_range"];
int px_size = p_options["msdf_size"];
Dictionary ot_ov = p_options["opentype_feature_overrides"];
Dictionary ot_ov = p_options["opentype_features"];
bool autohinter = p_options["force_autohinter"];
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
real_t embolden = p_options["embolden"];
Transform2D transform = p_options["transform"];
Array fallbacks = p_options["fallbacks"];
// Load base font data.
Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
// Create font.
Ref<FontData> font;
Ref<FontFile> font;
font.instantiate();
font->set_data(data);
font->set_face_index(face_index);
font->set_antialiased(antialiased);
font->set_generate_mipmaps(generate_mipmaps);
font->set_multichannel_signed_distance_field(msdf);
@ -216,105 +168,52 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_fixed_size(0);
font->set_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
font->set_embolden(embolden);
font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);
font->set_fallbacks(fallbacks);
Vector<String> lang_en = p_options["support_overrides/language_enabled"];
for (int i = 0; i < lang_en.size(); i++) {
font->set_language_support_override(lang_en[i], true);
Dictionary langs = p_options["language_support"];
for (int i = 0; i < langs.size(); i++) {
String key = langs.get_key_at_index(i);
bool enabled = langs.get_value_at_index(i);
font->set_language_support_override(key, enabled);
}
Vector<String> lang_dis = p_options["support_overrides/language_disabled"];
for (int i = 0; i < lang_dis.size(); i++) {
font->set_language_support_override(lang_dis[i], false);
Dictionary scripts = p_options["script_support"];
for (int i = 0; i < scripts.size(); i++) {
String key = scripts.get_key_at_index(i);
bool enabled = scripts.get_value_at_index(i);
font->set_script_support_override(key, enabled);
}
Vector<String> scr_en = p_options["support_overrides/script_enabled"];
for (int i = 0; i < scr_en.size(); i++) {
font->set_script_support_override(scr_en[i], true);
}
Array preload_configurations = p_options["preload"];
Vector<String> scr_dis = p_options["support_overrides/script_disabled"];
for (int i = 0; i < scr_dis.size(); i++) {
font->set_script_support_override(scr_dis[i], false);
}
for (int i = 0; i < preload_configurations.size(); i++) {
Dictionary preload_config = preload_configurations[i];
Vector<String> variations = p_options["preload/configurations"];
Vector<String> char_ranges = p_options["preload/char_ranges"];
Vector<String> gl_ranges = p_options["preload/glyph_ranges"];
Dictionary variation = preload_config.has("variation_opentype") ? preload_config["variation_opentype"].operator Dictionary() : Dictionary();
double embolden = preload_config.has("variation_embolden") ? preload_config["variation_embolden"].operator double() : 0;
int face_index = preload_config.has("variation_face_index") ? preload_config["variation_face_index"].operator int() : 0;
Transform2D transform = preload_config.has("variation_transform") ? preload_config["variation_transform"].operator Transform2D() : Transform2D();
Vector2i size = preload_config.has("size") ? preload_config["size"].operator Vector2i() : Vector2i(16, 0);
String name = preload_config.has("name") ? preload_config["name"].operator String() : vformat("Configuration %d", i);
for (int i = 0; i < variations.size(); i++) {
String name;
Dictionary var;
Vector2i size = Vector2(16, 0);
Vector2i spacing;
RID conf_rid = font->find_variation(variation, face_index, embolden, transform);
Vector<String> variation_tags = variations[i].split(",");
for (int j = 0; j < variation_tags.size(); j++) {
if (!_decode_variation(variation_tags[j], var, size, name, spacing)) {
WARN_PRINT(vformat(TTR("Invalid variation: \"%s\""), variations[i]));
continue;
}
}
RID conf = font->find_cache(var);
for (int j = 0; j < char_ranges.size(); j++) {
int32_t start, end;
Vector<String> tokens = char_ranges[j].split("-");
if (tokens.size() == 2) {
if (!_decode_range(tokens[0], start) || !_decode_range(tokens[1], end)) {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
continue;
}
} else if (tokens.size() == 1) {
if (!_decode_range(tokens[0], start)) {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
continue;
}
end = start;
} else {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
continue;
}
// Preload character ranges for each variations / sizes.
print_verbose(vformat(TTR("Pre-rendering range U+%s...%s from configuration \"%s\" (%d / %d)..."), String::num_int64(start, 16), String::num_int64(end, 16), name, i + 1, variations.size()));
TS->font_render_range(conf, size, start, end);
Array chars = preload_config["chars"];
for (int j = 0; j < chars.size(); j++) {
char32_t c = chars[j].operator int();
TS->font_render_range(conf_rid, size, c, c);
}
for (int j = 0; j < gl_ranges.size(); j++) {
int32_t start, end;
Vector<String> tokens = gl_ranges[j].split("-");
if (tokens.size() == 2) {
if (!_decode_range(tokens[0], start) || !_decode_range(tokens[1], end)) {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
continue;
}
} else if (tokens.size() == 1) {
if (!_decode_range(tokens[0], start)) {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
continue;
}
end = start;
} else {
WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
continue;
}
// Preload glyph range for each variations / sizes.
print_verbose(vformat(TTR("Pre-rendering glyph range 0x%s...%s from configuration \"%s\" (%d / %d)..."), String::num_int64(start, 16), String::num_int64(end, 16), name, i + 1, variations.size()));
for (int32_t k = start; k <= end; k++) {
TS->font_render_glyph(conf, size, k);
}
Array glyphs = preload_config["glyphs"];
for (int j = 0; j < glyphs.size(); j++) {
int32_t c = glyphs[j];
TS->font_render_glyph(conf_rid, size, c);
}
TS->font_set_spacing(conf, size.x, TextServer::SPACING_SPACE, spacing.x);
TS->font_set_spacing(conf, size.x, TextServer::SPACING_GLYPH, spacing.y);
}
int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}

View File

@ -43,9 +43,6 @@ class ResourceImporterDynamicFont : public ResourceImporter {
};
public:
static bool _decode_range(const String &p_token, int32_t &r_pos);
static bool _decode_variation(const String &p_token, Dictionary &r_variations, Vector2i &r_size, String &r_name, Vector2i &r_spacing);
virtual String get_importer_name() const override;
virtual String get_visible_name() const override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;

View File

@ -52,7 +52,7 @@ String ResourceImporterImageFont::get_save_extension() const {
}
String ResourceImporterImageFont::get_resource_type() const {
return "FontData";
return "FontFile";
}
bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@ -64,6 +64,9 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "font_size"), 14));
r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
@ -92,8 +95,9 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
int rows = p_options["rows"];
int base_size = p_options["font_size"];
Vector<String> ranges = p_options["character_ranges"];
Array fallbacks = p_options["fallbacks"];
Ref<FontData> font;
Ref<FontFile> font;
font.instantiate();
font->set_antialiased(false);
font->set_generate_mipmaps(false);
@ -103,6 +107,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
font->set_force_autohinter(false);
font->set_hinting(TextServer::HINTING_NONE);
font->set_oversampling(1.0f);
font->set_fallbacks(fallbacks);
Ref<Image> img;
img.instantiate();
@ -145,10 +150,10 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range.");
}
}
font->set_ascent(0, base_size, 0.5 * chr_height);
font->set_descent(0, base_size, 0.5 * chr_height);
font->set_cache_ascent(0, base_size, 0.5 * chr_height);
font->set_cache_descent(0, base_size, 0.5 * chr_height);
int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}

View File

@ -565,7 +565,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
String num = String::num(vertex.vertex);
Size2 num_size = font->get_string_size(num, font_size);
Size2 num_size = font->get_string_size(num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
p_overlay->draw_string(font, point - num_size * 0.5, num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
}

View File

@ -1224,7 +1224,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<StyleBox> sb = selected_nodes.has(E) ? style_selected : style;
Size2 s = sb->get_minimum_size();
int strsize = font->get_string_size(name, font_size).width;
int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
s.width += strsize;
s.height += MAX(font->get_height(font_size), play->get_height());
s.width += sep + play->get_width();
@ -1379,7 +1379,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<AnimationNode> anode = state_machine->get_node(name);
bool needs_editor = AnimationTreeEditor::get_singleton()->can_edit(anode);
Ref<StyleBox> sb = selected_nodes.has(name) ? style_selected : style;
int strsize = font->get_string_size(name, font_size).width;
int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
NodeRect &nr = node_rects.write[i];
Vector2 offset = nr.node.position;

View File

@ -2677,7 +2677,7 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string
color.a = 0.8;
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Size2 text_size = font->get_string_size(p_string, font_size);
Size2 text_size = font->get_string_size(p_string, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
switch (p_side) {
case SIDE_LEFT:
p_position += Vector2(-text_size.x - 5, text_size.y / 2);
@ -2749,16 +2749,18 @@ void CanvasItemEditor::_draw_guides() {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)));
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Size2 text_size = font->get_string_size(str, font_size);
viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color);
Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
viewport->draw_string_outline(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
}
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)));
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
Size2 text_size = font->get_string_size(str, font_size);
viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color);
Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
viewport->draw_string_outline(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
}
}
@ -2970,13 +2972,15 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
if (begin.is_equal_approx(end)) {
viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
viewport->draw_texture(get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons")), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
return;
}
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
@ -2994,16 +2998,19 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 v_angle_text_pos = Point2();
v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 h_angle_text_pos = Point2();
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
@ -3020,7 +3027,8 @@ void CanvasItemEditor::_draw_ruler_tool() {
h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
}
}
viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
// Angle arcs
int arc_point_count = 8;
@ -3055,17 +3063,21 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2);
if (draw_secondary_lines) {
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
} else {
viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
}
}
} else {
@ -3611,7 +3623,7 @@ void CanvasItemEditor::_draw_hover() {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Size2 node_name_size = font->get_string_size(node_name, font_size);
Size2 node_name_size = font->get_string_size(node_name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3));
Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4);
@ -3685,7 +3697,7 @@ void CanvasItemEditor::_draw_transform_message() {
return;
}
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
Ref<FontFile> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Point2 msgpos = Point2(RULER_WIDTH + 5 * EDSCALE, viewport->get_size().y - 20 * EDSCALE);
viewport->draw_string(font, msgpos + Point2(1, 1), transform_message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8));

View File

@ -812,19 +812,12 @@ void EditorFontPreviewPlugin::_preview_done() {
}
bool EditorFontPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "FontData") || ClassDB::is_parent_class(p_type, "Font");
return ClassDB::is_parent_class(p_type, "Font");
}
Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const {
Ref<Resource> res = ResourceLoader::load(p_path);
ERR_FAIL_COND_V(res.is_null(), Ref<Texture2D>());
Ref<Font> sampled_font;
if (res->is_class("Font")) {
sampled_font = res->duplicate();
} else if (res->is_class("FontData")) {
sampled_font.instantiate();
sampled_font->add_data(res->duplicate());
}
Ref<Font> sampled_font = ResourceLoader::load(p_path);
ERR_FAIL_COND_V(sampled_font.is_null(), Ref<Texture2D>());
String sample;
static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀";
@ -836,18 +829,16 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
if (sample.is_empty()) {
sample = sampled_font->get_supported_chars().substr(0, 6);
}
Vector2 size = sampled_font->get_string_size(sample, 50);
Vector2 size = sampled_font->get_string_size(sample, HORIZONTAL_ALIGNMENT_LEFT, -1, 50);
Vector2 pos;
pos.x = 64 - size.x / 2;
pos.y = 80;
Ref<Font> font = sampled_font;
const Color c = GLOBAL_GET("rendering/environment/defaults/default_clear_color");
const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0;
font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);

View File

@ -0,0 +1,979 @@
/*************************************************************************/
/* font_config_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "font_config_plugin.h"
#include "editor/editor_scale.h"
#include "editor/import/dynamic_font_import_settings.h"
/*************************************************************************/
/* EditorPropertyFontMetaObject */
/*************************************************************************/
bool EditorPropertyFontMetaObject::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name.begins_with("keys")) {
String key = name.get_slicec('/', 1);
dict[key] = p_value;
return true;
}
return false;
}
bool EditorPropertyFontMetaObject::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name;
if (name.begins_with("keys")) {
String key = name.get_slicec('/', 1);
r_ret = dict[key];
return true;
}
return false;
}
void EditorPropertyFontMetaObject::_bind_methods() {
}
void EditorPropertyFontMetaObject::set_dict(const Dictionary &p_dict) {
dict = p_dict;
}
Dictionary EditorPropertyFontMetaObject::get_dict() {
return dict;
}
/*************************************************************************/
/* EditorPropertyFontOTObject */
/*************************************************************************/
bool EditorPropertyFontOTObject::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
dict[key] = p_value;
return true;
}
return false;
}
bool EditorPropertyFontOTObject::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name;
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
r_ret = dict[key];
return true;
}
return false;
}
void EditorPropertyFontOTObject::_bind_methods() {
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorPropertyFontOTObject::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorPropertyFontOTObject::property_get_revert);
}
void EditorPropertyFontOTObject::set_dict(const Dictionary &p_dict) {
dict = p_dict;
}
Dictionary EditorPropertyFontOTObject::get_dict() {
return dict;
}
void EditorPropertyFontOTObject::set_defaults(const Dictionary &p_dict) {
defaults_dict = p_dict;
}
Dictionary EditorPropertyFontOTObject::get_defaults() {
return defaults_dict;
}
bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
String name = p_name;
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
if (defaults_dict.has(key) && dict.has(key)) {
int value = dict[key];
Vector3i range = defaults_dict[key];
return range.z != value;
}
}
return false;
}
Variant EditorPropertyFontOTObject::property_get_revert(const String &p_name) {
String name = p_name;
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
if (defaults_dict.has(key)) {
Vector3i range = defaults_dict[key];
return range.z;
}
}
return Variant();
}
/*************************************************************************/
/* EditorPropertyFontMetaOverride */
/*************************************************************************/
void EditorPropertyFontMetaOverride::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
if (Object::cast_to<Button>(button_add)) {
button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
}
} break;
}
}
void EditorPropertyFontMetaOverride::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("keys")) {
Dictionary dict = object->get_dict();
String key = p_property.get_slice("/", 1);
dict[key] = (bool)p_value;
emit_changed(get_edited_property(), dict, "", true);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
}
}
void EditorPropertyFontMetaOverride::_remove(Object *p_button, const String &p_key) {
Dictionary dict = object->get_dict();
dict.erase(p_key);
emit_changed(get_edited_property(), dict, "", false);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyFontMetaOverride::_add_menu() {
if (script_editor) {
Size2 size = get_size();
menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
menu->reset_size();
menu->popup();
} else {
locale_select->popup_locale_dialog();
}
}
void EditorPropertyFontMetaOverride::_add_script(int p_option) {
Dictionary dict = object->get_dict();
dict[script_codes[p_option]] = true;
emit_changed(get_edited_property(), dict, "", false);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyFontMetaOverride::_add_lang(const String &p_locale) {
Dictionary dict = object->get_dict();
dict[p_locale] = true;
emit_changed(get_edited_property(), dict, "", false);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyFontMetaOverride::_object_id_selected(const StringName &p_property, ObjectID p_id) {
emit_signal(SNAME("object_id_selected"), p_property, p_id);
}
void EditorPropertyFontMetaOverride::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
Dictionary dict = updated_val;
edit->set_text(vformat(TTR("Overrides (%d)"), dict.size()));
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
edit->set_pressed(unfolded);
}
if (unfolded) {
updating = true;
if (!container) {
container = memnew(MarginContainer);
container->set_theme_type_variation("MarginContainer4px");
add_child(container);
set_bottom_editor(container);
VBoxContainer *vbox = memnew(VBoxContainer);
vbox->set_v_size_flags(SIZE_EXPAND_FILL);
container->add_child(vbox);
property_vbox = memnew(VBoxContainer);
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
vbox->add_child(property_vbox);
paginator = memnew(EditorPaginator);
paginator->connect("page_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_page_changed));
vbox->add_child(paginator);
} else {
// Queue children for deletion, deleting immediately might cause errors.
for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
property_vbox->get_child(i)->queue_delete();
}
button_add = nullptr;
}
int size = dict.size();
int max_page = MAX(0, size - 1) / page_length;
page_index = MIN(page_index, max_page);
paginator->update(page_index, max_page);
paginator->set_visible(max_page > 0);
int offset = page_index * page_length;
int amount = MIN(size - offset, page_length);
dict = dict.duplicate();
object->set_dict(dict);
for (int i = 0; i < amount; i++) {
String name = dict.get_key_at_index(i);
EditorProperty *prop = memnew(EditorPropertyCheck);
prop->set_object_and_property(object.ptr(), "keys/" + name);
if (script_editor) {
prop->set_label(TranslationServer::get_singleton()->get_script_name(name));
} else {
prop->set_label(TranslationServer::get_singleton()->get_locale_name(name));
}
prop->set_tooltip(name);
prop->set_selectable(false);
prop->connect("property_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_object_id_selected));
HBoxContainer *hbox = memnew(HBoxContainer);
property_vbox->add_child(hbox);
hbox->add_child(prop);
prop->set_h_size_flags(SIZE_EXPAND_FILL);
Button *remove = memnew(Button);
remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbox->add_child(remove);
remove->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_remove), varray(remove, name));
prop->update_property();
}
if (script_editor) {
button_add = EditorInspector::create_inspector_action_button(TTR("Add Script"));
} else {
button_add = EditorInspector::create_inspector_action_button(TTR("Add Locale"));
}
button_add->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_menu));
property_vbox->add_child(button_add);
updating = false;
} else {
if (container) {
set_bottom_editor(nullptr);
memdelete(container);
button_add = nullptr;
container = nullptr;
}
}
}
void EditorPropertyFontMetaOverride::_edit_pressed() {
Variant prop_val = get_edited_object()->get(get_edited_property());
if (prop_val.get_type() == Variant::NIL) {
Callable::CallError ce;
Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
get_edited_object()->set(get_edited_property(), prop_val);
}
get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
update_property();
}
void EditorPropertyFontMetaOverride::_page_changed(int p_page) {
if (updating) {
return;
}
page_index = p_page;
update_property();
}
EditorPropertyFontMetaOverride::EditorPropertyFontMetaOverride(bool p_script) {
script_editor = p_script;
object.instantiate();
page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
edit->set_clip_text(true);
edit->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_edit_pressed));
edit->set_toggle_mode(true);
add_child(edit);
add_focusable(edit);
menu = memnew(PopupMenu);
if (script_editor) {
script_codes = TranslationServer::get_singleton()->get_all_scripts();
for (int i = 0; i < script_codes.size(); i++) {
menu->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i);
}
}
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_script));
locale_select = memnew(EditorLocaleDialog);
locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_add_lang));
add_child(locale_select);
}
/*************************************************************************/
/* EditorPropertyOTVariation */
/*************************************************************************/
void EditorPropertyOTVariation::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
} break;
}
}
void EditorPropertyOTVariation::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("keys")) {
Dictionary dict = object->get_dict();
Dictionary defaults_dict = object->get_defaults();
int key = p_property.get_slice("/", 1).to_int();
dict[key] = (int)p_value;
if (defaults_dict.has(key)) {
Vector3i range = defaults_dict[key];
if (range.z == (int)p_value) {
dict.erase(key);
}
}
emit_changed(get_edited_property(), dict, "", true);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
}
}
void EditorPropertyOTVariation::_object_id_selected(const StringName &p_property, ObjectID p_id) {
emit_signal(SNAME("object_id_selected"), p_property, p_id);
}
void EditorPropertyOTVariation::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
Dictionary dict = updated_val;
Ref<Font> fd;
if (Object::cast_to<Font>(get_edited_object()) != nullptr) {
fd = get_edited_object();
} else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) {
Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object());
fd = imp->get_font();
}
Dictionary supported = (fd.is_valid()) ? fd->get_supported_variation_list() : Dictionary();
edit->set_text(vformat(TTR("Variation Coordinates (%d)"), supported.size()));
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
edit->set_pressed(unfolded);
}
if (unfolded) {
updating = true;
if (!container) {
container = memnew(MarginContainer);
container->set_theme_type_variation("MarginContainer4px");
add_child(container);
set_bottom_editor(container);
VBoxContainer *vbox = memnew(VBoxContainer);
vbox->set_v_size_flags(SIZE_EXPAND_FILL);
container->add_child(vbox);
property_vbox = memnew(VBoxContainer);
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
vbox->add_child(property_vbox);
paginator = memnew(EditorPaginator);
paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTVariation::_page_changed));
vbox->add_child(paginator);
} else {
// Queue children for deletion, deleting immediately might cause errors.
for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
property_vbox->get_child(i)->queue_delete();
}
}
int size = supported.size();
int max_page = MAX(0, size - 1) / page_length;
page_index = MIN(page_index, max_page);
paginator->update(page_index, max_page);
paginator->set_visible(max_page > 0);
int offset = page_index * page_length;
int amount = MIN(size - offset, page_length);
dict = dict.duplicate();
object->set_dict(dict);
object->set_defaults(supported);
for (int i = 0; i < amount; i++) {
int name_tag = supported.get_key_at_index(i);
Vector3i range = supported.get_value_at_index(i);
EditorPropertyInteger *prop = memnew(EditorPropertyInteger);
prop->setup(range.x, range.y, 1, false, false);
prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
String name = TS->tag_to_name(name_tag);
prop->set_label(name.capitalize());
prop->set_tooltip(name);
prop->set_selectable(false);
prop->connect("property_changed", callable_mp(this, &EditorPropertyOTVariation::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTVariation::_object_id_selected));
property_vbox->add_child(prop);
prop->update_property();
}
updating = false;
} else {
if (container) {
set_bottom_editor(nullptr);
memdelete(container);
container = nullptr;
}
}
}
void EditorPropertyOTVariation::_edit_pressed() {
Variant prop_val = get_edited_object()->get(get_edited_property());
if (prop_val.get_type() == Variant::NIL) {
Callable::CallError ce;
Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
get_edited_object()->set(get_edited_property(), prop_val);
}
get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
update_property();
}
void EditorPropertyOTVariation::_page_changed(int p_page) {
if (updating) {
return;
}
page_index = p_page;
update_property();
}
EditorPropertyOTVariation::EditorPropertyOTVariation() {
object.instantiate();
page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
edit->set_clip_text(true);
edit->connect("pressed", callable_mp(this, &EditorPropertyOTVariation::_edit_pressed));
edit->set_toggle_mode(true);
add_child(edit);
add_focusable(edit);
}
/*************************************************************************/
/* EditorPropertyOTFeatures */
/*************************************************************************/
void EditorPropertyOTFeatures::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
if (Object::cast_to<Button>(button_add)) {
button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
}
} break;
}
}
void EditorPropertyOTFeatures::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
if (p_property.begins_with("keys")) {
Dictionary dict = object->get_dict();
int key = p_property.get_slice("/", 1).to_int();
dict[key] = (int)p_value;
emit_changed(get_edited_property(), dict, "", true);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
}
}
void EditorPropertyOTFeatures::_remove(Object *p_button, int p_key) {
Dictionary dict = object->get_dict();
dict.erase(p_key);
emit_changed(get_edited_property(), dict, "", false);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyOTFeatures::_add_menu() {
Size2 size = get_size();
menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
menu->reset_size();
menu->popup();
}
void EditorPropertyOTFeatures::_add_feature(int p_option) {
Dictionary dict = object->get_dict();
dict[p_option] = 1;
emit_changed(get_edited_property(), dict, "", false);
dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
void EditorPropertyOTFeatures::_object_id_selected(const StringName &p_property, ObjectID p_id) {
emit_signal(SNAME("object_id_selected"), p_property, p_id);
}
void EditorPropertyOTFeatures::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
Dictionary dict = updated_val;
Ref<Font> fd;
if (Object::cast_to<FontVariation>(get_edited_object()) != nullptr) {
fd = get_edited_object();
} else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) {
Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object());
fd = imp->get_font();
}
Dictionary supported;
if (fd.is_valid()) {
supported = fd->get_supported_feature_list();
}
edit->set_text(vformat(TTR("Features (%d of %d set)"), dict.size(), supported.size()));
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
edit->set_pressed(unfolded);
}
if (unfolded) {
updating = true;
if (!container) {
container = memnew(MarginContainer);
container->set_theme_type_variation("MarginContainer4px");
add_child(container);
set_bottom_editor(container);
VBoxContainer *vbox = memnew(VBoxContainer);
vbox->set_v_size_flags(SIZE_EXPAND_FILL);
container->add_child(vbox);
property_vbox = memnew(VBoxContainer);
property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
vbox->add_child(property_vbox);
paginator = memnew(EditorPaginator);
paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTFeatures::_page_changed));
vbox->add_child(paginator);
} else {
// Queue children for deletion, deleting immediately might cause errors.
for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
property_vbox->get_child(i)->queue_delete();
}
button_add = nullptr;
}
// Update add menu items.
menu->clear();
bool have_sub[FGRP_MAX];
for (int i = 0; i < FGRP_MAX; i++) {
menu_sub[i]->clear();
have_sub[i] = false;
}
bool show_hidden = EDITOR_GET("interface/inspector/show_low_level_opentype_features");
for (int i = 0; i < supported.size(); i++) {
int name_tag = supported.get_key_at_index(i);
Dictionary info = supported.get_value_at_index(i);
bool hidden = info["hidden"].operator bool();
String name = TS->tag_to_name(name_tag);
FeatureGroups grp = FGRP_MAX;
if (hidden && !show_hidden) {
continue;
}
if (name.begins_with("stylistic_set_")) {
grp = FGRP_STYLISTIC_SET;
} else if (name.begins_with("character_variant_")) {
grp = FGRP_CHARACTER_VARIANT;
} else if (name.ends_with("_capitals")) {
grp = FGRP_CAPITLS;
} else if (name.ends_with("_ligatures")) {
grp = FGRP_LIGATURES;
} else if (name.ends_with("_alternates")) {
grp = FGRP_ALTERNATES;
} else if (name.ends_with("_kanji_forms") || name.begins_with("jis") || name == "simplified_forms" || name == "traditional_name_forms" || name == "traditional_forms") {
grp = FGRP_EAL;
} else if (name.ends_with("_widths")) {
grp = FGRP_EAW;
} else if (name == "tabular_figures" || name == "proportional_figures") {
grp = FGRP_NUMAL;
} else if (name.begins_with("custom_")) {
grp = FGRP_CUSTOM;
}
String disp_name = name.capitalize();
if (info.has("label")) {
disp_name = vformat("%s (%s)", disp_name, info["label"].operator String());
}
if (grp == FGRP_MAX) {
menu->add_item(disp_name, name_tag);
} else {
menu_sub[grp]->add_item(disp_name, name_tag);
have_sub[grp] = true;
}
}
for (int i = 0; i < FGRP_MAX; i++) {
if (have_sub[i]) {
menu->add_submenu_item(RTR(group_names[i]), "FTRMenu_" + itos(i));
}
}
int size = dict.size();
int max_page = MAX(0, size - 1) / page_length;
page_index = MIN(page_index, max_page);
paginator->update(page_index, max_page);
paginator->set_visible(max_page > 0);
int offset = page_index * page_length;
int amount = MIN(size - offset, page_length);
dict = dict.duplicate();
object->set_dict(dict);
for (int i = 0; i < amount; i++) {
int name_tag = dict.get_key_at_index(i);
if (supported.has(name_tag)) {
Dictionary info = supported[name_tag];
Variant::Type vtype = Variant::Type(info["type"].operator int());
bool hidden = info["hidden"].operator bool();
if (hidden && !show_hidden) {
continue;
}
EditorProperty *prop = nullptr;
switch (vtype) {
case Variant::NIL: {
prop = memnew(EditorPropertyNil);
} break;
case Variant::BOOL: {
prop = memnew(EditorPropertyCheck);
} break;
case Variant::INT: {
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
editor->setup(0, 255, 1, false, false);
prop = editor;
} break;
default: {
ERR_CONTINUE_MSG(true, vformat("Unsupported OT feature data type %s", Variant::get_type_name(vtype)));
}
}
prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
String name = TS->tag_to_name(name_tag);
String disp_name = name.capitalize();
if (info.has("label")) {
disp_name = vformat("%s (%s)", disp_name, info["label"].operator String());
}
prop->set_label(disp_name);
prop->set_tooltip(name);
prop->set_selectable(false);
prop->connect("property_changed", callable_mp(this, &EditorPropertyOTFeatures::_property_changed));
prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTFeatures::_object_id_selected));
HBoxContainer *hbox = memnew(HBoxContainer);
property_vbox->add_child(hbox);
hbox->add_child(prop);
prop->set_h_size_flags(SIZE_EXPAND_FILL);
Button *remove = memnew(Button);
remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbox->add_child(remove);
remove->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_remove), varray(remove, name_tag));
prop->update_property();
}
}
button_add = EditorInspector::create_inspector_action_button(TTR("Add Feature"));
button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
button_add->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_menu));
property_vbox->add_child(button_add);
updating = false;
} else {
if (container) {
set_bottom_editor(nullptr);
memdelete(container);
button_add = nullptr;
container = nullptr;
}
}
}
void EditorPropertyOTFeatures::_edit_pressed() {
Variant prop_val = get_edited_object()->get(get_edited_property());
if (prop_val.get_type() == Variant::NIL) {
Callable::CallError ce;
Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
get_edited_object()->set(get_edited_property(), prop_val);
}
get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
update_property();
}
void EditorPropertyOTFeatures::_page_changed(int p_page) {
if (updating) {
return;
}
page_index = p_page;
update_property();
}
EditorPropertyOTFeatures::EditorPropertyOTFeatures() {
object.instantiate();
page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
edit = memnew(Button);
edit->set_h_size_flags(SIZE_EXPAND_FILL);
edit->set_clip_text(true);
edit->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_edit_pressed));
edit->set_toggle_mode(true);
add_child(edit);
add_focusable(edit);
menu = memnew(PopupMenu);
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature));
for (int i = 0; i < FGRP_MAX; i++) {
menu_sub[i] = memnew(PopupMenu);
menu_sub[i]->set_name("FTRMenu_" + itos(i));
menu->add_child(menu_sub[i]);
menu_sub[i]->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature));
}
group_names[FGRP_STYLISTIC_SET] = "Stylistic Sets";
group_names[FGRP_CHARACTER_VARIANT] = "Character Variants";
group_names[FGRP_CAPITLS] = "Capitals";
group_names[FGRP_LIGATURES] = "Ligatures";
group_names[FGRP_ALTERNATES] = "Alternates";
group_names[FGRP_EAL] = "East Asian Language";
group_names[FGRP_EAW] = "East Asian Widths";
group_names[FGRP_NUMAL] = "Numeral Alignment";
group_names[FGRP_CUSTOM] = "Custom";
}
/*************************************************************************/
/* EditorInspectorPluginFontVariation */
/*************************************************************************/
bool EditorInspectorPluginFontVariation::can_handle(Object *p_object) {
return (Object::cast_to<FontVariation>(p_object) != nullptr) || (Object::cast_to<DynamicFontImportSettingsData>(p_object) != nullptr);
}
bool EditorInspectorPluginFontVariation::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
if (p_path == "variation_opentype") {
add_property_editor(p_path, memnew(EditorPropertyOTVariation));
return true;
} else if (p_path == "opentype_features") {
add_property_editor(p_path, memnew(EditorPropertyOTFeatures));
return true;
} else if (p_path == "language_support") {
add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(false)));
return true;
} else if (p_path == "script_support") {
add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(true)));
return true;
}
return false;
}
/*************************************************************************/
/* FontPreview */
/*************************************************************************/
void FontPreview::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
// Draw font name (style).
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
// Draw font preview.
Vector2 pos = Vector2(0, font->get_height(font_size)) + (get_size() - Vector2(0, font->get_height(font_size)) - line->get_size()) / 2;
line->draw(get_canvas_item(), pos, text_color);
// Draw font baseline.
Color line_color = text_color;
line_color.a *= 0.6;
draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color);
draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color);
} break;
}
}
void FontPreview::_bind_methods() {}
Size2 FontPreview::get_minimum_size() const {
return Vector2(64, 64) * EDSCALE;
}
void FontPreview::set_data(const Ref<Font> &p_f) {
line->clear();
if (p_f.is_valid()) {
name = vformat("%s (%s)", p_f->get_font_name(), p_f->get_font_style_name());
if (p_f->is_class("FontVariation")) {
name += " " + TTR(" - Variation");
}
String sample;
static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀";
for (int i = 0; i < sample_base.length(); i++) {
if (p_f->has_char(sample_base[i])) {
sample += sample_base[i];
}
}
if (sample.is_empty()) {
sample = p_f->get_supported_chars().substr(0, 6);
}
line->add_string(sample, p_f, 50);
}
update();
}
FontPreview::FontPreview() {
line.instantiate();
}
/*************************************************************************/
/* EditorInspectorPluginFontPreview */
/*************************************************************************/
bool EditorInspectorPluginFontPreview::can_handle(Object *p_object) {
return Object::cast_to<Font>(p_object) != nullptr;
}
void EditorInspectorPluginFontPreview::parse_begin(Object *p_object) {
Font *fd = Object::cast_to<Font>(p_object);
ERR_FAIL_COND(!fd);
FontPreview *editor = memnew(FontPreview);
editor->set_data(fd);
add_custom_control(editor);
}
bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
return false;
}
/*************************************************************************/
/* FontEditorPlugin */
/*************************************************************************/
FontEditorPlugin::FontEditorPlugin() {
Ref<EditorInspectorPluginFontVariation> fc_plugin;
fc_plugin.instantiate();
EditorInspector::add_inspector_plugin(fc_plugin);
Ref<EditorInspectorPluginFontPreview> fp_plugin;
fp_plugin.instantiate();
EditorInspector::add_inspector_plugin(fp_plugin);
}

View File

@ -0,0 +1,261 @@
/*************************************************************************/
/* font_config_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OT_FEATURES_PLUGIN_H
#define OT_FEATURES_PLUGIN_H
#include "core/io/marshalls.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
/*************************************************************************/
class EditorPropertyFontMetaObject : public RefCounted {
GDCLASS(EditorPropertyFontMetaObject, RefCounted);
Dictionary dict;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
static void _bind_methods();
public:
void set_dict(const Dictionary &p_dict);
Dictionary get_dict();
EditorPropertyFontMetaObject(){};
};
/*************************************************************************/
class EditorPropertyFontOTObject : public RefCounted {
GDCLASS(EditorPropertyFontOTObject, RefCounted);
Dictionary dict;
Dictionary defaults_dict;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
static void _bind_methods();
public:
void set_dict(const Dictionary &p_dict);
Dictionary get_dict();
void set_defaults(const Dictionary &p_dict);
Dictionary get_defaults();
bool property_can_revert(const String &p_name);
Variant property_get_revert(const String &p_name);
EditorPropertyFontOTObject(){};
};
/*************************************************************************/
class EditorPropertyFontMetaOverride : public EditorProperty {
GDCLASS(EditorPropertyFontMetaOverride, EditorProperty);
Ref<EditorPropertyFontMetaObject> object;
MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
Button *button_add = nullptr;
Button *edit = nullptr;
PopupMenu *menu = nullptr;
EditorLocaleDialog *locale_select = nullptr;
Vector<String> script_codes;
bool script_editor = false;
bool updating = false;
int page_length = 20;
int page_index = 0;
EditorPaginator *paginator = nullptr;
protected:
void _notification(int p_what);
static void _bind_methods(){};
void _edit_pressed();
void _page_changed(int p_page);
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
void _remove(Object *p_button, const String &p_key);
void _add_menu();
void _add_script(int p_option);
void _add_lang(const String &p_locale);
void _object_id_selected(const StringName &p_property, ObjectID p_id);
public:
virtual void update_property() override;
EditorPropertyFontMetaOverride(bool p_script);
};
/*************************************************************************/
class EditorPropertyOTVariation : public EditorProperty {
GDCLASS(EditorPropertyOTVariation, EditorProperty);
Ref<EditorPropertyFontOTObject> object;
MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
Button *edit = nullptr;
bool updating = false;
int page_length = 20;
int page_index = 0;
EditorPaginator *paginator = nullptr;
protected:
void _notification(int p_what);
static void _bind_methods(){};
void _edit_pressed();
void _page_changed(int p_page);
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
void _object_id_selected(const StringName &p_property, ObjectID p_id);
public:
virtual void update_property() override;
EditorPropertyOTVariation();
};
/*************************************************************************/
class EditorPropertyOTFeatures : public EditorProperty {
GDCLASS(EditorPropertyOTFeatures, EditorProperty);
enum FeatureGroups {
FGRP_STYLISTIC_SET,
FGRP_CHARACTER_VARIANT,
FGRP_CAPITLS,
FGRP_LIGATURES,
FGRP_ALTERNATES,
FGRP_EAL,
FGRP_EAW,
FGRP_NUMAL,
FGRP_CUSTOM,
FGRP_MAX,
};
Ref<EditorPropertyFontOTObject> object;
MarginContainer *container = nullptr;
VBoxContainer *property_vbox = nullptr;
Button *button_add = nullptr;
Button *edit = nullptr;
PopupMenu *menu = nullptr;
PopupMenu *menu_sub[FGRP_MAX];
String group_names[FGRP_MAX];
bool updating = false;
int page_length = 20;
int page_index = 0;
EditorPaginator *paginator = nullptr;
protected:
void _notification(int p_what);
static void _bind_methods(){};
void _edit_pressed();
void _page_changed(int p_page);
void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
void _remove(Object *p_button, int p_key);
void _add_menu();
void _add_feature(int p_option);
void _object_id_selected(const StringName &p_property, ObjectID p_id);
public:
virtual void update_property() override;
EditorPropertyOTFeatures();
};
/*************************************************************************/
class EditorInspectorPluginFontVariation : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginFontVariation, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
};
/*************************************************************************/
class FontPreview : public Control {
GDCLASS(FontPreview, Control);
protected:
void _notification(int p_what);
static void _bind_methods();
String name;
Ref<TextLine> line;
public:
virtual Size2 get_minimum_size() const override;
void set_data(const Ref<Font> &p_f);
FontPreview();
};
/*************************************************************************/
class EditorInspectorPluginFontPreview : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginFontPreview, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
};
/*************************************************************************/
class FontEditorPlugin : public EditorPlugin {
GDCLASS(FontEditorPlugin, EditorPlugin);
public:
FontEditorPlugin();
virtual String get_name() const override { return "Font"; }
};
#endif // OT_FEATURES_PLUGIN_H

View File

@ -1,106 +0,0 @@
/*************************************************************************/
/* font_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "font_editor_plugin.h"
#include "editor/editor_scale.h"
void FontDataPreview::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
Color line_color = text_color;
line_color.a *= 0.6;
Vector2 pos = (get_size() - line->get_size()) / 2;
line->draw(get_canvas_item(), pos, text_color);
draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color);
draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color);
} break;
}
}
void FontDataPreview::_bind_methods() {}
Size2 FontDataPreview::get_minimum_size() const {
return Vector2(64, 64) * EDSCALE;
}
void FontDataPreview::set_data(const Ref<FontData> &p_data) {
Ref<Font> f = memnew(Font);
f->add_data(p_data);
line->clear();
if (p_data.is_valid()) {
String sample;
static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀";
for (int i = 0; i < sample_base.length(); i++) {
if (p_data->has_char(sample_base[i])) {
sample += sample_base[i];
}
}
if (sample.is_empty()) {
sample = p_data->get_supported_chars().substr(0, 6);
}
line->add_string(sample, f, 72);
}
update();
}
FontDataPreview::FontDataPreview() {
line.instantiate();
}
/*************************************************************************/
bool EditorInspectorPluginFont::can_handle(Object *p_object) {
return Object::cast_to<FontData>(p_object) != nullptr;
}
void EditorInspectorPluginFont::parse_begin(Object *p_object) {
FontData *fd = Object::cast_to<FontData>(p_object);
ERR_FAIL_COND(!fd);
FontDataPreview *editor = memnew(FontDataPreview);
editor->set_data(fd);
add_custom_control(editor);
}
bool EditorInspectorPluginFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
return false;
}
/*************************************************************************/
FontEditorPlugin::FontEditorPlugin() {
Ref<EditorInspectorPluginFont> fd_plugin;
fd_plugin.instantiate();
EditorInspector::add_inspector_plugin(fd_plugin);
}

View File

@ -1,77 +0,0 @@
/*************************************************************************/
/* font_editor_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FONT_EDITOR_PLUGIN_H
#define FONT_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
#include "scene/resources/font.h"
#include "scene/resources/text_line.h"
class FontDataPreview : public Control {
GDCLASS(FontDataPreview, Control);
protected:
void _notification(int p_what);
static void _bind_methods();
Ref<TextLine> line;
public:
virtual Size2 get_minimum_size() const override;
void set_data(const Ref<FontData> &p_data);
FontDataPreview();
};
/*************************************************************************/
class EditorInspectorPluginFont : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginFont, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
};
/*************************************************************************/
class FontEditorPlugin : public EditorPlugin {
GDCLASS(FontEditorPlugin, EditorPlugin);
public:
FontEditorPlugin();
virtual String get_name() const override { return "Font"; }
};
#endif // FONT_EDITOR_PLUGIN_H

View File

@ -145,7 +145,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) {
// Draw the axis letter for the positive axes.
const String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z");
draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha));
draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha));
} else {
// Draw an outline around the negative axes.
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c);
@ -2725,7 +2725,8 @@ static void draw_indicator_bar(Control &p_surface, real_t p_fill, const Ref<Text
p_surface.draw_texture(p_icon, icon_pos, p_color);
// Draw text below the bar (for speed/zoom information).
p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color, Math::round(2 * EDSCALE), Color(0, 0, 0));
p_surface.draw_string_outline(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, Math::round(2 * EDSCALE), Color(0, 0, 0));
p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color);
}
void Node3DEditorViewport::_draw() {

View File

@ -1,235 +0,0 @@
/*************************************************************************/
/* ot_features_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "ot_features_plugin.h"
#include "scene/3d/label_3d.h"
#include "scene/resources/primitive_meshes.h"
void OpenTypeFeaturesEditor::_value_changed(double val) {
if (setting) {
return;
}
emit_changed(get_edited_property(), spin->get_value());
}
void OpenTypeFeaturesEditor::update_property() {
double val = get_edited_object()->get(get_edited_property());
setting = true;
spin->set_value(val);
setting = false;
}
void OpenTypeFeaturesEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
button->set_size(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))->get_size());
spin->add_theme_color_override("label_color", base);
} break;
}
}
void OpenTypeFeaturesEditor::_remove_feature() {
get_edited_object()->set(get_edited_property(), -1);
}
void OpenTypeFeaturesEditor::_bind_methods() {
}
OpenTypeFeaturesEditor::OpenTypeFeaturesEditor() {
HBoxContainer *bc = memnew(HBoxContainer);
add_child(bc);
spin = memnew(EditorSpinSlider);
spin->set_flat(true);
bc->add_child(spin);
add_focusable(spin);
spin->connect("value_changed", callable_mp(this, &OpenTypeFeaturesEditor::_value_changed));
spin->set_h_size_flags(SIZE_EXPAND_FILL);
spin->set_min(0);
spin->set_max(65536);
spin->set_step(1);
spin->set_hide_slider(false);
spin->set_allow_greater(false);
spin->set_allow_lesser(false);
button = memnew(Button);
button->set_tooltip(RTR("Remove feature"));
button->set_flat(true);
bc->add_child(button);
button->connect("pressed", callable_mp(this, &OpenTypeFeaturesEditor::_remove_feature));
setting = false;
}
/*************************************************************************/
void OpenTypeFeaturesAdd::_add_feature(int p_option) {
edited_object->set("opentype_features/" + TS->tag_to_name(p_option), 1);
}
void OpenTypeFeaturesAdd::_features_menu() {
Size2 size = get_size();
menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
menu->reset_size();
menu->popup();
}
void OpenTypeFeaturesAdd::setup(Object *p_object) {
edited_object = p_object;
menu->clear();
menu_ss->clear();
menu_cv->clear();
menu_cu->clear();
bool have_ss = false;
bool have_cv = false;
bool have_cu = false;
Ref<Font> font;
Control *ctrl = Object::cast_to<Control>(edited_object);
if (ctrl != nullptr) {
font = ctrl->get_theme_font(SNAME("font"));
}
Label3D *l3d = Object::cast_to<Label3D>(edited_object);
if (l3d != nullptr) {
font = l3d->_get_font_or_default();
}
TextMesh *tm = Object::cast_to<TextMesh>(edited_object);
if (tm != nullptr) {
font = tm->_get_font_or_default();
}
if (font.is_null()) {
return;
}
Dictionary features = font->get_feature_list();
for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) {
String ftr_name = TS->tag_to_name(*ftr);
if (ftr_name.begins_with("stylistic_set_")) {
menu_ss->add_item(ftr_name.capitalize(), (int32_t)*ftr);
have_ss = true;
} else if (ftr_name.begins_with("character_variant_")) {
menu_cv->add_item(ftr_name.capitalize(), (int32_t)*ftr);
have_cv = true;
} else if (ftr_name.begins_with("custom_")) {
menu_cu->add_item(ftr_name.replace("custom_", ""), (int32_t)*ftr);
have_cu = true;
} else {
menu->add_item(ftr_name.capitalize(), (int32_t)*ftr);
}
}
if (have_ss) {
menu->add_submenu_item(RTR("Stylistic Sets"), "SSMenu");
}
if (have_cv) {
menu->add_submenu_item(RTR("Character Variants"), "CVMenu");
}
if (have_cu) {
menu->add_submenu_item(RTR("Custom"), "CUMenu");
}
}
void OpenTypeFeaturesAdd::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
}
void OpenTypeFeaturesAdd::_bind_methods() {
}
OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
set_text(TTR("Add Feature..."));
menu = memnew(PopupMenu);
add_child(menu);
menu_cv = memnew(PopupMenu);
menu_cv->set_name("CVMenu");
menu->add_child(menu_cv);
menu_ss = memnew(PopupMenu);
menu_ss->set_name("SSMenu");
menu->add_child(menu_ss);
menu_cu = memnew(PopupMenu);
menu_cu->set_name("CUMenu");
menu->add_child(menu_cu);
menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_cu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
}
/*************************************************************************/
bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) {
return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr) || (Object::cast_to<TextMesh>(p_object) != nullptr);
}
bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
if (p_path == "opentype_features/_new") {
OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd);
editor->setup(p_object);
add_custom_control(editor);
return true;
} else if (p_path.begins_with("opentype_features")) {
OpenTypeFeaturesEditor *editor = memnew(OpenTypeFeaturesEditor);
add_property_editor(p_path, editor);
return true;
}
return false;
}
/*************************************************************************/
OpenTypeFeaturesEditorPlugin::OpenTypeFeaturesEditorPlugin() {
Ref<EditorInspectorPluginOpenTypeFeatures> ftr_plugin;
ftr_plugin.instantiate();
EditorInspector::add_inspector_plugin(ftr_plugin);
}

View File

@ -1,102 +0,0 @@
/*************************************************************************/
/* ot_features_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OT_FEATURES_PLUGIN_H
#define OT_FEATURES_PLUGIN_H
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
/*************************************************************************/
class OpenTypeFeaturesEditor : public EditorProperty {
GDCLASS(OpenTypeFeaturesEditor, EditorProperty);
EditorSpinSlider *spin = nullptr;
bool setting = true;
void _value_changed(double p_val);
Button *button = nullptr;
void _remove_feature();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
virtual void update_property() override;
OpenTypeFeaturesEditor();
};
/*************************************************************************/
class OpenTypeFeaturesAdd : public Button {
GDCLASS(OpenTypeFeaturesAdd, Button);
Object *edited_object = nullptr;
PopupMenu *menu = nullptr;
PopupMenu *menu_ss = nullptr;
PopupMenu *menu_cv = nullptr;
PopupMenu *menu_cu = nullptr;
void _add_feature(int p_option);
void _features_menu();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
void setup(Object *p_object);
OpenTypeFeaturesAdd();
};
/*************************************************************************/
class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginOpenTypeFeatures, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
};
/*************************************************************************/
class OpenTypeFeaturesEditorPlugin : public EditorPlugin {
GDCLASS(OpenTypeFeaturesEditorPlugin, EditorPlugin);
public:
OpenTypeFeaturesEditorPlugin();
virtual String get_name() const override { return "OpenTypeFeatures"; }
};
#endif // OT_FEATURES_PLUGIN_H

View File

@ -1,660 +0,0 @@
/*************************************************************************/
/* text_control_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "text_control_editor_plugin.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/multi_node_edit.h"
void TextControlEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) {
EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts), make_binds(""));
}
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
clear_formatting->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_EXIT_TREE: {
if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) {
EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts));
}
} break;
}
}
void TextControlEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_control"), &TextControlEditor::_update_control);
}
void TextControlEditor::_find_resources(EditorFileSystemDirectory *p_dir) {
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
_find_resources(p_dir->get_subdir(i));
}
for (int i = 0; i < p_dir->get_file_count(); i++) {
if (p_dir->get_file_type(i) == "FontData") {
Ref<FontData> fd = ResourceLoader::load(p_dir->get_file_path(i));
if (fd.is_valid()) {
String name = fd->get_font_name();
String sty = fd->get_font_style_name();
if (sty.is_empty()) {
sty = "Default";
}
fonts[name][sty] = p_dir->get_file_path(i);
}
}
}
}
void TextControlEditor::_reload_fonts(const String &p_path) {
fonts.clear();
_find_resources(EditorFileSystem::get_singleton()->get_filesystem());
_update_control();
}
void TextControlEditor::_update_fonts_menu() {
font_list->clear();
font_list->add_item(TTR("[Theme Default]"), FONT_INFO_THEME_DEFAULT);
if (custom_font.is_valid()) {
font_list->add_item(TTR("[Custom Font]"), FONT_INFO_USER_CUSTOM);
}
int id = FONT_INFO_ID;
for (const KeyValue<String, HashMap<String, String>> &E : fonts) {
font_list->add_item(E.key, id++);
}
if (font_list->get_item_count() > 1) {
font_list->show();
} else {
font_list->hide();
}
}
void TextControlEditor::_update_styles_menu() {
font_style_list->clear();
if ((font_list->get_selected_id() >= FONT_INFO_ID)) {
const String &name = font_list->get_item_text(font_list->get_selected());
for (KeyValue<String, String> &E : fonts[name]) {
font_style_list->add_item(E.key);
}
} else if (font_list->get_selected() >= 0) {
font_style_list->add_item("Default");
}
if (font_style_list->get_item_count() > 1) {
font_style_list->show();
} else {
font_style_list->hide();
}
}
void TextControlEditor::_update_control() {
if (!edited_controls.is_empty()) {
String font_selected;
bool same_font = true;
String style_selected;
bool same_style = true;
int font_size = 0;
bool same_font_size = true;
int outline_size = 0;
bool same_outline_size = true;
Color font_color = Color{ 1.0f, 1.0f, 1.0f };
bool same_font_color = true;
Color outline_color = Color{ 1.0f, 1.0f, 1.0f };
bool same_outline_color = true;
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
StringName edited_color;
StringName edited_font;
StringName edited_font_size;
// Get override names.
if (Object::cast_to<RichTextLabel>(edited_control)) {
edited_color = SNAME("default_color");
edited_font = SNAME("normal_font");
edited_font_size = SNAME("normal_font_size");
} else {
edited_color = SNAME("font_color");
edited_font = SNAME("font");
edited_font_size = SNAME("font_size");
}
// Get font override.
Ref<Font> font;
if (edited_control->has_theme_font_override(edited_font)) {
font = edited_control->get_theme_font(edited_font);
}
if (font.is_valid()) {
if (font->get_data_count() != 1) {
if (i > 0) {
same_font = same_font && (custom_font == font);
}
custom_font = font;
font_selected = TTR("[Custom Font]");
same_style = false;
} else {
String name = font->get_data(0)->get_font_name();
String style = font->get_data(0)->get_font_style_name();
if (fonts.has(name) && fonts[name].has(style)) {
if (i > 0) {
same_font = same_font && (name == font_selected);
same_style = same_style && (style == style_selected);
}
font_selected = name;
style_selected = style;
} else {
if (i > 0) {
same_font = same_font && (custom_font == font);
}
custom_font = font;
font_selected = TTR("[Custom Font]");
same_style = false;
}
}
} else {
if (i > 0) {
same_font = same_font && (font_selected == TTR("[Theme Default]"));
}
font_selected = TTR("[Theme Default]");
same_style = false;
}
int current_font_size = edited_control->get_theme_font_size(edited_font_size);
int current_outline_size = edited_control->get_theme_constant(SNAME("outline_size"));
Color current_font_color = edited_control->get_theme_color(edited_color);
Color current_outline_color = edited_control->get_theme_color(SNAME("font_outline_color"));
if (i > 0) {
same_font_size = same_font_size && (font_size == current_font_size);
same_outline_size = same_outline_size && (outline_size == current_outline_size);
same_font_color = same_font_color && (font_color == current_font_color);
same_outline_color = same_outline_color && (outline_color == current_outline_color);
}
font_size = current_font_size;
outline_size = current_outline_size;
font_color = current_font_color;
outline_color = current_outline_color;
}
_update_fonts_menu();
if (same_font) {
for (int j = 0; j < font_list->get_item_count(); j++) {
if (font_list->get_item_text(j) == font_selected) {
font_list->select(j);
break;
}
}
} else {
custom_font = Ref<Font>();
font_list->select(-1);
}
_update_styles_menu();
if (same_style) {
for (int j = 0; j < font_style_list->get_item_count(); j++) {
if (font_style_list->get_item_text(j) == style_selected) {
font_style_list->select(j);
break;
}
}
} else {
font_style_list->select(-1);
}
// Get other theme overrides.
font_size_list->set_block_signals(true);
if (same_font_size) {
font_size_list->get_line_edit()->set_text(String::num_uint64(font_size));
font_size_list->set_value(font_size);
} else {
font_size_list->get_line_edit()->set_text("");
}
font_size_list->set_block_signals(false);
outline_size_list->set_block_signals(true);
if (same_outline_size) {
outline_size_list->get_line_edit()->set_text(String::num_uint64(outline_size));
outline_size_list->set_value(outline_size);
} else {
outline_size_list->get_line_edit()->set_text("");
}
outline_size_list->set_block_signals(false);
if (!same_font_color) {
font_color = Color{ 1.0f, 1.0f, 1.0f };
}
font_color_picker->set_pick_color(font_color);
if (!same_outline_color) {
outline_color = Color{ 1.0f, 1.0f, 1.0f };
}
outline_color_picker->set_pick_color(outline_color);
}
}
void TextControlEditor::_font_selected(int p_id) {
_update_styles_menu();
_set_font();
}
void TextControlEditor::_font_style_selected(int p_id) {
_set_font();
}
void TextControlEditor::_set_font() {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Font"));
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
StringName edited_font;
if (Object::cast_to<RichTextLabel>(edited_control)) {
edited_font = SNAME("normal_font");
} else {
edited_font = SNAME("font");
}
if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) {
// Remove font override.
ur->add_do_method(edited_control, "remove_theme_font_override", edited_font);
} else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) {
// Restore "custom_font".
ur->add_do_method(edited_control, "add_theme_font_override", edited_font, custom_font);
} else if (font_list->get_selected() >= 0) {
// Load new font resource using selected name and style.
String name = font_list->get_item_text(font_list->get_selected());
String style = font_style_list->get_item_text(font_style_list->get_selected());
if (style.is_empty()) {
style = "Default";
}
if (fonts.has(name)) {
Ref<FontData> fd = ResourceLoader::load(fonts[name][style]);
if (fd.is_valid()) {
Ref<Font> font;
font.instantiate();
font->add_data(fd);
ur->add_do_method(edited_control, "add_theme_font_override", edited_font, font);
}
}
}
if (edited_control->has_theme_font_override(edited_font)) {
ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font));
} else {
ur->add_undo_method(edited_control, "remove_theme_font_override", edited_font);
}
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::_font_size_selected(double p_size) {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Font Size"));
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
StringName edited_font_size;
if (Object::cast_to<RichTextLabel>(edited_control)) {
edited_font_size = SNAME("normal_font_size");
} else {
edited_font_size = SNAME("font_size");
}
ur->add_do_method(edited_control, "add_theme_font_size_override", edited_font_size, p_size);
if (edited_control->has_theme_font_size_override(edited_font_size)) {
ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size));
} else {
ur->add_undo_method(edited_control, "remove_theme_font_size_override", edited_font_size);
}
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::_outline_size_selected(double p_size) {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Font Outline Size"));
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
ur->add_do_method(edited_control, "add_theme_constant_override", "outline_size", p_size);
if (edited_control->has_theme_constant_override("outline_size")) {
ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size")));
} else {
ur->add_undo_method(edited_control, "remove_theme_constant_override", "outline_size");
}
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::_font_color_changed(const Color &p_color) {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Font Color"), UndoRedo::MERGE_ENDS);
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
StringName edited_color;
if (Object::cast_to<RichTextLabel>(edited_control)) {
edited_color = SNAME("default_color");
} else {
edited_color = SNAME("font_color");
}
ur->add_do_method(edited_control, "add_theme_color_override", edited_color, p_color);
if (edited_control->has_theme_color_override(edited_color)) {
ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color));
} else {
ur->add_undo_method(edited_control, "remove_theme_color_override", edited_color);
}
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::_outline_color_changed(const Color &p_color) {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Font Outline Color"), UndoRedo::MERGE_ENDS);
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
ur->add_do_method(edited_control, "add_theme_color_override", "font_outline_color", p_color);
if (edited_control->has_theme_color_override("font_outline_color")) {
ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color")));
} else {
ur->add_undo_method(edited_control, "remove_theme_color_override", "font_outline_color");
}
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::_clear_formatting() {
if (edited_controls.is_empty()) {
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Clear Control Formatting"));
int count = edited_controls.size();
for (int i = 0; i < count; ++i) {
Control *edited_control = edited_controls[i];
StringName edited_color;
StringName edited_font;
StringName edited_font_size;
// Get override names.
if (Object::cast_to<RichTextLabel>(edited_control)) {
edited_color = SNAME("default_color");
edited_font = SNAME("normal_font");
edited_font_size = SNAME("normal_font_size");
} else {
edited_color = SNAME("font_color");
edited_font = SNAME("font");
edited_font_size = SNAME("font_size");
}
ur->add_do_method(edited_control, "begin_bulk_theme_override");
ur->add_undo_method(edited_control, "begin_bulk_theme_override");
ur->add_do_method(edited_control, "remove_theme_font_override", edited_font);
if (edited_control->has_theme_font_override(edited_font)) {
ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font));
}
ur->add_do_method(edited_control, "remove_theme_font_size_override", edited_font_size);
if (edited_control->has_theme_font_size_override(edited_font_size)) {
ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size));
}
ur->add_do_method(edited_control, "remove_theme_color_override", edited_color);
if (edited_control->has_theme_color_override(edited_color)) {
ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color));
}
ur->add_do_method(edited_control, "remove_theme_color_override", "font_outline_color");
if (edited_control->has_theme_color_override("font_outline_color")) {
ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color")));
}
ur->add_do_method(edited_control, "remove_theme_constant_override", "outline_size");
if (edited_control->has_theme_constant_override("outline_size")) {
ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size")));
}
ur->add_do_method(edited_control, "end_bulk_theme_override");
ur->add_undo_method(edited_control, "end_bulk_theme_override");
}
ur->add_do_method(this, "_update_control");
ur->add_undo_method(this, "_update_control");
ur->commit_action();
}
void TextControlEditor::edit(Object *p_object) {
Control *ctrl = Object::cast_to<Control>(p_object);
MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object);
edited_controls.clear();
custom_font = Ref<Font>();
if (ctrl) {
edited_controls.append(ctrl);
_update_control();
} else if (multi_node && handles(multi_node)) {
int count = multi_node->get_node_count();
Node *scene = EditorNode::get_singleton()->get_edited_scene();
for (int i = 0; i < count; ++i) {
Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i)));
edited_controls.append(child);
}
_update_control();
}
}
bool TextControlEditor::handles(Object *p_object) const {
Control *ctrl = Object::cast_to<Control>(p_object);
MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object);
if (!ctrl && !multi_node) {
return false;
} else if (ctrl) {
bool valid = false;
ctrl->get("text", &valid);
return valid;
} else {
bool valid = true;
int count = multi_node->get_node_count();
Node *scene = EditorNode::get_singleton()->get_edited_scene();
for (int i = 0; i < count; ++i) {
bool temp_valid = false;
Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i)));
if (child) {
child->get("text", &temp_valid);
}
valid = valid && temp_valid;
if (!valid) {
break;
}
}
return valid;
}
}
TextControlEditor::TextControlEditor() {
add_child(memnew(VSeparator));
font_list = memnew(OptionButton);
font_list->set_flat(true);
font_list->set_tooltip(TTR("Font"));
add_child(font_list);
font_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_selected));
font_style_list = memnew(OptionButton);
font_style_list->set_flat(true);
font_style_list->set_tooltip(TTR("Font style"));
font_style_list->set_toggle_mode(true);
add_child(font_style_list);
font_style_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_style_selected));
font_size_list = memnew(SpinBox);
font_size_list->set_tooltip(TTR("Font Size"));
font_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2);
font_size_list->set_min(6);
font_size_list->set_step(1);
font_size_list->set_max(96);
font_size_list->get_line_edit()->set_flat(true);
add_child(font_size_list);
font_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_font_size_selected));
font_color_picker = memnew(ColorPickerButton);
font_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
font_color_picker->set_flat(true);
font_color_picker->set_tooltip(TTR("Text Color"));
add_child(font_color_picker);
font_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_font_color_changed));
add_child(memnew(VSeparator));
outline_size_list = memnew(SpinBox);
outline_size_list->set_tooltip(TTR("Outline Size"));
outline_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2);
outline_size_list->set_min(0);
outline_size_list->set_step(1);
outline_size_list->set_max(96);
outline_size_list->get_line_edit()->set_flat(true);
add_child(outline_size_list);
outline_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_outline_size_selected));
outline_color_picker = memnew(ColorPickerButton);
outline_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
outline_color_picker->set_flat(true);
outline_color_picker->set_tooltip(TTR("Outline Color"));
add_child(outline_color_picker);
outline_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_outline_color_changed));
add_child(memnew(VSeparator));
clear_formatting = memnew(Button);
clear_formatting->set_flat(true);
clear_formatting->set_tooltip(TTR("Clear Formatting"));
add_child(clear_formatting);
clear_formatting->connect("pressed", callable_mp(this, &TextControlEditor::_clear_formatting));
}
/*************************************************************************/
void TextControlEditorPlugin::edit(Object *p_object) {
text_ctl_editor->edit(p_object);
}
bool TextControlEditorPlugin::handles(Object *p_object) const {
return text_ctl_editor->handles(p_object);
}
void TextControlEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
text_ctl_editor->show();
} else {
text_ctl_editor->hide();
text_ctl_editor->edit(nullptr);
}
}
TextControlEditorPlugin::TextControlEditorPlugin() {
text_ctl_editor = memnew(TextControlEditor);
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(text_ctl_editor);
text_ctl_editor->hide();
}

View File

@ -1,115 +0,0 @@
/*************************************************************************/
/* text_control_editor_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef TEXT_CONTROL_EDITOR_PLUGIN_H
#define TEXT_CONTROL_EDITOR_PLUGIN_H
#include "canvas_item_editor_plugin.h"
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/color_rect.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/popup_menu.h"
/*************************************************************************/
class TextControlEditor : public HBoxContainer {
GDCLASS(TextControlEditor, HBoxContainer);
enum FontInfoID {
FONT_INFO_THEME_DEFAULT = 0,
FONT_INFO_USER_CUSTOM = 1,
FONT_INFO_ID = 100,
};
HashMap<String, HashMap<String, String>> fonts;
OptionButton *font_list = nullptr;
SpinBox *font_size_list = nullptr;
OptionButton *font_style_list = nullptr;
ColorPickerButton *font_color_picker = nullptr;
SpinBox *outline_size_list = nullptr;
ColorPickerButton *outline_color_picker = nullptr;
Button *clear_formatting = nullptr;
Vector<Control *> edited_controls;
Ref<Font> custom_font;
protected:
void _notification(int p_what);
static void _bind_methods();
void _find_resources(EditorFileSystemDirectory *p_dir);
void _reload_fonts(const String &p_path);
void _update_fonts_menu();
void _update_styles_menu();
void _update_control();
void _font_selected(int p_id);
void _font_style_selected(int p_id);
void _set_font();
void _font_size_selected(double p_size);
void _outline_size_selected(double p_size);
void _font_color_changed(const Color &p_color);
void _outline_color_changed(const Color &p_color);
void _clear_formatting();
public:
void edit(Object *p_object);
bool handles(Object *p_object) const;
TextControlEditor();
};
/*************************************************************************/
class TextControlEditorPlugin : public EditorPlugin {
GDCLASS(TextControlEditorPlugin, EditorPlugin);
TextControlEditor *text_ctl_editor = nullptr;
public:
virtual String get_name() const override { return "TextControlFontEditor"; }
bool has_main_screen() const override { return false; }
virtual void edit(Object *p_object) override;
virtual bool handles(Object *p_object) const override;
virtual void make_visible(bool p_visible) override;
TextControlEditorPlugin();
};
#endif // TEXT_CONTROL_EDITOR_PLUGIN_H

View File

@ -2931,10 +2931,6 @@ void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) {
ur->add_undo_method(*edited_theme, "set_font", p_item_name, edited_type, Ref<Font>());
}
} break;
case Theme::DATA_TYPE_FONT_SIZE: {
ur->add_do_method(*edited_theme, "clear_font_size", p_item_name, edited_type);
ur->add_undo_method(*edited_theme, "set_font_size", p_item_name, edited_type, edited_theme->get_font_size(p_item_name, edited_type));
} break;
case Theme::DATA_TYPE_ICON: {
ur->add_do_method(*edited_theme, "clear_icon", p_item_name, edited_type);
if (edited_theme->has_icon(p_item_name, edited_type)) {
@ -3698,7 +3694,7 @@ bool ThemeEditorPlugin::handles(Object *p_node) const {
// If we are editing a theme already and this particular resource happens to belong to it,
// then we just keep editing it, despite not being able to directly handle it.
// This only goes one layer deep, but if required this can be extended to support, say, FontData inside of Font.
// This only goes one layer deep, but if required this can be extended to support, say, Font inside of Font.
bool belongs_to_theme = false;
if (Object::cast_to<Font>(p_node)) {

View File

@ -126,7 +126,7 @@ void ThemeEditorPreview::_draw_picker_overlay() {
}
Rect2 highlight_label_rect = highlight_rect;
highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, theme_cache.font_size);
highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size);
int margin_top = theme_cache.preview_picker_label->get_margin(SIDE_TOP);
int margin_left = theme_cache.preview_picker_label->get_margin(SIDE_LEFT);

View File

@ -218,7 +218,7 @@ void GenericTilePolygonEditor::_base_control_draw() {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
String text = multiple_polygon_mode ? vformat("%d:%d", tinted_polygon_index, tinted_point_index) : vformat("%d", tinted_point_index);
Size2 text_size = font->get_string_size(text, font_size);
Size2 text_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
base_control->draw_string(font, xform.xform(polygons[tinted_polygon_index][tinted_point_index]) - text_size * 0.5, text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
@ -1116,8 +1116,9 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
}
}
Vector2 string_size = font->get_string_size(text, font_size);
p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
p_canvas_item->draw_string_outline(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
@ -1727,8 +1728,9 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
} else {
text = "-";
}
Vector2 string_size = font->get_string_size(text, font_size);
p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
}
@ -1918,8 +1920,9 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
} else {
text = "-";
}
Vector2 string_size = font->get_string_size(text, font_size);
p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
}

View File

@ -1253,7 +1253,7 @@ static const char *class_renames[][2] = {
{ "AudioStreamRandomPitch", "AudioStreamRandomizer" },
{ "BakedLightmap", "LightmapGI" },
{ "BakedLightmapData", "LightmapGIData" },
{ "BitmapFont", "Font" },
{ "BitmapFont", "FontFile" },
{ "BoneAttachment", "BoneAttachment3D" },
{ "BoxShape", "BoxShape3D" },
{ "CPUParticles", "CPUParticles3D" },
@ -1279,8 +1279,8 @@ static const char *class_renames[][2] = {
{ "CubeMesh", "BoxMesh" },
{ "CylinderShape", "CylinderShape3D" },
{ "DirectionalLight", "DirectionalLight3D" },
{ "DynamicFont", "Font" },
{ "DynamicFontData", "FontData" },
{ "DynamicFont", "FontFile" },
{ "DynamicFontData", "FontFile" },
{ "EditorNavigationMeshGenerator", "NavigationMeshGenerator" },
{ "EditorSceneImporter", "EditorSceneFormatImporter" },
{ "EditorSceneImporterFBX", "EditorSceneFormatImporterFBX" },

File diff suppressed because it is too large Load Diff

View File

@ -133,12 +133,19 @@ class TextServerAdvanced : public TextServerExtension {
};
Vector<NumSystemData> num_systems;
struct FeatureInfo {
StringName name;
Variant::Type vtype = Variant::INT;
bool hidden = false;
};
HashMap<StringName, int32_t> feature_sets;
HashMap<int32_t, StringName> feature_sets_inv;
HashMap<int32_t, FeatureInfo> feature_sets_inv;
void _insert_num_systems_lang();
void _insert_feature_sets();
_FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag);
_FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype = Variant::INT, bool p_hidden = false);
// ICU support data.
@ -176,7 +183,7 @@ class TextServerAdvanced : public TextServerExtension {
Vector2 advance;
};
struct FontDataForSizeAdvanced {
struct FontForSizeAdvanced {
double ascent = 0.0;
double descent = 0.0;
double underline_position = 0.0;
@ -184,9 +191,6 @@ class TextServerAdvanced : public TextServerExtension {
double scale = 1.0;
double oversampling = 1.0;
int spacing_glyph = 0;
int spacing_space = 0;
Vector2i size;
Vector<FontTexture> textures;
@ -199,7 +203,7 @@ class TextServerAdvanced : public TextServerExtension {
FT_StreamRec stream;
#endif
~FontDataForSizeAdvanced() {
~FontForSizeAdvanced() {
if (hb_handle != nullptr) {
hb_font_destroy(hb_handle);
}
@ -211,7 +215,7 @@ class TextServerAdvanced : public TextServerExtension {
}
};
struct FontDataAdvanced {
struct FontAdvanced {
Mutex mutex;
bool antialiased = true;
@ -232,7 +236,7 @@ class TextServerAdvanced : public TextServerExtension {
String font_name;
String style_name;
HashMap<Vector2i, FontDataForSizeAdvanced *, VariantHasher, VariantComparator> cache;
HashMap<Vector2i, FontForSizeAdvanced *, VariantHasher, VariantComparator> cache;
bool face_init = false;
HashSet<uint32_t> supported_scripts;
@ -250,28 +254,28 @@ class TextServerAdvanced : public TextServerExtension {
int face_index = 0;
mutable ThreadWorkPool work_pool;
~FontDataAdvanced() {
~FontAdvanced() {
work_pool.finish();
for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : cache) {
for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : cache) {
memdelete(E.value);
}
cache.clear();
}
};
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
#ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
#endif
_FORCE_INLINE_ bool _ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const;
_FORCE_INLINE_ void _font_clear_cache(FontDataAdvanced *p_font_data);
_FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const;
_FORCE_INLINE_ void _font_clear_cache(FontAdvanced *p_font_data);
void _generateMTSDF_threaded(uint32_t y, void *p_td) const;
_FORCE_INLINE_ Vector2i _get_size(const FontDataAdvanced *p_font_data, int p_size) const {
_FORCE_INLINE_ Vector2i _get_size(const FontAdvanced *p_font_data, int p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@ -281,7 +285,7 @@ class TextServerAdvanced : public TextServerExtension {
}
}
_FORCE_INLINE_ Vector2i _get_size_outline(const FontDataAdvanced *p_font_data, const Vector2i &p_size) const {
_FORCE_INLINE_ Vector2i _get_size_outline(const FontAdvanced *p_font_data, const Vector2i &p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@ -292,6 +296,8 @@ class TextServerAdvanced : public TextServerExtension {
}
_FORCE_INLINE_ double _get_extra_advance(RID p_font_rid, int p_font_size) const;
_FORCE_INLINE_ Variant::Type _get_tag_type(int64_t p_tag) const;
_FORCE_INLINE_ bool _get_tag_hidden(int64_t p_tag) const;
// Shaped text cache data.
struct TrimData {
@ -351,6 +357,7 @@ class TextServerAdvanced : public TextServerExtension {
double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical.
double width = 0.0; // Width for horizontal layout, height for vertical.
double width_trimmed = 0.0;
int extra_spacing[4] = { 0, 0, 0, 0 };
double upos = 0.0;
double uthk = 0.0;
@ -389,7 +396,7 @@ class TextServerAdvanced : public TextServerExtension {
// Common data.
double oversampling = 1.0;
mutable RID_PtrOwner<FontDataAdvanced> font_owner;
mutable RID_PtrOwner<FontAdvanced> font_owner;
mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner;
void _realign(ShapedTextDataAdvanced *p_sd) const;
@ -407,11 +414,11 @@ class TextServerAdvanced : public TextServerExtension {
static hb_font_funcs_t *funcs;
struct bmp_font_t {
TextServerAdvanced::FontDataForSizeAdvanced *face = nullptr;
TextServerAdvanced::FontForSizeAdvanced *face = nullptr;
bool unref = false; /* Whether to destroy bm_face when done. */
};
static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref);
static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref);
static void _bmp_font_destroy(void *p_data);
static hb_bool_t _bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data);
static hb_position_t _bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data);
@ -422,8 +429,8 @@ class TextServerAdvanced : public TextServerExtension {
static hb_bool_t _bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data);
static void _bmp_create_font_funcs();
static void _bmp_free_font_funcs();
static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref);
static hb_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy);
static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref);
static hb_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy);
hb_font_t *_font_get_hb_handle(const RID &p_font, int64_t p_font_size) const;
@ -546,9 +553,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
@ -646,6 +650,9 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@ class TextServerFallback : public TextServerExtension {
Vector2 advance;
};
struct FontDataForSizeFallback {
struct FontForSizeFallback {
double ascent = 0.0;
double descent = 0.0;
double underline_position = 0.0;
@ -152,9 +152,6 @@ class TextServerFallback : public TextServerExtension {
double scale = 1.0;
double oversampling = 1.0;
int spacing_glyph = 0;
int spacing_space = 0;
Vector2i size;
Vector<FontTexture> textures;
@ -166,7 +163,7 @@ class TextServerFallback : public TextServerExtension {
FT_StreamRec stream;
#endif
~FontDataForSizeFallback() {
~FontForSizeFallback() {
#ifdef MODULE_FREETYPE_ENABLED
if (face != nullptr) {
FT_Done_Face(face);
@ -175,7 +172,7 @@ class TextServerFallback : public TextServerExtension {
}
};
struct FontDataFallback {
struct FontFallback {
Mutex mutex;
bool antialiased = true;
@ -196,7 +193,7 @@ class TextServerFallback : public TextServerExtension {
String font_name;
String style_name;
HashMap<Vector2i, FontDataForSizeFallback *, VariantHasher, VariantComparator> cache;
HashMap<Vector2i, FontForSizeFallback *, VariantHasher, VariantComparator> cache;
bool face_init = false;
Dictionary supported_varaitions;
@ -213,28 +210,28 @@ class TextServerFallback : public TextServerExtension {
mutable ThreadWorkPool work_pool;
~FontDataFallback() {
~FontFallback() {
work_pool.finish();
for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : cache) {
for (const KeyValue<Vector2i, FontForSizeFallback *> &E : cache) {
memdelete(E.value);
}
cache.clear();
}
};
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
#ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
#endif
_FORCE_INLINE_ bool _ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const;
_FORCE_INLINE_ void _font_clear_cache(FontDataFallback *p_font_data);
_FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const;
_FORCE_INLINE_ void _font_clear_cache(FontFallback *p_font_data);
void _generateMTSDF_threaded(uint32_t y, void *p_td) const;
_FORCE_INLINE_ Vector2i _get_size(const FontDataFallback *p_font_data, int p_size) const {
_FORCE_INLINE_ Vector2i _get_size(const FontFallback *p_font_data, int p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@ -244,7 +241,7 @@ class TextServerFallback : public TextServerExtension {
}
}
_FORCE_INLINE_ Vector2i _get_size_outline(const FontDataFallback *p_font_data, const Vector2i &p_size) const {
_FORCE_INLINE_ Vector2i _get_size_outline(const FontFallback *p_font_data, const Vector2i &p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@ -312,6 +309,7 @@ class TextServerFallback : public TextServerExtension {
double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical.
double width = 0.0; // Width for horizontal layout, height for vertical.
double width_trimmed = 0.0;
int extra_spacing[4] = { 0, 0, 0, 0 };
double upos = 0.0;
double uthk = 0.0;
@ -326,7 +324,7 @@ class TextServerFallback : public TextServerExtension {
// Common data.
double oversampling = 1.0;
mutable RID_PtrOwner<FontDataFallback> font_owner;
mutable RID_PtrOwner<FontFallback> font_owner;
mutable RID_PtrOwner<ShapedTextDataFallback> shaped_owner;
void _realign(ShapedTextDataFallback *p_sd) const;
@ -437,9 +435,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
@ -536,6 +531,9 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;

View File

@ -53,10 +53,6 @@ void Label3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label3D::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Label3D::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label3D::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label3D::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label3D::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Label3D::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Label3D::get_language);
@ -140,7 +136,7 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,suffix:px"), "set_outline_size", "get_outline_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
@ -148,12 +144,12 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:px"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
ADD_GROUP("Locale", "");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
BIND_ENUM_CONSTANT(FLAG_SHADED);
BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED);
@ -166,56 +162,6 @@ void Label3D::_bind_methods() {
BIND_ENUM_CONSTANT(ALPHA_CUT_OPAQUE_PREPASS);
}
bool Label3D::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
dirty_font = true;
_queue_update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
dirty_font = true;
_queue_update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool Label3D::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void Label3D::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void Label3D::_validate_property(PropertyInfo &property) const {
if (property.name == "material_override" || property.name == "material_overlay") {
property.usage = PROPERTY_USAGE_NO_EDITOR;
@ -280,7 +226,7 @@ Ref<TriangleMesh> Label3D::generate_triangle_mesh() const {
float total_h = 0.0;
float max_line_w = 0.0;
for (int i = 0; i < lines_rid.size(); i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
max_line_w = MAX(max_line_w, TS->shaped_text_get_width(lines_rid[i]));
}
@ -471,7 +417,10 @@ void Label3D::_shape() {
TS->shaped_text_set_direction(text_rid, text_direction);
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language);
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
Array stt;
if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
@ -487,7 +436,10 @@ void Label3D::_shape() {
} else if (dirty_font) {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
}
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
dirty_font = false;
@ -534,7 +486,7 @@ void Label3D::_shape() {
// Generate surfaces and materials.
float total_h = 0.0;
for (int i = 0; i < lines_rid.size(); i++) {
total_h += (TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing) * pixel_size;
total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size;
}
float vbegin = 0.0;
@ -570,7 +522,7 @@ void Label3D::_shape() {
} break;
}
offset.x += lbl_offset.x * pixel_size;
offset.y -= (TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP)) * pixel_size;
offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
if (outline_modulate.a != 0.0 && outline_size > 0) {
// Outline surfaces.
@ -584,7 +536,7 @@ void Label3D::_shape() {
for (int j = 0; j < gl_size; j++) {
_generate_glyph_surfaces(glyphs[j], offset, modulate, render_priority);
}
offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size;
offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
}
for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) {
@ -657,29 +609,6 @@ TextServer::Direction Label3D::get_text_direction() const {
return text_direction;
}
void Label3D::clear_opentype_features() {
opentype_features.clear();
dirty_font = true;
_queue_update();
}
void Label3D::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
dirty_font = true;
_queue_update();
}
}
int Label3D::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void Label3D::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -781,7 +710,7 @@ Ref<Font> Label3D::_get_font_or_default() const {
theme_font.unref();
}
if (font_override.is_valid() && font_override->get_data_count() > 0) {
if (font_override.is_valid()) {
return font_override;
}

View File

@ -122,7 +122,6 @@ private:
float line_spacing = 0.f;
Dictionary opentype_features;
String language;
TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@ -150,9 +149,6 @@ protected:
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
void _validate_property(PropertyInfo &property) const override;
void _im_update();
@ -180,10 +176,6 @@ public:
void set_text_direction(TextServer::Direction p_text_direction);
TextServer::Direction get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -342,12 +342,7 @@ void Button::_notification(int p_what) {
} break;
}
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
text_buf->draw_outline(ci, text_ofs, get_theme_constant(SNAME("outline_size")), get_theme_color(SNAME("font_outline_color")));
text_buf->draw(ci, text_ofs, color);
} break;
}
@ -363,7 +358,7 @@ void Button::_shape() {
} else {
text_buf->set_direction((TextServer::Direction)text_direction);
}
text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
text_buf->add_string(xl_text, font, font_size, language);
text_buf->set_text_overrun_behavior(overrun_behavior);
}
@ -409,29 +404,6 @@ Control::TextDirection Button::get_text_direction() const {
return text_direction;
}
void Button::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
}
void Button::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int Button::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void Button::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -512,56 +484,6 @@ HorizontalAlignment Button::get_icon_alignment() const {
return icon_alignment;
}
bool Button::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool Button::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void Button::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
@ -569,9 +491,6 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Button::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Button::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Button::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon);
@ -588,8 +507,6 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
@ -597,6 +514,10 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_alignment", "get_icon_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
}
Button::Button(const String &p_text) {

View File

@ -43,7 +43,6 @@ private:
String xl_text;
Ref<TextParagraph> text_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
@ -62,10 +61,6 @@ protected:
void _notification(int p_what);
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
virtual Size2 get_minimum_size() const override;
@ -78,10 +73,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -46,7 +46,7 @@ void CodeEdit::_notification(int p_what) {
line_spacing = get_theme_constant(SNAME("line_spacing"));
set_gutter_width(main_gutter, get_line_height());
set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width);
set_gutter_width(fold_gutter, get_line_height() / 1.2);
breakpoint_color = get_theme_color(SNAME("breakpoint_color"));
@ -86,7 +86,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 float char_size = font->get_char_size('0', 0, font_size).width;
const float char_size = font->get_char_size('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();
@ -123,7 +123,7 @@ void CodeEdit::_notification(int p_what) {
}
const int scroll_width = code_completion_options_count > code_completion_max_lines ? code_completion_scroll_width : 0;
const int code_completion_base_width = font->get_string_size(code_completion_base, font_size).width;
const int code_completion_base_width = font->get_string_size(code_completion_base, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
if (caret_pos.x - code_completion_base_width + code_completion_rect.size.width + scroll_width > get_size().width) {
code_completion_rect.position.x = get_size().width - code_completion_rect.size.width - scroll_width;
} else {
@ -178,8 +178,8 @@ void CodeEdit::_notification(int p_what) {
for (int j = 0; j < code_completion_options[l].matches.size(); j++) {
Pair<int, int> match = code_completion_options[l].matches[j];
int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), font_size).width;
int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), font_size).width;
int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
draw_rect(Rect2(match_pos + Point2(match_offset, 0), Size2(match_len, row_height)), code_completion_existing_color);
}
@ -208,11 +208,11 @@ void CodeEdit::_notification(int p_what) {
int max_width = 0;
for (int i = 0; i < line_count; i++) {
max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], font_size).x);
max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x);
}
Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (line_spacing * line_count - 1));
int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), font_size).x;
int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
if (code_hint_xpos == -0xFFFF) {
code_hint_xpos = get_caret_draw_pos().x - offset;
}
@ -232,8 +232,8 @@ void CodeEdit::_notification(int p_what) {
int begin = 0;
int end = 0;
if (line.contains(String::chr(0xFFFF))) {
begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), font_size).x;
end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), font_size).x;
begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
}
Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent(font_size) + font_height * i + yofs);
@ -2795,7 +2795,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
offset = line_height;
}
max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
code_completion_options.push_back(option);
}
@ -2906,7 +2906,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
if (string_to_complete.length() == 0) {
code_completion_options.push_back(option);
max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
continue;
}
@ -3012,7 +3012,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
option.matches.append_array(ssq_matches);
completion_options_subseq.push_back(option);
}
max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
} else if (!*ssq_lower) { // Matched the whole subsequence in s_lower.
option.matches.clear();
@ -3029,7 +3029,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
option.matches.append_array(ssq_lower_matches);
completion_options_subseq_casei.push_back(option);
}
max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
}
}
@ -3085,7 +3085,7 @@ void CodeEdit::_text_changed() {
}
if (font.is_valid()) {
set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width);
}
lc = get_line_count();

View File

@ -1115,7 +1115,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String
Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Ref<Font> *font = data.font_override.getptr(p_name);
if (font && (*font)->get_data_count() > 0) {
if (font) {
return *font;
}
}

View File

@ -44,26 +44,6 @@ struct _MinSizeCache {
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
notify_property_list_changed();
return true;
}
if (!str.begins_with("slot/")) {
return false;
@ -106,18 +86,6 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
if (!str.begins_with("slot/")) {
return false;
}
@ -156,12 +124,6 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
}
void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
int idx = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@ -471,7 +433,7 @@ void GraphNode::_shape() {
} else {
title_buf->set_direction((TextServer::Direction)text_direction);
}
title_buf->add_string(title, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
title_buf->add_string(title, font, font_size, language);
}
#ifdef TOOLS_ENABLED
@ -726,29 +688,6 @@ Control::TextDirection GraphNode::get_text_direction() const {
return text_direction;
}
void GraphNode::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
}
void GraphNode::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int GraphNode::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void GraphNode::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -1043,9 +982,6 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_title"), &GraphNode::get_title);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &GraphNode::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &GraphNode::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &GraphNode::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &GraphNode::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &GraphNode::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &GraphNode::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &GraphNode::get_language);
@ -1105,8 +1041,6 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_overlay"), &GraphNode::get_overlay);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
@ -1114,6 +1048,10 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "comment"), "set_comment", "is_comment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_SIGNAL(MethodInfo("position_offset_changed"));
ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "idx")));
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));

View File

@ -60,7 +60,6 @@ private:
String title;
Ref<TextLine> title_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@ -148,10 +147,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -43,7 +43,7 @@ void ItemList::_shape(int p_idx) {
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.opentype_features, (!item.language.is_empty()) ? item.language : TranslationServer::get_singleton()->get_tool_locale());
item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
item.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
@ -117,35 +117,6 @@ Control::TextDirection ItemList::get_item_text_direction(int p_idx) const {
return items[p_idx].text_direction;
}
void ItemList::clear_item_opentype_features(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].opentype_features.clear();
_shape(p_idx);
update();
}
void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) {
if (p_idx < 0) {
p_idx += get_item_count();
}
ERR_FAIL_INDEX(p_idx, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_idx].opentype_features.has(tag) || (int)items[p_idx].opentype_features[tag] != p_value) {
items.write[p_idx].opentype_features[tag] = p_value;
_shape(p_idx);
update();
}
}
int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_idx].opentype_features.has(tag)) {
return -1;
}
return items[p_idx].opentype_features[tag];
}
void ItemList::set_item_language(int p_idx, const String &p_language) {
if (p_idx < 0) {
p_idx += get_item_count();
@ -1656,10 +1627,6 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_text_direction", "idx", "direction"), &ItemList::set_item_text_direction);
ClassDB::bind_method(D_METHOD("get_item_text_direction", "idx"), &ItemList::get_item_text_direction);
ClassDB::bind_method(D_METHOD("set_item_opentype_feature", "idx", "tag", "value"), &ItemList::set_item_opentype_feature);
ClassDB::bind_method(D_METHOD("get_item_opentype_feature", "idx", "tag"), &ItemList::get_item_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_item_opentype_features", "idx"), &ItemList::clear_item_opentype_features);
ClassDB::bind_method(D_METHOD("set_item_language", "idx", "language"), &ItemList::set_item_language);
ClassDB::bind_method(D_METHOD("get_item_language", "idx"), &ItemList::get_item_language);

View File

@ -58,7 +58,6 @@ private:
Ref<Texture2D> tag_icon;
String text;
Ref<TextParagraph> text_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@ -145,10 +144,6 @@ public:
void set_item_text_direction(int p_idx, TextDirection p_text_direction);
TextDirection get_item_text_direction(int p_idx) const;
void set_item_opentype_feature(int p_idx, const String &p_name, int p_value);
int get_item_opentype_feature(int p_idx, const String &p_name) const;
void clear_item_opentype_features(int p_idx);
void set_item_language(int p_idx, const String &p_language);
String get_item_language(int p_idx) const;

View File

@ -66,11 +66,11 @@ bool Label::is_uppercase() const {
int Label::get_line_height(int p_line) const {
Ref<Font> font = get_theme_font(SNAME("font"));
if (p_line >= 0 && p_line < lines_rid.size()) {
return TS->shaped_text_get_size(lines_rid[p_line]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
return TS->shaped_text_get_size(lines_rid[p_line]).y;
} else if (lines_rid.size() > 0) {
int h = 0;
for (int i = 0; i < lines_rid.size(); i++) {
h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y);
}
return h;
} else {
@ -83,7 +83,6 @@ void Label::_shape() {
int width = (get_size().width - style->get_minimum_size().width);
if (dirty || font_dirty) {
String lang = (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale();
if (dirty) {
TS->shaped_text_clear(text_rid);
}
@ -95,18 +94,21 @@ void Label::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null());
String text = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text;
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
text = text.substr(0, visible_chars);
}
if (dirty) {
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, lang);
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
} else {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
}
}
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text));
dirty = false;
font_dirty = false;
@ -233,7 +235,7 @@ void Label::_update_visible() {
minsize.height = 0;
int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped);
for (int64_t i = lines_skipped; i < last_line; i++) {
minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (minsize.height > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@ -314,7 +316,7 @@ void Label::_notification(int p_what) {
// Get number of lines to fit to the height.
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@ -334,7 +336,7 @@ void Label::_notification(int p_what) {
int total_glyphs = 0;
total_h = 0;
for (int64_t i = lines_skipped; i < last_line; i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]);
}
int visible_glyphs = total_glyphs * percent_visible;
@ -374,7 +376,7 @@ void Label::_notification(int p_what) {
for (int i = lines_skipped; i < last_line; i++) {
Size2 line_size = TS->shaped_text_get_size(lines_rid[i]);
ofs.x = 0;
ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP);
ofs.y += TS->shaped_text_get_ascent(lines_rid[i]);
switch (horizontal_alignment) {
case HORIZONTAL_ALIGNMENT_FILL:
if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) {
@ -527,7 +529,7 @@ void Label::_notification(int p_what) {
}
}
}
ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM);
ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing;
}
} break;
@ -551,7 +553,7 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
Ref<Font> font = get_theme_font(SNAME("font"));
min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))));
Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
@ -582,7 +584,7 @@ int Label::get_visible_line_count() const {
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@ -674,29 +676,6 @@ Control::TextDirection Label::get_text_direction() const {
return text_direction;
}
void Label::clear_opentype_features() {
opentype_features.clear();
font_dirty = true;
update();
}
void Label::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
font_dirty = true;
update();
}
}
int Label::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void Label::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -818,56 +797,6 @@ int Label::get_total_character_count() const {
return xl_text.length();
}
bool Label::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
font_dirty = true;
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
font_dirty = true;
update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool Label::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void Label::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label::set_horizontal_alignment);
ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &Label::get_horizontal_alignment);
@ -877,9 +806,6 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &Label::get_text);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Label::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Label::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Label::get_language);
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label::set_autowrap_mode);
@ -924,11 +850,9 @@ void Label::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
ADD_GROUP("Locale", "");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}

View File

@ -53,7 +53,6 @@ private:
RID text_rid;
Vector<RID> lines_rid;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@ -74,10 +73,6 @@ protected:
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
virtual Size2 get_minimum_size() const override;
@ -93,10 +88,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -787,7 +787,7 @@ void LineEdit::_notification(int p_what) {
int x_ofs = 0;
bool using_placeholder = text.is_empty() && ime_text.is_empty();
float text_width = TS->shaped_text_get_size(text_rid).x;
float text_height = TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
float text_height = TS->shaped_text_get_size(text_rid).y;
switch (alignment) {
case HORIZONTAL_ALIGNMENT_FILL:
@ -1451,29 +1451,6 @@ Control::TextDirection LineEdit::get_text_direction() const {
return text_direction;
}
void LineEdit::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
}
void LineEdit::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int LineEdit::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void LineEdit::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -1688,7 +1665,7 @@ Size2 LineEdit::get_minimum_size() const {
Size2 min_size;
// Minimum size of text.
float em_space_size = font->get_char_size('M', 0, font_size).x;
float em_space_size = font->get_char_size('M', font_size).x;
min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
if (expand_to_text_length) {
@ -1696,7 +1673,7 @@ Size2 LineEdit::get_minimum_size() const {
min_size.width = MAX(min_size.width, full_width + em_space_size);
}
min_size.height = MAX(TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM), font->get_height(font_size));
min_size.height = MAX(TS->shaped_text_get_size(text_rid).y, font->get_height(font_size));
// Take icons into account.
int icon_max_width = 0;
@ -2155,7 +2132,10 @@ void LineEdit::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null());
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language);
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, t));
full_width = TS->shaped_text_get_size(text_rid).x;
@ -2236,56 +2216,6 @@ Key LineEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
bool LineEdit::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool LineEdit::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void LineEdit::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void LineEdit::_validate_property(PropertyInfo &property) const {
if (!caret_blink_enabled && property.name == "caret_blink_speed") {
property.usage = PROPERTY_USAGE_NO_EDITOR;
@ -2311,9 +2241,6 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_control_chars", "enable"), &LineEdit::set_draw_control_chars);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LineEdit::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &LineEdit::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &LineEdit::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &LineEdit::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &LineEdit::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LineEdit::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &LineEdit::get_language);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &LineEdit::set_structured_text_bidi_override);
@ -2419,18 +2346,20 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_caret_column", "get_caret_column");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_force_displayed"), "set_caret_force_displayed", "is_caret_force_displayed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
void LineEdit::_ensure_menu() {

View File

@ -105,7 +105,6 @@ private:
int scroll_offset = 0;
int max_length = 0; // 0 for no maximum.
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextDirection input_direction = TEXT_DIRECTION_LTR;
@ -210,9 +209,6 @@ protected:
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
void _validate_property(PropertyInfo &property) const override;
public:
@ -248,10 +244,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -43,7 +43,7 @@ void LinkButton::_shape() {
text_buf->set_direction((TextServer::Direction)text_direction);
}
TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text));
text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
text_buf->add_string(xl_text, font, font_size, language);
}
void LinkButton::set_text(const String &p_text) {
@ -96,29 +96,6 @@ Control::TextDirection LinkButton::get_text_direction() const {
return text_direction;
}
void LinkButton::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
}
void LinkButton::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int LinkButton::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void LinkButton::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -237,64 +214,11 @@ void LinkButton::_notification(int p_what) {
}
}
bool LinkButton::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool LinkButton::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void LinkButton::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void LinkButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &LinkButton::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &LinkButton::get_text);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LinkButton::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &LinkButton::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &LinkButton::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &LinkButton::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LinkButton::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &LinkButton::get_language);
ClassDB::bind_method(D_METHOD("set_underline_mode", "underline_mode"), &LinkButton::set_underline_mode);
@ -309,10 +233,11 @@ void LinkButton::_bind_methods() {
BIND_ENUM_CONSTANT(UNDERLINE_MODE_NEVER);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}

View File

@ -50,7 +50,6 @@ private:
Ref<TextLine> text_buf;
UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@ -63,10 +62,6 @@ protected:
void _notification(int p_what);
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
void set_text(const String &p_text);
String get_text() const;
@ -80,10 +75,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;

View File

@ -760,11 +760,11 @@ void PopupMenu::_shape_item(int p_item) {
} else {
items.write[p_item].text_buf->set_direction((TextServer::Direction)items[p_item].text_direction);
}
items.write[p_item].text_buf->add_string(items.write[p_item].xl_text, font, font_size, items[p_item].opentype_features, !items[p_item].language.is_empty() ? items[p_item].language : TranslationServer::get_singleton()->get_tool_locale());
items.write[p_item].text_buf->add_string(items.write[p_item].xl_text, font, font_size, items[p_item].language);
items.write[p_item].accel_text_buf->clear();
items.write[p_item].accel_text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
items.write[p_item].accel_text_buf->add_string(_get_accel_text(items.write[p_item]), font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
items.write[p_item].accel_text_buf->add_string(_get_accel_text(items.write[p_item]), font, font_size);
items.write[p_item].dirty = false;
}
}
@ -1067,29 +1067,6 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex
}
}
void PopupMenu::clear_item_opentype_features(int p_item) {
if (p_item < 0) {
p_item += get_item_count();
}
ERR_FAIL_INDEX(p_item, items.size());
items.write[p_item].opentype_features.clear();
items.write[p_item].dirty = true;
control->update();
}
void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int p_value) {
if (p_item < 0) {
p_item += get_item_count();
}
ERR_FAIL_INDEX(p_item, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_item].opentype_features.has(tag) || (int)items[p_item].opentype_features[tag] != p_value) {
items.write[p_item].opentype_features[tag] = p_value;
items.write[p_item].dirty = true;
control->update();
}
}
void PopupMenu::set_item_language(int p_item, const String &p_language) {
if (p_item < 0) {
p_item += get_item_count();
@ -1195,15 +1172,6 @@ Control::TextDirection PopupMenu::get_item_text_direction(int p_item) const {
return items[p_item].text_direction;
}
int PopupMenu::get_item_opentype_feature(int p_item, const String &p_name) const {
ERR_FAIL_INDEX_V(p_item, items.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_item].opentype_features.has(tag)) {
return -1;
}
return items[p_item].opentype_features[tag];
}
String PopupMenu::get_item_language(int p_item) const {
ERR_FAIL_INDEX_V(p_item, items.size(), "");
return items[p_item].language;
@ -1853,7 +1821,6 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_text", "index", "text"), &PopupMenu::set_item_text);
ClassDB::bind_method(D_METHOD("set_item_text_direction", "index", "direction"), &PopupMenu::set_item_text_direction);
ClassDB::bind_method(D_METHOD("set_item_opentype_feature", "index", "tag", "value"), &PopupMenu::set_item_opentype_feature);
ClassDB::bind_method(D_METHOD("set_item_language", "index", "language"), &PopupMenu::set_item_language);
ClassDB::bind_method(D_METHOD("set_item_icon", "index", "icon"), &PopupMenu::set_item_icon);
ClassDB::bind_method(D_METHOD("set_item_checked", "index", "checked"), &PopupMenu::set_item_checked);
@ -1876,8 +1843,6 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_text", "index"), &PopupMenu::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_text_direction", "index"), &PopupMenu::get_item_text_direction);
ClassDB::bind_method(D_METHOD("get_item_opentype_feature", "index", "tag"), &PopupMenu::get_item_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_item_opentype_features", "index"), &PopupMenu::clear_item_opentype_features);
ClassDB::bind_method(D_METHOD("get_item_language", "index"), &PopupMenu::get_item_language);
ClassDB::bind_method(D_METHOD("get_item_icon", "index"), &PopupMenu::get_item_icon);
ClassDB::bind_method(D_METHOD("is_item_checked", "index"), &PopupMenu::is_item_checked);

View File

@ -47,7 +47,6 @@ class PopupMenu : public Popup {
Ref<TextLine> text_buf;
Ref<TextLine> accel_text_buf;
Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_AUTO;
@ -171,8 +170,6 @@ public:
void set_item_text(int p_idx, const String &p_text);
void set_item_text_direction(int p_idx, Control::TextDirection p_text_direction);
void set_item_opentype_feature(int p_idx, const String &p_name, int p_value);
void clear_item_opentype_features(int p_idx);
void set_item_language(int p_idx, const String &p_language);
void set_item_icon(int p_idx, const Ref<Texture2D> &p_icon);
void set_item_checked(int p_idx, bool p_checked);
@ -195,7 +192,6 @@ public:
String get_item_text(int p_idx) const;
Control::TextDirection get_item_text_direction(int p_idx) const;
int get_item_opentype_feature(int p_idx, const String &p_name) const;
String get_item_language(int p_idx) const;
int get_item_idx_from_text(const String &text) const;
Ref<Texture2D> get_item_icon(int p_idx) const;

View File

@ -227,8 +227,10 @@ void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref<
if (font_size == -1) {
font_size = p_base_font_size;
}
Dictionary font_ftr = _find_font_features(it);
TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font_ftr);
TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font->get_opentype_features());
for (int j = 0; j < TextServer::SPACING_MAX; j++) {
TS->shaped_text_set_spacing(t, TextServer::SpacingType(j), font->get_spacing(TextServer::SpacingType(j)));
}
}
}
@ -263,7 +265,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@ -453,7 +455,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@ -483,7 +485,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (font_size == -1) {
font_size = p_base_font_size;
}
l.text_buf->add_string("\n", font, font_size, Dictionary(), "");
l.text_buf->add_string("\n", font, font_size);
text += "\n";
l.char_count++;
remaining_characters--;
@ -498,7 +500,6 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (font_size == -1) {
font_size = p_base_font_size;
}
Dictionary font_ftr = _find_font_features(it);
String lang = _find_language(it);
String tx = t->text;
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters >= 0) {
@ -506,7 +507,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
remaining_characters -= tx.length();
l.text_buf->add_string(tx, font, font_size, font_ftr, lang, (uint64_t)it);
l.text_buf->add_string(tx, font, font_size, lang, (uint64_t)it);
text += tx;
l.char_count += tx.length();
} break;
@ -837,7 +838,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
//draw_rect(Rect2(p_ofs + off, TS->shaped_text_get_size(rid)), Color(1,0,0), false, 2); //DEBUG_RECTS
off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top();
off.y += TS->shaped_text_get_ascent(rid);
// Draw inlined objects.
Array objects = TS->shaped_text_get_objects(rid);
for (int i = 0; i < objects.size(); i++) {
@ -1299,7 +1300,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw foreground color box
_draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 1);
off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom();
off.y += TS->shaped_text_get_descent(rid);
}
return line_count;
@ -1394,7 +1395,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
} break;
}
off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top();
off.y += TS->shaped_text_get_ascent(rid);
Array objects = TS->shaped_text_get_objects(rid);
for (int i = 0; i < objects.size(); i++) {
@ -1491,7 +1492,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
return table_offy;
}
off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom() + get_theme_constant(SNAME("line_separation"));
off.y += TS->shaped_text_get_descent(rid) + get_theme_constant(SNAME("line_separation"));
}
// Text line hit.
@ -2080,7 +2081,7 @@ Ref<Font> RichTextLabel::_find_font(Item *p_item) {
fontitem = fontitem->parent;
}
return Ref<Font>();
return Ref<FontFile>();
}
int RichTextLabel::_find_font_size(Item *p_item) {
@ -2113,21 +2114,6 @@ int RichTextLabel::_find_outline_size(Item *p_item, int p_default) {
return p_default;
}
Dictionary RichTextLabel::_find_font_features(Item *p_item) {
Item *ffitem = p_item;
while (ffitem) {
if (ffitem->type == ITEM_FONT_FEATURES) {
ItemFontFeatures *fi = static_cast<ItemFontFeatures *>(ffitem);
return fi->opentype_features;
}
ffitem = ffitem->parent;
}
return Dictionary();
}
RichTextLabel::ItemDropcap *RichTextLabel::_find_dc_item(Item *p_item) {
Item *item = p_item;
@ -2204,7 +2190,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
margin += tab_size * font->get_char_size(' ', 0, font_size).width;
margin += tab_size * font->get_char_size(' ', font_size).width;
} else if (item->type == ITEM_LIST) {
Ref<Font> font = _find_font(item);
@ -2215,7 +2201,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
margin += tab_size * font->get_char_size(' ', 0, font_size).width;
margin += tab_size * font->get_char_size(' ', font_size).width;
}
item = item->parent;
@ -2584,8 +2570,8 @@ void RichTextLabel::_process_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int ctrl_height = get_size().height;
int fi = main->first_invalid_line.load();
int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
@ -2950,25 +2936,14 @@ void RichTextLabel::push_font_size(int p_font_size) {
_add_item(item, true);
}
void RichTextLabel::push_font_features(const Dictionary &p_features) {
_stop_thread();
MutexLock data_lock(data_mutex);
ERR_FAIL_COND(current->type == ITEM_TABLE);
ItemFontFeatures *item = memnew(ItemFontFeatures);
item->opentype_features = p_features;
_add_item(item, true);
}
void RichTextLabel::push_outline_size(int p_font_size) {
void RichTextLabel::push_outline_size(int p_ol_size) {
_stop_thread();
MutexLock data_lock(data_mutex);
ERR_FAIL_COND(current->type == ITEM_TABLE);
ItemOutlineSize *item = memnew(ItemOutlineSize);
item->outline_size = p_font_size;
item->outline_size = p_ol_size;
_add_item(item, true);
}
@ -3840,8 +3815,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front("hint");
} else if (tag.begins_with("dropcap")) {
Vector<String> subtag = tag.substr(5, tag.length()).split(" ");
Ref<Font> f = get_theme_font(SNAME("normal_font"));
int fs = get_theme_font_size(SNAME("normal_font_size")) * 3;
Ref<Font> f = get_theme_font(SNAME("normal_font"));
Color color = get_theme_color(SNAME("default_color"));
Color outline_color = get_theme_color(SNAME("outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
@ -3974,64 +3949,127 @@ void RichTextLabel::append_text(const String &p_bbcode) {
pos = brk_end + 1;
tag_stack.push_front("outline_color");
} else if (tag.begins_with("font=")) {
String fnt = tag.substr(5, tag.length());
Ref<Font> font = ResourceLoader::load(fnt, "Font");
if (font.is_valid()) {
push_font(font);
} else {
push_font(normal_font);
}
pos = brk_end + 1;
tag_stack.push_front("font");
} else if (tag.begins_with("font_size=")) {
int fnt_size = tag.substr(10, tag.length()).to_int();
push_font_size(fnt_size);
pos = brk_end + 1;
tag_stack.push_front("font_size");
} else if (tag.begins_with("opentype_features=")) {
String fnt_ftr = tag.substr(18, tag.length());
Vector<String> subtag = fnt_ftr.split(",");
Dictionary ftrs;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
} else if (subtag_a.size() == 1) {
ftrs[TS->name_to_tag(subtag_a[0])] = 1;
if (subtag.size() > 0) {
Ref<Font> font = _find_font(current);
if (font.is_null()) {
font = normal_font;
}
Ref<FontVariation> fc;
fc.instantiate();
fc->set_base_font(font);
Dictionary features;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
features[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
} else if (subtag_a.size() == 1) {
features[TS->name_to_tag(subtag_a[0])] = 1;
}
}
fc->set_opentype_features(features);
push_font(fc);
}
push_font_features(ftrs);
pos = brk_end + 1;
tag_stack.push_front("opentype_features");
} else if (tag.begins_with("font=")) {
String fnt = tag.substr(5, tag.length());
Ref<Font> fc = ResourceLoader::load(fnt, "Font");
if (fc.is_valid()) {
push_font(fc);
}
pos = brk_end + 1;
tag_stack.push_front("font");
} else if (tag.begins_with("font ")) {
Vector<String> subtag = tag.substr(2, tag.length()).split(" ");
Ref<FontVariation> fc;
fc.instantiate();
for (int i = 1; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=", true, 2);
if (subtag_a.size() == 2) {
if (subtag_a[0] == "name" || subtag_a[0] == "n") {
String fnt = subtag_a[1];
Ref<Font> font = ResourceLoader::load(fnt, "Font");
if (font.is_valid()) {
push_font(font);
} else {
push_font(normal_font);
Ref<Font> font_data = ResourceLoader::load(fnt, "FontFile");
if (font_data.is_valid()) {
fc->set_base_font(font_data);
}
} else if (subtag_a[0] == "size" || subtag_a[0] == "s") {
int fnt_size = subtag_a[1].to_int();
push_font_size(fnt_size);
if (fnt_size > 0) {
push_font_size(fnt_size);
}
} else if (subtag_a[0] == "glyph_spacing" || subtag_a[0] == "gl") {
int spacing = subtag_a[1].to_int();
fc->set_spacing(TextServer::SPACING_GLYPH, spacing);
} else if (subtag_a[0] == "space_spacing" || subtag_a[0] == "sp") {
int spacing = subtag_a[1].to_int();
fc->set_spacing(TextServer::SPACING_SPACE, spacing);
} else if (subtag_a[0] == "top_spacing" || subtag_a[0] == "top") {
int spacing = subtag_a[1].to_int();
fc->set_spacing(TextServer::SPACING_TOP, spacing);
} else if (subtag_a[0] == "bottom_spacing" || subtag_a[0] == "bt") {
int spacing = subtag_a[1].to_int();
fc->set_spacing(TextServer::SPACING_BOTTOM, spacing);
} else if (subtag_a[0] == "embolden" || subtag_a[0] == "emb") {
float emb = subtag_a[1].to_float();
fc->set_variation_embolden(emb);
} else if (subtag_a[0] == "face_index" || subtag_a[0] == "fi") {
int fi = subtag_a[1].to_int();
fc->set_variation_face_index(fi);
} else if (subtag_a[0] == "slant" || subtag_a[0] == "sln") {
float slant = subtag_a[1].to_float();
fc->set_variation_transform(Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0));
} else if (subtag_a[0] == "opentype_variation" || subtag_a[0] == "otv") {
Dictionary variations;
if (!subtag_a[1].is_empty()) {
Vector<String> variation_tags = subtag_a[1].split(",");
for (int j = 0; j < variation_tags.size(); j++) {
Vector<String> subtag_b = variation_tags[j].split("=");
if (subtag_b.size() == 2) {
variations[TS->name_to_tag(subtag_b[0])] = subtag_b[1].to_float();
}
}
fc->set_variation_opentype(variations);
}
} else if (subtag_a[0] == "opentype_features" || subtag_a[0] == "otf") {
Dictionary features;
if (!subtag_a[1].is_empty()) {
Vector<String> feature_tags = subtag_a[1].split(",");
for (int j = 0; j < feature_tags.size(); j++) {
Vector<String> subtag_b = feature_tags[j].split("=");
if (subtag_b.size() == 2) {
features[TS->name_to_tag(subtag_b[0])] = subtag_b[1].to_float();
} else if (subtag_b.size() == 1) {
features[TS->name_to_tag(subtag_b[0])] = 1;
}
}
fc->set_opentype_features(features);
}
}
}
}
push_font(fc);
pos = brk_end + 1;
tag_stack.push_front("font");
} else if (tag.begins_with("outline_size=")) {
int fnt_size = tag.substr(13, tag.length()).to_int();
push_outline_size(fnt_size);
if (fnt_size > 0) {
push_outline_size(fnt_size);
}
pos = brk_end + 1;
tag_stack.push_front("outline_size");
@ -4854,7 +4892,6 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);
ClassDB::bind_method(D_METHOD("push_font_size", "font_size"), &RichTextLabel::push_font_size);
ClassDB::bind_method(D_METHOD("push_font_features", "opentype_features"), &RichTextLabel::push_font_features);
ClassDB::bind_method(D_METHOD("push_normal"), &RichTextLabel::push_normal);
ClassDB::bind_method(D_METHOD("push_bold"), &RichTextLabel::push_bold);
ClassDB::bind_method(D_METHOD("push_bold_italics"), &RichTextLabel::push_bold_italics);
@ -5018,11 +5055,9 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_GROUP("Locale", "");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");

View File

@ -186,11 +186,6 @@ private:
ItemFontSize() { type = ITEM_FONT_SIZE; }
};
struct ItemFontFeatures : public Item {
Dictionary opentype_features;
ItemFontFeatures() { type = ITEM_FONT_FEATURES; }
};
struct ItemColor : public Item {
Color color;
ItemColor() { type = ITEM_COLOR; }
@ -466,9 +461,8 @@ private:
Item *_get_item_at_pos(Item *p_item_from, Item *p_item_to, int p_position);
void _find_frame(Item *p_item, ItemFrame **r_frame, int *r_line);
Ref<Font> _find_font(Item *p_item);
int _find_font_size(Item *p_item);
Dictionary _find_font_features(Item *p_item);
Ref<Font> _find_font(Item *p_item);
int _find_outline_size(Item *p_item, int p_default);
ItemList *_find_list_item(Item *p_item);
ItemDropcap *_find_dc_item(Item *p_item);
@ -525,7 +519,6 @@ public:
void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0));
void push_font(const Ref<Font> &p_font);
void push_font_size(int p_font_size);
void push_font_features(const Dictionary &p_features);
void push_outline_size(int p_font_size);
void push_normal();
void push_bold();

View File

@ -311,7 +311,7 @@ void TabBar::_shape(int p_tab) {
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
}
tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, !tabs[p_tab].language.is_empty() ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale());
tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].language);
}
void TabBar::_notification(int p_what) {
@ -667,48 +667,6 @@ Control::TextDirection TabBar::get_tab_text_direction(int p_tab) const {
return tabs[p_tab].text_direction;
}
void TabBar::clear_tab_opentype_features(int p_tab) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].opentype_features.clear();
_shape(p_tab);
_update_cache();
_ensure_no_over_offset();
if (scroll_to_selected) {
ensure_tab_visible(current);
}
update();
update_minimum_size();
}
void TabBar::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_tab, tabs.size());
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag) || (int)tabs[p_tab].opentype_features[tag] != p_value) {
tabs.write[p_tab].opentype_features[tag] = p_value;
_shape(p_tab);
_update_cache();
_ensure_no_over_offset();
if (scroll_to_selected) {
ensure_tab_visible(current);
}
update();
update_minimum_size();
}
}
int TabBar::get_tab_opentype_feature(int p_tab, const String &p_name) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag)) {
return -1;
}
return tabs[p_tab].opentype_features[tag];
}
void TabBar::set_tab_language(int p_tab, const String &p_language) {
ERR_FAIL_INDEX(p_tab, tabs.size());
@ -1553,9 +1511,6 @@ void TabBar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabBar::get_tab_title);
ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &TabBar::set_tab_text_direction);
ClassDB::bind_method(D_METHOD("get_tab_text_direction", "tab_idx"), &TabBar::get_tab_text_direction);
ClassDB::bind_method(D_METHOD("set_tab_opentype_feature", "tab_idx", "tag", "values"), &TabBar::set_tab_opentype_feature);
ClassDB::bind_method(D_METHOD("get_tab_opentype_feature", "tab_idx", "tag"), &TabBar::get_tab_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_tab_opentype_features", "tab_idx"), &TabBar::clear_tab_opentype_features);
ClassDB::bind_method(D_METHOD("set_tab_language", "tab_idx", "language"), &TabBar::set_tab_language);
ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &TabBar::get_tab_language);
ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabBar::set_tab_icon);

View File

@ -57,7 +57,6 @@ private:
String text;
String xl_text;
Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
@ -137,10 +136,6 @@ public:
void set_tab_text_direction(int p_tab, TextDirection p_text_direction);
TextDirection get_tab_text_direction(int p_tab) const;
void set_tab_opentype_feature(int p_tab, const String &p_name, int p_value);
int get_tab_opentype_feature(int p_tab, const String &p_name) const;
void clear_tab_opentype_features(int p_tab);
void set_tab_language(int p_tab, const String &p_language);
String get_tab_language(int p_tab) const;

View File

@ -75,14 +75,6 @@ int TextEdit::Text::get_tab_size() const {
return tab_size;
}
void TextEdit::Text::set_font_features(const Dictionary &p_features) {
if (opentype_features.hash() == p_features.hash()) {
return;
}
opentype_features = p_features;
is_dirty = true;
}
void TextEdit::Text::set_direction_and_language(TextServer::Direction p_direction, const String &p_language) {
if (direction == p_direction && language == p_language) {
return;
@ -178,7 +170,7 @@ void TextEdit::Text::_calculate_max_line_width() {
void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_changed, const String &p_ime_text, const Array &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size());
if (font.is_null() || font_size <= 0) {
if (font.is_null()) {
return; // Not in tree?
}
@ -191,14 +183,14 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
text.write[p_line].data_buf->set_preserve_control(draw_control_chars);
if (p_ime_text.length() > 0) {
if (p_text_changed) {
text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, opentype_features, language);
text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, language);
}
if (!p_bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), p_bidi_override);
}
} else {
if (p_text_changed) {
text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, opentype_features, language);
text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, language);
}
if (!text[p_line].bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), text[p_line].bidi_override);
@ -209,14 +201,17 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
RID r = text.write[p_line].data_buf->get_rid();
int spans = TS->shaped_get_span_count(r);
for (int i = 0; i < spans; i++) {
TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, opentype_features);
TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, font->get_opentype_features());
}
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
TS->shaped_text_set_spacing(r, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
}
// Apply tab align.
if (tab_size > 0) {
Vector<float> tabs;
tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
tabs.push_back(font->get_char_size(' ', font_size).width * tab_size);
text.write[p_line].data_buf->tab_align(tabs);
}
@ -255,7 +250,7 @@ void TextEdit::Text::invalidate_all_lines() {
if (tab_size_dirty) {
if (tab_size > 0) {
Vector<float> tabs;
tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
tabs.push_back(font->get_char_size(' ', font_size).width * tab_size);
text.write[i].data_buf->tab_align(tabs);
}
// Tabs have changes, force width update.
@ -277,7 +272,7 @@ void TextEdit::Text::invalidate_font() {
max_width = -1;
line_height = -1;
if (!font.is_null() && font_size > 0) {
if (font.is_valid() && font_size > 0) {
font_height = font->get_height(font_size);
}
@ -295,7 +290,7 @@ void TextEdit::Text::invalidate_all() {
max_width = -1;
line_height = -1;
if (!font.is_null() && font_size > 0) {
if (font.is_valid() && font_size > 0) {
font_height = font->get_height(font_size);
}
@ -973,7 +968,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) {
float char_w = font->get_char_size(' ', 0, font_size).width;
float char_w = font->get_char_size(' ', 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 {
@ -1071,7 +1066,7 @@ void TextEdit::_notification(int p_what) {
// Draw line.
RID rid = ldata->get_line_rid(line_wrap_index);
float text_height = TS->shaped_text_get_size(rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
float text_height = TS->shaped_text_get_size(rid).y;
if (rtl) {
char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x;
@ -1355,7 +1350,7 @@ void TextEdit::_notification(int p_what) {
ts_caret.l_caret.size.y = caret_width;
}
if (ts_caret.l_caret.position.x >= TS->shaped_text_get_size(rid).x) {
ts_caret.l_caret.size.x = font->get_char_size('m', 0, font_size).x;
ts_caret.l_caret.size.x = font->get_char_size('m', font_size).x;
} else {
ts_caret.l_caret.size.x = 3 * caret_width;
}
@ -2573,7 +2568,7 @@ void TextEdit::_update_placeholder() {
placeholder_data_buf->set_width(text.get_width());
placeholder_data_buf->set_direction((TextServer::Direction)text_direction);
placeholder_data_buf->set_preserve_control(draw_control_chars);
placeholder_data_buf->add_string(placeholder_text, font, font_size, opentype_features, language);
placeholder_data_buf->add_string(placeholder_text, font, font_size, language);
placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text);
if (placeholder_bidi_override.is_empty()) {
@ -2582,7 +2577,7 @@ void TextEdit::_update_placeholder() {
if (get_tab_size() > 0) {
Vector<float> tabs;
tabs.push_back(font->get_char_size(' ', 0, font_size).width * get_tab_size());
tabs.push_back(font->get_char_size(' ', font_size).width * get_tab_size());
placeholder_data_buf->tab_align(tabs);
}
@ -2653,7 +2648,6 @@ void TextEdit::_update_caches() {
dir = (TextServer::Direction)text_direction;
}
text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
text.set_font_features(opentype_features);
text.set_draw_control_chars(draw_control_chars);
text.set_font(font);
text.set_font_size(font_size);
@ -2858,33 +2852,6 @@ Control::TextDirection TextEdit::get_text_direction() const {
return text_direction;
}
void TextEdit::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
text.set_font_features(opentype_features);
text.invalidate_font();
_update_placeholder();
update();
}
}
int TextEdit::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void TextEdit::clear_opentype_features() {
opentype_features.clear();
text.set_font_features(opentype_features);
text.invalidate_font();
_update_placeholder();
update();
}
void TextEdit::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@ -5071,10 +5038,6 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextEdit::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &TextEdit::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &TextEdit::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &TextEdit::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &TextEdit::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &TextEdit::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &TextEdit::get_language);
@ -5107,6 +5070,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &TextEdit::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text);
ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count);
ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &TextEdit::set_placeholder);
@ -5427,8 +5391,6 @@ void TextEdit::_bind_methods() {
/* Inspector */
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text", PROPERTY_HINT_MULTILINE_TEXT), "set_placeholder", "get_placeholder");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
@ -5468,7 +5430,9 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_move_on_right_click"), "set_move_caret_on_right_click_enabled", "is_move_caret_on_right_click_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
ADD_GROUP("Structured Text", "structured_text_");
ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
@ -5493,60 +5457,6 @@ void TextEdit::_bind_methods() {
ProjectSettings::get_singleton()->set_custom_property_info("gui/common/text_edit_undo_stack_max_size", PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers.
}
bool TextEdit::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
int value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
text.set_font_features(opentype_features);
text.invalidate_font();
_update_placeholder();
update();
}
} else {
if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
opentype_features[tag] = value;
text.set_font_features(opentype_features);
text.invalidate_font();
_update_placeholder();
update();
}
}
notify_property_list_changed();
return true;
}
return false;
}
bool TextEdit::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void TextEdit::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
/* Internal API for CodeEdit. */
// Line hiding.
void TextEdit::_set_hiding_enabled(bool p_enabled) {

View File

@ -160,7 +160,6 @@ private:
int font_size = -1;
int font_height = 0;
Dictionary opentype_features;
String language;
TextServer::Direction direction = TextServer::DIRECTION_AUTO;
bool draw_control_chars = false;
@ -180,7 +179,6 @@ private:
int get_tab_size() const;
void set_font(const Ref<Font> &p_font);
void set_font_size(int p_font_size);
void set_font_features(const Dictionary &p_features);
void set_direction_and_language(TextServer::Direction p_direction, const String &p_language);
void set_draw_control_chars(bool p_enabled);
@ -271,7 +269,6 @@ private:
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextDirection input_direction = TEXT_DIRECTION_LTR;
Dictionary opentype_features;
String language = "";
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@ -581,10 +578,6 @@ protected:
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
/* Internal API for CodeEdit, pending public API. */
// brace matching
bool highlight_matching_braces_enabled = false;
@ -650,10 +643,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;
@ -686,6 +675,7 @@ public:
void set_text(const String &p_text);
String get_text() const;
int get_line_count() const;
void set_placeholder(const String &p_text);

View File

@ -303,37 +303,6 @@ Control::TextDirection TreeItem::get_text_direction(int p_column) const {
return cells[p_column].text_direction;
}
void TreeItem::clear_opentype_features(int p_column) {
ERR_FAIL_INDEX(p_column, cells.size());
cells.write[p_column].opentype_features.clear();
cells.write[p_column].dirty = true;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
void TreeItem::set_opentype_feature(int p_column, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_column, cells.size());
int32_t tag = TS->name_to_tag(p_name);
if (!cells[p_column].opentype_features.has(tag) || (int)cells[p_column].opentype_features[tag] != p_value) {
cells.write[p_column].opentype_features[tag] = p_value;
cells.write[p_column].dirty = true;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
}
int TreeItem::get_opentype_feature(int p_column, const String &p_name) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!cells[p_column].opentype_features.has(tag)) {
return -1;
}
return cells[p_column].opentype_features[tag];
}
void TreeItem::set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser) {
ERR_FAIL_INDEX(p_column, cells.size());
@ -1269,10 +1238,6 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "column", "direction"), &TreeItem::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction", "column"), &TreeItem::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "column", "tag", "value"), &TreeItem::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "column", "tag"), &TreeItem::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features", "column"), &TreeItem::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "column", "parser"), &TreeItem::set_structured_text_bidi_override);
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override", "column"), &TreeItem::get_structured_text_bidi_override);
@ -1667,7 +1632,7 @@ void Tree::update_column(int p_col) {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].opentype_features, !columns[p_col].language.is_empty() ? columns[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].language);
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@ -1725,7 +1690,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
} else {
font_size = cache.font_size;
}
p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].opentype_features, !p_item->cells[p_col].language.is_empty() ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
p_item->cells.write[p_col].dirty = false;
}
@ -4192,7 +4157,7 @@ int Tree::get_column_minimum_width(int p_column) const {
// Check if the visible title of the column is wider.
if (show_column_titles) {
min_width = MAX(cache.font->get_string_size(columns[p_column].title, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
min_width = MAX(cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
}
if (!columns[p_column].clip_content) {
@ -4471,32 +4436,6 @@ Control::TextDirection Tree::get_column_title_direction(int p_column) const {
return columns[p_column].text_direction;
}
void Tree::clear_column_title_opentype_features(int p_column) {
ERR_FAIL_INDEX(p_column, columns.size());
columns.write[p_column].opentype_features.clear();
update_column(p_column);
update();
}
void Tree::set_column_title_opentype_feature(int p_column, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_column, columns.size());
int32_t tag = TS->name_to_tag(p_name);
if (!columns[p_column].opentype_features.has(tag) || (int)columns[p_column].opentype_features[tag] != p_value) {
columns.write[p_column].opentype_features[tag] = p_value;
update_column(p_column);
update();
}
}
int Tree::get_column_title_opentype_feature(int p_column, const String &p_name) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!columns[p_column].opentype_features.has(tag)) {
return -1;
}
return columns[p_column].opentype_features[tag];
}
void Tree::set_column_title_language(int p_column, const String &p_language) {
ERR_FAIL_INDEX(p_column, columns.size());
if (columns[p_column].language != p_language) {
@ -4983,10 +4922,6 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_column_title_direction", "column", "direction"), &Tree::set_column_title_direction);
ClassDB::bind_method(D_METHOD("get_column_title_direction", "column"), &Tree::get_column_title_direction);
ClassDB::bind_method(D_METHOD("set_column_title_opentype_feature", "column", "tag", "value"), &Tree::set_column_title_opentype_feature);
ClassDB::bind_method(D_METHOD("get_column_title_opentype_feature", "column", "tag"), &Tree::get_column_title_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_column_title_opentype_features", "column"), &Tree::clear_column_title_opentype_features);
ClassDB::bind_method(D_METHOD("set_column_title_language", "column", "language"), &Tree::set_column_title_language);
ClassDB::bind_method(D_METHOD("get_column_title_language", "column"), &Tree::get_column_title_language);

View File

@ -63,7 +63,6 @@ private:
String text;
String suffix;
Ref<TextLine> text_buf;
Dictionary opentype_features;
String language;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
@ -220,10 +219,6 @@ public:
void set_text_direction(int p_column, Control::TextDirection p_text_direction);
Control::TextDirection get_text_direction(int p_column) const;
void set_opentype_feature(int p_column, const String &p_name, int p_value);
int get_opentype_feature(int p_column, const String &p_name) const;
void clear_opentype_features(int p_column);
void set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override(int p_column) const;
@ -429,7 +424,6 @@ private:
bool clip_content = false;
String title;
Ref<TextLine> text_buf;
Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
ColumnInfo() {
@ -666,10 +660,6 @@ public:
void set_column_title_direction(int p_column, Control::TextDirection p_text_direction);
Control::TextDirection get_column_title_direction(int p_column) const;
void set_column_title_opentype_feature(int p_column, const String &p_name, int p_value);
int get_column_title_opentype_feature(int p_column, const String &p_name) const;
void clear_column_title_opentype_features(int p_column);
void set_column_title_language(int p_column, const String &p_language);
String get_column_title_language(int p_column) const;

View File

@ -658,24 +658,48 @@ void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Tex
RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid);
}
void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint16_t p_flags) const {
void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_modulate, p_flags, p_direction, p_orientation);
}
void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, real_t p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint16_t p_flags) const {
void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_max_lines, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_flags, p_direction, p_orientation);
}
real_t CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const {
ERR_FAIL_COND_V_MSG(!drawing, 0.f, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND_V(p_font.is_null(), 0.f);
ERR_FAIL_COND_V(p_char.length() != 1, 0.f);
void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], p_size, p_modulate, p_outline_size, p_outline_modulate);
p_font->draw_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_size, p_modulate, p_flags, p_direction, p_orientation);
}
void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
p_font->draw_multiline_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_size, p_modulate, p_flags, p_direction, p_orientation);
}
void CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, const Color &p_modulate) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_char.length() != 1);
ERR_FAIL_COND(p_font.is_null());
p_font->draw_char(canvas_item, p_pos, p_char[0], p_font_size, p_modulate);
}
void CanvasItem::draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, int p_size, const Color &p_modulate) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_char.length() != 1);
ERR_FAIL_COND(p_font.is_null());
p_font->draw_char_outline(canvas_item, p_pos, p_char[0], p_font_size, p_size, p_modulate);
}
void CanvasItem::_notify_transform(CanvasItem *p_node) {
@ -900,9 +924,12 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "next", "size", "modulate", "outline_size", "outline_modulate"), &CanvasItem::draw_char, DEFVAL(""), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)));
ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "font_size", "modulate"), &CanvasItem::draw_char, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)));
ClassDB::bind_method(D_METHOD("draw_char_outline", "font", "pos", "char", "font_size", "size", "modulate"), &CanvasItem::draw_char_outline, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture"), &CanvasItem::draw_multimesh);
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0)));

View File

@ -235,9 +235,14 @@ public:
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1));
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture);
void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, real_t p_width = -1, int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
real_t draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
void draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_size = 1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
void draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
void draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
void draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));
void draw_set_transform_matrix(const Transform2D &p_matrix);

View File

@ -219,7 +219,7 @@ void Viewport::_sub_window_update(Window *p_window) {
int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_offset"));
int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_offset"));
TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size);
title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
title_text.set_direction(p_window->is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
int x = (r.size.width - title_text.get_size().x) / 2;

View File

@ -853,8 +853,11 @@ void register_scene_types() {
GDREGISTER_CLASS(Animation);
GDREGISTER_CLASS(AnimationLibrary);
GDREGISTER_CLASS(FontData);
GDREGISTER_CLASS(Font);
GDREGISTER_ABSTRACT_CLASS(Font);
GDREGISTER_CLASS(FontFile);
GDREGISTER_CLASS(FontVariation);
GDREGISTER_CLASS(Curve);
GDREGISTER_CLASS(SceneReplicationConfig);
@ -921,9 +924,9 @@ void register_scene_types() {
ClassDB::add_compatibility_class("AnimationTreePlayer", "AnimationTree");
ClassDB::add_compatibility_class("BakedLightmap", "LightmapGI");
ClassDB::add_compatibility_class("BakedLightmapData", "LightmapGIData");
ClassDB::add_compatibility_class("BitmapFont", "Font");
ClassDB::add_compatibility_class("DynamicFont", "Font");
ClassDB::add_compatibility_class("DynamicFontData", "FontData");
ClassDB::add_compatibility_class("BitmapFont", "FontFile");
ClassDB::add_compatibility_class("DynamicFont", "FontFile");
ClassDB::add_compatibility_class("DynamicFontData", "FontFile");
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite");
@ -1113,7 +1116,7 @@ void initialize_theme() {
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));
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", 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));

View File

@ -918,8 +918,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("panel", "TooltipPanel",
make_flat_stylebox(Color(0, 0, 0, 0.5), 2 * default_margin, 0.5 * default_margin, 2 * default_margin, 0.5 * default_margin));
theme->set_font("font", "TooltipLabel", Ref<Font>());
theme->set_font_size("font_size", "TooltipLabel", -1);
theme->set_font("font", "TooltipLabel", Ref<Font>());
theme->set_color("font_color", "TooltipLabel", control_font_color);
theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0));
@ -939,7 +939,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_font("italics_font", "RichTextLabel", italics_font);
theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
theme->set_font_size("normal_font_size", "RichTextLabel", -1);
theme->set_font_size("bold_font_size", "RichTextLabel", -1);
theme->set_font_size("italics_font_size", "RichTextLabel", -1);
@ -1034,9 +1033,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
Ref<Font> bold_font;
Ref<Font> bold_italics_font;
Ref<Font> italics_font;
Ref<FontVariation> bold_font;
Ref<FontVariation> bold_italics_font;
Ref<FontVariation> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) {
@ -1046,48 +1045,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
// Use the default DynamicFont (separate from the editor font).
// The default DynamicFont is chosen to have a small file size since it's
// embedded in both editor and export template binaries.
Ref<Font> dynamic_font;
Ref<FontFile> dynamic_font;
dynamic_font.instantiate();
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_font_subpixel);
dynamic_font_data->set_hinting(p_font_hinting);
dynamic_font_data->set_antialiased(p_font_antialiased);
dynamic_font_data->set_multichannel_signed_distance_field(p_font_msdf);
dynamic_font_data->set_generate_mipmaps(p_font_generate_mipmaps);
dynamic_font->add_data(dynamic_font_data);
dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
dynamic_font->set_subpixel_positioning(p_font_subpixel);
dynamic_font->set_hinting(p_font_hinting);
dynamic_font->set_antialiased(p_font_antialiased);
dynamic_font->set_multichannel_signed_distance_field(p_font_msdf);
dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps);
default_font = dynamic_font;
}
if (default_font.is_valid()) {
bold_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
// Try to match OpenSans ExtraBold.
data->set_embolden(1.2);
bold_font->add_data(data);
}
bold_font->set_base_font(default_font);
bold_font->set_variation_embolden(1.2);
bold_italics_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
// Try to match OpenSans ExtraBold Italic.
data->set_embolden(1.2);
data->set_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
bold_italics_font->add_data(data);
}
bold_italics_font->set_base_font(default_font);
bold_italics_font->set_variation_embolden(1.2);
bold_italics_font->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
italics_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
// Try to match OpenSans Italic.
data->set_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
italics_font->add_data(data);
}
italics_font->set_base_font(default_font);
italics_font->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
}
fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);

Some files were not shown because too many files have changed in this diff Show More