Implement TextServer GDExtension interface, remove TextServer GDNative interface.

This commit is contained in:
bruvzg 2021-08-28 00:19:51 +03:00
parent 06c1b40b84
commit 0c0b5c84b0
58 changed files with 4388 additions and 3388 deletions

View file

@ -841,6 +841,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ {
Array native_structures; Array native_structures;
// AudioStream structures
{ {
Dictionary d; Dictionary d;
d["name"] = "AudioFrame"; d["name"] = "AudioFrame";
@ -849,6 +850,22 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
native_structures.push_back(d); native_structures.push_back(d);
} }
// TextServer structures
{
Dictionary d;
d["name"] = "Glyph";
d["format"] = "int start,int end,uint8_t count,uint8_t repeat,uint16_t flags,float x_off,float y_off,float advance,RID font_rid,int font_size,int32_t index";
native_structures.push_back(d);
}
{
Dictionary d;
d["name"] = "CaretInfo";
d["format"] = "Rect2 leading_caret,Rect2 trailing_caret,TextServer::Direction leading_direction,TextServer::Direction trailing_direction";
native_structures.push_back(d);
}
api_dump["native_structures"] = native_structures; api_dump["native_structures"] = native_structures;
} }

View file

@ -150,7 +150,7 @@
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 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="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" /> <argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="10" name="flags" type="int" default="51" /> <argument index="10" name="flags" type="int" default="99" />
<description> <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. 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> </description>

View file

@ -103,7 +103,7 @@
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 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="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" /> <argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
<argument index="10" name="flags" type="int" default="51" /> <argument index="10" name="flags" type="int" default="99" />
<description> <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. 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]. See also [method CanvasItem.draw_multiline_string].
@ -185,7 +185,7 @@
<argument index="0" name="text" type="String" /> <argument index="0" name="text" type="String" />
<argument index="1" name="width" type="float" default="-1" /> <argument index="1" name="width" type="float" default="-1" />
<argument index="2" name="size" type="int" default="-1" /> <argument index="2" name="size" type="int" default="-1" />
<argument index="3" name="flags" type="int" default="48" /> <argument index="3" name="flags" type="int" default="96" />
<description> <description>
Returns the size of a bounding box of a string broken into the lines, taking kerning and advance into account. 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]. See also [method draw_multiline_string].

View file

@ -246,7 +246,7 @@
<method name="get_name" qualifiers="const"> <method name="get_name" qualifiers="const">
<return type="String" /> <return type="String" />
<description> <description>
Returns the name of the host OS. Possible values are: [code]"Android"[/code], [code]"iOS"[/code], [code]"HTML5"[/code], [code]"OSX"[/code], [code]"Server"[/code], [code]"Windows"[/code], [code]"UWP"[/code], [code]"X11"[/code]. Returns the name of the host OS. Possible values are: [code]"Android"[/code], [code]"iOS"[/code], [code]"HTML5"[/code], [code]"macOS"[/code], [code]"Server"[/code], [code]"Windows"[/code], [code]"UWP"[/code], [code]"X11"[/code].
</description> </description>
</method> </method>
<method name="get_process_id" qualifiers="const"> <method name="get_process_id" qualifiers="const">

View file

@ -185,6 +185,18 @@
<description> <description>
</description> </description>
</method> </method>
<method name="canvas_item_add_msdf_texture_rect_region">
<return type="void" />
<argument index="0" name="item" type="RID" />
<argument index="1" name="rect" type="Rect2" />
<argument index="2" name="texture" type="RID" />
<argument index="3" name="src_rect" type="Rect2" />
<argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="5" name="outline_size" type="int" default="0" />
<argument index="6" name="px_range" type="float" default="1.0" />
<description>
</description>
</method>
<method name="canvas_item_add_multimesh"> <method name="canvas_item_add_multimesh">
<return type="void" /> <return type="void" />
<argument index="0" name="item" type="RID" /> <argument index="0" name="item" type="RID" />

View file

@ -281,7 +281,7 @@
<member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0"> <member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0">
Text writing direction. Text writing direction.
</member> </member>
<member name="flags" type="int" setter="set_flags" getter="get_flags" default="51"> <member name="flags" type="int" setter="set_flags" getter="get_flags" default="99">
Line breaking and alignment rules. For more info see [TextServer]. Line breaking and alignment rules. For more info see [TextServer].
</member> </member>
<member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1"> <member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="TextServer" inherits="Object" version="4.0"> <class name="TextServer" inherits="RefCounted" version="4.0">
<brief_description> <brief_description>
Interface for the fonts and complex text layouts. Interface for the fonts and complex text layouts.
</brief_description> </brief_description>
@ -487,8 +487,8 @@
</method> </method>
<method name="font_set_data"> <method name="font_set_data">
<return type="void" /> <return type="void" />
<argument index="0" name="data" type="RID" /> <argument index="0" name="font_rid" type="RID" />
<argument index="1" name="arg1" type="PackedByteArray" /> <argument index="1" name="data" type="PackedByteArray" />
<description> <description>
Sets font source data, e.g contents of the dynamic font source file. Sets font source data, e.g contents of the dynamic font source file.
</description> </description>
@ -714,12 +714,14 @@
<return type="Dictionary" /> <return type="Dictionary" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
<description> <description>
Returns the dictionary of the supported OpenType features.
</description> </description>
</method> </method>
<method name="font_supported_variation_list" qualifiers="const"> <method name="font_supported_variation_list" qualifiers="const">
<return type="Dictionary" /> <return type="Dictionary" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
<description> <description>
Returns the dictionary of the supported OpenType variation coordinates.
</description> </description>
</method> </method>
<method name="format_number" qualifiers="const"> <method name="format_number" qualifiers="const">
@ -737,6 +739,12 @@
Frees an object created by this [TextServer]. Frees an object created by this [TextServer].
</description> </description>
</method> </method>
<method name="get_features" qualifiers="const">
<return type="int" />
<description>
Returns text server features, see [enum Feature].
</description>
</method>
<method name="get_hex_code_box_size" qualifiers="const"> <method name="get_hex_code_box_size" qualifiers="const">
<return type="Vector2" /> <return type="Vector2" />
<argument index="0" name="size" type="int" /> <argument index="0" name="size" type="int" />
@ -751,6 +759,18 @@
Returns the name of the server interface. Returns the name of the server interface.
</description> </description>
</method> </method>
<method name="get_support_data_filename" qualifiers="const">
<return type="String" />
<description>
Returns default TextServer database (e.g. ICU break iterators and dictionaries) filename.
</description>
</method>
<method name="get_support_data_info" qualifiers="const">
<return type="String" />
<description>
Returns TextServer database (e.g. ICU break iterators and dictionaries) description.
</description>
</method>
<method name="has"> <method name="has">
<return type="bool" /> <return type="bool" />
<argument index="0" name="rid" type="RID" /> <argument index="0" name="rid" type="RID" />
@ -758,14 +778,14 @@
Returns [code]true[/code] if [code]rid[/code] is valid resource owned by this text server. Returns [code]true[/code] if [code]rid[/code] is valid resource owned by this text server.
</description> </description>
</method> </method>
<method name="has_feature"> <method name="has_feature" qualifiers="const">
<return type="bool" /> <return type="bool" />
<argument index="0" name="feature" type="int" enum="TextServer.Feature" /> <argument index="0" name="feature" type="int" enum="TextServer.Feature" />
<description> <description>
Returns [code]true[/code] if the server supports a feature. Returns [code]true[/code] if the server supports a feature.
</description> </description>
</method> </method>
<method name="is_locale_right_to_left"> <method name="is_locale_right_to_left" qualifiers="const">
<return type="bool" /> <return type="bool" />
<argument index="0" name="locale" type="String" /> <argument index="0" name="locale" type="String" />
<description> <description>
@ -802,6 +822,14 @@
Returns percent sign used in the [code]language[/code]. Returns percent sign used in the [code]language[/code].
</description> </description>
</method> </method>
<method name="save_support_data" qualifiers="const">
<return type="bool" />
<argument index="0" name="filename" type="String" />
<description>
Saves optional TextServer database (e.g. ICU break iterators and dictionaries) to the file.
Note: This function is used by during project export, to include TextServer database.
</description>
</method>
<method name="shaped_text_add_object"> <method name="shaped_text_add_object">
<return type="bool" /> <return type="bool" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
@ -898,7 +926,7 @@
Returns direction of the text. Returns direction of the text.
</description> </description>
</method> </method>
<method name="shaped_text_get_dominant_direciton_in_range" qualifiers="const"> <method name="shaped_text_get_dominant_direction_in_range" qualifiers="const">
<return type="int" enum="TextServer.Direction" /> <return type="int" enum="TextServer.Direction" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="start" type="int" /> <argument index="1" name="start" type="int" />
@ -907,30 +935,58 @@
Returns dominant direction of in the range of text. Returns dominant direction of in the range of text.
</description> </description>
</method> </method>
<method name="shaped_text_get_ellipsis_glyph_count" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns number of glyphs in the ellipsis.
</description>
</method>
<method name="shaped_text_get_ellipsis_glyphs" qualifiers="const">
<return type="Array" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns array of the glyphs in the ellipsis.
</description>
</method>
<method name="shaped_text_get_ellipsis_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns position of the ellipsis.
</description>
</method>
<method name="shaped_text_get_glyph_count" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns number of glyphs in the buffer.
</description>
</method>
<method name="shaped_text_get_glyphs" qualifiers="const"> <method name="shaped_text_get_glyphs" qualifiers="const">
<return type="Array" /> <return type="Array" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<description> <description>
Returns text glyphs. Returns text glyphs in the visual order.
</description> </description>
</method> </method>
<method name="shaped_text_get_line_breaks" qualifiers="const"> <method name="shaped_text_get_line_breaks" qualifiers="const">
<return type="Array" /> <return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" /> <argument index="1" name="width" type="float" />
<argument index="2" name="start" type="int" default="0" /> <argument index="2" name="start" type="int" default="0" />
<argument index="3" name="break_flags" type="int" default="48" /> <argument index="3" name="break_flags" type="int" default="96" />
<description> <description>
Breaks text to the lines and returns character ranges for each line. Breaks text to the lines and returns character ranges for each line.
</description> </description>
</method> </method>
<method name="shaped_text_get_line_breaks_adv" qualifiers="const"> <method name="shaped_text_get_line_breaks_adv" qualifiers="const">
<return type="Array" /> <return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="PackedFloat32Array" /> <argument index="1" name="width" type="PackedFloat32Array" />
<argument index="2" name="start" type="int" default="0" /> <argument index="2" name="start" type="int" default="0" />
<argument index="3" name="once" type="bool" default="true" /> <argument index="3" name="once" type="bool" default="true" />
<argument index="4" name="break_flags" type="int" default="48" /> <argument index="4" name="break_flags" type="int" default="96" />
<description> <description>
Breaks text to the lines and columns. Returns character ranges for each segment. Breaks text to the lines and columns. Returns character ranges for each segment.
</description> </description>
@ -987,7 +1043,7 @@
</description> </description>
</method> </method>
<method name="shaped_text_get_selection" qualifiers="const"> <method name="shaped_text_get_selection" qualifiers="const">
<return type="Array" /> <return type="PackedVector2Array" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="start" type="int" /> <argument index="1" name="start" type="int" />
<argument index="2" name="end" type="int" /> <argument index="2" name="end" type="int" />
@ -1002,6 +1058,13 @@
Returns size of the text. Returns size of the text.
</description> </description>
</method> </method>
<method name="shaped_text_get_trim_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns position of the trim.
</description>
</method>
<method name="shaped_text_get_underline_position" qualifiers="const"> <method name="shaped_text_get_underline_position" qualifiers="const">
<return type="float" /> <return type="float" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
@ -1024,8 +1087,9 @@
</description> </description>
</method> </method>
<method name="shaped_text_get_word_breaks" qualifiers="const"> <method name="shaped_text_get_word_breaks" qualifiers="const">
<return type="Array" /> <return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="grapheme_flags" type="int" />
<description> <description>
Breaks text into words and returns array of character ranges. Breaks text into words and returns array of character ranges.
</description> </description>
@ -1053,7 +1117,7 @@
Returns [code]true[/code] if buffer is successfully shaped. Returns [code]true[/code] if buffer is successfully shaped.
</description> </description>
</method> </method>
<method name="shaped_text_next_grapheme_pos"> <method name="shaped_text_next_grapheme_pos" qualifiers="const">
<return type="int" /> <return type="int" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="pos" type="int" /> <argument index="1" name="pos" type="int" />
@ -1070,7 +1134,7 @@
Trims text if it exceeds the given width. Trims text if it exceeds the given width.
</description> </description>
</method> </method>
<method name="shaped_text_prev_grapheme_pos"> <method name="shaped_text_prev_grapheme_pos" qualifiers="const">
<return type="int" /> <return type="int" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
<argument index="1" name="pos" type="int" /> <argument index="1" name="pos" type="int" />
@ -1139,6 +1203,13 @@
Note: It is not necessary to call this function manually, buffer will be shaped automatically as soon as any of its output data is requested. Note: It is not necessary to call this function manually, buffer will be shaped automatically as soon as any of its output data is requested.
</description> </description>
</method> </method>
<method name="shaped_text_sort_logical">
<return type="Array" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns text glyphs in the logical order.
</description>
</method>
<method name="shaped_text_substr" qualifiers="const"> <method name="shaped_text_substr" qualifiers="const">
<return type="RID" /> <return type="RID" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
@ -1196,18 +1267,24 @@
<constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag"> <constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag">
Only apply justification to the part of the text after the last tab. Only apply justification to the part of the text after the last tab.
</constant> </constant>
<constant name="JUSTIFICATION_CONSTRAIN_ELLIPSIS" value="16" enum="JustificationFlag">
Apply justification to the trimmed line with ellipsis.
</constant>
<constant name="BREAK_NONE" value="0" enum="LineBreakFlag"> <constant name="BREAK_NONE" value="0" enum="LineBreakFlag">
Do not break the line. Do not break the line.
</constant> </constant>
<constant name="BREAK_MANDATORY" value="16" enum="LineBreakFlag"> <constant name="BREAK_MANDATORY" value="32" enum="LineBreakFlag">
Break the line at the line mandatory break characters (e.g. [code]"\n"[/code]). Break the line at the line mandatory break characters (e.g. [code]"\n"[/code]).
</constant> </constant>
<constant name="BREAK_WORD_BOUND" value="32" enum="LineBreakFlag"> <constant name="BREAK_WORD_BOUND" value="64" enum="LineBreakFlag">
Break the line between the words. Break the line between the words.
</constant> </constant>
<constant name="BREAK_GRAPHEME_BOUND" value="64" enum="LineBreakFlag"> <constant name="BREAK_GRAPHEME_BOUND" value="128" enum="LineBreakFlag">
Break the line between any unconnected graphemes. Break the line between any unconnected graphemes.
</constant> </constant>
<constant name="BREAK_WORD_BOUND_ADAPTIVE" value="320" enum="LineBreakFlag">
Break the line between the words, or any unconnected graphemes if line is too short to fit the whole word.
</constant>
<constant name="OVERRUN_NO_TRIMMING" value="0" enum="TextOverrunFlag"> <constant name="OVERRUN_NO_TRIMMING" value="0" enum="TextOverrunFlag">
No trimming is performed. No trimming is performed.
</constant> </constant>
@ -1223,6 +1300,11 @@
<constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag"> <constant name="OVERRUN_ENFORCE_ELLIPSIS" value="8" enum="TextOverrunFlag">
Determines whether the ellipsis at the end of the text is enforced and may not be hidden. Determines whether the ellipsis at the end of the text is enforced and may not be hidden.
</constant> </constant>
<constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag">
</constant>
<constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag">
Grapheme is supprted by the font, and can be drawn.
</constant>
<constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag"> <constant name="GRAPHEME_IS_RTL" value="2" enum="GraphemeFlag">
Grapheme is part of right-to-left or bottom-to-top run. Grapheme is part of right-to-left or bottom-to-top run.
</constant> </constant>

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,13 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<methods> <methods>
<method name="add_interface">
<return type="void" />
<argument index="0" name="interface" type="TextServer" />
<description>
Registers an [TextServer] interface.
</description>
</method>
<method name="find_interface" qualifiers="const"> <method name="find_interface" qualifiers="const">
<return type="TextServer" /> <return type="TextServer" />
<argument index="0" name="name" type="String" /> <argument index="0" name="name" type="String" />
@ -19,7 +26,7 @@
</method> </method>
<method name="get_interface" qualifiers="const"> <method name="get_interface" qualifiers="const">
<return type="TextServer" /> <return type="TextServer" />
<argument index="0" name="index" type="int" /> <argument index="0" name="idx" type="int" />
<description> <description>
Returns the interface registered at a given index. Returns the interface registered at a given index.
</description> </description>
@ -30,20 +37,6 @@
Returns the number of interfaces currently registered. Returns the number of interfaces currently registered.
</description> </description>
</method> </method>
<method name="get_interface_features" qualifiers="const">
<return type="int" />
<argument index="0" name="index" type="int" />
<description>
Returns text server supported features (binary OR).
</description>
</method>
<method name="get_interface_name" qualifiers="const">
<return type="String" />
<argument index="0" name="index" type="int" />
<description>
Returns the interface name registered at a given index.
</description>
</method>
<method name="get_interfaces" qualifiers="const"> <method name="get_interfaces" qualifiers="const">
<return type="Array" /> <return type="Array" />
<description> <description>
@ -53,15 +46,36 @@
<method name="get_primary_interface" qualifiers="const"> <method name="get_primary_interface" qualifiers="const">
<return type="TextServer" /> <return type="TextServer" />
<description> <description>
Returns the primary [TextServer] interface. Returns the primary [TextServer] interface currently in use.
</description>
</method>
<method name="remove_interface">
<return type="void" />
<argument index="0" name="interface" type="TextServer" />
<description>
Removes interface. All fonts and shaped text caches should be freed before removing interface.
</description> </description>
</method> </method>
<method name="set_primary_interface"> <method name="set_primary_interface">
<return type="bool" /> <return type="void" />
<argument index="0" name="index" type="int" /> <argument index="0" name="index" type="TextServer" />
<description> <description>
Sets (and initializes it if required) interface registered at a given index as the primary. Invalidates all references to the fonts and text buffers. Sets the primary [TextServer] interface.
</description> </description>
</method> </method>
</methods> </methods>
<signals>
<signal name="interface_added">
<argument index="0" name="interface_name" type="StringName" />
<description>
Emitted when a new interface has been added.
</description>
</signal>
<signal name="interface_removed">
<argument index="0" name="interface_name" type="StringName" />
<description>
Emitted when an interface is removed.
</description>
</signal>
</signals>
</class> </class>

View file

@ -330,9 +330,8 @@ void EditorSpinSlider::_draw_spin_slider() {
float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep); 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); Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(num_rid); int v_size = TS->shaped_text_get_glyph_count(num_rid);
int v_size = visual.size(); const Glyph *glyphs = TS->shaped_text_get_glyphs(num_rid);
const TextServer::Glyph *glyphs = visual.ptr();
for (int i = 0; i < v_size; i++) { for (int i = 0; i < v_size; i++) {
for (int j = 0; j < glyphs[i].repeat; j++) { for (int j = 0; j < glyphs[i].repeat; j++) {
if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) { if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) {

View file

@ -1011,9 +1011,10 @@ void DynamicFontImportSettings::_glyph_text_selected() {
if (text_rid.is_valid()) { if (text_rid.is_valid()) {
TS->shaped_text_add_string(text_rid, text_edit->get_text(), font_main->get_rids(), 16, ftrs, text_edit->get_language()); TS->shaped_text_add_string(text_rid, text_edit->get_text(), font_main->get_rids(), 16, ftrs, text_edit->get_language());
TS->shaped_text_shape(text_rid); TS->shaped_text_shape(text_rid);
const Vector<TextServer::Glyph> &gl = TS->shaped_text_get_glyphs(text_rid); const Glyph *gl = TS->shaped_text_get_glyphs(text_rid);
const int gl_size = TS->shaped_text_get_glyph_count(text_rid);
for (int i = 0; i < gl.size(); i++) { for (int i = 0; i < gl_size; i++) {
if (gl[i].font_rid.is_valid() && gl[i].index != 0) { if (gl[i].font_rid.is_valid() && gl[i].index != 0) {
selected_glyphs.insert(gl[i].index); selected_glyphs.insert(gl[i].index);
} }

View file

@ -407,6 +407,7 @@ Error Main::test_setup() {
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
translation_server = memnew(TranslationServer); translation_server = memnew(TranslationServer);
tsman = memnew(TextServerManager);
register_core_extensions(); register_core_extensions();
@ -440,6 +441,9 @@ Error Main::test_setup() {
register_module_types(); register_module_types();
register_driver_types(); register_driver_types();
ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE);
TextServerManager::get_singleton()->set_primary_interface(TextServerManager::get_singleton()->get_interface(0));
ClassDB::set_current_api(ClassDB::API_NONE); ClassDB::set_current_api(ClassDB::API_NONE);
_start_success = true; _start_success = true;
@ -459,6 +463,7 @@ void Main::test_cleanup() {
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
EditorNode::unregister_editor_types(); EditorNode::unregister_editor_types();
#endif #endif
unregister_module_types(); unregister_module_types();
unregister_platform_apis(); unregister_platform_apis();
unregister_scene_types(); unregister_scene_types();
@ -469,6 +474,9 @@ void Main::test_cleanup() {
if (translation_server) { if (translation_server) {
memdelete(translation_server); memdelete(translation_server);
} }
if (tsman) {
memdelete(tsman);
}
if (globals) { if (globals) {
memdelete(globals); memdelete(globals);
} }
@ -1461,6 +1469,8 @@ error:
} }
Error Main::setup2(Thread::ID p_main_tid_override) { Error Main::setup2(Thread::ID p_main_tid_override) {
tsman = memnew(TextServerManager);
preregister_module_types(); preregister_module_types();
preregister_server_types(); preregister_server_types();
@ -1479,64 +1489,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
} }
#endif #endif
/* Determine text driver */
if (text_driver == "") {
text_driver = GLOBAL_GET("internationalization/rendering/text_driver");
}
if (text_driver != "") {
/* Load user selected text server. */
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (text_driver == TextServerManager::get_interface_name(i)) {
text_driver_idx = i;
break;
}
}
}
if (text_driver_idx < 0) {
/* If not selected, use one with the most features available. */
int max_features = 0;
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
uint32_t ftrs = TextServerManager::get_interface_features(i);
int features = 0;
while (ftrs) {
features += ftrs & 1;
ftrs >>= 1;
}
if (features >= max_features) {
max_features = features;
text_driver_idx = i;
}
}
}
print_verbose("Using \"" + TextServerManager::get_interface_name(text_driver_idx) + "\" text server...");
/* Initialize Text Server */
{
tsman = memnew(TextServerManager);
Error err;
TextServer *text_server = TextServerManager::initialize(text_driver_idx, err);
if (err != OK || text_server == nullptr) {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (i == text_driver_idx) {
continue; //don't try the same twice
}
text_server = TextServerManager::initialize(i, err);
if (err == OK && text_server != nullptr) {
break;
}
}
}
if (err != OK || text_server == nullptr) {
ERR_PRINT("Unable to create TextServer, all text drivers failed.");
return err;
}
}
/* Initialize Input */ /* Initialize Input */
input = memnew(Input); input = memnew(Input);
@ -1781,6 +1733,57 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
ResourceLoader::load_path_remaps(); ResourceLoader::load_path_remaps();
MAIN_PRINT("Main: Load TextServer");
/* Enum text drivers */
GLOBAL_DEF("internationalization/rendering/text_driver", "");
String text_driver_options;
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
if (i > 0) {
text_driver_options += ",";
}
text_driver_options += TextServerManager::get_singleton()->get_interface(i)->get_name();
}
ProjectSettings::get_singleton()->set_custom_property_info("internationalization/rendering/text_driver", PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options));
/* Determine text driver */
if (text_driver == "") {
text_driver = GLOBAL_GET("internationalization/rendering/text_driver");
}
if (text_driver != "") {
/* Load user selected text server. */
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
if (TextServerManager::get_singleton()->get_interface(i)->get_name() == text_driver) {
text_driver_idx = i;
break;
}
}
}
if (text_driver_idx < 0) {
/* If not selected, use one with the most features available. */
int max_features = 0;
for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
uint32_t features = TextServerManager::get_singleton()->get_interface(i)->get_features();
int feature_number = 0;
while (features) {
feature_number += features & 1;
features >>= 1;
}
if (feature_number >= max_features) {
max_features = feature_number;
text_driver_idx = i;
}
}
}
if (text_driver_idx >= 0) {
TextServerManager::get_singleton()->set_primary_interface(TextServerManager::get_singleton()->get_interface(text_driver_idx));
} else {
ERR_PRINT("TextServer: Unable to create TextServer interface.");
return ERR_CANT_CREATE;
}
MAIN_PRINT("Main: Load Scene Types"); MAIN_PRINT("Main: Load Scene Types");
register_scene_types(); register_scene_types();
@ -1793,7 +1796,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#endif #endif
MAIN_PRINT("Main: Load Modules, Physics, Drivers, Scripts"); MAIN_PRINT("Main: Load Modules");
register_platform_apis(); register_platform_apis();
register_module_types(); register_module_types();
@ -1817,6 +1820,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
camera_server = CameraServer::create(); camera_server = CameraServer::create();
MAIN_PRINT("Main: Load Physics, Drivers, Scripts");
initialize_physics(); initialize_physics();
initialize_navigation_server(); initialize_navigation_server();
register_server_singletons(); register_server_singletons();
@ -2728,10 +2733,6 @@ void Main::cleanup(bool p_force) {
finalize_navigation_server(); finalize_navigation_server();
finalize_display(); finalize_display();
if (tsman) {
memdelete(tsman);
}
if (input) { if (input) {
memdelete(input); memdelete(input);
} }
@ -2754,6 +2755,9 @@ void Main::cleanup(bool p_force) {
if (translation_server) { if (translation_server) {
memdelete(translation_server); memdelete(translation_server);
} }
if (tsman) {
memdelete(tsman);
}
if (globals) { if (globals) {
memdelete(globals); memdelete(globals);
} }

View file

@ -18,7 +18,6 @@ Export("env_gdnative")
SConscript("pluginscript/SCsub") SConscript("pluginscript/SCsub")
SConscript("videodecoder/SCsub") SConscript("videodecoder/SCsub")
SConscript("text/SCsub")
import gdnative_builders import gdnative_builders

View file

@ -5103,489 +5103,6 @@
] ]
} }
] ]
},
{
"name": "text",
"type": "TEXT",
"version": {
"major": 1,
"minor": 0
},
"next": null,
"api": [
{
"name": "godot_text_register_interface",
"return_type": "void",
"arguments": [
[
"const godot_text_interface_gdnative *",
"p_interface"
],
[
"const godot_string *",
"p_name"
],
[
"uint32_t",
"p_features"
]
]
},
{
"name": "godot_glyph_new",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"r_dest"
]
]
},
{
"name": "godot_glyph_get_range",
"return_type": "godot_vector2i",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_range",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"const godot_vector2i *",
"p_range"
]
]
},
{
"name": "godot_glyph_get_count",
"return_type": "godot_int",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_count",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_int",
"p_count"
]
]
},
{
"name": "godot_glyph_get_repeat",
"return_type": "godot_int",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_repeat",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_int",
"p_repeat"
]
]
},
{
"name": "godot_glyph_get_flags",
"return_type": "godot_int",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_flags",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_int",
"p_flags"
]
]
},
{
"name": "godot_glyph_get_offset",
"return_type": "godot_vector2",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_offset",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"const godot_vector2 *",
"p_offset"
]
]
},
{
"name": "godot_glyph_get_advance",
"return_type": "godot_real_t",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_advance",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_real_t",
"p_advance"
]
]
},
{
"name": "godot_glyph_get_font",
"return_type": "godot_rid",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_font",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_rid *",
"p_font"
]
]
},
{
"name": "godot_glyph_get_font_size",
"return_type": "godot_int",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_font_size",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_int",
"p_size"
]
]
},
{
"name": "godot_glyph_get_index",
"return_type": "godot_int",
"arguments": [
[
"const godot_glyph *",
"p_self"
]
]
},
{
"name": "godot_glyph_set_index",
"return_type": "void",
"arguments": [
[
"godot_glyph *",
"p_self"
],
[
"godot_int",
"p_index"
]
]
},
{
"name": "godot_packed_glyph_array_new",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"r_dest"
]
]
},
{
"name": "godot_packed_glyph_array_new_copy",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"r_dest"
],
[
"const godot_packed_glyph_array *",
"p_src"
]
]
},
{
"name": "godot_packed_glyph_array_is_empty",
"return_type": "godot_bool",
"arguments": [
[
"const godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_append",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_glyph *",
"p_data"
]
]
},
{
"name": "godot_packed_glyph_array_append_array",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_packed_glyph_array *",
"p_array"
]
]
},
{
"name": "godot_packed_glyph_array_insert",
"return_type": "godot_error",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_int",
"p_idx"
],
[
"const godot_glyph *",
"p_data"
]
]
},
{
"name": "godot_packed_glyph_array_has",
"return_type": "godot_bool",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_glyph *",
"p_value"
]
]
},
{
"name": "godot_packed_glyph_array_sort",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_reverse",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_push_back",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_glyph *",
"p_data"
]
]
},
{
"name": "godot_packed_glyph_array_remove",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_int",
"p_idx"
]
]
},
{
"name": "godot_packed_glyph_array_resize",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_int",
"p_size"
]
]
},
{
"name": "godot_packed_glyph_array_ptr",
"return_type": "const godot_glyph *",
"arguments": [
[
"const godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_ptrw",
"return_type": "godot_glyph *",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_set",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
],
[
"const godot_int",
"p_idx"
],
[
"const godot_glyph *",
"p_data"
]
]
},
{
"name": "godot_packed_glyph_array_get",
"return_type": "godot_glyph",
"arguments": [
[
"const godot_packed_glyph_array *",
"p_self"
],
[
"const godot_int",
"p_idx"
]
]
},
{
"name": "godot_packed_glyph_array_size",
"return_type": "godot_int",
"arguments": [
[
"const godot_packed_glyph_array *",
"p_self"
]
]
},
{
"name": "godot_packed_glyph_array_destroy",
"return_type": "void",
"arguments": [
[
"godot_packed_glyph_array *",
"p_self"
]
]
}
]
} }
] ]
} }

View file

@ -22,7 +22,6 @@ def _build_gdnative_api_struct_header(api):
"#include <nativescript/godot_nativescript.h>", "#include <nativescript/godot_nativescript.h>",
"#include <pluginscript/godot_pluginscript.h>", "#include <pluginscript/godot_pluginscript.h>",
"#include <videodecoder/godot_videodecoder.h>", "#include <videodecoder/godot_videodecoder.h>",
"#include <text/godot_text.h>",
"", "",
"#ifdef __cplusplus", "#ifdef __cplusplus",
'extern "C" {', 'extern "C" {',

View file

@ -1,283 +0,0 @@
/*************************************************************************/
/* godot_text.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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 GODOT_NATIVETEXT_H
#define GODOT_NATIVETEXT_H
#include <gdnative/gdnative.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GODOT_TEXT_API_MAJOR 1
#define GODOT_TEXT_API_MINOR 0
#define GODOT_GLYPH_SIZE 40
#ifndef GODOT_TEXT_API_GODOT_GLYPH_TYPE_DEFINED
#define GODOT_TEXT_API_GODOT_GLYPH_TYPE_DEFINED
typedef struct {
uint8_t _dont_touch_that[GODOT_GLYPH_SIZE];
} godot_glyph;
#endif
#define GODOT_PACKED_GLYPH_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_TEXT_API_GODOT_PACKED_GLYPH_ARRAY_TYPE_DEFINED
#define GODOT_TEXT_API_GODOT_PACKED_GLYPH_ARRAY_TYPE_DEFINED
typedef struct {
uint8_t _dont_touch_that[GODOT_PACKED_GLYPH_ARRAY_SIZE];
} godot_packed_glyph_array;
#endif
typedef struct {
godot_gdnative_api_version version;
void *(*constructor)(godot_object *);
void (*destructor)(void *);
godot_string (*get_name)(const void *);
godot_bool (*has_feature)(const void *, godot_int);
void (*free)(void *, godot_rid *);
bool (*has)(void *, godot_rid *);
bool (*load_support_data)(void *, const godot_string *);
godot_string (*get_support_data_filename)(const void *);
godot_string (*get_support_data_info)(const void *);
bool (*save_support_data)(void *, const godot_string *);
bool (*is_locale_right_to_left)(void *, const godot_string *);
int32_t (*name_to_tag)(const void *, const godot_string *);
godot_string (*tag_to_name)(const void *, int32_t);
godot_rid (*create_font)(void *);
void (*font_set_data)(void *, godot_rid *, const godot_packed_byte_array *);
void (*font_set_data_ptr)(void *, godot_rid *, const uint8_t *, size_t);
void (*font_set_antialiased)(void *, godot_rid *, bool);
bool (*font_is_antialiased)(const void *, godot_rid *);
void (*font_set_multichannel_signed_distance_field)(void *, godot_rid *, bool);
bool (*font_is_multichannel_signed_distance_field)(const void *, godot_rid *);
void (*font_set_msdf_pixel_range)(void *, godot_rid *, godot_int);
godot_int (*font_get_msdf_pixel_range)(const void *, godot_rid *);
void (*font_set_msdf_size)(void *, godot_rid *, godot_int);
godot_int (*font_get_msdf_size)(const void *, godot_rid *);
void (*font_set_fixed_size)(void *, godot_rid *, godot_int);
godot_int (*font_get_fixed_size)(const void *, godot_rid *);
void (*font_set_force_autohinter)(void *, godot_rid *, bool);
bool (*font_is_force_autohinter)(const void *, godot_rid *);
void (*font_set_hinting)(void *, godot_rid *, godot_int);
godot_int (*font_get_hinting)(const void *, godot_rid *);
void (*font_set_variation_coordinates)(void *, godot_rid *, const godot_dictionary *);
godot_dictionary (*font_get_variation_coordinates)(const void *, godot_rid *);
void (*font_set_oversampling)(void *, godot_rid *, godot_real_t);
godot_real_t (*font_get_oversampling)(const void *, godot_rid *);
godot_array (*font_get_size_cache_list)(const void *, godot_rid *);
void (*font_clear_size_cache)(void *, godot_rid *);
void (*font_remove_size_cache)(void *, godot_rid *, const godot_vector2i *);
void (*font_set_ascent)(void *, godot_rid *, godot_int, godot_real_t);
godot_real_t (*font_get_ascent)(const void *, godot_rid *, godot_int);
void (*font_set_descent)(void *, godot_rid *, godot_int, godot_real_t);
godot_real_t (*font_get_descent)(const void *, godot_rid *, godot_int);
void (*font_set_underline_position)(void *, godot_rid *, godot_int, godot_real_t);
godot_real_t (*font_get_underline_position)(const void *, godot_rid *, godot_int);
void (*font_set_underline_thickness)(void *, godot_rid *, godot_int, godot_real_t);
godot_real_t (*font_get_underline_thickness)(const void *, godot_rid *, godot_int);
void (*font_set_scale)(void *, godot_rid *, godot_int, godot_real_t);
godot_real_t (*font_get_scale)(const void *, godot_rid *, godot_int);
void (*font_set_spacing)(void *, godot_rid *, godot_int, godot_int, godot_int);
godot_int (*font_get_spacing)(const void *, godot_rid *, godot_int, godot_int);
godot_int (*font_get_texture_count)(const void *, godot_rid *, const godot_vector2i *);
void (*font_clear_textures)(void *, godot_rid *, const godot_vector2i *);
void (*font_remove_texture)(void *, godot_rid *, const godot_vector2i *, godot_int);
void (*font_set_texture_image)(void *, godot_rid *, const godot_vector2i *, godot_int, const godot_object *);
godot_object *(*font_get_texture_image)(const void *, godot_rid *, const godot_vector2i *, godot_int);
void (*font_set_texture_offsets)(void *, godot_rid *, const godot_vector2i *, godot_int, const godot_packed_int32_array *);
godot_packed_int32_array (*font_get_texture_offsets)(const void *, godot_rid *, const godot_vector2i *, godot_int);
godot_array (*font_get_glyph_list)(const void *, godot_rid *, const godot_vector2i *);
void (*font_clear_glyphs)(void *, godot_rid *, const godot_vector2i *);
void (*font_remove_glyph)(void *, godot_rid *, const godot_vector2i *, int32_t);
godot_vector2 (*font_get_glyph_advance)(const void *, godot_rid *, godot_int, int32_t);
void (*font_set_glyph_advance)(void *, godot_rid *, godot_int, int32_t, const godot_vector2 *);
godot_vector2 (*font_get_glyph_offset)(const void *, godot_rid *, const godot_vector2i *, int32_t);
void (*font_set_glyph_offset)(void *, godot_rid *, const godot_vector2i *, int32_t, const godot_vector2 *);
godot_vector2 (*font_get_glyph_size)(const void *, godot_rid *, const godot_vector2i *, int32_t);
void (*font_set_glyph_size)(void *, godot_rid *, const godot_vector2i *, int32_t, const godot_vector2 *);
godot_rect2 (*font_get_glyph_uv_rect)(const void *, godot_rid *, const godot_vector2i *, int32_t);
void (*font_set_glyph_uv_rect)(void *, godot_rid *, const godot_vector2i *, int32_t, const godot_rect2 *);
godot_int (*font_get_glyph_texture_idx)(const void *, godot_rid *, const godot_vector2i *, int32_t);
void (*font_set_glyph_texture_idx)(void *, godot_rid *, const godot_vector2i *, int32_t, godot_int);
bool (*font_get_glyph_contours)(const void *, godot_rid *, godot_int, int32_t, godot_packed_vector3_array *, godot_packed_int32_array *, bool *);
godot_array (*font_get_kerning_list)(const void *, godot_rid *, godot_int);
void (*font_clear_kerning_map)(void *, godot_rid *, godot_int);
void (*font_remove_kerning)(void *, godot_rid *, godot_int, const godot_vector2i *);
void (*font_set_kerning)(void *, godot_rid *, godot_int, const godot_vector2i *, const godot_vector2 *);
godot_vector2 (*font_get_kerning)(const void *, godot_rid *, godot_int, const godot_vector2i *);
int32_t (*font_get_glyph_index)(const void *, godot_rid *, godot_int, char32_t, char32_t);
bool (*font_has_char)(const void *, godot_rid *, char32_t);
godot_string (*font_get_supported_chars)(const void *, godot_rid *);
void (*font_render_range)(void *, godot_rid *, const godot_vector2i *, char32_t, char32_t);
void (*font_render_glyph)(void *, godot_rid *, const godot_vector2i *, int32_t);
void (*font_draw_glyph)(const void *, godot_rid *, godot_rid *, godot_int, const godot_vector2 *, int32_t, const godot_color *);
void (*font_draw_glyph_outline)(const void *, godot_rid *, godot_rid *, godot_int, godot_int, const godot_vector2 *, int32_t, const godot_color *);
bool (*font_is_language_supported)(const void *, godot_rid *, const godot_string *);
void (*font_set_language_support_override)(void *, godot_rid *, const godot_string *, bool);
bool (*font_get_language_support_override)(const void *, godot_rid *, const godot_string *);
void (*font_remove_language_support_override)(void *, godot_rid *, const godot_string *);
godot_packed_string_array (*font_get_language_support_overrides)(const void *, godot_rid *);
bool (*font_is_script_supported)(const void *, godot_rid *, const godot_string *);
void (*font_set_script_support_override)(void *, godot_rid *, const godot_string *, bool);
bool (*font_get_script_support_override)(const void *, godot_rid *, const godot_string *);
void (*font_remove_script_support_override)(void *, godot_rid *, const godot_string *);
godot_packed_string_array (*font_get_script_support_overrides)(const void *, godot_rid *);
godot_dictionary (*font_supported_feature_list)(const void *, godot_rid *);
godot_dictionary (*font_supported_variation_list)(const void *, godot_rid *);
godot_real_t (*font_get_global_oversampling)(const void *);
void (*font_set_global_oversampling)(void *, godot_real_t);
godot_rid (*create_shaped_text)(void *, godot_int, godot_int);
void (*shaped_text_clear)(void *, godot_rid *);
void (*shaped_text_set_direction)(void *, godot_rid *, godot_int);
godot_int (*shaped_text_get_direction)(void *, godot_rid *);
void (*shaped_text_set_bidi_override)(void *, godot_rid *, const godot_packed_vector2i_array *);
void (*shaped_text_set_orientation)(void *, godot_rid *, godot_int);
godot_int (*shaped_text_get_orientation)(void *, godot_rid *);
void (*shaped_text_set_preserve_invalid)(void *, godot_rid *, bool);
bool (*shaped_text_get_preserve_invalid)(void *, godot_rid *);
void (*shaped_text_set_preserve_control)(void *, godot_rid *, bool);
bool (*shaped_text_get_preserve_control)(void *, godot_rid *);
bool (*shaped_text_add_string)(void *, godot_rid *, const godot_string *, const godot_rid **, int, const godot_dictionary *, const godot_string *);
bool (*shaped_text_add_object)(void *, godot_rid *, const godot_variant *, const godot_vector2 *, godot_int, godot_int);
bool (*shaped_text_resize_object)(void *, godot_rid *, const godot_variant *, const godot_vector2 *, godot_int);
godot_rid (*shaped_text_substr)(void *, godot_rid *, godot_int, godot_int);
godot_rid (*shaped_text_get_parent)(void *, godot_rid *);
godot_real_t (*shaped_text_fit_to_width)(void *, godot_rid *, godot_real_t, uint8_t);
godot_real_t (*shaped_text_tab_align)(void *, godot_rid *, godot_packed_float32_array *);
bool (*shaped_text_shape)(void *, godot_rid *);
bool (*shaped_text_update_breaks)(void *, godot_rid *);
bool (*shaped_text_update_justification_ops)(void *, godot_rid *);
void (*shaped_text_overrun_trim_to_width)(void *, godot_rid *, godot_real_t, uint8_t);
bool (*shaped_text_is_ready)(void *, godot_rid *);
godot_packed_glyph_array (*shaped_text_get_glyphs)(void *, godot_rid *);
godot_vector2i (*shaped_text_get_range)(void *, godot_rid *);
godot_packed_glyph_array (*shaped_text_sort_logical)(void *, godot_rid *);
godot_packed_vector2i_array (*shaped_text_get_line_breaks_adv)(void *, godot_rid *, godot_packed_float32_array *, int, bool, uint8_t);
godot_packed_vector2i_array (*shaped_text_get_line_breaks)(void *, godot_rid *, godot_real_t, int, uint8_t);
godot_packed_vector2i_array (*shaped_text_get_word_breaks)(void *, godot_rid *, int);
godot_array (*shaped_text_get_objects)(void *, godot_rid *);
godot_rect2 (*shaped_text_get_object_rect)(void *, godot_rid *, const godot_variant *);
godot_vector2 (*shaped_text_get_size)(void *, godot_rid *);
godot_real_t (*shaped_text_get_ascent)(void *, godot_rid *);
godot_real_t (*shaped_text_get_descent)(void *, godot_rid *);
godot_real_t (*shaped_text_get_width)(void *, godot_rid *);
godot_real_t (*shaped_text_get_underline_position)(void *, godot_rid *);
godot_real_t (*shaped_text_get_underline_thickness)(void *, godot_rid *);
godot_string (*format_number)(void *, const godot_string *, const godot_string *);
godot_string (*parse_number)(void *, const godot_string *, const godot_string *);
godot_string (*percent_sign)(void *, const godot_string *);
} godot_text_interface_gdnative;
void GDAPI godot_text_register_interface(const godot_text_interface_gdnative *p_interface, const godot_string *p_name, uint32_t p_features);
// Glyph
void GDAPI godot_glyph_new(godot_glyph *r_dest);
godot_vector2i GDAPI godot_glyph_get_range(const godot_glyph *p_self);
void GDAPI godot_glyph_set_range(godot_glyph *p_self, const godot_vector2i *p_range);
godot_int GDAPI godot_glyph_get_count(const godot_glyph *p_self);
void GDAPI godot_glyph_set_count(godot_glyph *p_self, godot_int p_count);
godot_int GDAPI godot_glyph_get_repeat(const godot_glyph *p_self);
void GDAPI godot_glyph_set_repeat(godot_glyph *p_self, godot_int p_repeat);
godot_int GDAPI godot_glyph_get_flags(const godot_glyph *p_self);
void GDAPI godot_glyph_set_flags(godot_glyph *p_self, godot_int p_flags);
godot_vector2 GDAPI godot_glyph_get_offset(const godot_glyph *p_self);
void GDAPI godot_glyph_set_offset(godot_glyph *p_self, const godot_vector2 *p_offset);
godot_real_t GDAPI godot_glyph_get_advance(const godot_glyph *p_self);
void GDAPI godot_glyph_set_advance(godot_glyph *p_self, godot_real_t p_advance);
godot_rid GDAPI godot_glyph_get_font(const godot_glyph *p_self);
void GDAPI godot_glyph_set_font(godot_glyph *p_self, godot_rid *p_font);
godot_int GDAPI godot_glyph_get_font_size(const godot_glyph *p_self);
void GDAPI godot_glyph_set_font_size(godot_glyph *p_self, godot_int p_size);
godot_int GDAPI godot_glyph_get_index(const godot_glyph *p_self);
void GDAPI godot_glyph_set_index(godot_glyph *p_self, godot_int p_index);
// GlyphArray
void GDAPI godot_packed_glyph_array_new(godot_packed_glyph_array *r_dest);
void GDAPI godot_packed_glyph_array_new_copy(godot_packed_glyph_array *r_dest, const godot_packed_glyph_array *p_src);
const godot_glyph GDAPI *godot_packed_glyph_array_ptr(const godot_packed_glyph_array *p_self);
godot_glyph GDAPI *godot_packed_glyph_array_ptrw(godot_packed_glyph_array *p_self);
void GDAPI godot_packed_glyph_array_append(godot_packed_glyph_array *p_self, const godot_glyph *p_data);
void GDAPI godot_packed_glyph_array_append_array(godot_packed_glyph_array *p_self, const godot_packed_glyph_array *p_array);
godot_error GDAPI godot_packed_glyph_array_insert(godot_packed_glyph_array *p_self, const godot_int p_idx, const godot_glyph *p_data);
godot_bool GDAPI godot_packed_glyph_array_has(godot_packed_glyph_array *p_self, const godot_glyph *p_value);
void GDAPI godot_packed_glyph_array_sort(godot_packed_glyph_array *p_self);
void GDAPI godot_packed_glyph_array_reverse(godot_packed_glyph_array *p_self);
void GDAPI godot_packed_glyph_array_push_back(godot_packed_glyph_array *p_self, const godot_glyph *p_data);
void GDAPI godot_packed_glyph_array_remove(godot_packed_glyph_array *p_self, godot_int p_idx);
void GDAPI godot_packed_glyph_array_resize(godot_packed_glyph_array *p_self, godot_int p_size);
void GDAPI godot_packed_glyph_array_set(godot_packed_glyph_array *p_self, godot_int p_idx, const godot_glyph *p_data);
godot_glyph GDAPI godot_packed_glyph_array_get(const godot_packed_glyph_array *p_self, godot_int p_idx);
godot_int GDAPI godot_packed_glyph_array_size(const godot_packed_glyph_array *p_self);
godot_bool GDAPI godot_packed_glyph_array_is_empty(const godot_packed_glyph_array *p_self);
void GDAPI godot_packed_glyph_array_destroy(godot_packed_glyph_array *p_self);
// Grapheme
#ifdef __cplusplus
}
#endif
#endif /* !GODOT_NATIVETEXT_H */

View file

@ -1,6 +0,0 @@
#!/usr/bin/env python
Import("env")
Import("env_gdnative")
env_gdnative.add_source_files(env.modules_sources, "*.cpp")

View file

@ -1,6 +0,0 @@
def can_build(env, platform):
return True
def configure(env):
pass

View file

@ -1,36 +0,0 @@
/*************************************************************************/
/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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 "register_types.h"
#include "text_server_gdnative.h"
void register_text_server_gdn_types() {}
void unregister_text_server_gdn_types() {}

View file

@ -1,37 +0,0 @@
/*************************************************************************/
/* register_types.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_REGISTER_TYPES_H
#define TEXT_REGISTER_TYPES_H
void register_text_server_gdn_types();
void unregister_text_server_gdn_types();
#endif // TEXT_REGISTER_TYPES_H

File diff suppressed because it is too large Load diff

View file

@ -1,254 +0,0 @@
/*************************************************************************/
/* text_server_gdnative.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_SERVER_GDNATIVE_H
#define TEXT_SERVER_GDNATIVE_H
#include "modules/gdnative/gdnative.h"
#include "servers/text_server.h"
class TextServerGDNative : public TextServer {
GDCLASS(TextServerGDNative, TextServer);
const godot_text_interface_gdnative *interface = nullptr;
void *data = nullptr;
protected:
static void _bind_methods(){};
public:
virtual bool has_feature(Feature p_feature) override;
virtual String get_name() const override;
virtual void free(RID p_rid) override;
virtual bool has(RID p_rid) override;
virtual bool load_support_data(const String &p_filename) override;
#ifdef TOOLS_ENABLED
virtual String get_support_data_filename() override;
virtual String get_support_data_info() override;
virtual bool save_support_data(const String &p_filename) override;
#endif
virtual bool is_locale_right_to_left(const String &p_locale) override;
virtual int32_t name_to_tag(const String &p_name) const override;
virtual String tag_to_name(int32_t p_tag) const override;
/* Font interface */
virtual RID create_font() override;
virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override;
virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override;
virtual bool font_is_antialiased(RID p_font_rid) const override;
virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const override;
virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) override;
virtual int font_get_msdf_pixel_range(RID p_font_rid) const override;
virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) override;
virtual int font_get_msdf_size(RID p_font_rid) const override;
virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) override;
virtual int font_get_fixed_size(RID p_font_rid) const override;
virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) override;
virtual bool font_is_force_autohinter(RID p_font_rid) const override;
virtual void font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) override;
virtual TextServer::Hinting font_get_hinting(RID p_font_rid) const override;
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
virtual void font_set_oversampling(RID p_font_rid, real_t p_oversampling) override;
virtual real_t font_get_oversampling(RID p_font_rid) const override;
virtual Array font_get_size_cache_list(RID p_font_rid) const override;
virtual void font_clear_size_cache(RID p_font_rid) override;
virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) override;
virtual real_t font_get_ascent(RID p_font_rid, int p_size) const override;
virtual void font_set_descent(RID p_font_rid, int p_size, real_t p_descent) override;
virtual real_t font_get_descent(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) override;
virtual real_t font_get_underline_position(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) override;
virtual real_t font_get_underline_thickness(RID p_font_rid, int p_size) const override;
virtual void font_set_scale(RID p_font_rid, int p_size, real_t p_scale) override;
virtual real_t font_get_scale(RID p_font_rid, int p_size) const override;
virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) override;
virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) override;
virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) override;
virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) override;
virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) override;
virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) override;
virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) override;
virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) override;
virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) override;
virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const override;
virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector = 0) const override;
virtual bool font_has_char(RID p_font_rid, char32_t p_char) const override;
virtual String font_get_supported_chars(RID p_font_rid) const override;
virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) override;
virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) override;
virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const override;
virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) override;
virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) override;
virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) override;
virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) override;
virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const override;
virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) override;
virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) override;
virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) override;
virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) override;
virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
virtual real_t font_get_global_oversampling() const override;
virtual void font_set_global_oversampling(real_t p_oversampling) override;
/* Shaped text buffer interface */
virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual void shaped_text_clear(RID p_shaped) override;
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(RID p_shaped) const override;
virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) override;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override;
virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) override;
virtual bool shaped_text_shape(RID p_shaped) override;
virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, real_t p_width, uint8_t p_trim_flags) override;
virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override;
virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) override;
virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start = 0, uint8_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
virtual Array shaped_text_get_objects(RID p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
virtual Size2 shaped_text_get_size(RID p_shaped) const override;
virtual real_t shaped_text_get_ascent(RID p_shaped) const override;
virtual real_t shaped_text_get_descent(RID p_shaped) const override;
virtual real_t shaped_text_get_width(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_position(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_thickness(RID p_shaped) const override;
virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override;
static TextServer *create_func(Error &r_error, void *p_user_data);
TextServerGDNative();
~TextServerGDNative();
};
#endif // TEXT_SERVER_GDNATIVE_H

View file

@ -4,3 +4,13 @@ def can_build(env, platform):
def configure(env): def configure(env):
pass pass
def get_doc_classes():
return [
"TextServerAdvanced",
]
def get_doc_path():
return "doc_classes"

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextServerAdvanced" inherits="TextServer" version="4.0">
<brief_description>
Text Server using HarfBuzz, ICU and SIL Graphite to support BiDi, complex text layouts and contextual OpenType features.
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
</class>

View file

@ -33,7 +33,12 @@
#include "text_server_adv.h" #include "text_server_adv.h"
void preregister_text_server_adv_types() { void preregister_text_server_adv_types() {
TextServerAdvanced::register_server(); GDREGISTER_CLASS(TextServerAdvanced);
if (TextServerManager::get_singleton()) {
Ref<TextServerAdvanced> ts;
ts.instantiate();
TextServerManager::get_singleton()->add_interface(ts);
}
} }
void register_text_server_adv_types() { void register_text_server_adv_types() {

View file

@ -322,7 +322,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite"; String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE; uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE;
bool TextServerAdvanced::has_feature(Feature p_feature) { bool TextServerAdvanced::has_feature(Feature p_feature) const {
return (interface_features & p_feature) == p_feature; return (interface_features & p_feature) == p_feature;
} }
@ -330,6 +330,10 @@ String TextServerAdvanced::get_name() const {
return interface_name; return interface_name;
} }
uint32_t TextServerAdvanced::get_features() const {
return interface_features;
}
void TextServerAdvanced::free(RID p_rid) { void TextServerAdvanced::free(RID p_rid) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) { if (font_owner.owns(p_rid)) {
@ -394,9 +398,23 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) {
return true; return true;
} }
#ifdef TOOLS_ENABLED String TextServerAdvanced::get_support_data_filename() const {
#ifdef ICU_STATIC_DATA
return _MKSTR(ICU_DATA_NAME);
#else
return String();
#endif
}
bool TextServerAdvanced::save_support_data(const String &p_filename) { String TextServerAdvanced::get_support_data_info() const {
#ifdef ICU_STATIC_DATA
return String("ICU break iteration data (") + _MKSTR(ICU_DATA_NAME) + String(").");
#else
return String();
#endif
}
bool TextServerAdvanced::save_support_data(const String &p_filename) const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
#ifdef ICU_STATIC_DATA #ifdef ICU_STATIC_DATA
@ -415,9 +433,7 @@ bool TextServerAdvanced::save_support_data(const String &p_filename) {
#endif #endif
} }
#endif bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) const {
bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) {
String l = p_locale.get_slicec('_', 0); String l = p_locale.get_slicec('_', 0);
if ((l == "ar") || (l == "dv") || (l == "he") || (l == "fa") || (l == "ff") || (l == "ku") || (l == "ur")) { if ((l == "ar") || (l == "dv") || (l == "he") || (l == "fa") || (l == "ff") || (l == "ku") || (l == "ur")) {
return true; return true;
@ -1142,7 +1158,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
int error = FT_Load_Glyph(fd->face, p_glyph, flags); int error = FT_Load_Glyph(fd->face, p_glyph, flags);
if (error) { if (error) {
fd->glyph_map[p_glyph] = FontGlyph(); fd->glyph_map[p_glyph] = FontGlyph();
ERR_FAIL_V_MSG(false, "FreeType: Failed to load glyph."); return false;
} }
if (!outline) { if (!outline) {
@ -1236,7 +1252,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
fd->oversampling = 1.0f; fd->oversampling = 1.0f;
fd->size.x = p_font_data->msdf_source_size; fd->size.x = p_font_data->msdf_source_size;
} else if (p_font_data->oversampling <= 0.0f) { } else if (p_font_data->oversampling <= 0.0f) {
fd->oversampling = TS->font_get_global_oversampling(); fd->oversampling = font_get_global_oversampling();
} else { } else {
fd->oversampling = p_font_data->oversampling; fd->oversampling = p_font_data->oversampling;
} }
@ -1244,13 +1260,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
if (FT_HAS_COLOR(fd->face) && fd->face->num_fixed_sizes > 0) { if (FT_HAS_COLOR(fd->face) && fd->face->num_fixed_sizes > 0) {
int best_match = 0; int best_match = 0;
int diff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[0].width)); int diff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[0].width));
fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width; fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width;
for (int i = 1; i < fd->face->num_fixed_sizes; i++) { for (int i = 1; i < fd->face->num_fixed_sizes; i++) {
int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width)); int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width));
if (ndiff < diff) { if (ndiff < diff) {
best_match = i; best_match = i;
diff = ndiff; diff = ndiff;
fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width; fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width;
} }
} }
FT_Select_Size(fd->face, best_match); FT_Select_Size(fd->face, best_match);
@ -1786,7 +1802,7 @@ Dictionary TextServerAdvanced::font_get_variation_coordinates(RID p_font_rid) co
return fd->variation_coordinates; return fd->variation_coordinates;
} }
void TextServerAdvanced::font_set_oversampling(RID p_font_rid, real_t p_oversampling) { void TextServerAdvanced::font_set_oversampling(RID p_font_rid, float p_oversampling) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1797,7 +1813,7 @@ void TextServerAdvanced::font_set_oversampling(RID p_font_rid, real_t p_oversamp
} }
} }
real_t TextServerAdvanced::font_get_oversampling(RID p_font_rid) const { float TextServerAdvanced::font_get_oversampling(RID p_font_rid) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1839,7 +1855,7 @@ void TextServerAdvanced::font_remove_size_cache(RID p_font_rid, const Vector2i &
} }
} }
void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) { void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1850,7 +1866,7 @@ void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, real_t p_as
fd->cache[size]->ascent = p_ascent; fd->cache[size]->ascent = p_ascent;
} }
real_t TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const { float TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1860,13 +1876,13 @@ real_t TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->ascent * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->ascent * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->ascent; return fd->cache[size]->ascent;
} }
} }
void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, real_t p_descent) { void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, float p_descent) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1876,7 +1892,7 @@ void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, real_t p_d
fd->cache[size]->descent = p_descent; fd->cache[size]->descent = p_descent;
} }
real_t TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const { float TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1886,13 +1902,13 @@ real_t TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->descent * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->descent * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->descent; return fd->cache[size]->descent;
} }
} }
void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) { void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1903,7 +1919,7 @@ void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size,
fd->cache[size]->underline_position = p_underline_position; fd->cache[size]->underline_position = p_underline_position;
} }
real_t TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_size) const { float TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_size) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1913,13 +1929,13 @@ real_t TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_siz
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->underline_position * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->underline_position * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->underline_position; return fd->cache[size]->underline_position;
} }
} }
void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) { void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1930,7 +1946,7 @@ void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size
fd->cache[size]->underline_thickness = p_underline_thickness; fd->cache[size]->underline_thickness = p_underline_thickness;
} }
real_t TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_size) const { float TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_size) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1940,13 +1956,13 @@ real_t TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->underline_thickness * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->underline_thickness * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->underline_thickness; return fd->cache[size]->underline_thickness;
} }
} }
void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, real_t p_scale) { void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, float p_scale) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1957,7 +1973,7 @@ void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, real_t p_sca
fd->cache[size]->scale = p_scale; fd->cache[size]->scale = p_scale;
} }
real_t TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const { float TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1967,7 +1983,7 @@ real_t TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->scale * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->scale * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->scale / fd->cache[size]->oversampling; return fd->cache[size]->scale / fd->cache[size]->oversampling;
} }
@ -2006,14 +2022,14 @@ int TextServerAdvanced::font_get_spacing(RID p_font_rid, int p_size, TextServer:
switch (p_spacing) { switch (p_spacing) {
case TextServer::SPACING_GLYPH: { case TextServer::SPACING_GLYPH: {
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->spacing_glyph * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->spacing_glyph * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->spacing_glyph; return fd->cache[size]->spacing_glyph;
} }
} break; } break;
case TextServer::SPACING_SPACE: { case TextServer::SPACING_SPACE: {
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->spacing_space * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->spacing_space * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->spacing_space; return fd->cache[size]->spacing_space;
} }
@ -2182,7 +2198,7 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].advance * (real_t)p_size / (real_t)fd->msdf_source_size; return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].advance; return gl[p_glyph].advance;
} }
@ -2218,7 +2234,7 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(RID p_font_rid, const Vector2i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].rect.position * (real_t)p_size.x / (real_t)fd->msdf_source_size; return gl[p_glyph].rect.position * (float)p_size.x / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].rect.position; return gl[p_glyph].rect.position;
} }
@ -2254,7 +2270,7 @@ Vector2 TextServerAdvanced::font_get_glyph_size(RID p_font_rid, const Vector2i &
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].rect.size * (real_t)p_size.x / (real_t)fd->msdf_source_size; return gl[p_glyph].rect.size * (float)p_size.x / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].rect.size; return gl[p_glyph].rect.size;
} }
@ -2337,38 +2353,46 @@ void TextServerAdvanced::font_set_glyph_texture_idx(RID p_font_rid, const Vector
gl[p_glyph].found = true; gl[p_glyph].found = true;
} }
bool TextServerAdvanced::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { Dictionary TextServerAdvanced::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
Vector2i size = _get_size(fd, p_size); Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Dictionary());
Vector<Vector3> points;
Vector<int32_t> contours;
bool orientation;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
int error = FT_Load_Glyph(fd->cache[size]->face, p_index, FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); int error = FT_Load_Glyph(fd->cache[size]->face, p_index, FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
ERR_FAIL_COND_V(error, false); ERR_FAIL_COND_V(error, Dictionary());
r_points.clear(); points.clear();
r_contours.clear(); contours.clear();
real_t h = fd->cache[size]->ascent; float h = fd->cache[size]->ascent;
real_t scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; float scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
if (fd->msdf) { if (fd->msdf) {
scale = scale * (real_t)p_size / (real_t)fd->msdf_source_size; scale = scale * (float)p_size / (float)fd->msdf_source_size;
} }
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) { for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) {
r_points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
} }
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) { for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) {
r_contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]);
} }
r_orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT);
#else #else
return false; return Dictionary();
#endif #endif
return true;
Dictionary out;
out["points"] = points;
out["contours"] = contours;
out["orientation"] = orientation;
return out;
} }
Array TextServerAdvanced::font_get_kerning_list(RID p_font_rid, int p_size) const { Array TextServerAdvanced::font_get_kerning_list(RID p_font_rid, int p_size) const {
@ -2433,7 +2457,7 @@ Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const V
if (kern.has(p_glyph_pair)) { if (kern.has(p_glyph_pair)) {
if (fd->msdf) { if (fd->msdf) {
return kern[p_glyph_pair] * (real_t)p_size / (real_t)fd->msdf_source_size; return kern[p_glyph_pair] * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return kern[p_glyph_pair]; return kern[p_glyph_pair];
} }
@ -2443,7 +2467,7 @@ Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const V
FT_Vector delta; FT_Vector delta;
FT_Get_Kerning(fd->cache[size]->face, p_glyph_pair.x, p_glyph_pair.y, FT_KERNING_DEFAULT, &delta); FT_Get_Kerning(fd->cache[size]->face, p_glyph_pair.x, p_glyph_pair.y, FT_KERNING_DEFAULT, &delta);
if (fd->msdf) { if (fd->msdf) {
return Vector2(delta.x, delta.y) * (real_t)p_size / (real_t)fd->msdf_source_size; return Vector2(delta.x, delta.y) * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return Vector2(delta.x, delta.y); return Vector2(delta.x, delta.y);
} }
@ -2582,8 +2606,8 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
if (fd->msdf) { if (fd->msdf) {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size;
Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else { } else {
Point2i cpos = p_pos; Point2i cpos = p_pos;
@ -2622,8 +2646,8 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
if (fd->msdf) { if (fd->msdf) {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size;
Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else { } else {
Point2i cpos = p_pos; Point2i cpos = p_pos;
@ -2694,7 +2718,7 @@ bool TextServerAdvanced::font_is_script_supported(RID p_font_rid, const String &
} else { } else {
Vector2i size = _get_size(fd, 16); Vector2i size = _get_size(fd, 16);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false);
return fd->supported_scripts.has(TS->name_to_tag(p_script)); return fd->supported_scripts.has(hb_tag_from_string(p_script.ascii().get_data(), -1));
} }
} }
@ -2754,11 +2778,11 @@ Dictionary TextServerAdvanced::font_supported_variation_list(RID p_font_rid) con
return fd->supported_varaitions; return fd->supported_varaitions;
} }
real_t TextServerAdvanced::font_get_global_oversampling() const { float TextServerAdvanced::font_get_global_oversampling() const {
return oversampling; return oversampling;
} }
void TextServerAdvanced::font_set_global_oversampling(real_t p_oversampling) { void TextServerAdvanced::font_set_global_oversampling(float p_oversampling) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (oversampling != p_oversampling) { if (oversampling != p_oversampling) {
oversampling = p_oversampling; oversampling = p_oversampling;
@ -2904,7 +2928,7 @@ TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped
return sd->direction; return sd->direction;
} }
void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) { void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND(!sd); ERR_FAIL_COND(!sd);
@ -2912,7 +2936,10 @@ void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Vecto
if (sd->parent != RID()) { if (sd->parent != RID()) {
full_copy(sd); full_copy(sd);
} }
sd->bidi_override = p_override; sd->bidi_override.clear();
for (int i = 0; i < p_override.size(); i++) {
sd->bidi_override.push_back(p_override[i]);
}
invalidate(sd); invalidate(sd);
} }
@ -3096,8 +3123,7 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key,
} else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) { } else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box. // Glyph not found, replace with hex code box.
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else { } else {
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
@ -3108,8 +3134,8 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key,
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = sd->ascent; float full_ascent = sd->ascent;
real_t full_descent = sd->descent; float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) { if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
@ -3283,8 +3309,7 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
} else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) { } else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box. // Glyph not found, replace with hex code box.
if (new_sd->orientation == ORIENTATION_HORIZONTAL) { if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else { } else {
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
@ -3299,8 +3324,8 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = new_sd->ascent; float full_ascent = new_sd->ascent;
real_t full_descent = new_sd->descent; float full_descent = new_sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) { if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
@ -3378,7 +3403,7 @@ RID TextServerAdvanced::shaped_text_get_parent(RID p_shaped) const {
return sd->parent; return sd->parent;
} }
real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags) { float TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3419,7 +3444,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width
} }
} }
real_t justification_width; float justification_width;
if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) {
if (sd->overrun_trim_data.trim_pos >= 0) { if (sd->overrun_trim_data.trim_pos >= 0) {
start_pos = sd->overrun_trim_data.trim_pos; start_pos = sd->overrun_trim_data.trim_pos;
@ -3459,7 +3484,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width
} }
if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) { if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) {
real_t delta_width_per_kashida = (p_width - justification_width) / elongation_count; float delta_width_per_kashida = (p_width - justification_width) / elongation_count;
for (int i = start_pos; i <= end_pos; i++) { for (int i = start_pos; i <= end_pos; i++) {
Glyph &gl = sd->glyphs.write[i]; Glyph &gl = sd->glyphs.write[i];
if (gl.count > 0) { if (gl.count > 0) {
@ -3474,15 +3499,15 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width
} }
} }
} }
real_t adv_remain = 0; float adv_remain = 0;
if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) {
real_t delta_width_per_space = (p_width - justification_width) / space_count; float delta_width_per_space = (p_width - justification_width) / space_count;
for (int i = start_pos; i <= end_pos; i++) { for (int i = start_pos; i <= end_pos; i++) {
Glyph &gl = sd->glyphs.write[i]; Glyph &gl = sd->glyphs.write[i];
if (gl.count > 0) { if (gl.count > 0) {
if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
real_t old_adv = gl.advance; float old_adv = gl.advance;
real_t new_advance; float new_advance;
if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
new_advance = MAX(gl.advance + delta_width_per_space, 0.f); new_advance = MAX(gl.advance + delta_width_per_space, 0.f);
} else { } else {
@ -3514,7 +3539,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width
return sd->width; return sd->width;
} }
real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) { float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3527,7 +3552,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
} }
int tab_index = 0; int tab_index = 0;
real_t off = 0.f; float off = 0.f;
int start, end, delta; int start, end, delta;
if (sd->para_direction == DIRECTION_LTR) { if (sd->para_direction == DIRECTION_LTR) {
@ -3544,7 +3569,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
for (int i = start; i != end; i += delta) { for (int i = start; i != end; i += delta) {
if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) {
real_t tab_off = 0.f; float tab_off = 0.f;
while (tab_off <= off) { while (tab_off <= off) {
tab_off += p_tab_stops[tab_index]; tab_off += p_tab_stops[tab_index];
tab_index++; tab_index++;
@ -3552,7 +3577,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
tab_index = 0; tab_index = 0;
} }
} }
real_t old_adv = gl[i].advance; float old_adv = gl[i].advance;
gl[i].advance = tab_off - off; gl[i].advance = tab_off - off;
sd->width += gl[i].advance - old_adv; sd->width += gl[i].advance - old_adv;
off = 0; off = 0;
@ -3564,7 +3589,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
return 0.f; return 0.f;
} }
void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, real_t p_width, uint8_t p_trim_flags) { void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line);
ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid."); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid.");
@ -3607,7 +3632,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
} }
int ell_min_characters = 6; int ell_min_characters = 6;
real_t width = sd->width; float width = sd->width;
bool is_rtl = sd->direction == DIRECTION_RTL || (sd->direction == DIRECTION_AUTO && sd->para_direction == DIRECTION_RTL); bool is_rtl = sd->direction == DIRECTION_RTL || (sd->direction == DIRECTION_AUTO && sd->para_direction == DIRECTION_RTL);
@ -3663,7 +3688,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) {
// Insert an additional space when cutting word bound for aesthetics. // Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) { if (cut_per_word && (ellipsis_pos > 0)) {
TextServer::Glyph gl; Glyph gl;
gl.count = 1; gl.count = 1;
gl.advance = whitespace_adv.x; gl.advance = whitespace_adv.x;
gl.index = whitespace_gl_idx; gl.index = whitespace_gl_idx;
@ -3674,7 +3699,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
sd->overrun_trim_data.ellipsis_glyph_buf.append(gl); sd->overrun_trim_data.ellipsis_glyph_buf.append(gl);
} }
// Add ellipsis dots. // Add ellipsis dots.
TextServer::Glyph gl; Glyph gl;
gl.count = 1; gl.count = 1;
gl.repeat = 3; gl.repeat = 3;
gl.advance = dot_adv.x; gl.advance = dot_adv.x;
@ -3691,12 +3716,36 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
} }
} }
TextServer::TrimData TextServerAdvanced::shaped_text_get_trim_data(RID p_shaped) const { int TextServerAdvanced::shaped_text_get_trim_pos(RID p_shaped) const {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, TrimData(), "ShapedTextDataAdvanced invalid."); ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid.");
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
return sd->overrun_trim_data; return sd->overrun_trim_data.trim_pos;
}
int TextServerAdvanced::shaped_text_get_ellipsis_pos(RID p_shaped) const {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_pos;
}
const Glyph *TextServerAdvanced::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextDataAdvanced invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_glyph_buf.ptr();
}
int TextServerAdvanced::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextDataAdvanced invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_glyph_buf.size();
} }
bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
@ -3783,7 +3832,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
if (is_whitespace(c)) { if (is_whitespace(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT; sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT;
} else { } else {
TextServer::Glyph gl; Glyph gl;
gl.start = sd_glyphs[i].start; gl.start = sd_glyphs[i].start;
gl.end = sd_glyphs[i].end; gl.end = sd_glyphs[i].end;
gl.count = 1; gl.count = 1;
@ -3964,7 +4013,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_ELONGATION; sd->glyphs.write[i].flags |= GRAPHEME_IS_ELONGATION;
} else { } else {
if (sd->glyphs[i].font_rid != RID()) { if (sd->glyphs[i].font_rid != RID()) {
TextServer::Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size); Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size);
if ((gl.flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) { if ((gl.flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
gl.start = sd->glyphs[i].start; gl.start = sd->glyphs[i].start;
gl.end = sd->glyphs[i].end; gl.end = sd->glyphs[i].end;
@ -3982,7 +4031,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
} }
} }
} else if (!is_whitespace(c)) { } else if (!is_whitespace(c)) {
TextServer::Glyph gl; Glyph gl;
gl.start = sd->glyphs[i].start; gl.start = sd->glyphs[i].start;
gl.end = sd->glyphs[i].end; gl.end = sd->glyphs[i].end;
gl.count = 1; gl.count = 1;
@ -4007,9 +4056,9 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
return sd->justification_ops_valid; return sd->justification_ops_valid;
} }
TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size) { Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size) {
hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size); hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size);
ERR_FAIL_COND_V(hb_font == nullptr, TextServer::Glyph()); ERR_FAIL_COND_V(hb_font == nullptr, Glyph());
hb_buffer_clear_contents(p_sd->hb_buffer); hb_buffer_clear_contents(p_sd->hb_buffer);
hb_buffer_set_direction(p_sd->hb_buffer, p_direction); hb_buffer_set_direction(p_sd->hb_buffer, p_direction);
@ -4024,7 +4073,7 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count);
// Process glyphs. // Process glyphs.
TextServer::Glyph gl; Glyph gl;
if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) { if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) {
gl.flags |= TextServer::GRAPHEME_IS_RTL; gl.flags |= TextServer::GRAPHEME_IS_RTL;
@ -4034,7 +4083,7 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced
gl.font_size = p_font_size; gl.font_size = p_font_size;
if (glyph_count > 0) { if (glyph_count > 0) {
real_t scale = font_get_scale(p_font, p_font_size); float scale = font_get_scale(p_font, p_font_size);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale)); gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale));
} else { } else {
@ -4059,7 +4108,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
// Add fallback glyphs. // Add fallback glyphs.
for (int i = p_start; i < p_end; i++) { for (int i = p_start; i < p_end; i++) {
if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) { if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) {
TextServer::Glyph gl; Glyph gl;
gl.start = i; gl.start = i;
gl.end = i + 1; gl.end = i + 1;
gl.count = 1; gl.count = 1;
@ -4071,8 +4120,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
} }
if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = get_hex_code_box_size(fs, gl.index).x; gl.advance = get_hex_code_box_size(fs, gl.index).x;
p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.75f)); p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y);
p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.25f));
} else { } else {
gl.advance = get_hex_code_box_size(fs, gl.index).y; gl.advance = get_hex_code_box_size(fs, gl.index).y;
p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5f)); p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5f));
@ -4126,7 +4174,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
// Process glyphs. // Process glyphs.
if (glyph_count > 0) { if (glyph_count > 0) {
TextServer::Glyph *w = (TextServer::Glyph *)memalloc(glyph_count * sizeof(TextServer::Glyph)); Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph));
int end = (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) ? p_end : 0; int end = (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) ? p_end : 0;
uint32_t last_cluster_id = UINT32_MAX; uint32_t last_cluster_id = UINT32_MAX;
@ -4155,8 +4203,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
last_cluster_id = glyph_info[i].cluster; last_cluster_id = glyph_info[i].cluster;
TextServer::Glyph &gl = w[i]; Glyph &gl = w[i];
gl = TextServer::Glyph(); gl = Glyph();
gl.start = glyph_info[i].cluster; gl.start = glyph_info[i].cluster;
gl.end = end; gl.end = end;
@ -4171,7 +4219,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
gl.index = glyph_info[i].codepoint; gl.index = glyph_info[i].codepoint;
if (gl.index != 0) { if (gl.index != 0) {
real_t scale = font_get_scale(f, fs); float scale = font_get_scale(f, fs);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale)); gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
} else { } else {
@ -4411,8 +4459,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = sd->ascent; float full_ascent = sd->ascent;
real_t full_descent = sd->descent; float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) {
@ -4486,28 +4534,31 @@ bool TextServerAdvanced::shaped_text_is_ready(RID p_shaped) const {
return sd->valid; return sd->valid;
} }
Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_get_glyphs(RID p_shaped) const { const Glyph *TextServerAdvanced::shaped_text_get_glyphs(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>()); ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
if (!sd->valid) { if (!sd->valid) {
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
} }
return sd->glyphs; return sd->glyphs.ptr();
} }
Vector2i TextServerAdvanced::shaped_text_get_range(RID p_shaped) const { int TextServerAdvanced::shaped_text_get_glyph_count(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector2i()); ERR_FAIL_COND_V(!sd, 0);
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
return Vector2(sd->start, sd->end); if (!sd->valid) {
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
}
return sd->glyphs.size();
} }
Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_sort_logical(RID p_shaped) { const Glyph *TextServerAdvanced::shaped_text_sort_logical(RID p_shaped) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>()); ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
if (!sd->valid) { if (!sd->valid) {
@ -4516,11 +4567,19 @@ Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_sort_logical(RID p_sha
if (!sd->sort_valid) { if (!sd->sort_valid) {
sd->glyphs_logical = sd->glyphs; sd->glyphs_logical = sd->glyphs;
sd->glyphs_logical.sort_custom<TextServer::GlyphCompare>(); sd->glyphs_logical.sort_custom<GlyphCompare>();
sd->sort_valid = true; sd->sort_valid = true;
} }
return sd->glyphs_logical; return sd->glyphs_logical.ptr();
}
Vector2i TextServerAdvanced::shaped_text_get_range(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector2i());
MutexLock lock(sd->mutex);
return Vector2(sd->start, sd->end);
} }
Array TextServerAdvanced::shaped_text_get_objects(RID p_shaped) const { Array TextServerAdvanced::shaped_text_get_objects(RID p_shaped) const {
@ -4563,7 +4622,7 @@ Size2 TextServerAdvanced::shaped_text_get_size(RID p_shaped) const {
} }
} }
real_t TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const { float TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -4574,7 +4633,7 @@ real_t TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const {
return sd->ascent; return sd->ascent;
} }
real_t TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const { float TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -4585,7 +4644,7 @@ real_t TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const {
return sd->descent; return sd->descent;
} }
real_t TextServerAdvanced::shaped_text_get_width(RID p_shaped) const { float TextServerAdvanced::shaped_text_get_width(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -4596,7 +4655,7 @@ real_t TextServerAdvanced::shaped_text_get_width(RID p_shaped) const {
return (sd->text_trimmed ? sd->width_trimmed : sd->width); return (sd->text_trimmed ? sd->width_trimmed : sd->width);
} }
real_t TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) const { float TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -4608,7 +4667,7 @@ real_t TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) cons
return sd->upos; return sd->upos;
} }
real_t TextServerAdvanced::shaped_text_get_underline_thickness(RID p_shaped) const { float TextServerAdvanced::shaped_text_get_underline_thickness(RID p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -4752,15 +4811,6 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
return "%"; return "%";
} }
TextServer *TextServerAdvanced::create_func(Error &r_error, void *p_user_data) {
r_error = OK;
return memnew(TextServerAdvanced());
}
void TextServerAdvanced::register_server() {
TextServerManager::register_create_function(interface_name, interface_features, create_func, nullptr);
}
TextServerAdvanced::TextServerAdvanced() { TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang(); _insert_num_systems_lang();
_insert_feature_sets(); _insert_feature_sets();

View file

@ -115,12 +115,12 @@ class TextServerAdvanced : public TextServer {
}; };
struct FontDataForSizeAdvanced { struct FontDataForSizeAdvanced {
real_t ascent = 0.f; float ascent = 0.f;
real_t descent = 0.f; float descent = 0.f;
real_t underline_position = 0.f; float underline_position = 0.f;
real_t underline_thickness = 0.f; float underline_thickness = 0.f;
real_t scale = 1.f; float scale = 1.f;
real_t oversampling = 1.f; float oversampling = 1.f;
int spacing_glyph = 0; int spacing_glyph = 0;
int spacing_space = 0; int spacing_space = 0;
@ -161,7 +161,7 @@ class TextServerAdvanced : public TextServer {
bool force_autohinter = false; bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
Dictionary variation_coordinates; Dictionary variation_coordinates;
real_t oversampling = 0.f; float oversampling = 0.f;
Map<Vector2i, FontDataForSizeAdvanced *> cache; Map<Vector2i, FontDataForSizeAdvanced *> cache;
@ -245,14 +245,14 @@ class TextServerAdvanced : public TextServer {
// Common data. // Common data.
real_t oversampling = 1.f; float oversampling = 1.f;
mutable RID_PtrOwner<FontDataAdvanced> font_owner; mutable RID_PtrOwner<FontDataAdvanced> font_owner;
mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner; mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner;
int _convert_pos(const ShapedTextDataAdvanced *p_sd, int p_pos) const; int _convert_pos(const ShapedTextDataAdvanced *p_sd, int p_pos) const;
int _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int p_pos) const; int _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int p_pos) const;
void _shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_start, int32_t p_end, hb_script_t p_script, hb_direction_t p_direction, Vector<RID> p_fonts, int p_span, int p_fb_index); void _shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_start, int32_t p_end, hb_script_t p_script, hb_direction_t p_direction, Vector<RID> p_fonts, int p_span, int p_fb_index);
TextServer::Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size); Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size);
// HarfBuzz bitmap font interface. // HarfBuzz bitmap font interface.
@ -284,20 +284,19 @@ protected:
void invalidate(ShapedTextDataAdvanced *p_shaped); void invalidate(ShapedTextDataAdvanced *p_shaped);
public: public:
virtual bool has_feature(Feature p_feature) override; virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override; virtual String get_name() const override;
virtual uint32_t get_features() const override;
virtual void free(RID p_rid) override; virtual void free(RID p_rid) override;
virtual bool has(RID p_rid) override; virtual bool has(RID p_rid) override;
virtual bool load_support_data(const String &p_filename) override; virtual bool load_support_data(const String &p_filename) override;
#ifdef TOOLS_ENABLED virtual String get_support_data_filename() const override;
virtual String get_support_data_filename() override { return _MKSTR(ICU_DATA_NAME); }; virtual String get_support_data_info() const override;
virtual String get_support_data_info() override { return String("ICU break iteration data (") + _MKSTR(ICU_DATA_NAME) + String(")."); }; virtual bool save_support_data(const String &p_filename) const override;
virtual bool save_support_data(const String &p_filename) override;
#endif
virtual bool is_locale_right_to_left(const String &p_locale) override; virtual bool is_locale_right_to_left(const String &p_locale) const override;
virtual int32_t name_to_tag(const String &p_name) const override; virtual int32_t name_to_tag(const String &p_name) const override;
virtual String tag_to_name(int32_t p_tag) const override; virtual String tag_to_name(int32_t p_tag) const override;
@ -332,8 +331,8 @@ public:
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
virtual void font_set_oversampling(RID p_font_rid, real_t p_oversampling) override; virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override;
virtual real_t font_get_oversampling(RID p_font_rid) const override; virtual float font_get_oversampling(RID p_font_rid) const override;
virtual Array font_get_size_cache_list(RID p_font_rid) const override; virtual Array font_get_size_cache_list(RID p_font_rid) const override;
virtual void font_clear_size_cache(RID p_font_rid) override; virtual void font_clear_size_cache(RID p_font_rid) override;
@ -341,20 +340,20 @@ public:
hb_font_t *_font_get_hb_handle(RID p_font, int p_font_size) const; hb_font_t *_font_get_hb_handle(RID p_font, int p_font_size) const;
virtual void font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) override; virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override;
virtual real_t font_get_ascent(RID p_font_rid, int p_size) const override; virtual float font_get_ascent(RID p_font_rid, int p_size) const override;
virtual void font_set_descent(RID p_font_rid, int p_size, real_t p_descent) override; virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override;
virtual real_t font_get_descent(RID p_font_rid, int p_size) const override; virtual float font_get_descent(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) override; virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override;
virtual real_t font_get_underline_position(RID p_font_rid, int p_size) const override; virtual float font_get_underline_position(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) override; virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override;
virtual real_t font_get_underline_thickness(RID p_font_rid, int p_size) const override; virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override;
virtual void font_set_scale(RID p_font_rid, int p_size, real_t p_scale) override; virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override;
virtual real_t font_get_scale(RID p_font_rid, int p_size) const override; virtual float font_get_scale(RID p_font_rid, int p_size) const override;
virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override; virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override; virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
@ -388,7 +387,7 @@ public:
virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override; virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override;
virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override; virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override; virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
@ -423,8 +422,8 @@ public:
virtual Dictionary font_supported_feature_list(RID p_font_rid) const override; virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const override; virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
virtual real_t font_get_global_oversampling() const override; virtual float font_get_global_oversampling() const override;
virtual void font_set_global_oversampling(real_t p_oversampling) override; virtual void font_set_global_oversampling(float p_oversampling) override;
/* Shaped text buffer interface */ /* Shaped text buffer interface */
@ -435,7 +434,7 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override; virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(RID p_shaped) const override; virtual Direction shaped_text_get_direction(RID p_shaped) const override;
virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) override; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
@ -453,41 +452,42 @@ public:
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override; virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override; virtual RID shaped_text_get_parent(RID p_shaped) const override;
virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) override; virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override;
virtual bool shaped_text_shape(RID p_shaped) override; virtual bool shaped_text_shape(RID p_shaped) override;
virtual bool shaped_text_update_breaks(RID p_shaped) override; virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override; virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, real_t p_width, uint8_t p_trim_flags) override; virtual int shaped_text_get_trim_pos(RID p_shaped) const override;
virtual TrimData shaped_text_get_trim_data(RID p_shaped) const override; virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override;
virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override;
virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override;
virtual bool shaped_text_is_ready(RID p_shaped) const override; virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override; virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override;
virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override;
virtual int shaped_text_get_glyph_count(RID p_shaped) const override;
virtual Vector2i shaped_text_get_range(RID p_shaped) const override; virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) override;
virtual Array shaped_text_get_objects(RID p_shaped) const override; virtual Array shaped_text_get_objects(RID p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override; virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
virtual Size2 shaped_text_get_size(RID p_shaped) const override; virtual Size2 shaped_text_get_size(RID p_shaped) const override;
virtual real_t shaped_text_get_ascent(RID p_shaped) const override; virtual float shaped_text_get_ascent(RID p_shaped) const override;
virtual real_t shaped_text_get_descent(RID p_shaped) const override; virtual float shaped_text_get_descent(RID p_shaped) const override;
virtual real_t shaped_text_get_width(RID p_shaped) const override; virtual float shaped_text_get_width(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_position(RID p_shaped) const override; virtual float shaped_text_get_underline_position(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_thickness(RID p_shaped) const override; virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
virtual String format_number(const String &p_string, const String &p_language = "") const override; virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override; virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override; virtual String percent_sign(const String &p_language = "") const override;
static TextServer *create_func(Error &r_error, void *p_user_data);
static void register_server();
TextServerAdvanced(); TextServerAdvanced();
~TextServerAdvanced(); ~TextServerAdvanced();
}; };

View file

@ -9,3 +9,13 @@ def configure(env):
def is_enabled(): def is_enabled():
# The module is disabled by default. Use module_text_server_fb_enabled=yes to enable it. # The module is disabled by default. Use module_text_server_fb_enabled=yes to enable it.
return False return False
def get_doc_classes():
return [
"TextServerFallback",
]
def get_doc_path():
return "doc_classes"

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextServerFallback" inherits="TextServer" version="4.0">
<brief_description>
Fallback implementation of the Text Server, without BiDi and complex text layout support.
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
</class>

View file

@ -33,7 +33,12 @@
#include "text_server_fb.h" #include "text_server_fb.h"
void preregister_text_server_fb_types() { void preregister_text_server_fb_types() {
TextServerFallback::register_server(); GDREGISTER_CLASS(TextServerFallback);
if (TextServerManager::get_singleton()) {
Ref<TextServerFallback> ts;
ts.instantiate();
TextServerManager::get_singleton()->add_interface(ts);
}
} }
void register_text_server_fb_types() { void register_text_server_fb_types() {

View file

@ -69,7 +69,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
String TextServerFallback::interface_name = "Fallback"; String TextServerFallback::interface_name = "Fallback";
uint32_t TextServerFallback::interface_features = 0; // Nothing is supported. uint32_t TextServerFallback::interface_features = 0; // Nothing is supported.
bool TextServerFallback::has_feature(Feature p_feature) { bool TextServerFallback::has_feature(Feature p_feature) const {
return (interface_features & p_feature) == p_feature; return (interface_features & p_feature) == p_feature;
} }
@ -77,6 +77,10 @@ String TextServerFallback::get_name() const {
return interface_name; return interface_name;
} }
uint32_t TextServerFallback::get_features() const {
return interface_features;
}
void TextServerFallback::free(RID p_rid) { void TextServerFallback::free(RID p_rid) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) { if (font_owner.owns(p_rid)) {
@ -99,15 +103,11 @@ bool TextServerFallback::load_support_data(const String &p_filename) {
return false; // No extra data used. return false; // No extra data used.
} }
#ifdef TOOLS_ENABLED bool TextServerFallback::save_support_data(const String &p_filename) const {
bool TextServerFallback::save_support_data(const String &p_filename) {
return false; // No extra data used. return false; // No extra data used.
} }
#endif bool TextServerFallback::is_locale_right_to_left(const String &p_locale) const {
bool TextServerFallback::is_locale_right_to_left(const String &p_locale) {
return false; // No RTL support. return false; // No RTL support.
} }
@ -420,7 +420,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
FontTexture &tex = p_data->textures.write[tex_pos.index]; FontTexture &tex = p_data->textures.write[tex_pos.index];
edgeColoringSimple(shape, 3.0); // Max. angle. edgeColoringSimple(shape, 3.0); // Max. angle.
msdfgen::Bitmap<real_t, 4> image(w, h); // Texture size. msdfgen::Bitmap<float, 4> image(w, h); // Texture size.
//msdfgen::generateMTSDF(image, shape, p_pixel_range, 1.0, msdfgen::Vector2(-bounds.l, -bounds.b)); // Range, scale, translation. //msdfgen::generateMTSDF(image, shape, p_pixel_range, 1.0, msdfgen::Vector2(-bounds.l, -bounds.b)); // Range, scale, translation.
DistancePixelConversion distancePixelConversion(p_pixel_range); DistancePixelConversion distancePixelConversion(p_pixel_range);
@ -620,7 +620,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
int error = FT_Load_Glyph(fd->face, glyph_index, flags); int error = FT_Load_Glyph(fd->face, glyph_index, flags);
if (error) { if (error) {
fd->glyph_map[p_glyph] = FontGlyph(); fd->glyph_map[p_glyph] = FontGlyph();
ERR_FAIL_V_MSG(false, "FreeType: Failed to load glyph."); return false;
} }
if (!outline) { if (!outline) {
@ -714,7 +714,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
fd->oversampling = 1.0f; fd->oversampling = 1.0f;
fd->size.x = p_font_data->msdf_source_size; fd->size.x = p_font_data->msdf_source_size;
} else if (p_font_data->oversampling <= 0.0f) { } else if (p_font_data->oversampling <= 0.0f) {
fd->oversampling = TS->font_get_global_oversampling(); fd->oversampling = font_get_global_oversampling();
} else { } else {
fd->oversampling = p_font_data->oversampling; fd->oversampling = p_font_data->oversampling;
} }
@ -722,13 +722,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
if (FT_HAS_COLOR(fd->face) && fd->face->num_fixed_sizes > 0) { if (FT_HAS_COLOR(fd->face) && fd->face->num_fixed_sizes > 0) {
int best_match = 0; int best_match = 0;
int diff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[0].width)); int diff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[0].width));
fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width; fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width;
for (int i = 1; i < fd->face->num_fixed_sizes; i++) { for (int i = 1; i < fd->face->num_fixed_sizes; i++) {
int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width)); int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width));
if (ndiff < diff) { if (ndiff < diff) {
best_match = i; best_match = i;
diff = ndiff; diff = ndiff;
fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width; fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width;
} }
} }
FT_Select_Size(fd->face, best_match); FT_Select_Size(fd->face, best_match);
@ -769,7 +769,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
for (FT_UInt i = 0; i < amaster->num_axis; i++) { for (FT_UInt i = 0; i < amaster->num_axis; i++) {
// Reset to default. // Reset to default.
int32_t var_tag = amaster->axis[i].tag; int32_t var_tag = amaster->axis[i].tag;
real_t var_value = (double)amaster->axis[i].def / 65536.f; float var_value = (double)amaster->axis[i].def / 65536.f;
coords.write[i] = amaster->axis[i].def; coords.write[i] = amaster->axis[i].def;
if (p_font_data->variation_coordinates.has(var_tag)) { if (p_font_data->variation_coordinates.has(var_tag)) {
@ -983,7 +983,7 @@ Dictionary TextServerFallback::font_get_variation_coordinates(RID p_font_rid) co
return fd->variation_coordinates; return fd->variation_coordinates;
} }
void TextServerFallback::font_set_oversampling(RID p_font_rid, real_t p_oversampling) { void TextServerFallback::font_set_oversampling(RID p_font_rid, float p_oversampling) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -994,7 +994,7 @@ void TextServerFallback::font_set_oversampling(RID p_font_rid, real_t p_oversamp
} }
} }
real_t TextServerFallback::font_get_oversampling(RID p_font_rid) const { float TextServerFallback::font_get_oversampling(RID p_font_rid) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1036,7 +1036,7 @@ void TextServerFallback::font_remove_size_cache(RID p_font_rid, const Vector2i &
} }
} }
void TextServerFallback::font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) { void TextServerFallback::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1047,7 +1047,7 @@ void TextServerFallback::font_set_ascent(RID p_font_rid, int p_size, real_t p_as
fd->cache[size]->ascent = p_ascent; fd->cache[size]->ascent = p_ascent;
} }
real_t TextServerFallback::font_get_ascent(RID p_font_rid, int p_size) const { float TextServerFallback::font_get_ascent(RID p_font_rid, int p_size) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1057,13 +1057,13 @@ real_t TextServerFallback::font_get_ascent(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->ascent * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->ascent * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->ascent; return fd->cache[size]->ascent;
} }
} }
void TextServerFallback::font_set_descent(RID p_font_rid, int p_size, real_t p_descent) { void TextServerFallback::font_set_descent(RID p_font_rid, int p_size, float p_descent) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1073,7 +1073,7 @@ void TextServerFallback::font_set_descent(RID p_font_rid, int p_size, real_t p_d
fd->cache[size]->descent = p_descent; fd->cache[size]->descent = p_descent;
} }
real_t TextServerFallback::font_get_descent(RID p_font_rid, int p_size) const { float TextServerFallback::font_get_descent(RID p_font_rid, int p_size) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1083,13 +1083,13 @@ real_t TextServerFallback::font_get_descent(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->descent * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->descent * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->descent; return fd->cache[size]->descent;
} }
} }
void TextServerFallback::font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) { void TextServerFallback::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1100,7 +1100,7 @@ void TextServerFallback::font_set_underline_position(RID p_font_rid, int p_size,
fd->cache[size]->underline_position = p_underline_position; fd->cache[size]->underline_position = p_underline_position;
} }
real_t TextServerFallback::font_get_underline_position(RID p_font_rid, int p_size) const { float TextServerFallback::font_get_underline_position(RID p_font_rid, int p_size) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1110,13 +1110,13 @@ real_t TextServerFallback::font_get_underline_position(RID p_font_rid, int p_siz
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->underline_position * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->underline_position * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->underline_position; return fd->cache[size]->underline_position;
} }
} }
void TextServerFallback::font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) { void TextServerFallback::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1127,7 +1127,7 @@ void TextServerFallback::font_set_underline_thickness(RID p_font_rid, int p_size
fd->cache[size]->underline_thickness = p_underline_thickness; fd->cache[size]->underline_thickness = p_underline_thickness;
} }
real_t TextServerFallback::font_get_underline_thickness(RID p_font_rid, int p_size) const { float TextServerFallback::font_get_underline_thickness(RID p_font_rid, int p_size) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1137,13 +1137,13 @@ real_t TextServerFallback::font_get_underline_thickness(RID p_font_rid, int p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->underline_thickness * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->underline_thickness * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->underline_thickness; return fd->cache[size]->underline_thickness;
} }
} }
void TextServerFallback::font_set_scale(RID p_font_rid, int p_size, real_t p_scale) { void TextServerFallback::font_set_scale(RID p_font_rid, int p_size, float p_scale) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
@ -1154,7 +1154,7 @@ void TextServerFallback::font_set_scale(RID p_font_rid, int p_size, real_t p_sca
fd->cache[size]->scale = p_scale; fd->cache[size]->scale = p_scale;
} }
real_t TextServerFallback::font_get_scale(RID p_font_rid, int p_size) const { float TextServerFallback::font_get_scale(RID p_font_rid, int p_size) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f); ERR_FAIL_COND_V(!fd, 0.f);
@ -1164,7 +1164,7 @@ real_t TextServerFallback::font_get_scale(RID p_font_rid, int p_size) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f);
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->scale * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->scale * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->scale / fd->cache[size]->oversampling; return fd->cache[size]->scale / fd->cache[size]->oversampling;
} }
@ -1203,14 +1203,14 @@ int TextServerFallback::font_get_spacing(RID p_font_rid, int p_size, TextServer:
switch (p_spacing) { switch (p_spacing) {
case TextServer::SPACING_GLYPH: { case TextServer::SPACING_GLYPH: {
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->spacing_glyph * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->spacing_glyph * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->spacing_glyph; return fd->cache[size]->spacing_glyph;
} }
} break; } break;
case TextServer::SPACING_SPACE: { case TextServer::SPACING_SPACE: {
if (fd->msdf) { if (fd->msdf) {
return fd->cache[size]->spacing_space * (real_t)p_size / (real_t)fd->msdf_source_size; return fd->cache[size]->spacing_space * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return fd->cache[size]->spacing_space; return fd->cache[size]->spacing_space;
} }
@ -1379,7 +1379,7 @@ Vector2 TextServerFallback::font_get_glyph_advance(RID p_font_rid, int p_size, i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].advance * (real_t)p_size / (real_t)fd->msdf_source_size; return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].advance; return gl[p_glyph].advance;
} }
@ -1415,7 +1415,7 @@ Vector2 TextServerFallback::font_get_glyph_offset(RID p_font_rid, const Vector2i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].rect.position * (real_t)p_size.x / (real_t)fd->msdf_source_size; return gl[p_glyph].rect.position * (float)p_size.x / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].rect.position; return gl[p_glyph].rect.position;
} }
@ -1451,7 +1451,7 @@ Vector2 TextServerFallback::font_get_glyph_size(RID p_font_rid, const Vector2i &
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
if (fd->msdf) { if (fd->msdf) {
return gl[p_glyph].rect.size * (real_t)p_size.x / (real_t)fd->msdf_source_size; return gl[p_glyph].rect.size * (float)p_size.x / (float)fd->msdf_source_size;
} else { } else {
return gl[p_glyph].rect.size; return gl[p_glyph].rect.size;
} }
@ -1534,38 +1534,46 @@ void TextServerFallback::font_set_glyph_texture_idx(RID p_font_rid, const Vector
gl[p_glyph].found = true; gl[p_glyph].found = true;
} }
bool TextServerFallback::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { Dictionary TextServerFallback::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
Vector2i size = _get_size(fd, p_size); Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Dictionary());
Vector<Vector3> points;
Vector<int32_t> contours;
bool orientation;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
int error = FT_Load_Glyph(fd->cache[size]->face, FT_Get_Char_Index(fd->cache[size]->face, p_index), FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); int error = FT_Load_Glyph(fd->cache[size]->face, FT_Get_Char_Index(fd->cache[size]->face, p_index), FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
ERR_FAIL_COND_V(error, false); ERR_FAIL_COND_V(error, Dictionary());
r_points.clear(); points.clear();
r_contours.clear(); contours.clear();
real_t h = fd->cache[size]->ascent; float h = fd->cache[size]->ascent;
real_t scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; float scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
if (fd->msdf) { if (fd->msdf) {
scale = scale * (real_t)p_size / (real_t)fd->msdf_source_size; scale = scale * (float)p_size / (float)fd->msdf_source_size;
} }
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) { for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) {
r_points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
} }
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) { for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) {
r_contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]);
} }
r_orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT);
#else #else
return false; return Dictionary();
#endif #endif
return true;
Dictionary out;
out["points"] = points;
out["contours"] = contours;
out["orientation"] = orientation;
return out;
} }
Array TextServerFallback::font_get_kerning_list(RID p_font_rid, int p_size) const { Array TextServerFallback::font_get_kerning_list(RID p_font_rid, int p_size) const {
@ -1630,7 +1638,7 @@ Vector2 TextServerFallback::font_get_kerning(RID p_font_rid, int p_size, const V
if (kern.has(p_glyph_pair)) { if (kern.has(p_glyph_pair)) {
if (fd->msdf) { if (fd->msdf) {
return kern[p_glyph_pair] * (real_t)p_size / (real_t)fd->msdf_source_size; return kern[p_glyph_pair] * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return kern[p_glyph_pair]; return kern[p_glyph_pair];
} }
@ -1642,7 +1650,7 @@ Vector2 TextServerFallback::font_get_kerning(RID p_font_rid, int p_size, const V
int32_t glyph_b = FT_Get_Char_Index(fd->cache[size]->face, p_glyph_pair.y); int32_t glyph_b = FT_Get_Char_Index(fd->cache[size]->face, p_glyph_pair.y);
FT_Get_Kerning(fd->cache[size]->face, glyph_a, glyph_b, FT_KERNING_DEFAULT, &delta); FT_Get_Kerning(fd->cache[size]->face, glyph_a, glyph_b, FT_KERNING_DEFAULT, &delta);
if (fd->msdf) { if (fd->msdf) {
return Vector2(delta.x, delta.y) * (real_t)p_size / (real_t)fd->msdf_source_size; return Vector2(delta.x, delta.y) * (float)p_size / (float)fd->msdf_source_size;
} else { } else {
return Vector2(delta.x, delta.y); return Vector2(delta.x, delta.y);
} }
@ -1756,8 +1764,8 @@ void TextServerFallback::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz
RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
if (fd->msdf) { if (fd->msdf) {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size;
Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else { } else {
Point2i cpos = p_pos; Point2i cpos = p_pos;
@ -1796,8 +1804,8 @@ void TextServerFallback::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i
RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid();
if (fd->msdf) { if (fd->msdf) {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size;
Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else { } else {
Point2i cpos = p_pos; Point2i cpos = p_pos;
@ -1922,11 +1930,11 @@ Dictionary TextServerFallback::font_supported_variation_list(RID p_font_rid) con
return fd->supported_varaitions; return fd->supported_varaitions;
} }
real_t TextServerFallback::font_get_global_oversampling() const { float TextServerFallback::font_get_global_oversampling() const {
return oversampling; return oversampling;
} }
void TextServerFallback::font_set_global_oversampling(real_t p_oversampling) { void TextServerFallback::font_set_global_oversampling(float p_oversampling) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (oversampling != p_oversampling) { if (oversampling != p_oversampling) {
oversampling = p_oversampling; oversampling = p_oversampling;
@ -2037,7 +2045,7 @@ void TextServerFallback::shaped_text_set_orientation(RID p_shaped, TextServer::O
} }
} }
void TextServerFallback::shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) { void TextServerFallback::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
// No BiDi support, ignore. // No BiDi support, ignore.
} }
@ -2223,8 +2231,7 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
} else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) { } else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box. // Glyph not found, replace with hex code box.
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else { } else {
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
@ -2235,8 +2242,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = sd->ascent; float full_ascent = sd->ascent;
real_t full_descent = sd->descent; float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) { if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
@ -2373,8 +2380,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
} else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) { } else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box. // Glyph not found, replace with hex code box.
if (new_sd->orientation == ORIENTATION_HORIZONTAL) { if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else { } else {
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
@ -2387,8 +2393,8 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = new_sd->ascent; float full_ascent = new_sd->ascent;
real_t full_descent = new_sd->descent; float full_descent = new_sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) { if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
@ -2466,7 +2472,7 @@ RID TextServerFallback::shaped_text_get_parent(RID p_shaped) const {
return sd->parent; return sd->parent;
} }
real_t TextServerFallback::shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags) { float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags) {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -2530,12 +2536,12 @@ real_t TextServerFallback::shaped_text_fit_to_width(RID p_shaped, real_t p_width
} }
if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) {
real_t delta_width_per_space = (p_width - sd->width) / space_count; float delta_width_per_space = (p_width - sd->width) / space_count;
for (int i = start_pos; i <= end_pos; i++) { for (int i = start_pos; i <= end_pos; i++) {
Glyph &gl = sd->glyphs.write[i]; Glyph &gl = sd->glyphs.write[i];
if (gl.count > 0) { if (gl.count > 0) {
if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
real_t old_adv = gl.advance; float old_adv = gl.advance;
gl.advance = MAX(gl.advance + delta_width_per_space, Math::round(0.1 * gl.font_size)); gl.advance = MAX(gl.advance + delta_width_per_space, Math::round(0.1 * gl.font_size));
sd->width += (gl.advance - old_adv); sd->width += (gl.advance - old_adv);
} }
@ -2546,7 +2552,7 @@ real_t TextServerFallback::shaped_text_fit_to_width(RID p_shaped, real_t p_width
return sd->width; return sd->width;
} }
real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) { float TextServerFallback::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -2559,7 +2565,7 @@ real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<real
} }
int tab_index = 0; int tab_index = 0;
real_t off = 0.f; float off = 0.f;
int start, end, delta; int start, end, delta;
if (sd->para_direction == DIRECTION_LTR) { if (sd->para_direction == DIRECTION_LTR) {
@ -2576,7 +2582,7 @@ real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<real
for (int i = start; i != end; i += delta) { for (int i = start; i != end; i += delta) {
if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) {
real_t tab_off = 0.f; float tab_off = 0.f;
while (tab_off <= off) { while (tab_off <= off) {
tab_off += p_tab_stops[tab_index]; tab_off += p_tab_stops[tab_index];
tab_index++; tab_index++;
@ -2584,7 +2590,7 @@ real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<real
tab_index = 0; tab_index = 0;
} }
} }
real_t old_adv = gl[i].advance; float old_adv = gl[i].advance;
gl[i].advance = tab_off - off; gl[i].advance = tab_off - off;
sd->width += gl[i].advance - old_adv; sd->width += gl[i].advance - old_adv;
off = 0; off = 0;
@ -2653,7 +2659,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(RID p_shaped) {
return true; return true;
} }
void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, real_t p_width, uint8_t p_trim_flags) { void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped_line); ShapedTextData *sd = shaped_owner.get_or_null(p_shaped_line);
ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid."); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid.");
@ -2696,7 +2702,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
} }
int ell_min_characters = 6; int ell_min_characters = 6;
real_t width = sd->width; float width = sd->width;
int trim_pos = 0; int trim_pos = 0;
int ellipsis_pos = (enforce_ellipsis) ? 0 : -1; int ellipsis_pos = (enforce_ellipsis) ? 0 : -1;
@ -2742,7 +2748,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) {
// Insert an additional space when cutting word bound for aesthetics. // Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) { if (cut_per_word && (ellipsis_pos > 0)) {
TextServer::Glyph gl; Glyph gl;
gl.count = 1; gl.count = 1;
gl.advance = whitespace_adv.x; gl.advance = whitespace_adv.x;
gl.index = whitespace_gl_idx; gl.index = whitespace_gl_idx;
@ -2753,7 +2759,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
sd->overrun_trim_data.ellipsis_glyph_buf.append(gl); sd->overrun_trim_data.ellipsis_glyph_buf.append(gl);
} }
// Add ellipsis dots. // Add ellipsis dots.
TextServer::Glyph gl; Glyph gl;
gl.count = 1; gl.count = 1;
gl.repeat = 3; gl.repeat = 3;
gl.advance = dot_adv.x; gl.advance = dot_adv.x;
@ -2770,12 +2776,36 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(RID p_shaped_line, re
} }
} }
TextServer::TrimData TextServerFallback::shaped_text_get_trim_data(RID p_shaped) const { int TextServerFallback::shaped_text_get_trim_pos(RID p_shaped) const {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, TrimData(), "ShapedTextDataFallback invalid."); ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid.");
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
return sd->overrun_trim_data; return sd->overrun_trim_data.trim_pos;
}
int TextServerFallback::shaped_text_get_ellipsis_pos(RID p_shaped) const {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_pos;
}
const Glyph *TextServerFallback::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextData invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_glyph_buf.ptr();
}
int TextServerFallback::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextData invalid.");
MutexLock lock(sd->mutex);
return sd->overrun_trim_data.ellipsis_glyph_buf.size();
} }
bool TextServerFallback::shaped_text_shape(RID p_shaped) { bool TextServerFallback::shaped_text_shape(RID p_shaped) {
@ -2890,8 +2920,7 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
// Glyph not found, replace with hex code box. // Glyph not found, replace with hex code box.
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = get_hex_code_box_size(gl.font_size, gl.index).x; gl.advance = get_hex_code_box_size(gl.font_size, gl.index).x;
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else { } else {
gl.advance = get_hex_code_box_size(gl.font_size, gl.index).y; gl.advance = get_hex_code_box_size(gl.font_size, gl.index).y;
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
@ -2905,8 +2934,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
} }
// Align embedded objects to baseline. // Align embedded objects to baseline.
real_t full_ascent = sd->ascent; float full_ascent = sd->ascent;
real_t full_descent = sd->descent; float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) {
@ -2980,15 +3009,38 @@ bool TextServerFallback::shaped_text_is_ready(RID p_shaped) const {
return sd->valid; return sd->valid;
} }
Vector<TextServer::Glyph> TextServerFallback::shaped_text_get_glyphs(RID p_shaped) const { const Glyph *TextServerFallback::shaped_text_get_glyphs(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>()); ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex); MutexLock lock(sd->mutex);
if (!sd->valid) { if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped); const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
} }
return sd->glyphs; return sd->glyphs.ptr();
}
int TextServerFallback::shaped_text_get_glyph_count(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0);
MutexLock lock(sd->mutex);
if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
return sd->glyphs.size();
}
const Glyph *TextServerFallback::shaped_text_sort_logical(RID p_shaped) {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex);
if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
return sd->glyphs.ptr(); // Already in the logical order, return as is.
} }
Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const { Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
@ -2999,18 +3051,6 @@ Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
return Vector2(sd->start, sd->end); return Vector2(sd->start, sd->end);
} }
Vector<TextServer::Glyph> TextServerFallback::shaped_text_sort_logical(RID p_shaped) {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>());
MutexLock lock(sd->mutex);
if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
return sd->glyphs; // Already in the logical order, return as is.
}
Array TextServerFallback::shaped_text_get_objects(RID p_shaped) const { Array TextServerFallback::shaped_text_get_objects(RID p_shaped) const {
Array ret; Array ret;
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
@ -3051,7 +3091,7 @@ Size2 TextServerFallback::shaped_text_get_size(RID p_shaped) const {
} }
} }
real_t TextServerFallback::shaped_text_get_ascent(RID p_shaped) const { float TextServerFallback::shaped_text_get_ascent(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3062,7 +3102,7 @@ real_t TextServerFallback::shaped_text_get_ascent(RID p_shaped) const {
return sd->ascent; return sd->ascent;
} }
real_t TextServerFallback::shaped_text_get_descent(RID p_shaped) const { float TextServerFallback::shaped_text_get_descent(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3073,7 +3113,7 @@ real_t TextServerFallback::shaped_text_get_descent(RID p_shaped) const {
return sd->descent; return sd->descent;
} }
real_t TextServerFallback::shaped_text_get_width(RID p_shaped) const { float TextServerFallback::shaped_text_get_width(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3084,7 +3124,7 @@ real_t TextServerFallback::shaped_text_get_width(RID p_shaped) const {
return sd->width; return sd->width;
} }
real_t TextServerFallback::shaped_text_get_underline_position(RID p_shaped) const { float TextServerFallback::shaped_text_get_underline_position(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3096,7 +3136,7 @@ real_t TextServerFallback::shaped_text_get_underline_position(RID p_shaped) cons
return sd->upos; return sd->upos;
} }
real_t TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) const { float TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) const {
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0.f); ERR_FAIL_COND_V(!sd, 0.f);
@ -3108,15 +3148,6 @@ real_t TextServerFallback::shaped_text_get_underline_thickness(RID p_shaped) con
return sd->uthk; return sd->uthk;
} }
TextServer *TextServerFallback::create_func(Error &r_error, void *p_user_data) {
r_error = OK;
return memnew(TextServerFallback());
}
void TextServerFallback::register_server() {
TextServerManager::register_create_function(interface_name, interface_features, create_func, nullptr);
}
TextServerFallback::TextServerFallback(){}; TextServerFallback::TextServerFallback(){};
TextServerFallback::~TextServerFallback() { TextServerFallback::~TextServerFallback() {

View file

@ -93,12 +93,12 @@ class TextServerFallback : public TextServer {
}; };
struct FontDataForSizeFallback { struct FontDataForSizeFallback {
real_t ascent = 0.f; float ascent = 0.f;
real_t descent = 0.f; float descent = 0.f;
real_t underline_position = 0.f; float underline_position = 0.f;
real_t underline_thickness = 0.f; float underline_thickness = 0.f;
real_t scale = 1.f; float scale = 1.f;
real_t oversampling = 1.f; float oversampling = 1.f;
int spacing_glyph = 0; int spacing_glyph = 0;
int spacing_space = 0; int spacing_space = 0;
@ -134,7 +134,7 @@ class TextServerFallback : public TextServer {
bool force_autohinter = false; bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
Dictionary variation_coordinates; Dictionary variation_coordinates;
real_t oversampling = 0.f; float oversampling = 0.f;
Map<Vector2i, FontDataForSizeFallback *> cache; Map<Vector2i, FontDataForSizeFallback *> cache;
@ -194,7 +194,7 @@ class TextServerFallback : public TextServer {
// Common data. // Common data.
real_t oversampling = 1.f; float oversampling = 1.f;
mutable RID_PtrOwner<FontDataFallback> font_owner; mutable RID_PtrOwner<FontDataFallback> font_owner;
mutable RID_PtrOwner<ShapedTextData> shaped_owner; mutable RID_PtrOwner<ShapedTextData> shaped_owner;
@ -205,20 +205,19 @@ protected:
void invalidate(ShapedTextData *p_shaped); void invalidate(ShapedTextData *p_shaped);
public: public:
virtual bool has_feature(Feature p_feature) override; virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override; virtual String get_name() const override;
virtual uint32_t get_features() const override;
virtual void free(RID p_rid) override; virtual void free(RID p_rid) override;
virtual bool has(RID p_rid) override; virtual bool has(RID p_rid) override;
virtual bool load_support_data(const String &p_filename) override; virtual bool load_support_data(const String &p_filename) override;
#ifdef TOOLS_ENABLED virtual String get_support_data_filename() const override { return ""; };
virtual String get_support_data_filename() override { return ""; }; virtual String get_support_data_info() const override { return "Not supported"; };
virtual String get_support_data_info() override { return "Not supported"; }; virtual bool save_support_data(const String &p_filename) const override;
virtual bool save_support_data(const String &p_filename) override;
#endif
virtual bool is_locale_right_to_left(const String &p_locale) override; virtual bool is_locale_right_to_left(const String &p_locale) const override;
virtual int32_t name_to_tag(const String &p_name) const override; virtual int32_t name_to_tag(const String &p_name) const override;
virtual String tag_to_name(int32_t p_tag) const override; virtual String tag_to_name(int32_t p_tag) const override;
@ -253,27 +252,27 @@ public:
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
virtual void font_set_oversampling(RID p_font_rid, real_t p_oversampling) override; virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override;
virtual real_t font_get_oversampling(RID p_font_rid) const override; virtual float font_get_oversampling(RID p_font_rid) const override;
virtual Array font_get_size_cache_list(RID p_font_rid) const override; virtual Array font_get_size_cache_list(RID p_font_rid) const override;
virtual void font_clear_size_cache(RID p_font_rid) override; virtual void font_clear_size_cache(RID p_font_rid) override;
virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override; virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) override; virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override;
virtual real_t font_get_ascent(RID p_font_rid, int p_size) const override; virtual float font_get_ascent(RID p_font_rid, int p_size) const override;
virtual void font_set_descent(RID p_font_rid, int p_size, real_t p_descent) override; virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override;
virtual real_t font_get_descent(RID p_font_rid, int p_size) const override; virtual float font_get_descent(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) override; virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override;
virtual real_t font_get_underline_position(RID p_font_rid, int p_size) const override; virtual float font_get_underline_position(RID p_font_rid, int p_size) const override;
virtual void font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) override; virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override;
virtual real_t font_get_underline_thickness(RID p_font_rid, int p_size) const override; virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override;
virtual void font_set_scale(RID p_font_rid, int p_size, real_t p_scale) override; virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override;
virtual real_t font_get_scale(RID p_font_rid, int p_size) const override; virtual float font_get_scale(RID p_font_rid, int p_size) const override;
virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override; virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override; virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
@ -307,7 +306,7 @@ public:
virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override; virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override;
virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override; virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override; virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
@ -342,8 +341,8 @@ public:
virtual Dictionary font_supported_feature_list(RID p_font_rid) const override; virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const override; virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
virtual real_t font_get_global_oversampling() const override; virtual float font_get_global_oversampling() const override;
virtual void font_set_global_oversampling(real_t p_oversampling) override; virtual void font_set_global_oversampling(float p_oversampling) override;
/* Shaped text buffer interface */ /* Shaped text buffer interface */
@ -354,7 +353,7 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override; virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(RID p_shaped) const override; virtual Direction shaped_text_get_direction(RID p_shaped) const override;
virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) override; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
@ -372,36 +371,37 @@ public:
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override; virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override; virtual RID shaped_text_get_parent(RID p_shaped) const override;
virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) override; virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override;
virtual bool shaped_text_shape(RID p_shaped) override; virtual bool shaped_text_shape(RID p_shaped) override;
virtual bool shaped_text_update_breaks(RID p_shaped) override; virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override; virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, real_t p_width, uint8_t p_trim_flags) override; virtual int shaped_text_get_trim_pos(RID p_shaped) const override;
virtual TrimData shaped_text_get_trim_data(RID p_shaped) const override; virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override;
virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override;
virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override;
virtual bool shaped_text_is_ready(RID p_shaped) const override; virtual bool shaped_text_is_ready(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override; virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override;
virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override;
virtual int shaped_text_get_glyph_count(RID p_shaped) const override;
virtual Vector2i shaped_text_get_range(RID p_shaped) const override; virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) override;
virtual Array shaped_text_get_objects(RID p_shaped) const override; virtual Array shaped_text_get_objects(RID p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override; virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
virtual Size2 shaped_text_get_size(RID p_shaped) const override; virtual Size2 shaped_text_get_size(RID p_shaped) const override;
virtual real_t shaped_text_get_ascent(RID p_shaped) const override; virtual float shaped_text_get_ascent(RID p_shaped) const override;
virtual real_t shaped_text_get_descent(RID p_shaped) const override; virtual float shaped_text_get_descent(RID p_shaped) const override;
virtual real_t shaped_text_get_width(RID p_shaped) const override; virtual float shaped_text_get_width(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_position(RID p_shaped) const override; virtual float shaped_text_get_underline_position(RID p_shaped) const override;
virtual real_t shaped_text_get_underline_thickness(RID p_shaped) const override; virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
static TextServer *create_func(Error &r_error, void *p_user_data);
static void register_server();
TextServerFallback(); TextServerFallback();
~TextServerFallback(); ~TextServerFallback();

View file

@ -314,17 +314,27 @@ String OS_OSX::get_name() const {
return "macOS"; return "macOS";
} }
_FORCE_INLINE_ String _get_framework_executable(const String p_path) {
// Append framework executable name, or return as is if p_path is not a framework.
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->dir_exists(p_path) && da->file_exists(p_path.plus_file(p_path.get_file().get_basename()))) {
return p_path.plus_file(p_path.get_file().get_basename());
} else {
return p_path;
}
}
Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
String path = p_path; String path = _get_framework_executable(p_path);
if (!FileAccess::exists(path)) { if (!FileAccess::exists(path)) {
//this code exists so gdnative can load .dylib files from within the executable path // This code exists so gdnative can load .dylib files from within the executable path.
path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); path = _get_framework_executable(get_executable_path().get_base_dir().plus_file(p_path.get_file()));
} }
if (!FileAccess::exists(path)) { if (!FileAccess::exists(path)) {
//this code exists so gdnative can load .dylib files from a standard macOS location // This code exists so gdnative can load .dylib files from a standard macOS location.
path = get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file()); path = _get_framework_executable(get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file()));
} }
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);

View file

@ -2449,8 +2449,8 @@ bool Control::is_text_field() const {
return false; return false;
} }
Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const { Array Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const {
Vector<Vector2i> ret; Array ret;
switch (p_theme_type) { switch (p_theme_type) {
case STRUCTURED_TEXT_URI: { case STRUCTURED_TEXT_URI: {
int prev = 0; int prev = 0;

View file

@ -283,7 +283,7 @@ protected:
//virtual void _window_gui_input(InputEvent p_event); //virtual void _window_gui_input(InputEvent p_event);
virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const; virtual Array structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const;
bool _set(const StringName &p_name, const Variant &p_value); bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const; bool _get(const StringName &p_name, Variant &r_ret) const;

View file

@ -108,7 +108,7 @@ void Label::_shape() {
} }
lines_rid.clear(); lines_rid.clear();
uint8_t autowrap_flags = TextServer::BREAK_MANDATORY; uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) { switch (autowrap_mode) {
case AUTOWRAP_WORD_SMART: case AUTOWRAP_WORD_SMART:
autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
@ -122,10 +122,10 @@ void Label::_shape() {
case AUTOWRAP_OFF: case AUTOWRAP_OFF:
break; break;
} }
Vector<Vector2i> line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
for (int i = 0; i < line_breaks.size(); i++) { for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(text_rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x); RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
lines_rid.push_back(line); lines_rid.push_back(line);
} }
} }
@ -145,7 +145,7 @@ void Label::_shape() {
} }
if (lines_dirty) { if (lines_dirty) {
uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING; uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
switch (overrun_behavior) { switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS: case OVERRUN_TRIM_WORD_ELLIPSIS:
overrun_flags |= TextServer::OVERRUN_TRIM; overrun_flags |= TextServer::OVERRUN_TRIM;
@ -231,7 +231,7 @@ void Label::_update_visible() {
} }
} }
inline void draw_glyph(const TextServer::Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) { inline void draw_glyph(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) {
if (p_gl.font_rid != RID()) { if (p_gl.font_rid != RID()) {
TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color); TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off), p_gl.index, p_font_color);
} else { } else {
@ -239,7 +239,7 @@ inline void draw_glyph(const TextServer::Glyph &p_gl, const RID &p_canvas, const
} }
} }
inline void draw_glyph_outline(const TextServer::Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Color &p_font_shadow_color, const Color &p_font_outline_color, const int &p_shadow_outline_size, const int &p_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) { inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Color &p_font_shadow_color, const Color &p_font_outline_color, const int &p_shadow_outline_size, const int &p_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
if (p_gl.font_rid != RID()) { if (p_gl.font_rid != RID()) {
if (p_font_shadow_color.a > 0) { if (p_font_shadow_color.a > 0) {
TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color); TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
@ -387,21 +387,25 @@ void Label::_notification(int p_what) {
} break; } break;
} }
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(lines_rid[i]); const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
const TextServer::Glyph *glyphs = visual.ptr(); int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
int gl_size = visual.size();
TextServer::TrimData trim_data = TS->shaped_text_get_trim_data(lines_rid[i]); int ellipsis_pos = TS->shaped_text_get_ellipsis_pos(lines_rid[i]);
int trim_pos = TS->shaped_text_get_trim_pos(lines_rid[i]);
const Glyph *ellipsis_glyphs = TS->shaped_text_get_ellipsis_glyphs(lines_rid[i]);
int ellipsis_gl_size = TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]);
// Draw outline. Note: Do not merge this into the single loop with the main text, to prevent overlaps. // Draw outline. Note: Do not merge this into the single loop with the main text, to prevent overlaps.
if (font_shadow_color.a > 0 || (font_outline_color.a != 0.0 && outline_size > 0)) { if (font_shadow_color.a > 0 || (font_outline_color.a != 0.0 && outline_size > 0)) {
Vector2 offset = ofs; Vector2 offset = ofs;
// Draw RTL ellipsis string when necessary. // Draw RTL ellipsis string when necessary.
if (rtl && trim_data.ellipsis_pos >= 0) { if (rtl && ellipsis_pos >= 0) {
for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) { for (int gl_idx = ellipsis_gl_size - 1; gl_idx >= 0; gl_idx--) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) { for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow. //Draw glyph outlines and shadow.
draw_glyph_outline(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs); draw_glyph_outline(ellipsis_glyphs[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance; offset.x += ellipsis_glyphs[gl_idx].advance;
} }
} }
} }
@ -410,13 +414,13 @@ void Label::_notification(int p_what) {
for (int j = 0; j < gl_size; j++) { for (int j = 0; j < gl_size; j++) {
for (int k = 0; k < glyphs[j].repeat; k++) { for (int k = 0; k < glyphs[j].repeat; k++) {
// Trim when necessary. // Trim when necessary.
if (trim_data.trim_pos >= 0) { if (trim_pos >= 0) {
if (rtl) { if (rtl) {
if (j < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { if (j < trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
continue; continue;
} }
} else { } else {
if (j >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { if (j >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break; break;
} }
} }
@ -428,12 +432,12 @@ void Label::_notification(int p_what) {
} }
} }
// Draw LTR ellipsis string when necessary. // Draw LTR ellipsis string when necessary.
if (!rtl && trim_data.ellipsis_pos >= 0) { if (!rtl && ellipsis_pos >= 0) {
for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) { for (int gl_idx = 0; gl_idx < ellipsis_gl_size; gl_idx++) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) { for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow. //Draw glyph outlines and shadow.
draw_glyph_outline(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs); draw_glyph_outline(ellipsis_glyphs[gl_idx], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance; offset.x += ellipsis_glyphs[gl_idx].advance;
} }
} }
} }
@ -442,12 +446,12 @@ void Label::_notification(int p_what) {
// Draw main text. Note: Do not merge this into the single loop with the outline, to prevent overlaps. // Draw main text. Note: Do not merge this into the single loop with the outline, to prevent overlaps.
// Draw RTL ellipsis string when necessary. // Draw RTL ellipsis string when necessary.
if (rtl && trim_data.ellipsis_pos >= 0) { if (rtl && ellipsis_pos >= 0) {
for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) { for (int gl_idx = ellipsis_gl_size - 1; gl_idx >= 0; gl_idx--) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) { for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow. //Draw glyph outlines and shadow.
draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs); draw_glyph(ellipsis_glyphs[gl_idx], ci, font_color, ofs);
ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance; ofs.x += ellipsis_glyphs[gl_idx].advance;
} }
} }
} }
@ -456,13 +460,13 @@ void Label::_notification(int p_what) {
for (int j = 0; j < gl_size; j++) { for (int j = 0; j < gl_size; j++) {
for (int k = 0; k < glyphs[j].repeat; k++) { for (int k = 0; k < glyphs[j].repeat; k++) {
// Trim when necessary. // Trim when necessary.
if (trim_data.trim_pos >= 0) { if (trim_pos >= 0) {
if (rtl) { if (rtl) {
if (j < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { if (j < trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
continue; continue;
} }
} else { } else {
if (j >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { if (j >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break; break;
} }
} }
@ -474,12 +478,12 @@ void Label::_notification(int p_what) {
} }
} }
// Draw LTR ellipsis string when necessary. // Draw LTR ellipsis string when necessary.
if (!rtl && trim_data.ellipsis_pos >= 0) { if (!rtl && ellipsis_pos >= 0) {
for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) { for (int gl_idx = 0; gl_idx < ellipsis_gl_size; gl_idx++) {
for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) { for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow. //Draw glyph outlines and shadow.
draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs); draw_glyph(ellipsis_glyphs[gl_idx], ci, font_color, ofs);
ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance; ofs.x += ellipsis_glyphs[gl_idx].advance;
} }
} }
} }

View file

@ -67,10 +67,10 @@ void LineEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
if (p_move_by_word) { if (p_move_by_word) {
int cc = caret_column; int cc = caret_column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid); PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = words.size() - 1; i >= 0; i--) { for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i].x < cc) { if (words[i] < cc) {
cc = words[i].x; cc = words[i];
break; break;
} }
} }
@ -99,10 +99,10 @@ void LineEdit::_move_caret_right(bool p_select, bool p_move_by_word) {
if (p_move_by_word) { if (p_move_by_word) {
int cc = caret_column; int cc = caret_column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid); PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = 0; i < words.size(); i++) { for (int i = 1; i < words.size(); i = i + 2) {
if (words[i].y > cc) { if (words[i] > cc) {
cc = words[i].y; cc = words[i];
break; break;
} }
} }
@ -151,10 +151,10 @@ void LineEdit::_backspace(bool p_word, bool p_all_to_left) {
if (p_word) { if (p_word) {
int cc = caret_column; int cc = caret_column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid); PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = words.size() - 1; i >= 0; i--) { for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i].x < cc) { if (words[i] < cc) {
cc = words[i].x; cc = words[i];
break; break;
} }
} }
@ -194,10 +194,10 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) {
if (p_word) { if (p_word) {
int cc = caret_column; int cc = caret_column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid); PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = 0; i < words.size(); i++) { for (int i = 1; i < words.size(); i = i + 2) {
if (words[i].y > cc) { if (words[i] > cc) {
cc = words[i].y; cc = words[i];
break; break;
} }
} }
@ -276,12 +276,12 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
// Double-click select word. // Double-click select word.
last_dblclk = OS::get_singleton()->get_ticks_msec(); last_dblclk = OS::get_singleton()->get_ticks_msec();
last_dblclk_pos = b->get_position(); last_dblclk_pos = b->get_position();
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid); PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
for (int i = 0; i < words.size(); i++) { for (int i = 0; i < words.size(); i = i + 2) {
if ((words[i].x < caret_column && words[i].y > caret_column) || (i == words.size() - 1 && caret_column == words[i].y)) { if ((words[i] < caret_column && words[i + 1] > caret_column) || (i == words.size() - 2 && caret_column == words[i + 1])) {
selection.enabled = true; selection.enabled = true;
selection.begin = words[i].x; selection.begin = words[i];
selection.end = words[i].y; selection.end = words[i + 1];
selection.double_click = true; selection.double_click = true;
caret_column = selection.end; caret_column = selection.end;
break; break;
@ -737,9 +737,8 @@ void LineEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, rect, selection_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, rect, selection_color);
} }
} }
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(text_rid); const Glyph *glyphs = TS->shaped_text_get_glyphs(text_rid);
const TextServer::Glyph *glyphs = visual.ptr(); int gl_size = TS->shaped_text_get_glyph_count(text_rid);
int gl_size = visual.size();
// Draw text. // Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid); ofs.y += TS->shaped_text_get_ascent(text_rid);
@ -783,38 +782,36 @@ void LineEdit::_notification(int p_what) {
if (draw_caret) { if (draw_caret) {
if (ime_text.length() == 0) { if (ime_text.length() == 0) {
// Normal caret. // Normal caret.
Rect2 l_caret, t_caret; CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column);
TextServer::Direction l_dir, t_dir;
TS->shaped_text_get_carets(text_rid, caret_column, l_caret, l_dir, t_caret, t_dir);
if (l_caret == Rect2() && t_caret == Rect2()) { if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
// No carets, add one at the start. // No carets, add one at the start.
int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size"))); int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
int y = style->get_offset().y + (y_area - h) / 2; int y = style->get_offset().y + (y_area - h) / 2;
if (rtl) { if (rtl) {
l_dir = TextServer::DIRECTION_RTL; caret.l_dir = TextServer::DIRECTION_RTL;
l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h)); caret.l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
} else { } else {
l_dir = TextServer::DIRECTION_LTR; caret.l_dir = TextServer::DIRECTION_LTR;
l_caret = Rect2(Vector2(x_ofs, y), Size2(caret_width, h)); caret.l_caret = Rect2(Vector2(x_ofs, y), Size2(caret_width, h));
} }
RenderingServer::get_singleton()->canvas_item_add_rect(ci, l_caret, caret_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.l_caret, caret_color);
} else { } else {
if (l_caret != Rect2() && l_dir == TextServer::DIRECTION_AUTO) { if (caret.l_caret != Rect2() && caret.l_dir == TextServer::DIRECTION_AUTO) {
// Draw extra marker on top of mid caret. // Draw extra marker on top of mid caret.
Rect2 trect = Rect2(l_caret.position.x - 3 * caret_width, l_caret.position.y, 6 * caret_width, caret_width); Rect2 trect = Rect2(caret.l_caret.position.x - 3 * caret_width, caret.l_caret.position.y, 6 * caret_width, caret_width);
trect.position += ofs; trect.position += ofs;
RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color);
} }
l_caret.position += ofs; caret.l_caret.position += ofs;
l_caret.size.x = caret_width; caret.l_caret.size.x = caret_width;
RenderingServer::get_singleton()->canvas_item_add_rect(ci, l_caret, caret_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.l_caret, caret_color);
t_caret.position += ofs; caret.t_caret.position += ofs;
t_caret.size.x = caret_width; caret.t_caret.size.x = caret_width;
RenderingServer::get_singleton()->canvas_item_add_rect(ci, t_caret, caret_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.t_caret, caret_color);
} }
} else { } else {
{ {
@ -1114,32 +1111,31 @@ Vector2i LineEdit::get_caret_pixel_pos() {
} }
Vector2i ret; Vector2i ret;
Rect2 l_caret, t_caret; CaretInfo caret;
TextServer::Direction l_dir, t_dir;
// Get position of the start of caret. // Get position of the start of caret.
if (ime_text.length() != 0 && ime_selection.x != 0) { if (ime_text.length() != 0 && ime_selection.x != 0) {
TS->shaped_text_get_carets(text_rid, caret_column + ime_selection.x, l_caret, l_dir, t_caret, t_dir); caret = TS->shaped_text_get_carets(text_rid, caret_column + ime_selection.x);
} else { } else {
TS->shaped_text_get_carets(text_rid, caret_column, l_caret, l_dir, t_caret, t_dir); caret = TS->shaped_text_get_carets(text_rid, caret_column);
} }
if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) { if ((caret.l_caret != Rect2() && (caret.l_dir == TextServer::DIRECTION_AUTO || caret.l_dir == (TextServer::Direction)input_direction)) || (caret.t_caret == Rect2())) {
ret.x = x_ofs + l_caret.position.x + scroll_offset; ret.x = x_ofs + caret.l_caret.position.x + scroll_offset;
} else { } else {
ret.x = x_ofs + t_caret.position.x + scroll_offset; ret.x = x_ofs + caret.t_caret.position.x + scroll_offset;
} }
// Get position of the end of caret. // Get position of the end of caret.
if (ime_text.length() != 0) { if (ime_text.length() != 0) {
if (ime_selection.y != 0) { if (ime_selection.y != 0) {
TS->shaped_text_get_carets(text_rid, caret_column + ime_selection.x + ime_selection.y, l_caret, l_dir, t_caret, t_dir); caret = TS->shaped_text_get_carets(text_rid, caret_column + ime_selection.x + ime_selection.y);
} else { } else {
TS->shaped_text_get_carets(text_rid, caret_column + ime_text.size(), l_caret, l_dir, t_caret, t_dir); caret = TS->shaped_text_get_carets(text_rid, caret_column + ime_text.size());
} }
if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) { if ((caret.l_caret != Rect2() && (caret.l_dir == TextServer::DIRECTION_AUTO || caret.l_dir == (TextServer::Direction)input_direction)) || (caret.t_caret == Rect2())) {
ret.y = x_ofs + l_caret.position.x + scroll_offset; ret.y = x_ofs + caret.l_caret.position.x + scroll_offset;
} else { } else {
ret.y = x_ofs + t_caret.position.x + scroll_offset; ret.y = x_ofs + caret.t_caret.position.x + scroll_offset;
} }
} else { } else {
ret.y = ret.x; ret.y = ret.x;
@ -1502,7 +1498,7 @@ void LineEdit::insert_text_at_caret(String p_text) {
String post = text.substr(caret_column, text.length() - caret_column); String post = text.substr(caret_column, text.length() - caret_column);
text = pre + p_text + post; text = pre + p_text + post;
_shape(); _shape();
TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text_rid, caret_column, caret_column + p_text.length()); TextServer::Direction dir = TS->shaped_text_get_dominant_direction_in_range(text_rid, caret_column, caret_column + p_text.length());
if (dir != TextServer::DIRECTION_AUTO) { if (dir != TextServer::DIRECTION_AUTO) {
input_direction = (TextDirection)dir; input_direction = (TextDirection)dir;
} }

View file

@ -819,9 +819,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} }
} }
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(rid); const Glyph *glyphs = TS->shaped_text_get_glyphs(rid);
const TextServer::Glyph *glyphs = visual.ptr(); int gl_size = TS->shaped_text_get_glyph_count(rid);
int gl_size = visual.size();
Vector2 gloff = off; Vector2 gloff = off;
// Draw oulines and shadow. // Draw oulines and shadow.
@ -1593,18 +1592,18 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (c_frame) { if (c_frame) {
const Line &l = c_frame->lines[c_line]; const Line &l = c_frame->lines[c_line];
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(l.text_buf->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(l.text_buf->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 0; i < words.size(); i = i + 2) {
if (c_index >= words[i].x && c_index < words[i].y) { if (c_index >= words[i] && c_index < words[i + 1]) {
selection.from_frame = c_frame; selection.from_frame = c_frame;
selection.from_line = c_line; selection.from_line = c_line;
selection.from_item = c_item; selection.from_item = c_item;
selection.from_char = words[i].x; selection.from_char = words[i];
selection.to_frame = c_frame; selection.to_frame = c_frame;
selection.to_line = c_line; selection.to_line = c_line;
selection.to_item = c_item; selection.to_item = c_item;
selection.to_char = words[i].y; selection.to_char = words[i + 1];
selection.active = true; selection.active = true;
update(); update();

View file

@ -186,7 +186,7 @@ void TextEdit::Text::_calculate_max_line_width() {
max_width = width; max_width = width;
} }
void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_ime_text, const Vector<Vector2i> &p_bidi_override) { void TextEdit::Text::invalidate_cache(int p_line, int p_column, const String &p_ime_text, const Array &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size()); ERR_FAIL_INDEX(p_line, text.size());
if (font.is_null() || font_size <= 0) { if (font.is_null() || font_size <= 0) {
@ -278,14 +278,14 @@ void TextEdit::Text::invalidate_all() {
void TextEdit::Text::clear() { void TextEdit::Text::clear() {
text.clear(); text.clear();
insert(0, "", Vector<Vector2i>()); insert(0, "", Array());
} }
int TextEdit::Text::get_max_width() const { int TextEdit::Text::get_max_width() const {
return max_width; return max_width;
} }
void TextEdit::Text::set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override) { void TextEdit::Text::set(int p_line, const String &p_text, const Array &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size()); ERR_FAIL_INDEX(p_line, text.size());
text.write[p_line].data = p_text; text.write[p_line].data = p_text;
@ -293,7 +293,7 @@ void TextEdit::Text::set(int p_line, const String &p_text, const Vector<Vector2i
invalidate_cache(p_line); invalidate_cache(p_line);
} }
void TextEdit::Text::insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override) { void TextEdit::Text::insert(int p_at, const String &p_text, const Array &p_bidi_override) {
Line line; Line line;
line.gutters.resize(gutter_count); line.gutters.resize(gutter_count);
line.hidden = false; line.hidden = false;
@ -1076,9 +1076,8 @@ void TextEdit::_notification(int p_what) {
ofs_y += (row_height - text_height) / 2; ofs_y += (row_height - text_height) / 2;
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(rid); const Glyph *glyphs = TS->shaped_text_get_glyphs(rid);
const TextServer::Glyph *glyphs = visual.ptr(); int gl_size = TS->shaped_text_get_glyph_count(rid);
int gl_size = visual.size();
ofs_y += ldata->get_line_ascent(line_wrap_index); ofs_y += ldata->get_line_ascent(line_wrap_index);
int char_ofs = 0; int char_ofs = 0;
@ -1185,27 +1184,26 @@ void TextEdit::_notification(int p_what) {
caret.draw_pos.y = ofs_y + ldata->get_line_descent(line_wrap_index); caret.draw_pos.y = ofs_y + ldata->get_line_descent(line_wrap_index);
if (ime_text.length() == 0) { if (ime_text.length() == 0) {
Rect2 l_caret, t_caret; CaretInfo ts_caret;
TextServer::Direction l_dir, t_dir;
if (str.length() != 0) { if (str.length() != 0) {
// Get carets. // Get carets.
TS->shaped_text_get_carets(rid, caret.column, l_caret, l_dir, t_caret, t_dir); ts_caret = TS->shaped_text_get_carets(rid, caret.column);
} else { } else {
// No carets, add one at the start. // No carets, add one at the start.
int h = font->get_height(font_size); int h = font->get_height(font_size);
if (rtl) { if (rtl) {
l_dir = TextServer::DIRECTION_RTL; ts_caret.l_dir = TextServer::DIRECTION_RTL;
l_caret = Rect2(Vector2(xmargin_end - char_margin + ofs_x, -h / 2), Size2(caret_width * 4, h)); ts_caret.l_caret = Rect2(Vector2(xmargin_end - char_margin + ofs_x, -h / 2), Size2(caret_width * 4, h));
} else { } else {
l_dir = TextServer::DIRECTION_LTR; ts_caret.l_dir = TextServer::DIRECTION_LTR;
l_caret = Rect2(Vector2(char_ofs, -h / 2), Size2(caret_width * 4, h)); ts_caret.l_caret = Rect2(Vector2(char_ofs, -h / 2), Size2(caret_width * 4, h));
} }
} }
if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) { if ((ts_caret.l_caret != Rect2() && (ts_caret.l_dir == TextServer::DIRECTION_AUTO || ts_caret.l_dir == (TextServer::Direction)input_direction)) || (ts_caret.t_caret == Rect2())) {
caret.draw_pos.x = char_margin + ofs_x + l_caret.position.x; caret.draw_pos.x = char_margin + ofs_x + ts_caret.l_caret.position.x;
} else { } else {
caret.draw_pos.x = char_margin + ofs_x + t_caret.position.x; caret.draw_pos.x = char_margin + ofs_x + ts_caret.t_caret.position.x;
} }
if (caret.draw_pos.x >= xmargin_beg && caret.draw_pos.x < xmargin_end) { if (caret.draw_pos.x >= xmargin_beg && caret.draw_pos.x < xmargin_end) {
@ -1215,64 +1213,64 @@ void TextEdit::_notification(int p_what) {
//Block or underline caret, draw trailing carets at full height. //Block or underline caret, draw trailing carets at full height.
int h = font->get_height(font_size); int h = font->get_height(font_size);
if (t_caret != Rect2()) { if (ts_caret.t_caret != Rect2()) {
if (overtype_mode) { if (overtype_mode) {
t_caret.position.y = TS->shaped_text_get_descent(rid); ts_caret.t_caret.position.y = TS->shaped_text_get_descent(rid);
t_caret.size.y = caret_width; ts_caret.t_caret.size.y = caret_width;
} else { } else {
t_caret.position.y = -TS->shaped_text_get_ascent(rid); ts_caret.t_caret.position.y = -TS->shaped_text_get_ascent(rid);
t_caret.size.y = h; ts_caret.t_caret.size.y = h;
} }
t_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
draw_rect(t_caret, caret_color, overtype_mode); draw_rect(ts_caret.t_caret, caret_color, overtype_mode);
if (l_caret != Rect2() && l_dir != t_dir) { if (ts_caret.l_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) {
l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
l_caret.size.x = caret_width; ts_caret.l_caret.size.x = caret_width;
draw_rect(l_caret, caret_color * Color(1, 1, 1, 0.5)); draw_rect(ts_caret.l_caret, caret_color * Color(1, 1, 1, 0.5));
} }
} else { // End of the line. } else { // End of the line.
if (gl_size > 0) { if (gl_size > 0) {
// Adjust for actual line dimensions. // Adjust for actual line dimensions.
if (overtype_mode) { if (overtype_mode) {
l_caret.position.y = TS->shaped_text_get_descent(rid); ts_caret.l_caret.position.y = TS->shaped_text_get_descent(rid);
l_caret.size.y = caret_width; ts_caret.l_caret.size.y = caret_width;
} else { } else {
l_caret.position.y = -TS->shaped_text_get_ascent(rid); ts_caret.l_caret.position.y = -TS->shaped_text_get_ascent(rid);
l_caret.size.y = h; ts_caret.l_caret.size.y = h;
} }
} else if (overtype_mode) { } else if (overtype_mode) {
l_caret.position.y += l_caret.size.y; ts_caret.l_caret.position.y += ts_caret.l_caret.size.y;
l_caret.size.y = caret_width; ts_caret.l_caret.size.y = caret_width;
} }
if (l_caret.position.x >= TS->shaped_text_get_size(rid).x) { if (ts_caret.l_caret.position.x >= TS->shaped_text_get_size(rid).x) {
l_caret.size.x = font->get_char_size('m', 0, font_size).x; ts_caret.l_caret.size.x = font->get_char_size('m', 0, font_size).x;
} else { } else {
l_caret.size.x = 3 * caret_width; ts_caret.l_caret.size.x = 3 * caret_width;
} }
l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
if (l_dir == TextServer::DIRECTION_RTL) { if (ts_caret.l_dir == TextServer::DIRECTION_RTL) {
l_caret.position.x -= l_caret.size.x; ts_caret.l_caret.position.x -= ts_caret.l_caret.size.x;
} }
draw_rect(l_caret, caret_color, overtype_mode); draw_rect(ts_caret.l_caret, caret_color, overtype_mode);
} }
} else { } else {
// Normal caret. // Normal caret.
if (l_caret != Rect2() && l_dir == TextServer::DIRECTION_AUTO) { if (ts_caret.l_caret != Rect2() && ts_caret.l_dir == TextServer::DIRECTION_AUTO) {
// Draw extra marker on top of mid caret. // Draw extra marker on top of mid caret.
Rect2 trect = Rect2(l_caret.position.x - 3 * caret_width, l_caret.position.y, 6 * caret_width, caret_width); Rect2 trect = Rect2(ts_caret.l_caret.position.x - 3 * caret_width, ts_caret.l_caret.position.y, 6 * caret_width, caret_width);
trect.position += Vector2(char_margin + ofs_x, ofs_y); trect.position += Vector2(char_margin + ofs_x, ofs_y);
RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color);
} }
l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
l_caret.size.x = caret_width; ts_caret.l_caret.size.x = caret_width;
draw_rect(l_caret, caret_color); draw_rect(ts_caret.l_caret, caret_color);
t_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
t_caret.size.x = caret_width; ts_caret.t_caret.size.x = caret_width;
draw_rect(t_caret, caret_color); draw_rect(ts_caret.t_caret, caret_color);
} }
} }
} }
@ -1968,10 +1966,10 @@ void TextEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
set_caret_line(caret.line - 1); set_caret_line(caret.line - 1);
set_caret_column(text[caret.line].length()); set_caret_column(text[caret.line].length());
} else { } else {
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = words.size() - 1; i >= 0; i--) { for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i].x < cc) { if (words[i] < cc) {
cc = words[i].x; cc = words[i];
break; break;
} }
} }
@ -2019,10 +2017,10 @@ void TextEdit::_move_caret_right(bool p_select, bool p_move_by_word) {
set_caret_line(caret.line + 1); set_caret_line(caret.line + 1);
set_caret_column(0); set_caret_column(0);
} else { } else {
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 1; i < words.size(); i = i + 2) {
if (words[i].y > cc) { if (words[i] > cc) {
cc = words[i].y; cc = words[i];
break; break;
} }
} }
@ -2214,10 +2212,10 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
int line = caret.line; int line = caret.line;
int column = caret.column; int column = caret.column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
for (int i = words.size() - 1; i >= 0; i--) { for (int i = words.size() - 2; i >= 0; i = i - 2) {
if (words[i].x < column) { if (words[i] < column) {
column = words[i].x; column = words[i];
break; break;
} }
} }
@ -2257,10 +2255,10 @@ void TextEdit::_delete(bool p_word, bool p_all_to_right) {
int line = caret.line; int line = caret.line;
int column = caret.column; int column = caret.column;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 1; i < words.size(); i = i + 2) {
if (words[i].y > column) { if (words[i] > column) {
column = words[i].y; column = words[i];
break; break;
} }
} }
@ -3631,10 +3629,10 @@ int TextEdit::get_caret_wrap_index() const {
} }
String TextEdit::get_word_under_caret() const { String TextEdit::get_word_under_caret() const {
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 0; i < words.size(); i = i + 2) {
if (words[i].x <= caret.column && words[i].y > caret.column) { if (words[i] <= caret.column && words[i + 1] > caret.column) {
return text[caret.line].substr(words[i].x, words[i].y - words[i].x); return text[caret.line].substr(words[i], words[i + 1] - words[i]);
} }
} }
return ""; return "";
@ -3718,11 +3716,11 @@ void TextEdit::select_word_under_caret() {
int begin = 0; int begin = 0;
int end = 0; int end = 0;
const Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid()); const PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 0; i < words.size(); i = i + 2) {
if ((words[i].x < caret.column && words[i].y > caret.column) || (i == words.size() - 1 && caret.column == words[i].y)) { if ((words[i] < caret.column && words[i + 1] > caret.column) || (i == words.size() - 2 && caret.column == words[i + 1])) {
begin = words[i].x; begin = words[i];
end = words[i].y; end = words[i + 1];
break; break;
} }
} }
@ -5376,14 +5374,12 @@ int TextEdit::_get_column_x_offset_for_line(int p_char, int p_line) const {
} }
} }
Rect2 l_caret, t_caret;
TextServer::Direction l_dir, t_dir;
RID text_rid = text.get_line_data(p_line)->get_line_rid(row); RID text_rid = text.get_line_data(p_line)->get_line_rid(row);
TS->shaped_text_get_carets(text_rid, caret.column, l_caret, l_dir, t_caret, t_dir); CaretInfo ts_caret = TS->shaped_text_get_carets(text_rid, caret.column);
if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) { if ((ts_caret.l_caret != Rect2() && (ts_caret.l_dir == TextServer::DIRECTION_AUTO || ts_caret.l_dir == (TextServer::Direction)input_direction)) || (ts_caret.t_caret == Rect2())) {
return l_caret.position.x; return ts_caret.l_caret.position.x;
} else { } else {
return t_caret.position.x; return ts_caret.t_caret.position.x;
} }
} }
@ -5440,11 +5436,11 @@ void TextEdit::_update_selection_mode_word() {
int caret_pos = CLAMP(col, 0, text[line].length()); int caret_pos = CLAMP(col, 0, text[line].length());
int beg = caret_pos; int beg = caret_pos;
int end = beg; int end = beg;
Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid()); PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
for (int i = 0; i < words.size(); i++) { for (int i = 0; i < words.size(); i = i + 2) {
if ((words[i].x < caret_pos && words[i].y > caret_pos) || (i == words.size() - 1 && caret_pos == words[i].y)) { if ((words[i] < caret_pos && words[i + 1] > caret_pos) || (i == words.size() - 2 && caret_pos == words[i + 1])) {
beg = words[i].x; beg = words[i];
end = words[i].y; end = words[i + 1];
break; break;
} }
} }
@ -6032,7 +6028,7 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
r_end_line = p_line + substrings.size() - 1; r_end_line = p_line + substrings.size() - 1;
r_end_column = text[r_end_line].length() - postinsert_text.length(); r_end_column = text[r_end_line].length() - postinsert_text.length();
TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text.get_line_data(r_end_line)->get_rid(), (r_end_line == p_line) ? caret.column : 0, r_end_column); TextServer::Direction dir = TS->shaped_text_get_dominant_direction_in_range(text.get_line_data(r_end_line)->get_rid(), (r_end_line == p_line) ? caret.column : 0, r_end_column);
if (dir != TextServer::DIRECTION_AUTO) { if (dir != TextServer::DIRECTION_AUTO) {
input_direction = (TextDirection)dir; input_direction = (TextDirection)dir;
} }

View file

@ -139,7 +139,7 @@ private:
Vector<Gutter> gutters; Vector<Gutter> gutters;
String data; String data;
Vector<Vector2i> bidi_override; Array bidi_override;
Ref<TextParagraph> data_buf; Ref<TextParagraph> data_buf;
Color background_color = Color(0, 0, 0, 0); Color background_color = Color(0, 0, 0, 0);
@ -194,7 +194,7 @@ private:
Vector<Vector2i> get_line_wrap_ranges(int p_line) const; Vector<Vector2i> get_line_wrap_ranges(int p_line) const;
const Ref<TextParagraph> get_line_data(int p_line) const; const Ref<TextParagraph> get_line_data(int p_line) const;
void set(int p_line, const String &p_text, const Vector<Vector2i> &p_bidi_override); void set(int p_line, const String &p_text, const Array &p_bidi_override);
void set_hidden(int p_line, bool p_hidden) { void set_hidden(int p_line, bool p_hidden) {
text.write[p_line].hidden = p_hidden; text.write[p_line].hidden = p_hidden;
if (!p_hidden && text[p_line].width > max_width) { if (!p_hidden && text[p_line].width > max_width) {
@ -204,12 +204,12 @@ private:
} }
} }
bool is_hidden(int p_line) const { return text[p_line].hidden; } bool is_hidden(int p_line) const { return text[p_line].hidden; }
void insert(int p_at, const String &p_text, const Vector<Vector2i> &p_bidi_override); void insert(int p_at, const String &p_text, const Array &p_bidi_override);
void remove(int p_at); void remove(int p_at);
int size() const { return text.size(); } int size() const { return text.size(); }
void clear(); void clear();
void invalidate_cache(int p_line, int p_column = -1, const String &p_ime_text = String(), const Vector<Vector2i> &p_bidi_override = Vector<Vector2i>()); void invalidate_cache(int p_line, int p_column = -1, const String &p_ime_text = String(), const Array &p_bidi_override = Array());
void invalidate_all(); void invalidate_all();
void invalidate_all_lines(); void invalidate_all_lines();

View file

@ -647,13 +647,13 @@ 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); 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, HAlign p_align, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, 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 {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null()); ERR_FAIL_COND(p_font.is_null());
p_font->draw_string(canvas_item, p_pos, p_text, p_align, 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_align, p_width, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
} }
void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align, 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 {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null()); ERR_FAIL_COND(p_font.is_null());
p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_align, 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_align, p_width, p_max_lines, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);

View file

@ -235,8 +235,8 @@ 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_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_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, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, 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, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | 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, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, 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 = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) 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 = -1, 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_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(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));

View file

@ -1404,7 +1404,7 @@ real_t Font::get_underline_thickness(int p_size) const {
return ret; return ret;
} }
Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, real_t p_width, uint8_t p_flags) const { Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, real_t p_width, uint16_t p_flags) const {
ERR_FAIL_COND_V(data.is_empty(), Size2()); ERR_FAIL_COND_V(data.is_empty(), Size2());
int size = (p_size <= 0) ? base_size : p_size; int size = (p_size <= 0) ? base_size : p_size;
@ -1431,7 +1431,7 @@ Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, re
return buffer->get_size(); return buffer->get_size();
} }
Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int p_size, uint8_t p_flags) const { Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int p_size, uint16_t p_flags) const {
ERR_FAIL_COND_V(data.is_empty(), Size2()); ERR_FAIL_COND_V(data.is_empty(), Size2());
int size = (p_size <= 0) ? base_size : p_size; int size = (p_size <= 0) ? base_size : p_size;
@ -1470,7 +1470,7 @@ Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int
return ret; return ret;
} }
void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, 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 {
ERR_FAIL_COND(data.is_empty()); ERR_FAIL_COND(data.is_empty());
int size = (p_size <= 0) ? base_size : p_size; int size = (p_size <= 0) ? base_size : p_size;
@ -1512,7 +1512,7 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t
buffer->draw(p_canvas_item, ofs, p_modulate); buffer->draw(p_canvas_item, ofs, p_modulate);
} }
void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint8_t p_flags) const { void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, float 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 {
ERR_FAIL_COND(data.is_empty()); ERR_FAIL_COND(data.is_empty());
int size = (p_size <= 0) ? base_size : p_size; int size = (p_size <= 0) ? base_size : p_size;

View file

@ -266,11 +266,11 @@ public:
virtual real_t get_underline_thickness(int p_size = -1) const; virtual real_t get_underline_thickness(int p_size = -1) const;
// Drawing string. // Drawing string.
virtual Size2 get_string_size(const String &p_text, int p_size = -1, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; virtual Size2 get_string_size(const String &p_text, int p_size = -1, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
virtual Size2 get_multiline_string_size(const String &p_text, real_t p_width = -1, int p_size = -1, uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) const; virtual Size2 get_multiline_string_size(const String &p_text, real_t p_width = -1, int p_size = -1, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) const;
virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, 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;
virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint8_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const; virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, 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;
// Helper functions. // Helper functions.
virtual bool has_char(char32_t p_char) const; virtual bool has_char(char32_t p_char) const;

View file

@ -53,7 +53,7 @@ void TextLine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_control"), "set_preserve_control", "get_preserve_control"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_control"), "set_preserve_control", "get_preserve_control");
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextLine::_set_bidi_override); ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextLine::set_bidi_override);
ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL("")); ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL(""));
ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1)); ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
@ -112,7 +112,7 @@ void TextLine::_shape() {
TS->shaped_text_tab_align(rid, tab_stops); TS->shaped_text_tab_align(rid, tab_stops);
} }
uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING; uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
if (overrun_behavior != OVERRUN_NO_TRIMMING) { if (overrun_behavior != OVERRUN_NO_TRIMMING) {
switch (overrun_behavior) { switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS: case OVERRUN_TRIM_WORD_ELLIPSIS:
@ -195,15 +195,7 @@ TextServer::Orientation TextLine::get_orientation() const {
return TS->shaped_text_get_orientation(rid); return TS->shaped_text_get_orientation(rid);
} }
void TextLine::_set_bidi_override(const Array &p_override) { void TextLine::set_bidi_override(const Array &p_override) {
Vector<Vector2i> overrides;
for (int i = 0; i < p_override.size(); i++) {
overrides.push_back(p_override[i]);
}
set_bidi_override(overrides);
}
void TextLine::set_bidi_override(const Vector<Vector2i> &p_override) {
TS->shaped_text_set_bidi_override(rid, p_override); TS->shaped_text_set_bidi_override(rid, p_override);
dirty = true; dirty = true;
} }
@ -256,14 +248,14 @@ void TextLine::tab_align(const Vector<float> &p_tab_stops) {
dirty = true; dirty = true;
} }
void TextLine::set_flags(uint8_t p_flags) { void TextLine::set_flags(uint16_t p_flags) {
if (flags != p_flags) { if (flags != p_flags) {
flags = p_flags; flags = p_flags;
dirty = true; dirty = true;
} }
} }
uint8_t TextLine::get_flags() const { uint16_t TextLine::get_flags() const {
return flags; return flags;
} }

View file

@ -56,7 +56,7 @@ private:
bool dirty = true; bool dirty = true;
float width = -1.0; float width = -1.0;
uint8_t flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; uint16_t flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
HAlign align = HALIGN_LEFT; HAlign align = HALIGN_LEFT;
OverrunBehavior overrun_behavior = OVERRUN_TRIM_ELLIPSIS; OverrunBehavior overrun_behavior = OVERRUN_TRIM_ELLIPSIS;
@ -75,7 +75,7 @@ public:
void set_direction(TextServer::Direction p_direction); void set_direction(TextServer::Direction p_direction);
TextServer::Direction get_direction() const; TextServer::Direction get_direction() const;
void set_bidi_override(const Vector<Vector2i> &p_override); void set_bidi_override(const Array &p_override);
void set_orientation(TextServer::Orientation p_orientation); void set_orientation(TextServer::Orientation p_orientation);
TextServer::Orientation get_orientation() const; TextServer::Orientation get_orientation() const;
@ -95,8 +95,8 @@ public:
void tab_align(const Vector<float> &p_tab_stops); void tab_align(const Vector<float> &p_tab_stops);
void set_flags(uint8_t p_flags); void set_flags(uint16_t p_flags);
uint8_t get_flags() const; uint16_t get_flags() const;
void set_text_overrun_behavior(OverrunBehavior p_behavior); void set_text_overrun_behavior(OverrunBehavior p_behavior);
OverrunBehavior get_text_overrun_behavior() const; OverrunBehavior get_text_overrun_behavior() const;
@ -120,8 +120,6 @@ public:
int hit_test(float p_coords) const; int hit_test(float p_coords) const;
void _set_bidi_override(const Array &p_override);
TextLine(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL); TextLine(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
TextLine(); TextLine();
~TextLine(); ~TextLine();

View file

@ -53,7 +53,7 @@ void TextParagraph::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_control"), "set_preserve_control", "get_preserve_control"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "preserve_control"), "set_preserve_control", "get_preserve_control");
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextParagraph::_set_bidi_override); ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextParagraph::set_bidi_override);
ClassDB::bind_method(D_METHOD("set_dropcap", "text", "fonts", "size", "dropcap_margins", "opentype_features", "language"), &TextParagraph::set_dropcap, DEFVAL(Rect2()), DEFVAL(Dictionary()), DEFVAL("")); ClassDB::bind_method(D_METHOD("set_dropcap", "text", "fonts", "size", "dropcap_margins", "opentype_features", "language"), &TextParagraph::set_dropcap, DEFVAL(Rect2()), DEFVAL(Dictionary()), DEFVAL(""));
ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap); ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap);
@ -158,9 +158,9 @@ void TextParagraph::_shape_lines() {
if (h_offset > 0) { if (h_offset > 0) {
// Dropcap, flow around. // Dropcap, flow around.
Vector<Vector2i> line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags); PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags);
for (int i = 0; i < line_breaks.size(); i++) { for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x); RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x; float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x;
if (v_offset < h) { if (v_offset < h) {
TS->free(line); TS->free(line);
@ -171,21 +171,21 @@ void TextParagraph::_shape_lines() {
} }
dropcap_lines++; dropcap_lines++;
v_offset -= h; v_offset -= h;
start = line_breaks[i].y; start = line_breaks[i + 1];
lines_rid.push_back(line); lines_rid.push_back(line);
} }
} }
// Use fixed for the rest of lines. // Use fixed for the rest of lines.
Vector<Vector2i> line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags); PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags);
for (int i = 0; i < line_breaks.size(); i++) { for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x); RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
if (!tab_stops.is_empty()) { if (!tab_stops.is_empty()) {
TS->shaped_text_tab_align(line, tab_stops); TS->shaped_text_tab_align(line, tab_stops);
} }
lines_rid.push_back(line); lines_rid.push_back(line);
} }
uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING; uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
if (overrun_behavior != OVERRUN_NO_TRIMMING) { if (overrun_behavior != OVERRUN_NO_TRIMMING) {
switch (overrun_behavior) { switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS: case OVERRUN_TRIM_WORD_ELLIPSIS:
@ -347,15 +347,7 @@ int TextParagraph::get_spacing_bottom() const {
return spacing_bottom; return spacing_bottom;
} }
void TextParagraph::_set_bidi_override(const Array &p_override) { void TextParagraph::set_bidi_override(const Array &p_override) {
Vector<Vector2i> overrides;
for (int i = 0; i < p_override.size(); i++) {
overrides.push_back(p_override[i]);
}
set_bidi_override(overrides);
}
void TextParagraph::set_bidi_override(const Vector<Vector2i> &p_override) {
TS->shaped_text_set_bidi_override(rid, p_override); TS->shaped_text_set_bidi_override(rid, p_override);
lines_dirty = true; lines_dirty = true;
} }
@ -392,14 +384,14 @@ void TextParagraph::tab_align(const Vector<float> &p_tab_stops) {
lines_dirty = true; lines_dirty = true;
} }
void TextParagraph::set_flags(uint8_t p_flags) { void TextParagraph::set_flags(uint16_t p_flags) {
if (flags != p_flags) { if (flags != p_flags) {
flags = p_flags; flags = p_flags;
lines_dirty = true; lines_dirty = true;
} }
} }
uint8_t TextParagraph::get_flags() const { uint16_t TextParagraph::get_flags() const {
return flags; return flags;
} }

View file

@ -63,7 +63,7 @@ private:
float width = -1.0; float width = -1.0;
int max_lines_visible = -1; int max_lines_visible = -1;
uint8_t flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA; uint16_t flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
OverrunBehavior overrun_behavior = OVERRUN_NO_TRIMMING; OverrunBehavior overrun_behavior = OVERRUN_NO_TRIMMING;
HAlign align = HALIGN_LEFT; HAlign align = HALIGN_LEFT;
@ -94,7 +94,7 @@ public:
void set_preserve_control(bool p_enabled); void set_preserve_control(bool p_enabled);
bool get_preserve_control() const; bool get_preserve_control() const;
void set_bidi_override(const Vector<Vector2i> &p_override); void set_bidi_override(const Array &p_override);
bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = ""); bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
void clear_dropcap(); void clear_dropcap();
@ -108,8 +108,8 @@ public:
void tab_align(const Vector<float> &p_tab_stops); void tab_align(const Vector<float> &p_tab_stops);
void set_flags(uint8_t p_flags); void set_flags(uint16_t p_flags);
uint8_t get_flags() const; uint16_t get_flags() const;
void set_text_overrun_behavior(OverrunBehavior p_behavior); void set_text_overrun_behavior(OverrunBehavior p_behavior);
OverrunBehavior get_text_overrun_behavior() const; OverrunBehavior get_text_overrun_behavior() const;
@ -153,8 +153,6 @@ public:
int hit_test(const Point2 &p_coords) const; int hit_test(const Point2 &p_coords) const;
void _set_bidi_override(const Array &p_override);
TextParagraph(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL); TextParagraph(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
TextParagraph(); TextParagraph();
~TextParagraph(); ~TextParagraph();

View file

@ -11,6 +11,7 @@ SConscript("physics_3d/SCsub")
SConscript("physics_2d/SCsub") SConscript("physics_2d/SCsub")
SConscript("rendering/SCsub") SConscript("rendering/SCsub")
SConscript("audio/SCsub") SConscript("audio/SCsub")
SConscript("text/SCsub")
lib = env.add_library("servers", env.servers_sources) lib = env.add_library("servers", env.servers_sources)

View file

@ -70,6 +70,7 @@
#include "rendering/rendering_device_binds.h" #include "rendering/rendering_device_binds.h"
#include "rendering_server.h" #include "rendering_server.h"
#include "servers/rendering/shader_types.h" #include "servers/rendering/shader_types.h"
#include "text/text_server_extension.h"
#include "text_server.h" #include "text_server.h"
#include "xr/xr_interface.h" #include "xr/xr_interface.h"
#include "xr/xr_interface_extension.h" #include "xr/xr_interface_extension.h"
@ -107,15 +108,11 @@ static bool has_server_feature_callback(const String &p_feature) {
void preregister_server_types() { void preregister_server_types() {
shader_types = memnew(ShaderTypes); shader_types = memnew(ShaderTypes);
GLOBAL_DEF("internationalization/rendering/text_driver", ""); GDREGISTER_CLASS(TextServerManager);
String text_driver_options; GDREGISTER_VIRTUAL_CLASS(TextServer);
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { GDREGISTER_CLASS(TextServerExtension);
if (i > 0) {
text_driver_options += ","; Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
}
text_driver_options += TextServerManager::get_interface_name(i);
}
ProjectSettings::get_singleton()->set_custom_property_info("internationalization/rendering/text_driver", PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options));
} }
void register_server_types() { void register_server_types() {
@ -125,8 +122,6 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(RenderingServer); GDREGISTER_VIRTUAL_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer); GDREGISTER_CLASS(AudioServer);
GDREGISTER_CLASS(TextServerManager);
GDREGISTER_VIRTUAL_CLASS(TextServer);
TextServer::initialize_hex_code_box_fonts(); TextServer::initialize_hex_code_box_fonts();
GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D); GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D);
@ -255,7 +250,6 @@ void register_server_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D")); Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton(), "PhysicsServer3D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut(), "NavigationServer2D")); Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut(), "NavigationServer2D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut(), "NavigationServer3D")); Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer3D", NavigationServer3D::get_singleton_mut(), "NavigationServer3D"));
Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer")); Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer")); Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
} }

View file

@ -2539,6 +2539,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect); ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));

5
servers/text/SCsub Normal file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import("env")
env.add_source_files(env.servers_sources, "*.cpp")

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,426 @@
/*************************************************************************/
/* text_server_extension.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_SERVER_EXTENSION_H
#define TEXT_SERVER_EXTENSION_H
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
#include "core/variant/native_ptr.h"
#include "servers/text_server.h"
class TextServerExtension : public TextServer {
GDCLASS(TextServerExtension, TextServer);
protected:
_THREAD_SAFE_CLASS_
static void _bind_methods();
public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
virtual uint32_t get_features() const override;
GDVIRTUAL1RC(bool, _has_feature, Feature);
GDVIRTUAL0RC(String, _get_name);
GDVIRTUAL0RC(uint32_t, _get_features);
virtual void free(RID p_rid) override;
virtual bool has(RID p_rid) override;
virtual bool load_support_data(const String &p_filename) override;
GDVIRTUAL1(_free, RID);
GDVIRTUAL1R(bool, _has, RID);
GDVIRTUAL1R(bool, _load_support_data, const String &);
virtual String get_support_data_filename() const override;
virtual String get_support_data_info() const override;
virtual bool save_support_data(const String &p_filename) const override;
GDVIRTUAL0RC(String, _get_support_data_filename);
GDVIRTUAL0RC(String, _get_support_data_info);
GDVIRTUAL1RC(bool, _save_support_data, const String &);
virtual bool is_locale_right_to_left(const String &p_locale) const override;
GDVIRTUAL1RC(bool, _is_locale_right_to_left, const String &);
virtual int32_t name_to_tag(const String &p_name) const override;
virtual String tag_to_name(int32_t p_tag) const override;
GDVIRTUAL1RC(int32_t, _name_to_tag, const String &);
GDVIRTUAL1RC(String, _tag_to_name, int32_t);
/* Font interface */
virtual RID create_font() override;
GDVIRTUAL0R(RID, _create_font);
virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) override;
GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t);
virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override;
virtual bool font_is_antialiased(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_antialiased, RID, bool);
GDVIRTUAL1RC(bool, _font_is_antialiased, RID);
virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_multichannel_signed_distance_field, RID, bool);
GDVIRTUAL1RC(bool, _font_is_multichannel_signed_distance_field, RID);
virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) override;
virtual int font_get_msdf_pixel_range(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_msdf_pixel_range, RID, int);
GDVIRTUAL1RC(int, _font_get_msdf_pixel_range, RID);
virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) override;
virtual int font_get_msdf_size(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_msdf_size, RID, int);
GDVIRTUAL1RC(int, _font_get_msdf_size, RID);
virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) override;
virtual int font_get_fixed_size(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_fixed_size, RID, int);
GDVIRTUAL1RC(int, _font_get_fixed_size, RID);
virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) override;
virtual bool font_is_force_autohinter(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_force_autohinter, RID, bool);
GDVIRTUAL1RC(bool, _font_is_force_autohinter, RID);
virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) override;
virtual Hinting font_get_hinting(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_hinting, RID, Hinting);
GDVIRTUAL1RC(/*Hinting*/ int, _font_get_hinting, RID);
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
GDVIRTUAL1RC(Dictionary, _font_get_variation_coordinates, RID);
virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override;
virtual float font_get_oversampling(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_oversampling, RID, float);
GDVIRTUAL1RC(float, _font_get_oversampling, RID);
virtual Array font_get_size_cache_list(RID p_font_rid) const override;
virtual void font_clear_size_cache(RID p_font_rid) override;
virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) override;
GDVIRTUAL1RC(Array, _font_get_size_cache_list, RID);
GDVIRTUAL1(_font_clear_size_cache, RID);
GDVIRTUAL2(_font_remove_size_cache, RID, const Vector2i &);
virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override;
virtual float font_get_ascent(RID p_font_rid, int p_size) const override;
GDVIRTUAL3(_font_set_ascent, RID, int, float);
GDVIRTUAL2RC(float, _font_get_ascent, RID, int);
virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override;
virtual float font_get_descent(RID p_font_rid, int p_size) const override;
GDVIRTUAL3(_font_set_descent, RID, int, float);
GDVIRTUAL2RC(float, _font_get_descent, RID, int);
virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override;
virtual float font_get_underline_position(RID p_font_rid, int p_size) const override;
GDVIRTUAL3(_font_set_underline_position, RID, int, float);
GDVIRTUAL2RC(float, _font_get_underline_position, RID, int);
virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override;
virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override;
GDVIRTUAL3(_font_set_underline_thickness, RID, int, float);
GDVIRTUAL2RC(float, _font_get_underline_thickness, RID, int);
virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override;
virtual float font_get_scale(RID p_font_rid, int p_size) const override;
GDVIRTUAL3(_font_set_scale, RID, int, float);
GDVIRTUAL2RC(float, _font_get_scale, RID, int);
virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override;
virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override;
GDVIRTUAL4(_font_set_spacing, RID, int, SpacingType, int);
GDVIRTUAL3RC(int, _font_get_spacing, RID, int, SpacingType);
virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) override;
GDVIRTUAL2RC(int, _font_get_texture_count, RID, const Vector2i &);
GDVIRTUAL2(_font_clear_textures, RID, const Vector2i &);
GDVIRTUAL3(_font_remove_texture, RID, const Vector2i &, int);
virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) override;
virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
GDVIRTUAL4(_font_set_texture_image, RID, const Vector2i &, int, const Ref<Image> &);
GDVIRTUAL3RC(Ref<Image>, _font_get_texture_image, RID, const Vector2i &, int);
virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) override;
virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const override;
GDVIRTUAL4(_font_set_texture_offsets, RID, const Vector2i &, int, const PackedInt32Array &);
GDVIRTUAL3RC(PackedInt32Array, _font_get_texture_offsets, RID, const Vector2i &, int);
virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) override;
GDVIRTUAL2RC(Array, _font_get_glyph_list, RID, const Vector2i &);
GDVIRTUAL2(_font_clear_glyphs, RID, const Vector2i &);
GDVIRTUAL3(_font_remove_glyph, RID, const Vector2i &, int32_t);
virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) override;
GDVIRTUAL3RC(Vector2, _font_get_glyph_advance, RID, int, int32_t);
GDVIRTUAL4(_font_set_glyph_advance, RID, int, int32_t, const Vector2 &);
virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) override;
GDVIRTUAL3RC(Vector2, _font_get_glyph_offset, RID, const Vector2i &, int32_t);
GDVIRTUAL4(_font_set_glyph_offset, RID, const Vector2i &, int32_t, const Vector2 &);
virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) override;
GDVIRTUAL3RC(Vector2, _font_get_glyph_size, RID, const Vector2i &, int32_t);
GDVIRTUAL4(_font_set_glyph_size, RID, const Vector2i &, int32_t, const Vector2 &);
virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) override;
GDVIRTUAL3RC(Rect2, _font_get_glyph_uv_rect, RID, const Vector2i &, int32_t);
GDVIRTUAL4(_font_set_glyph_uv_rect, RID, const Vector2i &, int32_t, const Rect2 &);
virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override;
GDVIRTUAL3RC(int, _font_get_glyph_texture_idx, RID, const Vector2i &, int32_t);
GDVIRTUAL4(_font_set_glyph_texture_idx, RID, const Vector2i &, int32_t, int);
virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override;
GDVIRTUAL3RC(Dictionary, _font_get_glyph_contours, RID, int, int32_t);
virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override;
virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override;
virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) override;
GDVIRTUAL2RC(Array, _font_get_kerning_list, RID, int);
GDVIRTUAL2(_font_clear_kerning_map, RID, int);
GDVIRTUAL3(_font_remove_kerning, RID, int, const Vector2i &);
virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const override;
GDVIRTUAL4(_font_set_kerning, RID, int, const Vector2i &, const Vector2 &);
GDVIRTUAL3RC(Vector2, _font_get_kerning, RID, int, const Vector2i &);
virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector = 0) const override;
GDVIRTUAL4RC(int32_t, _font_get_glyph_index, RID, int, char32_t, char32_t);
virtual bool font_has_char(RID p_font_rid, char32_t p_char) const override;
virtual String font_get_supported_chars(RID p_font_rid) const override;
GDVIRTUAL2RC(bool, _font_has_char, RID, char32_t);
GDVIRTUAL1RC(String, _font_get_supported_chars, RID);
virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) override;
virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) override;
GDVIRTUAL4(_font_render_range, RID, const Vector2i &, char32_t, char32_t);
GDVIRTUAL3(_font_render_glyph, RID, const Vector2i &, int32_t);
virtual void font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual void font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
GDVIRTUAL6C(_font_draw_glyph, RID, RID, int, const Vector2 &, int32_t, const Color &);
GDVIRTUAL7C(_font_draw_glyph_outline, RID, RID, int, int, const Vector2 &, int32_t, const Color &);
virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const override;
virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) override;
virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) override;
virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) override;
virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) override;
GDVIRTUAL2RC(bool, _font_is_language_supported, RID, const String &);
GDVIRTUAL3(_font_set_language_support_override, RID, const String &, bool);
GDVIRTUAL2R(bool, _font_get_language_support_override, RID, const String &);
GDVIRTUAL2(_font_remove_language_support_override, RID, const String &);
GDVIRTUAL1R(Vector<String>, _font_get_language_support_overrides, RID);
virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const override;
virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) override;
virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) override;
virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) override;
virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) override;
GDVIRTUAL2RC(bool, _font_is_script_supported, RID, const String &);
GDVIRTUAL3(_font_set_script_support_override, RID, const String &, bool);
GDVIRTUAL2R(bool, _font_get_script_support_override, RID, const String &);
GDVIRTUAL2(_font_remove_script_support_override, RID, const String &);
GDVIRTUAL1R(Vector<String>, _font_get_script_support_overrides, RID);
virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID);
GDVIRTUAL1RC(Dictionary, _font_supported_variation_list, RID);
virtual float font_get_global_oversampling() const override;
virtual void font_set_global_oversampling(float p_oversampling) override;
GDVIRTUAL0RC(float, _font_get_global_oversampling);
GDVIRTUAL1(_font_set_global_oversampling, float);
virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const override;
virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const override;
GDVIRTUAL2RC(Vector2, _get_hex_code_box_size, int, char32_t);
GDVIRTUAL5C(_draw_hex_code_box, RID, int, const Vector2 &, char32_t, const Color &);
/* Shaped text buffer interface */
virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
GDVIRTUAL2R(RID, _create_shaped_text, Direction, Orientation);
virtual void shaped_text_clear(RID p_shaped) override;
GDVIRTUAL1(_shaped_text_clear, RID);
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_direction, RID, Direction);
GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_direction, RID);
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);
GDVIRTUAL1RC(/*Orientation*/ int, _shaped_text_get_orientation, RID);
virtual void shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_invalid(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_preserve_invalid, RID, bool);
GDVIRTUAL1RC(bool, _shaped_text_get_preserve_invalid, RID);
virtual void shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_preserve_control, RID, bool);
GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID);
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
GDVIRTUAL6R(bool, _shaped_text_add_string, RID, const String &, const Array &, int, const Dictionary &, const String &);
GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlign, int);
GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlign);
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
GDVIRTUAL3RC(RID, _shaped_text_substr, RID, int, int);
GDVIRTUAL1RC(RID, _shaped_text_get_parent, RID);
virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override;
GDVIRTUAL3R(float, _shaped_text_fit_to_width, RID, float, uint16_t);
GDVIRTUAL2R(float, _shaped_text_tab_align, RID, const PackedFloat32Array &);
virtual bool shaped_text_shape(RID p_shaped) override;
virtual bool shaped_text_update_breaks(RID p_shaped) override;
virtual bool shaped_text_update_justification_ops(RID p_shaped) override;
GDVIRTUAL1R(bool, _shaped_text_shape, RID);
GDVIRTUAL1R(bool, _shaped_text_update_breaks, RID);
GDVIRTUAL1R(bool, _shaped_text_update_justification_ops, RID);
virtual bool shaped_text_is_ready(RID p_shaped) const override;
GDVIRTUAL1RC(bool, _shaped_text_is_ready, RID);
virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override;
virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override;
virtual int shaped_text_get_glyph_count(RID p_shaped) const override;
GDVIRTUAL2C(_shaped_text_get_glyphs, RID, GDNativePtr<const Glyph *>);
GDVIRTUAL2(_shaped_text_sort_logical, RID, GDNativePtr<const Glyph *>);
GDVIRTUAL1RC(int, _shaped_text_get_glyph_count, RID);
virtual Vector2i shaped_text_get_range(RID p_shaped) const override;
GDVIRTUAL1RC(Vector2i, _shaped_text_get_range, RID);
virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int, bool, uint16_t);
GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, float, int, uint16_t);
GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, int);
virtual int shaped_text_get_trim_pos(RID p_shaped) const override;
virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override;
virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override;
virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override;
GDVIRTUAL1RC(int, _shaped_text_get_trim_pos, RID);
GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_pos, RID);
GDVIRTUAL2C(_shaped_text_get_ellipsis_glyphs, RID, GDNativePtr<const Glyph *>);
GDVIRTUAL1RC(int, _shaped_text_get_ellipsis_glyph_count, RID);
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override;
GDVIRTUAL3(_shaped_text_overrun_trim_to_width, RID, float, uint16_t);
virtual Array shaped_text_get_objects(RID p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override;
GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID);
GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, Variant);
virtual Size2 shaped_text_get_size(RID p_shaped) const override;
virtual float shaped_text_get_ascent(RID p_shaped) const override;
virtual float shaped_text_get_descent(RID p_shaped) const override;
virtual float shaped_text_get_width(RID p_shaped) const override;
virtual float shaped_text_get_underline_position(RID p_shaped) const override;
virtual float shaped_text_get_underline_thickness(RID p_shaped) const override;
GDVIRTUAL1RC(Size2, _shaped_text_get_size, RID);
GDVIRTUAL1RC(float, _shaped_text_get_ascent, RID);
GDVIRTUAL1RC(float, _shaped_text_get_descent, RID);
GDVIRTUAL1RC(float, _shaped_text_get_width, RID);
GDVIRTUAL1RC(float, _shaped_text_get_underline_position, RID);
GDVIRTUAL1RC(float, _shaped_text_get_underline_thickness, RID);
virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const override;
GDVIRTUAL3RC(int, _shaped_text_get_dominant_direction_in_range, RID, int, int);
virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const override;
virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const override;
GDVIRTUAL3C(_shaped_text_get_carets, RID, int, GDNativePtr<CaretInfo>);
GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int, int);
virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const override;
virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const override;
GDVIRTUAL2RC(int, _shaped_text_hit_test_grapheme, RID, float);
GDVIRTUAL2RC(int, _shaped_text_hit_test_position, RID, float);
virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const override;
virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override;
GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &);
GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &);
virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override;
virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override;
GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int);
GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int);
virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override;
GDVIRTUAL2RC(String, _format_number, const String &, const String &);
GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
GDVIRTUAL1RC(String, _percent_sign, const String &);
TextServerExtension();
~TextServerExtension();
};
#endif // TEXT_SERVER_EXTENSION_H

File diff suppressed because it is too large Load diff

View file

@ -34,13 +34,17 @@
#include "core/object/ref_counted.h" #include "core/object/ref_counted.h"
#include "core/os/os.h" #include "core/os/os.h"
#include "core/templates/rid.h" #include "core/templates/rid.h"
#include "core/variant/native_ptr.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
class CanvasTexture; class CanvasTexture;
class TextServer : public Object { struct Glyph;
GDCLASS(TextServer, Object); struct CaretInfo;
class TextServer : public RefCounted {
GDCLASS(TextServer, RefCounted);
public: public:
enum Direction { enum Direction {
@ -63,12 +67,12 @@ public:
JUSTIFICATION_CONSTRAIN_ELLIPSIS = 1 << 4, JUSTIFICATION_CONSTRAIN_ELLIPSIS = 1 << 4,
}; };
enum LineBreakFlag { enum LineBreakFlag { // LineBreakFlag can be passed in the same value as the JustificationFlag, do not use the same values.
BREAK_NONE = 0, BREAK_NONE = 0,
BREAK_MANDATORY = 1 << 4, BREAK_MANDATORY = 1 << 5,
BREAK_WORD_BOUND = 1 << 5, BREAK_WORD_BOUND = 1 << 6,
BREAK_GRAPHEME_BOUND = 1 << 6, BREAK_GRAPHEME_BOUND = 1 << 7,
BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7, BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8,
}; };
enum TextOverrunFlag { enum TextOverrunFlag {
@ -124,50 +128,11 @@ public:
SPACING_BOTTOM, SPACING_BOTTOM,
}; };
struct Glyph { protected:
int start = -1; // Start offset in the source string.
int end = -1; // End offset in the source string.
uint8_t count = 0; // Number of glyphs in the grapheme, set in the first glyph only.
uint8_t repeat = 1; // Draw multiple times in the row.
uint16_t flags = 0; // Grapheme flags (valid, rtl, virtual), set in the first glyph only.
real_t x_off = 0.f; // Offset from the origin of the glyph on baseline.
real_t y_off = 0.f;
real_t advance = 0.f; // Advance to the next glyph along baseline(x for horizontal layout, y for vertical).
RID font_rid; // Font resource.
int font_size = 0; // Font size;
int32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs).
bool operator==(const Glyph &p_a) const;
bool operator!=(const Glyph &p_a) const;
bool operator<(const Glyph &p_a) const;
bool operator>(const Glyph &p_a) const;
};
struct GlyphCompare { // For line breaking reordering.
_FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
if (l.start == r.start) {
if (l.count == r.count) {
if ((l.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
return false;
} else {
return true;
}
}
return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
} else {
return l.start < r.start;
}
}
};
struct TrimData { struct TrimData {
int trim_pos = -1; int trim_pos = -1;
int ellipsis_pos = -1; int ellipsis_pos = -1;
Vector<TextServer::Glyph> ellipsis_glyph_buf; Vector<Glyph> ellipsis_glyph_buf;
}; };
struct ShapedTextData { struct ShapedTextData {
@ -215,22 +180,21 @@ public:
bool preserve_invalid = true; // Draw hex code box instead of missing characters. bool preserve_invalid = true; // Draw hex code box instead of missing characters.
bool preserve_control = false; // Draw control characters. bool preserve_control = false; // Draw control characters.
real_t ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical. float ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical.
real_t descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical. float descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical.
real_t width = 0.f; // Width for horizontal layout, height for vertical. float width = 0.f; // Width for horizontal layout, height for vertical.
real_t width_trimmed = 0.f; float width_trimmed = 0.f;
real_t upos = 0.f; float upos = 0.f;
real_t uthk = 0.f; float uthk = 0.f;
TrimData overrun_trim_data; TrimData overrun_trim_data;
bool fit_width_minimum_reached = false; bool fit_width_minimum_reached = false;
Vector<TextServer::Glyph> glyphs; Vector<Glyph> glyphs;
Vector<TextServer::Glyph> glyphs_logical; Vector<Glyph> glyphs_logical;
}; };
protected:
static void _bind_methods(); static void _bind_methods();
static Vector3 hex_code_box_font_size[2]; static Vector3 hex_code_box_font_size[2];
@ -240,20 +204,19 @@ public:
static void initialize_hex_code_box_fonts(); static void initialize_hex_code_box_fonts();
static void finish_hex_code_box_fonts(); static void finish_hex_code_box_fonts();
virtual bool has_feature(Feature p_feature) = 0; virtual bool has_feature(Feature p_feature) const = 0;
virtual String get_name() const = 0; virtual String get_name() const = 0;
virtual uint32_t get_features() const = 0;
virtual void free(RID p_rid) = 0; virtual void free(RID p_rid) = 0;
virtual bool has(RID p_rid) = 0; virtual bool has(RID p_rid) = 0;
virtual bool load_support_data(const String &p_filename) = 0; virtual bool load_support_data(const String &p_filename) = 0;
#ifdef TOOLS_ENABLED virtual String get_support_data_filename() const = 0;
virtual String get_support_data_filename() = 0; virtual String get_support_data_info() const = 0;
virtual String get_support_data_info() = 0; virtual bool save_support_data(const String &p_filename) const = 0;
virtual bool save_support_data(const String &p_filename) = 0;
#endif
virtual bool is_locale_right_to_left(const String &p_locale) = 0; virtual bool is_locale_right_to_left(const String &p_locale) const = 0;
virtual int32_t name_to_tag(const String &p_name) const { return 0; }; virtual int32_t name_to_tag(const String &p_name) const { return 0; };
virtual String tag_to_name(int32_t p_tag) const { return ""; }; virtual String tag_to_name(int32_t p_tag) const { return ""; };
@ -282,33 +245,33 @@ public:
virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0; virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0;
virtual bool font_is_force_autohinter(RID p_font_rid) const = 0; virtual bool font_is_force_autohinter(RID p_font_rid) const = 0;
virtual void font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) = 0; virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0;
virtual TextServer::Hinting font_get_hinting(RID p_font_rid) const = 0; virtual Hinting font_get_hinting(RID p_font_rid) const = 0;
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;
virtual void font_set_oversampling(RID p_font_rid, real_t p_oversampling) = 0; virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) = 0;
virtual real_t font_get_oversampling(RID p_font_rid) const = 0; virtual float font_get_oversampling(RID p_font_rid) const = 0;
virtual Array font_get_size_cache_list(RID p_font_rid) const = 0; virtual Array font_get_size_cache_list(RID p_font_rid) const = 0;
virtual void font_clear_size_cache(RID p_font_rid) = 0; virtual void font_clear_size_cache(RID p_font_rid) = 0;
virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) = 0; virtual void font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) = 0;
virtual void font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) = 0; virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) = 0;
virtual real_t font_get_ascent(RID p_font_rid, int p_size) const = 0; virtual float font_get_ascent(RID p_font_rid, int p_size) const = 0;
virtual void font_set_descent(RID p_font_rid, int p_size, real_t p_descent) = 0; virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) = 0;
virtual real_t font_get_descent(RID p_font_rid, int p_size) const = 0; virtual float font_get_descent(RID p_font_rid, int p_size) const = 0;
virtual void font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) = 0; virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) = 0;
virtual real_t font_get_underline_position(RID p_font_rid, int p_size) const = 0; virtual float font_get_underline_position(RID p_font_rid, int p_size) const = 0;
virtual void font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) = 0; virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) = 0;
virtual real_t font_get_underline_thickness(RID p_font_rid, int p_size) const = 0; virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const = 0;
virtual void font_set_scale(RID p_font_rid, int p_size, real_t p_scale) = 0; virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) = 0;
virtual real_t font_get_scale(RID p_font_rid, int p_size) const = 0; virtual float font_get_scale(RID p_font_rid, int p_size) const = 0;
virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) = 0; virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) = 0;
virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const = 0; virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const = 0;
@ -342,7 +305,7 @@ public:
virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0;
virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0; virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0;
virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const = 0; virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const = 0;
virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0; virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0;
virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0; virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0;
@ -377,11 +340,11 @@ public:
virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0; virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0; virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0;
virtual real_t font_get_global_oversampling() const = 0; virtual float font_get_global_oversampling() const = 0;
virtual void font_set_global_oversampling(real_t p_oversampling) = 0; virtual void font_set_global_oversampling(float p_oversampling) = 0;
Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const; virtual Vector2 get_hex_code_box_size(int p_size, char32_t p_index) const;
void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const; virtual void draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const;
/* Shaped text buffer interface */ /* Shaped text buffer interface */
@ -392,7 +355,7 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0; virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0;
virtual Direction shaped_text_get_direction(RID p_shaped) const = 0; virtual Direction shaped_text_get_direction(RID p_shaped) const = 0;
virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) = 0; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0; virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0;
@ -410,8 +373,8 @@ public:
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range. virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(RID p_shaped) const = 0; virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) = 0; virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
virtual bool shaped_text_shape(RID p_shaped) = 0; virtual bool shaped_text_shape(RID p_shaped) = 0;
virtual bool shaped_text_update_breaks(RID p_shaped) = 0; virtual bool shaped_text_update_breaks(RID p_shaped) = 0;
@ -419,119 +382,142 @@ public:
virtual bool shaped_text_is_ready(RID p_shaped) const = 0; virtual bool shaped_text_is_ready(RID p_shaped) const = 0;
virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const = 0; virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const = 0;
Array _shaped_text_get_glyphs_wrapper(RID p_shaped) const;
virtual const Glyph *shaped_text_sort_logical(RID p_shaped) = 0;
Array _shaped_text_sort_logical_wrapper(RID p_shaped);
virtual int shaped_text_get_glyph_count(RID p_shaped) const = 0;
virtual Vector2i shaped_text_get_range(RID p_shaped) const = 0; virtual Vector2i shaped_text_get_range(RID p_shaped) const = 0;
virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) = 0; virtual PackedInt32Array shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start = 0, bool p_once = true, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
virtual PackedInt32Array shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint16_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
virtual PackedInt32Array shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; virtual int shaped_text_get_trim_pos(RID p_shaped) const = 0;
virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const = 0;
virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const = 0;
Array _shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const;
virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const = 0;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) = 0;
virtual TrimData shaped_text_get_trim_data(RID p_shaped) const;
virtual void shaped_text_overrun_trim_to_width(RID p_shaped, real_t p_width, uint8_t p_trim_flags) = 0;
virtual Array shaped_text_get_objects(RID p_shaped) const = 0; virtual Array shaped_text_get_objects(RID p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0; virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const = 0;
virtual Size2 shaped_text_get_size(RID p_shaped) const = 0; virtual Size2 shaped_text_get_size(RID p_shaped) const = 0;
virtual real_t shaped_text_get_ascent(RID p_shaped) const = 0; virtual float shaped_text_get_ascent(RID p_shaped) const = 0;
virtual real_t shaped_text_get_descent(RID p_shaped) const = 0; virtual float shaped_text_get_descent(RID p_shaped) const = 0;
virtual real_t shaped_text_get_width(RID p_shaped) const = 0; virtual float shaped_text_get_width(RID p_shaped) const = 0;
virtual real_t shaped_text_get_underline_position(RID p_shaped) const = 0; virtual float shaped_text_get_underline_position(RID p_shaped) const = 0;
virtual real_t shaped_text_get_underline_thickness(RID p_shaped) const = 0; virtual float shaped_text_get_underline_thickness(RID p_shaped) const = 0;
virtual Direction shaped_text_get_dominant_direciton_in_range(RID p_shaped, int p_start, int p_end) const; virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const;
virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const;
Dictionary _shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const;
virtual void shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const;
virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const; virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
virtual int shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) const; // Return grapheme index. virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index.
virtual int shaped_text_hit_test_position(RID p_shaped, real_t p_coords) const; // Return caret/selection position. virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position.
virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos); virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const;
virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos); virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const;
// The pen position is always placed on the baseline and moveing left to right. // The pen position is always placed on the baseline and moveing left to right.
virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l = -1.f, real_t p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const; virtual void shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, const Color &p_color = Color(1, 1, 1)) const;
virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l = -1.f, real_t p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const; virtual void shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l = -1.f, float p_clip_r = -1.f, int p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const;
// Number conversion. // Number conversion.
virtual String format_number(const String &p_string, const String &p_language = "") const { return p_string; }; virtual String format_number(const String &p_string, const String &p_language = "") const { return p_string; };
virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; }; virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; };
virtual String percent_sign(const String &p_language = "") const { return "%"; }; virtual String percent_sign(const String &p_language = "") const { return "%"; };
/* GDScript wrappers */
RID _create_font_memory(const PackedByteArray &p_data, int p_base_size = 16);
Dictionary _font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const;
Array _shaped_text_get_glyphs(RID p_shaped) const;
Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const;
void _shaped_text_set_bidi_override(RID p_shaped, const Array &p_override);
Array _shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint8_t p_break_flags) const;
Array _shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const;
Array _shaped_text_get_word_breaks(RID p_shaped) const;
Array _shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
TextServer(); TextServer();
~TextServer(); ~TextServer();
}; };
/*************************************************************************/ /*************************************************************************/
struct Glyph {
int start = -1; // Start offset in the source string.
int end = -1; // End offset in the source string.
uint8_t count = 0; // Number of glyphs in the grapheme, set in the first glyph only.
uint8_t repeat = 1; // Draw multiple times in the row.
uint16_t flags = 0; // Grapheme flags (valid, rtl, virtual), set in the first glyph only.
float x_off = 0.f; // Offset from the origin of the glyph on baseline.
float y_off = 0.f;
float advance = 0.f; // Advance to the next glyph along baseline(x for horizontal layout, y for vertical).
RID font_rid; // Font resource.
int font_size = 0; // Font size;
int32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs).
bool operator==(const Glyph &p_a) const;
bool operator!=(const Glyph &p_a) const;
bool operator<(const Glyph &p_a) const;
bool operator>(const Glyph &p_a) const;
};
struct CaretInfo {
Rect2 l_caret;
Rect2 t_caret;
TextServer::Direction l_dir;
TextServer::Direction t_dir;
};
struct GlyphCompare { // For line breaking reordering.
_FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
if (l.start == r.start) {
if (l.count == r.count) {
if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
return false;
} else {
return true;
}
}
return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
} else {
return l.start < r.start;
}
}
};
/*************************************************************************/
class TextServerManager : public Object { class TextServerManager : public Object {
GDCLASS(TextServerManager, Object); GDCLASS(TextServerManager, Object);
public:
typedef TextServer *(*CreateFunction)(Error &r_error, void *p_user_data);
protected: protected:
static void _bind_methods(); static void _bind_methods();
private: private:
static TextServerManager *singleton; static TextServerManager *singleton;
static TextServer *server;
enum {
MAX_SERVERS = 64
};
struct TextServerCreate { Ref<TextServer> primary_interface;
String name; Vector<Ref<TextServer>> interfaces;
CreateFunction create_function = nullptr;
uint32_t features = 0;
TextServer *instance = nullptr;
void *user_data = nullptr;
};
static TextServerCreate server_create_functions[MAX_SERVERS];
static int server_create_count;
public: public:
_FORCE_INLINE_ static TextServerManager *get_singleton() { _FORCE_INLINE_ static TextServerManager *get_singleton() {
return singleton; return singleton;
} }
static void register_create_function(const String &p_name, uint32_t p_features, CreateFunction p_function, void *p_user_data); void add_interface(const Ref<TextServer> &p_interface);
static int get_interface_count(); void remove_interface(const Ref<TextServer> &p_interface);
static String get_interface_name(int p_index); int get_interface_count() const;
static uint32_t get_interface_features(int p_index); Ref<TextServer> get_interface(int p_index) const;
static TextServer *initialize(int p_index, Error &r_error); Ref<TextServer> find_interface(const String &p_name) const;
static TextServer *get_primary_interface(); Array get_interfaces() const;
/* GDScript wrappers */ _FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
int _get_interface_count() const; return primary_interface;
String _get_interface_name(int p_index) const; }
uint32_t _get_interface_features(int p_index) const; Ref<TextServer> _get_primary_interface() const;
TextServer *_get_interface(int p_index) const; void set_primary_interface(const Ref<TextServer> &p_primary_interface);
Array _get_interfaces() const;
TextServer *_find_interface(const String &p_name) const;
bool _set_primary_interface(int p_index);
TextServer *_get_primary_interface() const;
TextServerManager(); TextServerManager();
~TextServerManager(); ~TextServerManager();
@ -539,7 +525,7 @@ public:
/*************************************************************************/ /*************************************************************************/
#define TS TextServerManager::get_primary_interface() #define TS TextServerManager::get_singleton()->get_primary_interface()
VARIANT_ENUM_CAST(TextServer::Direction); VARIANT_ENUM_CAST(TextServer::Direction);
VARIANT_ENUM_CAST(TextServer::Orientation); VARIANT_ENUM_CAST(TextServer::Orientation);
@ -552,4 +538,8 @@ VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_ENUM_CAST(TextServer::SpacingType);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(Glyph *);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
#endif // TEXT_SERVER_H #endif // TEXT_SERVER_H

View file

@ -174,10 +174,8 @@ struct GodotTestCaseListener : public doctest::IReporter {
memnew(MessageQueue); memnew(MessageQueue);
GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false);
memnew(TextServerManager);
Error err = OK;
TextServerManager::initialize(0, err);
Error err = OK;
OS::get_singleton()->set_has_server_feature_callback(nullptr); OS::get_singleton()->set_has_server_feature_callback(nullptr);
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (String("headless") == DisplayServer::get_create_function_name(i)) { if (String("headless") == DisplayServer::get_create_function_name(i)) {
@ -224,10 +222,6 @@ struct GodotTestCaseListener : public doctest::IReporter {
clear_default_theme(); clear_default_theme();
if (TextServerManager::get_singleton()) {
memdelete(TextServerManager::get_singleton());
}
if (navigation_3d_server) { if (navigation_3d_server) {
memdelete(navigation_3d_server); memdelete(navigation_3d_server);
navigation_3d_server = nullptr; navigation_3d_server = nullptr;

View file

@ -41,19 +41,10 @@ namespace TestTextServer {
TEST_SUITE("[[TextServer]") { TEST_SUITE("[[TextServer]") {
TEST_CASE("[TextServer] Init, font loading and shaping") { TEST_CASE("[TextServer] Init, font loading and shaping") {
TextServerManager *tsman = memnew(TextServerManager);
Error err = OK;
SUBCASE("[TextServer] Init") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err);
TEST_FAIL_COND((err != OK || ts == nullptr), "Text server ", TextServerManager::get_interface_name(i), " init failed.");
}
}
SUBCASE("[TextServer] Loading fonts") { SUBCASE("[TextServer] Loading fonts") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err); Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font = ts->create_font(); RID font = ts->create_font();
ts->font_set_data_ptr(font, _font_NotoSans_Regular, _font_NotoSans_Regular_size); ts->font_set_data_ptr(font, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
@ -63,8 +54,9 @@ TEST_SUITE("[[TextServer]") {
} }
SUBCASE("[TextServer] Text layout: Font fallback") { SUBCASE("[TextServer] Text layout: Font fallback") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err); Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font1 = ts->create_font(); RID font1 = ts->create_font();
ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size); ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
@ -83,9 +75,10 @@ TEST_SUITE("[[TextServer]") {
bool ok = ts->shaped_text_add_string(ctx, test, font, 16); bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
Vector<TextServer::Glyph> glyphs = ts->shaped_text_get_glyphs(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
TEST_FAIL_COND(glyphs.size() == 0, "Shaping failed"); int gl_size = ts->shaped_text_get_glyph_count(ctx);
for (int j = 0; j < glyphs.size(); j++) { TEST_FAIL_COND(gl_size == 0, "Shaping failed");
for (int j = 0; j < gl_size; j++) {
if (glyphs[j].start < 6) { if (glyphs[j].start < 6) {
TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected."); TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected.");
} }
@ -110,8 +103,9 @@ TEST_SUITE("[[TextServer]") {
} }
SUBCASE("[TextServer] Text layout: BiDi") { SUBCASE("[TextServer] Text layout: BiDi") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err); Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
if (!ts->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) { if (!ts->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) {
continue; continue;
@ -134,9 +128,10 @@ TEST_SUITE("[[TextServer]") {
bool ok = ts->shaped_text_add_string(ctx, test, font, 16); bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
Vector<TextServer::Glyph> glyphs = ts->shaped_text_get_glyphs(ctx); const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
TEST_FAIL_COND(glyphs.size() == 0, "Shaping failed"); int gl_size = ts->shaped_text_get_glyph_count(ctx);
for (int j = 0; j < glyphs.size(); j++) { TEST_FAIL_COND(gl_size == 0, "Shaping failed");
for (int j = 0; j < gl_size; j++) {
if (glyphs[j].count > 0) { if (glyphs[j].count > 0) {
if (glyphs[j].start < 7) { if (glyphs[j].start < 7) {
TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction."); TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
@ -160,8 +155,9 @@ TEST_SUITE("[[TextServer]") {
} }
SUBCASE("[TextServer] Text layout: Line breaking") { SUBCASE("[TextServer] Text layout: Line breaking") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err); Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
String test_1 = U"test test test"; String test_1 = U"test test test";
// 5^ 10^ // 5^ 10^
@ -180,12 +176,17 @@ TEST_SUITE("[[TextServer]") {
bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16); bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed."); TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
Vector<Vector2i> brks = ts->shaped_text_get_line_breaks(ctx, 1); PackedInt32Array brks = ts->shaped_text_get_line_breaks(ctx, 1);
TEST_FAIL_COND(brks.size() != 3, "Invalid line breaks number."); TEST_FAIL_COND(brks.size() != 6, "Invalid line breaks number.");
if (brks.size() == 3) { if (brks.size() == 6) {
TEST_FAIL_COND(brks[0] != Vector2i(0, 5), "Invalid line break position."); TEST_FAIL_COND(brks[0] != 0, "Invalid line break position.");
TEST_FAIL_COND(brks[1] != Vector2i(5, 10), "Invalid line break position."); TEST_FAIL_COND(brks[1] != 5, "Invalid line break position.");
TEST_FAIL_COND(brks[2] != Vector2i(10, 14), "Invalid line break position.");
TEST_FAIL_COND(brks[2] != 5, "Invalid line break position.");
TEST_FAIL_COND(brks[3] != 10, "Invalid line break position.");
TEST_FAIL_COND(brks[4] != 10, "Invalid line break position.");
TEST_FAIL_COND(brks[5] != 14, "Invalid line break position.");
} }
ts->free(ctx); ts->free(ctx);
@ -198,8 +199,9 @@ TEST_SUITE("[[TextServer]") {
} }
SUBCASE("[TextServer] Text layout: Justification") { SUBCASE("[TextServer] Text layout: Justification") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) { for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err); Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font1 = ts->create_font(); RID font1 = ts->create_font();
ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size); ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
@ -263,7 +265,6 @@ TEST_SUITE("[[TextServer]") {
font.clear(); font.clear();
} }
} }
memdelete(tsman);
} }
} }
}; // namespace TestTextServer }; // namespace TestTextServer