summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/extension/extension_api_dump.cpp17
-rw-r--r--core/input/shortcut.cpp84
-rw-r--r--core/input/shortcut.h12
-rw-r--r--core/templates/search_array.h (renamed from modules/gdnative/text/register_types.h)42
-rw-r--r--core/templates/vector.h6
-rw-r--r--core/variant/array.cpp36
-rw-r--r--core/variant/variant_call.cpp9
-rw-r--r--doc/classes/CanvasItem.xml2
-rw-r--r--doc/classes/Control.xml6
-rw-r--r--doc/classes/DisplayServer.xml8
-rw-r--r--doc/classes/Font.xml4
-rw-r--r--doc/classes/OS.xml2
-rw-r--r--doc/classes/PackedByteArray.xml9
-rw-r--r--doc/classes/PackedColorArray.xml9
-rw-r--r--doc/classes/PackedFloat32Array.xml9
-rw-r--r--doc/classes/PackedFloat64Array.xml9
-rw-r--r--doc/classes/PackedInt32Array.xml9
-rw-r--r--doc/classes/PackedInt64Array.xml9
-rw-r--r--doc/classes/PackedStringArray.xml9
-rw-r--r--doc/classes/PackedVector2Array.xml9
-rw-r--r--doc/classes/PackedVector3Array.xml9
-rw-r--r--doc/classes/RenderingServer.xml12
-rw-r--r--doc/classes/Shortcut.xml14
-rw-r--r--doc/classes/Tabs.xml26
-rw-r--r--doc/classes/TextParagraph.xml2
-rw-r--r--doc/classes/TextServer.xml118
-rw-r--r--doc/classes/TextServerExtension.xml1262
-rw-r--r--doc/classes/TextServerManager.xml52
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_properties.cpp2
-rw-r--r--editor/editor_properties_array_dict.cpp6
-rw-r--r--editor/editor_settings.cpp153
-rw-r--r--editor/editor_settings.h2
-rw-r--r--editor/editor_spin_slider.cpp5
-rw-r--r--editor/editor_themes.cpp4
-rw-r--r--editor/import/dynamicfont_import_settings.cpp5
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp1
-rw-r--r--editor/plugins/theme_editor_plugin.cpp2
-rw-r--r--editor/settings_config_dialog.cpp438
-rw-r--r--editor/settings_config_dialog.h30
-rw-r--r--main/main.cpp130
-rw-r--r--modules/gdnative/SCsub1
-rw-r--r--modules/gdnative/gdnative_api.json483
-rw-r--r--modules/gdnative/gdnative_builders.py1
-rw-r--r--modules/gdnative/include/text/godot_text.h283
-rw-r--r--modules/gdnative/text/SCsub6
-rw-r--r--modules/gdnative/text/config.py6
-rw-r--r--modules/gdnative/text/register_types.cpp36
-rw-r--r--modules/gdnative/text/text_server_gdnative.cpp1086
-rw-r--r--modules/gdnative/text/text_server_gdnative.h254
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml17
-rw-r--r--modules/text_server_adv/config.py10
-rw-r--r--modules/text_server_adv/doc_classes/TextServerAdvanced.xml10
-rw-r--r--modules/text_server_adv/register_types.cpp7
-rw-r--r--modules/text_server_adv/text_server_adv.cpp296
-rw-r--r--modules/text_server_adv/text_server_adv.h94
-rw-r--r--modules/text_server_fb/config.py10
-rw-r--r--modules/text_server_fb/doc_classes/TextServerFallback.xml10
-rw-r--r--modules/text_server_fb/register_types.cpp7
-rw-r--r--modules/text_server_fb/text_server_fb.cpp245
-rw-r--r--modules/text_server_fb/text_server_fb.h92
-rw-r--r--platform/linuxbsd/display_server_x11.cpp18
-rw-r--r--platform/linuxbsd/display_server_x11.h1
-rw-r--r--platform/linuxbsd/key_mapping_x11.cpp12
-rw-r--r--platform/linuxbsd/key_mapping_x11.h1
-rw-r--r--platform/osx/display_server_osx.h1
-rw-r--r--platform/osx/display_server_osx.mm288
-rw-r--r--platform/osx/os_osx.mm20
-rw-r--r--platform/windows/display_server_windows.cpp36
-rw-r--r--platform/windows/display_server_windows.h1
-rw-r--r--platform/windows/key_mapping_windows.cpp10
-rw-r--r--platform/windows/key_mapping_windows.h1
-rw-r--r--scene/2d/physics_body_2d.cpp17
-rw-r--r--scene/3d/mesh_instance_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp30
-rw-r--r--scene/3d/physics_body_3d.h5
-rw-r--r--scene/gui/control.cpp15
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/gui/label.cpp78
-rw-r--r--scene/gui/line_edit.cpp104
-rw-r--r--scene/gui/rich_text_label.cpp15
-rw-r--r--scene/gui/tabs.cpp14
-rw-r--r--scene/gui/text_edit.cpp168
-rw-r--r--scene/gui/text_edit.h8
-rw-r--r--scene/main/canvas_item.cpp4
-rw-r--r--scene/main/canvas_item.h4
-rw-r--r--scene/resources/default_theme/default_theme.cpp4
-rw-r--r--scene/resources/font.cpp13
-rw-r--r--scene/resources/font.h8
-rw-r--r--scene/resources/navigation_mesh.cpp2
-rw-r--r--scene/resources/text_line.cpp18
-rw-r--r--scene/resources/text_line.h10
-rw-r--r--scene/resources/text_paragraph.cpp32
-rw-r--r--scene/resources/text_paragraph.h10
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--servers/SCsub1
-rw-r--r--servers/display_server.cpp5
-rw-r--r--servers/display_server.h1
-rw-r--r--servers/register_server_types.cpp18
-rw-r--r--servers/rendering/rendering_server_default.cpp3
-rw-r--r--servers/rendering_server.cpp1
-rw-r--r--servers/text/SCsub5
-rw-r--r--servers/text/text_server_extension.cpp1281
-rw-r--r--servers/text/text_server_extension.h426
-rw-r--r--servers/text_server.cpp561
-rw-r--r--servers/text_server.h294
-rw-r--r--tests/test_main.cpp8
-rw-r--r--tests/test_text_server.h67
-rw-r--r--tests/test_vector.h13
110 files changed, 5356 insertions, 3825 deletions
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 3856229eac..03b2426370 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -841,6 +841,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{
Array native_structures;
+ // AudioStream structures
{
Dictionary d;
d["name"] = "AudioFrame";
@@ -849,6 +850,22 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
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;
}
diff --git a/core/input/shortcut.cpp b/core/input/shortcut.cpp
index d0cb08724e..30e35190e4 100644
--- a/core/input/shortcut.cpp
+++ b/core/input/shortcut.cpp
@@ -31,14 +31,26 @@
#include "shortcut.h"
#include "core/os/keyboard.h"
-void Shortcut::set_event(const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND_MSG(Object::cast_to<InputEventShortcut>(*p_event), "Cannot set a shortcut event to an instance of InputEventShortcut.");
- event = p_event;
+void Shortcut::set_events(const Array &p_events) {
+ for (int i = 0; i < p_events.size(); i++) {
+ Ref<InputEventShortcut> ies = p_events[i];
+ ERR_FAIL_COND_MSG(ies.is_valid(), "Cannot set a shortcut event to an instance of InputEventShortcut.");
+ }
+
+ events = p_events;
emit_changed();
}
-Ref<InputEvent> Shortcut::get_event() const {
- return event;
+void Shortcut::set_events_list(const List<Ref<InputEvent>> *p_events) {
+ events.clear();
+
+ for (const Ref<InputEvent> &ie : *p_events) {
+ events.push_back(ie);
+ }
+}
+
+Array Shortcut::get_events() const {
+ return events;
}
bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
@@ -48,29 +60,73 @@ bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
return true;
}
}
- return event.is_valid() && event->is_match(p_event, true);
+
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ bool valid = ie.is_valid() && ie->is_match(p_event);
+
+ // Stop on first valid event - don't need to check further.
+ if (valid) {
+ return true;
+ }
+ }
+
+ return false;
}
String Shortcut::get_as_text() const {
- if (event.is_valid()) {
- return event->as_text();
- } else {
- return "None";
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ // Return first shortcut which is valid
+ if (ie.is_valid()) {
+ return ie->as_text();
+ }
}
+
+ return "None";
}
bool Shortcut::has_valid_event() const {
- return event.is_valid();
+ // Tests if there is ANY input event which is valid.
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> ie = events[i];
+ if (ie.is_valid()) {
+ return true;
+ }
+ }
+
+ return false;
}
void Shortcut::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_event", "event"), &Shortcut::set_event);
- ClassDB::bind_method(D_METHOD("get_event"), &Shortcut::get_event);
+ ClassDB::bind_method(D_METHOD("set_events", "events"), &Shortcut::set_events);
+ ClassDB::bind_method(D_METHOD("get_events"), &Shortcut::get_events);
ClassDB::bind_method(D_METHOD("has_valid_event"), &Shortcut::has_valid_event);
ClassDB::bind_method(D_METHOD("matches_event", "event"), &Shortcut::matches_event);
ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_event", "get_event");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "events", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")), "set_events", "get_events");
+}
+
+bool Shortcut::is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2) {
+ if (p_event_array1.size() != p_event_array2.size()) {
+ return false;
+ }
+
+ bool is_same = true;
+ for (int i = 0; i < p_event_array1.size(); i++) {
+ Ref<InputEvent> ie_1 = p_event_array1[i];
+ Ref<InputEvent> ie_2 = p_event_array2[i];
+
+ is_same = ie_1->is_match(ie_2);
+
+ // Break on the first that doesn't match - don't need to check further.
+ if (!is_same) {
+ break;
+ }
+ }
+
+ return is_same;
}
diff --git a/core/input/shortcut.h b/core/input/shortcut.h
index 249dd1971f..a989b10626 100644
--- a/core/input/shortcut.h
+++ b/core/input/shortcut.h
@@ -37,18 +37,22 @@
class Shortcut : public Resource {
GDCLASS(Shortcut, Resource);
- Ref<InputEvent> event;
+ Array events;
protected:
static void _bind_methods();
public:
- void set_event(const Ref<InputEvent> &p_shortcut);
- Ref<InputEvent> get_event() const;
+ void set_events(const Array &p_events);
+ Array get_events() const;
+
+ void set_events_list(const List<Ref<InputEvent>> *p_events);
+
bool matches_event(const Ref<InputEvent> &p_event) const;
bool has_valid_event() const;
String get_as_text() const;
-};
+ static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
+};
#endif // SHORTCUT_H
diff --git a/modules/gdnative/text/register_types.h b/core/templates/search_array.h
index cd4f2a3089..8efc32df82 100644
--- a/modules/gdnative/text/register_types.h
+++ b/core/templates/search_array.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* register_types.h */
+/* search_array.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,10 +28,40 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TEXT_REGISTER_TYPES_H
-#define TEXT_REGISTER_TYPES_H
+#ifndef SEARCH_ARRAY_H
+#define SEARCH_ARRAY_H
-void register_text_server_gdn_types();
-void unregister_text_server_gdn_types();
+#include <core/templates/sort_array.h>
-#endif // TEXT_REGISTER_TYPES_H
+template <class T, class Comparator = _DefaultComparator<T>>
+class SearchArray {
+public:
+ Comparator compare;
+
+ inline int bisect(const T *p_array, int p_len, const T &p_value, bool p_before) const {
+ int lo = 0;
+ int hi = p_len;
+ if (p_before) {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_array[mid], p_value)) {
+ lo = mid + 1;
+ } else {
+ hi = mid;
+ }
+ }
+ } else {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (compare(p_value, p_array[mid])) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ }
+ return lo;
+ }
+};
+
+#endif // SEARCH_ARRAY_H
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 2600604eb7..4b008a45a4 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -40,6 +40,7 @@
#include "core/error/error_macros.h"
#include "core/os/memory.h"
#include "core/templates/cowdata.h"
+#include "core/templates/search_array.h"
#include "core/templates/sort_array.h"
template <class T>
@@ -112,6 +113,11 @@ public:
sort_custom<_DefaultComparator<T>>();
}
+ int bsearch(const T &p_value, bool p_before) {
+ SearchArray<T> search;
+ return search.bisect(ptrw(), size(), p_value, p_before);
+ }
+
Vector<T> duplicate() {
return *this;
}
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 8373cbd4e8..b4d6dffc6f 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -34,6 +34,7 @@
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/templates/hashfuncs.h"
+#include "core/templates/search_array.h"
#include "core/templates/vector.h"
#include "core/variant/callable.h"
#include "core/variant/variant.h"
@@ -484,44 +485,19 @@ void Array::shuffle() {
}
}
-template <typename Less>
-_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
- int lo = 0;
- int hi = p_array.size();
- if (p_before) {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_array.get(mid), p_value)) {
- lo = mid + 1;
- } else {
- hi = mid;
- }
- }
- } else {
- while (lo < hi) {
- const int mid = (lo + hi) / 2;
- if (p_less(p_value, p_array.get(mid))) {
- hi = mid;
- } else {
- lo = mid + 1;
- }
- }
- }
- return lo;
-}
-
int Array::bsearch(const Variant &p_value, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1);
- return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
+ SearchArray<Variant, _ArrayVariantSort> avs;
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
int Array::bsearch_custom(const Variant &p_value, Callable p_callable, bool p_before) {
ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1);
- _ArrayVariantSortCustom less;
- less.func = p_callable;
+ SearchArray<Variant, _ArrayVariantSortCustom> avs;
+ avs.compare.func = p_callable;
- return bisect(_p->array, p_value, p_before, less);
+ return avs.bisect(_p->array.ptrw(), _p->array.size(), p_value, p_before);
}
void Array::reverse() {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 5682a7c7b5..6284caae2d 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1845,6 +1845,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedByteArray, reverse, sarray(), varray());
bind_method(PackedByteArray, subarray, sarray("from", "to"), varray());
bind_method(PackedByteArray, sort, sarray(), varray());
+ bind_method(PackedByteArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedByteArray, duplicate, sarray(), varray());
bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
@@ -1906,6 +1907,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt32Array, subarray, sarray("from", "to"), varray());
bind_method(PackedInt32Array, to_byte_array, sarray(), varray());
bind_method(PackedInt32Array, sort, sarray(), varray());
+ bind_method(PackedInt32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt32Array, duplicate, sarray(), varray());
/* Int64 Array */
@@ -1925,6 +1927,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedInt64Array, subarray, sarray("from", "to"), varray());
bind_method(PackedInt64Array, to_byte_array, sarray(), varray());
bind_method(PackedInt64Array, sort, sarray(), varray());
+ bind_method(PackedInt64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedInt64Array, duplicate, sarray(), varray());
/* Float32 Array */
@@ -1944,6 +1947,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat32Array, subarray, sarray("from", "to"), varray());
bind_method(PackedFloat32Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat32Array, sort, sarray(), varray());
+ bind_method(PackedFloat32Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat32Array, duplicate, sarray(), varray());
/* Float64 Array */
@@ -1963,6 +1967,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedFloat64Array, subarray, sarray("from", "to"), varray());
bind_method(PackedFloat64Array, to_byte_array, sarray(), varray());
bind_method(PackedFloat64Array, sort, sarray(), varray());
+ bind_method(PackedFloat64Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedFloat64Array, duplicate, sarray(), varray());
/* String Array */
@@ -1982,6 +1987,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedStringArray, subarray, sarray("from", "to"), varray());
bind_method(PackedStringArray, to_byte_array, sarray(), varray());
bind_method(PackedStringArray, sort, sarray(), varray());
+ bind_method(PackedStringArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedStringArray, duplicate, sarray(), varray());
/* Vector2 Array */
@@ -2001,6 +2007,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector2Array, subarray, sarray("from", "to"), varray());
bind_method(PackedVector2Array, to_byte_array, sarray(), varray());
bind_method(PackedVector2Array, sort, sarray(), varray());
+ bind_method(PackedVector2Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector2Array, duplicate, sarray(), varray());
/* Vector3 Array */
@@ -2020,6 +2027,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedVector3Array, subarray, sarray("from", "to"), varray());
bind_method(PackedVector3Array, to_byte_array, sarray(), varray());
bind_method(PackedVector3Array, sort, sarray(), varray());
+ bind_method(PackedVector3Array, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedVector3Array, duplicate, sarray(), varray());
/* Color Array */
@@ -2039,6 +2047,7 @@ static void _register_variant_builtin_methods() {
bind_method(PackedColorArray, subarray, sarray("from", "to"), varray());
bind_method(PackedColorArray, to_byte_array, sarray(), varray());
bind_method(PackedColorArray, sort, sarray(), varray());
+ bind_method(PackedColorArray, bsearch, sarray("value", "before"), varray(true));
bind_method(PackedColorArray, duplicate, sarray(), varray());
/* Register constants */
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 501f89fa0d..738594ea5d 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -150,7 +150,7 @@
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
- <argument index="10" name="flags" type="int" default="51" />
+ <argument index="10" name="flags" type="int" default="99" />
<description>
Breaks [code]text[/code] to the lines and draws it using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
</description>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index c9a2de66a8..b00bf1c250 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -742,10 +742,10 @@
</method>
<method name="set_drag_forwarding">
<return type="void" />
- <argument index="0" name="target" type="Control" />
+ <argument index="0" name="target" type="Node" />
<description>
- Forwards the handling of this control's drag and drop to [code]target[/code] control.
- Forwarding can be implemented in the target control similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences:
+ Forwards the handling of this control's drag and drop to [code]target[/code] node.
+ Forwarding can be implemented in the target node similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences:
1. The function name must be suffixed with [b]_fw[/b]
2. The function must take an extra argument that is the control doing the forwarding
[codeblocks]
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 4f495eaec9..7eff8db59c 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -276,6 +276,14 @@
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
</description>
</method>
+ <method name="keyboard_get_keycode_from_physical" qualifiers="const">
+ <return type="int" enum="Key" />
+ <argument index="0" name="keycode" type="int" enum="Key" />
+ <description>
+ Converts a physical (US QWERTY) [code]keycode[/code] to one in the active keyboard layout.
+ [b]Note:[/b] This method is implemented on Linux, macOS and Windows.
+ </description>
+ </method>
<method name="keyboard_get_layout_count" qualifiers="const">
<return type="int" />
<description>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index e8ff0f60ec..39881e9eb7 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -103,7 +103,7 @@
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
- <argument index="10" name="flags" type="int" default="51" />
+ <argument index="10" name="flags" type="int" default="99" />
<description>
Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws it into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_multiline_string].
@@ -185,7 +185,7 @@
<argument index="0" name="text" type="String" />
<argument index="1" name="width" type="float" 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>
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].
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 9d0d185c42..656fa61af7 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -246,7 +246,7 @@
<method name="get_name" qualifiers="const">
<return type="String" />
<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>
</method>
<method name="get_process_id" qualifiers="const">
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 8e94254a1f..39733baf40 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -43,6 +43,15 @@
Appends a [PackedByteArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="compress" qualifiers="const">
<return type="PackedByteArray" />
<argument index="0" name="compression_mode" type="int" default="0" />
diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml
index 4bccdcd939..00e670646d 100644
--- a/doc/classes/PackedColorArray.xml
+++ b/doc/classes/PackedColorArray.xml
@@ -43,6 +43,15 @@
Appends a [PackedColorArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Color" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedColorArray" />
<description>
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index 51e14ea3d4..2ee2ac44df 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedFloat32Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="float" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedFloat32Array" />
<description>
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index 25c9c025f7..7414bc72fc 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedFloat64Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="float" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedFloat64Array" />
<description>
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index 1a61ce0ead..8ecf4a70ae 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedInt32Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedInt32Array" />
<description>
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index 06f7900237..b82ce79009 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedInt64Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="int" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedInt64Array" />
<description>
diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml
index 763ed0cc55..353bbfb827 100644
--- a/doc/classes/PackedStringArray.xml
+++ b/doc/classes/PackedStringArray.xml
@@ -44,6 +44,15 @@
Appends a [PackedStringArray] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="String" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedStringArray" />
<description>
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index 3f0797bb59..7b7df221e7 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -44,6 +44,15 @@
Appends a [PackedVector2Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Vector2" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedVector2Array" />
<description>
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index 6b950cad61..efbf2169fd 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -43,6 +43,15 @@
Appends a [PackedVector3Array] at the end of this array.
</description>
</method>
+ <method name="bsearch">
+ <return type="int" />
+ <argument index="0" name="value" type="Vector3" />
+ <argument index="1" name="before" type="bool" default="true" />
+ <description>
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a [code]before[/code] specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array.
+ [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
+ </description>
+ </method>
<method name="duplicate">
<return type="PackedVector3Array" />
<description>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index b5be04fb01..d40ad80d68 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -185,6 +185,18 @@
<description>
</description>
</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">
<return type="void" />
<argument index="0" name="item" type="RID" />
diff --git a/doc/classes/Shortcut.xml b/doc/classes/Shortcut.xml
index 9fbe91f38b..f95d069069 100644
--- a/doc/classes/Shortcut.xml
+++ b/doc/classes/Shortcut.xml
@@ -4,8 +4,8 @@
A shortcut for binding input.
</brief_description>
<description>
- A shortcut for binding input.
Shortcuts are commonly used for interacting with a [Control] element from an [InputEvent] (also known as hotkeys).
+ One shortcut can contain multiple [InputEvent]'s, allowing the possibility of triggering one action with multiple different inputs.
</description>
<tutorials>
</tutorials>
@@ -13,27 +13,27 @@
<method name="get_as_text" qualifiers="const">
<return type="String" />
<description>
- Returns the shortcut's [InputEvent] as a [String].
+ Returns the shortcut's first valid [InputEvent] as a [String].
</description>
</method>
<method name="has_valid_event" qualifiers="const">
<return type="bool" />
<description>
- Returns whether the shortcut has a valid [member event] assigned to it.
+ Returns whether [member events] contains an [InputEvent] which is valid.
</description>
</method>
<method name="matches_event" qualifiers="const">
<return type="bool" />
<argument index="0" name="event" type="InputEvent" />
<description>
- Returns whether the shortcut's [member event] matches [code]event[/code].
+ Returns whether any [InputEvent] in [member events] equals [code]event[/code].
</description>
</method>
</methods>
<members>
- <member name="event" type="InputEvent" setter="set_event" getter="get_event">
- The shortcut's [InputEvent].
- Generally the [InputEvent] is a keyboard key, though it can be any [InputEvent], including an [InputEventAction].
+ <member name="events" type="Array" setter="set_events" getter="get_events" default="[]">
+ The shortcut's [InputEvent] array.
+ Generally the [InputEvent] used is an [InputEventKey], though it can be any [InputEvent], including an [InputEventAction].
</member>
</members>
</class>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 3ee3feb365..ded4f0b32f 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -217,18 +217,12 @@
</member>
</members>
<signals>
- <signal name="reposition_active_tab_request">
+ <signal name="active_tab_rearranged">
<argument index="0" name="idx_to" type="int" />
<description>
Emitted when the active tab is rearranged via mouse drag. See [member drag_to_rearrange_enabled].
</description>
</signal>
- <signal name="right_button_pressed">
- <argument index="0" name="tab" type="int" />
- <description>
- Emitted when a tab is right-clicked.
- </description>
- </signal>
<signal name="tab_changed">
<argument index="0" name="tab" type="int" />
<description>
@@ -253,6 +247,12 @@
Emitted when a tab is hovered by the mouse.
</description>
</signal>
+ <signal name="tab_rmb_clicked">
+ <argument index="0" name="tab" type="int" />
+ <description>
+ Emitted when a tab is right-clicked.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="ALIGN_LEFT" value="0" enum="TabAlign">
@@ -281,15 +281,15 @@
</constant>
</constants>
<theme_items>
- <theme_item name="button" data_type="style" type="StyleBox">
+ <theme_item name="close" data_type="icon" type="Texture2D">
+ The icon for the close button (see [member tab_close_display_policy]).
+ </theme_item>
+ <theme_item name="close_bg_highlight" data_type="style" type="StyleBox">
Background of the close button when it's being hovered with the cursor.
</theme_item>
- <theme_item name="button_pressed" data_type="style" type="StyleBox">
+ <theme_item name="close_bg_pressed" data_type="style" type="StyleBox">
Background of the close button when it's being pressed.
</theme_item>
- <theme_item name="close" data_type="icon" type="Texture2D">
- The icon for the close button (see [member tab_close_display_policy]).
- </theme_item>
<theme_item name="decrement" data_type="icon" type="Texture2D">
Icon for the left arrow button that appears when there are too many tabs to fit in the container width. When the button is disabled (i.e. the first tab is visible), it appears semi-transparent.
</theme_item>
@@ -315,7 +315,7 @@
Font color of the other, unselected tabs.
</theme_item>
<theme_item name="hseparation" data_type="constant" type="int" default="4">
- The horizontal separation between the tabs.
+ The horizontal separation between the elements inside tabs.
</theme_item>
<theme_item name="increment" data_type="icon" type="Texture2D">
Icon for the right arrow button that appears when there are too many tabs to fit in the container width. When the button is disabled (i.e. the last tab is visible) it appears semi-transparent.
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index aa35acdbd2..e06dfee698 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -281,7 +281,7 @@
<member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0">
Text writing direction.
</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].
</member>
<member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1">
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 7fe9278f2c..18ace85465 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -1,5 +1,5 @@
<?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>
Interface for the fonts and complex text layouts.
</brief_description>
@@ -487,8 +487,8 @@
</method>
<method name="font_set_data">
<return type="void" />
- <argument index="0" name="data" type="RID" />
- <argument index="1" name="arg1" type="PackedByteArray" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="data" type="PackedByteArray" />
<description>
Sets font source data, e.g contents of the dynamic font source file.
</description>
@@ -714,12 +714,14 @@
<return type="Dictionary" />
<argument index="0" name="font_rid" type="RID" />
<description>
+ Returns the dictionary of the supported OpenType features.
</description>
</method>
<method name="font_supported_variation_list" qualifiers="const">
<return type="Dictionary" />
<argument index="0" name="font_rid" type="RID" />
<description>
+ Returns the dictionary of the supported OpenType variation coordinates.
</description>
</method>
<method name="format_number" qualifiers="const">
@@ -737,6 +739,12 @@
Frees an object created by this [TextServer].
</description>
</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">
<return type="Vector2" />
<argument index="0" name="size" type="int" />
@@ -751,6 +759,18 @@
Returns the name of the server interface.
</description>
</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">
<return type="bool" />
<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.
</description>
</method>
- <method name="has_feature">
+ <method name="has_feature" qualifiers="const">
<return type="bool" />
<argument index="0" name="feature" type="int" enum="TextServer.Feature" />
<description>
Returns [code]true[/code] if the server supports a feature.
</description>
</method>
- <method name="is_locale_right_to_left">
+ <method name="is_locale_right_to_left" qualifiers="const">
<return type="bool" />
<argument index="0" name="locale" type="String" />
<description>
@@ -802,6 +822,14 @@
Returns percent sign used in the [code]language[/code].
</description>
</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">
<return type="bool" />
<argument index="0" name="shaped" type="RID" />
@@ -898,7 +926,7 @@
Returns direction of the text.
</description>
</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" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="start" type="int" />
@@ -907,30 +935,58 @@
Returns dominant direction of in the range of text.
</description>
</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">
<return type="Array" />
<argument index="0" name="shaped" type="RID" />
<description>
- Returns text glyphs.
+ Returns text glyphs in the visual order.
</description>
</method>
<method name="shaped_text_get_line_breaks" qualifiers="const">
- <return type="Array" />
+ <return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="width" type="float" />
<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>
Breaks text to the lines and returns character ranges for each line.
</description>
</method>
<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="1" name="width" type="PackedFloat32Array" />
<argument index="2" name="start" type="int" default="0" />
<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>
Breaks text to the lines and columns. Returns character ranges for each segment.
</description>
@@ -987,7 +1043,7 @@
</description>
</method>
<method name="shaped_text_get_selection" qualifiers="const">
- <return type="Array" />
+ <return type="PackedVector2Array" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="start" type="int" />
<argument index="2" name="end" type="int" />
@@ -1002,6 +1058,13 @@
Returns size of the text.
</description>
</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">
<return type="float" />
<argument index="0" name="shaped" type="RID" />
@@ -1024,8 +1087,9 @@
</description>
</method>
<method name="shaped_text_get_word_breaks" qualifiers="const">
- <return type="Array" />
+ <return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="grapheme_flags" type="int" />
<description>
Breaks text into words and returns array of character ranges.
</description>
@@ -1053,7 +1117,7 @@
Returns [code]true[/code] if buffer is successfully shaped.
</description>
</method>
- <method name="shaped_text_next_grapheme_pos">
+ <method name="shaped_text_next_grapheme_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="pos" type="int" />
@@ -1070,7 +1134,7 @@
Trims text if it exceeds the given width.
</description>
</method>
- <method name="shaped_text_prev_grapheme_pos">
+ <method name="shaped_text_prev_grapheme_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
<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.
</description>
</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">
<return type="RID" />
<argument index="0" name="shaped" type="RID" />
@@ -1196,18 +1267,24 @@
<constant name="JUSTIFICATION_AFTER_LAST_TAB" value="8" enum="JustificationFlag">
Only apply justification to the part of the text after the last tab.
</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">
Do not break the line.
</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]).
</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.
</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.
</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">
No trimming is performed.
</constant>
@@ -1223,6 +1300,11 @@
<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.
</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">
Grapheme is part of right-to-left or bottom-to-top run.
</constant>
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
new file mode 100644
index 0000000000..29571463d2
--- /dev/null
+++ b/doc/classes/TextServerExtension.xml
@@ -0,0 +1,1262 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="TextServerExtension" inherits="TextServer" version="4.0">
+ <brief_description>
+ Base class for TextServer custom implementations (plugins).
+ </brief_description>
+ <description>
+ External TextServer implementations should inherit from this class.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_create_font" qualifiers="virtual">
+ <return type="RID" />
+ <description>
+ Creates new, empty font cache entry resource. To free the resulting resourec, use [method _free] method.
+ </description>
+ </method>
+ <method name="_create_shaped_text" qualifiers="virtual">
+ <return type="RID" />
+ <argument index="0" name="direction" type="int" enum="TextServer.Direction" />
+ <argument index="1" name="orientation" type="int" enum="TextServer.Orientation" />
+ <description>
+ Creates new buffer for complex text layout, with the given [code]direction[/code] and [code]orientation[/code]. To free the resulting buffer, use [method _free] method.
+ Note: Direction is ignored if server does not support [code]FEATURE_BIDI_LAYOUT[/code] feature.
+ Note: Orientation is ignored if server does not support [code]FEATURE_VERTICAL_LAYOUT[/code] feature.
+ </description>
+ </method>
+ <method name="_draw_hex_code_box" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="canvas" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="pos" type="Vector2" />
+ <argument index="3" name="index" type="int" />
+ <argument index="4" name="color" type="Color" />
+ <description>
+ Draws box displaying character hexadecimal code. Used for replacing missing characters.
+ </description>
+ </method>
+ <method name="_font_clear_glyphs" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <description>
+ Removes all rendered glyphs information from the cache entry. Note: This function will not remove textures associated with the glyphs, use [method _font_remove_texture] to remove them manually.
+ </description>
+ </method>
+ <method name="_font_clear_kerning_map" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Removes all kerning overrides.
+ </description>
+ </method>
+ <method name="_font_clear_size_cache" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Removes all font sizes from the cache entry
+ </description>
+ </method>
+ <method name="_font_clear_textures" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <description>
+ Removes all textures from font cache entry. Note: This function will not remove glyphs associated with the texture, use [method _font_remove_glyph] to remove them manually.
+ </description>
+ </method>
+ <method name="_font_draw_glyph" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="canvas" type="RID" />
+ <argument index="2" name="size" type="int" />
+ <argument index="3" name="pos" type="Vector2" />
+ <argument index="4" name="index" type="int" />
+ <argument index="5" name="color" type="Color" />
+ <description>
+ Draws single glyph into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code].
+ Note: Glyph index is specific to the font, use glyphs indices returned by [method _shaped_text_get_glyphs] or [method _font_get_glyph_index].
+ </description>
+ </method>
+ <method name="_font_draw_glyph_outline" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="canvas" type="RID" />
+ <argument index="2" name="size" type="int" />
+ <argument index="3" name="outline_size" type="int" />
+ <argument index="4" name="pos" type="Vector2" />
+ <argument index="5" name="index" type="int" />
+ <argument index="6" name="color" type="Color" />
+ <description>
+ Draws single glyph outline of size [code]outline_size[/code] into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code].
+ Note: Glyph index is specific to the font, use glyphs indices returned by [method _shaped_text_get_glyphs] or [method _font_get_glyph_index].
+ </description>
+ </method>
+ <method name="_font_get_ascent" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns the font ascent (number of pixels above the baseline).
+ </description>
+ </method>
+ <method name="_font_get_descent" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns the font descent (number of pixels below the baseline).
+ </description>
+ </method>
+ <method name="_font_get_fixed_size" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns bitmap font fixed size.
+ </description>
+ </method>
+ <method name="_font_get_global_oversampling" qualifiers="virtual const">
+ <return type="float" />
+ <description>
+ Returns the font oversampling factor, shared by all fonts in the TextServer.
+ </description>
+ </method>
+ <method name="_font_get_glyph_advance" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns glyph advance (offset of the next glyph). Note: advance for glyphs outlines is the same as the base glyph advance and is not saved.
+ </description>
+ </method>
+ <method name="_font_get_glyph_contours" qualifiers="virtual const">
+ <return type="Dictionary" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="index" type="int" />
+ <description>
+ Returns outline contours of the glyph as a [code]Dictionary[/code] with the following contents:
+ [code]points[/code] - [PackedVector3Array], containing outline points. [code]x[/code] and [code]y[/code] are point coordinates. [code]z[/code] is the type of the point, using the [enum TextServer.ContourPointTag] values.
+ [code]contours[/code] - [PackedInt32Array], containing indices the end points of each contour.
+ [code]orientation[/code] - [bool], contour orientation. If [code]true[/code], clockwise contours must be filled.
+ </description>
+ </method>
+ <method name="_font_get_glyph_index" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="char" type="int" />
+ <argument index="3" name="variation_selector" type="int" />
+ <description>
+ Returns the glyph index of a [code]char[/code], optionally modified by the [code]variation_selector[/code].
+ </description>
+ </method>
+ <method name="_font_get_glyph_list" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <description>
+ Returns list of rendered glyphs in the cache entry.
+ </description>
+ </method>
+ <method name="_font_get_glyph_offset" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns glyph offset from the baseline.
+ </description>
+ </method>
+ <method name="_font_get_glyph_size" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns size of the glyph.
+ </description>
+ </method>
+ <method name="_font_get_glyph_texture_idx" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns index of the cache texture containing the glyph.
+ </description>
+ </method>
+ <method name="_font_get_glyph_uv_rect" qualifiers="virtual const">
+ <return type="Rect2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns rectangle in the cache texture containing the glyph.
+ </description>
+ </method>
+ <method name="_font_get_hinting" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns the font hinting mode. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_get_kerning" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="glyph_pair" type="Vector2i" />
+ <description>
+ Returns kerning for the pair of glyphs.
+ </description>
+ </method>
+ <method name="_font_get_kerning_list" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns list of the kerning overrides.
+ </description>
+ </method>
+ <method name="_font_get_language_support_override" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="language" type="String" />
+ <description>
+ Returns [code]true[/code] if support override is enabled for the [code]language[/code].
+ </description>
+ </method>
+ <method name="_font_get_language_support_overrides" qualifiers="virtual">
+ <return type="PackedStringArray" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns list of language support overrides.
+ </description>
+ </method>
+ <method name="_font_get_msdf_pixel_range" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Return the width of the range around the shape between the minimum and maximum representable signed distance.
+ </description>
+ </method>
+ <method name="_font_get_msdf_size" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns source font size used to generate MSDF textures.
+ </description>
+ </method>
+ <method name="_font_get_oversampling" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_get_scale" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns scaling factor of the color bitmap font.
+ </description>
+ </method>
+ <method name="_font_get_script_support_override" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="script" type="String" />
+ <description>
+ Returns [code]true[/code] if support override is enabled for the [code]script[/code].
+ </description>
+ </method>
+ <method name="_font_get_script_support_overrides" qualifiers="virtual">
+ <return type="PackedStringArray" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns list of script support overrides.
+ </description>
+ </method>
+ <method name="_font_get_size_cache_list" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Return list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
+ </description>
+ </method>
+ <method name="_font_get_spacing" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <description>
+ Returns extra spacing added between glyphs in pixels.
+ </description>
+ </method>
+ <method name="_font_get_supported_chars" qualifiers="virtual const">
+ <return type="String" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns a string containing all the characters available in the font.
+ </description>
+ </method>
+ <method name="_font_get_texture_count" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <description>
+ Returns number of textures used by font cache entry.
+ </description>
+ </method>
+ <method name="_font_get_texture_image" qualifiers="virtual const">
+ <return type="Image" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="texture_index" type="int" />
+ <description>
+ Returns font cache texture image data.
+ </description>
+ </method>
+ <method name="_font_get_texture_offsets" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="texture_index" type="int" />
+ <description>
+ Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
+ </description>
+ </method>
+ <method name="_font_get_underline_position" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns pixel offset of the underline below the baseline.
+ </description>
+ </method>
+ <method name="_font_get_underline_thickness" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ Returns thickness of the underline in pixels.
+ </description>
+ </method>
+ <method name="_font_get_variation_coordinates" qualifiers="virtual const">
+ <return type="Dictionary" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns variation coordinates for the specified font cache entry. See [method _font_supported_variation_list] for more info.
+ </description>
+ </method>
+ <method name="_font_has_char" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="char" type="int" />
+ <description>
+ Return [code]true[/code] if a Unicode [code]char[/code] is available in the font.
+ </description>
+ </method>
+ <method name="_font_is_antialiased" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled.
+ </description>
+ </method>
+ <method name="_font_is_force_autohinter" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if auto-hinting is supported and preffered over font built-in hinting. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_is_language_supported" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="language" type="String" />
+ <description>
+ Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code).
+ </description>
+ </method>
+ <method name="_font_is_multichannel_signed_distance_field" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data.
+ </description>
+ </method>
+ <method name="_font_is_script_supported" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="script" type="String" />
+ <description>
+ Returns [code]true[/code], if font supports given script (ISO 15924 code).
+ </description>
+ </method>
+ <method name="_font_remove_glyph" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Removes specified rendered glyph information from the cache entry. Note: This function will not remove textures associated with the glyphs, use [method _font_remove_texture] to remove them manually.
+ </description>
+ </method>
+ <method name="_font_remove_kerning" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="glyph_pair" type="Vector2i" />
+ <description>
+ Removes kerning override for the pair of glyphs.
+ </description>
+ </method>
+ <method name="_font_remove_language_support_override" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="language" type="String" />
+ <description>
+ Remove language support override.
+ </description>
+ </method>
+ <method name="_font_remove_script_support_override" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="script" type="String" />
+ <description>
+ Removes script support override.
+ </description>
+ </method>
+ <method name="_font_remove_size_cache" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <description>
+ Removes specified font size from the cache entry.
+ </description>
+ </method>
+ <method name="_font_remove_texture" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="texture_index" type="int" />
+ <description>
+ Removes specified texture from font cache entry. Note: This function will not remove glyphs associated with the texture, remove them manually, using [method _font_remove_glyph].
+ </description>
+ </method>
+ <method name="_font_render_glyph" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="index" type="int" />
+ <description>
+ Renders specified glyph the the font cache texture.
+ </description>
+ </method>
+ <method name="_font_render_range" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="start" type="int" />
+ <argument index="3" name="end" type="int" />
+ <description>
+ Renders the range of characters to the font cache texture.
+ </description>
+ </method>
+ <method name="_font_set_antialiased" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="antialiased" type="bool" />
+ <description>
+ If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_set_ascent" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="ascent" type="float" />
+ <description>
+ Sets the font ascent (number of pixels above the baseline).
+ </description>
+ </method>
+ <method name="_font_set_data" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="data" type="PackedByteArray" />
+ <description>
+ Sets font source data, e.g contents of the dynamic font source file.
+ </description>
+ </method>
+ <method name="_font_set_data_ptr" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="data_ptr" type="const uint8_t*" />
+ <argument index="2" name="data_size" type="int" />
+ <description>
+ Sets the font descent (number of pixels below the baseline).
+ </description>
+ </method>
+ <method name="_font_set_descent" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="descent" type="float" />
+ <description>
+ Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes.
+ </description>
+ </method>
+ <method name="_font_set_fixed_size" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="fixed_size" type="int" />
+ <description>
+ If set to [code]true[/code] auto-hinting is preffered over font built-in hinting.
+ </description>
+ </method>
+ <method name="_font_set_force_autohinter" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="force_autohinter" type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_font_set_global_oversampling" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="oversampling" type="float" />
+ <description>
+ Sets oversampling factor, shared by all font in the TextServer.
+ Note: This value can be automaticaly changed by display server.
+ </description>
+ </method>
+ <method name="_font_set_glyph_advance" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="glyph" type="int" />
+ <argument index="3" name="advance" type="Vector2" />
+ <description>
+ Sets glyph advance (offset of the next glyph). Note: advance for glyphs outlines is the same as the base glyph advance and is not saved.
+ </description>
+ </method>
+ <method name="_font_set_glyph_offset" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <argument index="3" name="offset" type="Vector2" />
+ <description>
+ Sets glyph offset from the baseline.
+ </description>
+ </method>
+ <method name="_font_set_glyph_size" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <argument index="3" name="gl_size" type="Vector2" />
+ <description>
+ Sets size of the glyph.
+ </description>
+ </method>
+ <method name="_font_set_glyph_texture_idx" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <argument index="3" name="texture_idx" type="int" />
+ <description>
+ Sets index of the cache texture containing the glyph.
+ </description>
+ </method>
+ <method name="_font_set_glyph_uv_rect" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <argument index="3" name="uv_rect" type="Rect2" />
+ <description>
+ Sets rectangle in the cache texture containing the glyph.
+ </description>
+ </method>
+ <method name="_font_set_hinting" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="hinting" type="int" enum="TextServer.Hinting" />
+ <description>
+ Sets font hinting mode. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_set_kerning" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="glyph_pair" type="Vector2i" />
+ <argument index="3" name="kerning" type="Vector2" />
+ <description>
+ Sets kerning for the pair of glyphs.
+ </description>
+ </method>
+ <method name="_font_set_language_support_override" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="language" type="String" />
+ <argument index="2" name="supported" type="bool" />
+ <description>
+ Adds override for [method _font_is_language_supported].
+ </description>
+ </method>
+ <method name="_font_set_msdf_pixel_range" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="msdf_pixel_range" type="int" />
+ <description>
+ Sets the width of the range around the shape between the minimum and maximum representable signed distance.
+ </description>
+ </method>
+ <method name="_font_set_msdf_size" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="msdf_size" type="int" />
+ <description>
+ Sets source font size used to generate MSDF textures.
+ </description>
+ </method>
+ <method name="_font_set_multichannel_signed_distance_field" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="msdf" type="bool" />
+ <description>
+ If set to [code]true[/code], glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data.
+ </description>
+ </method>
+ <method name="_font_set_oversampling" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="oversampling" type="float" />
+ <description>
+ Sets font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. Used by dynamic fonts only.
+ </description>
+ </method>
+ <method name="_font_set_scale" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="scale" type="float" />
+ <description>
+ Sets scaling factor of the color bitmap font.
+ </description>
+ </method>
+ <method name="_font_set_script_support_override" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="script" type="String" />
+ <argument index="2" name="supported" type="bool" />
+ <description>
+ Adds override for [method _font_is_script_supported].
+ </description>
+ </method>
+ <method name="_font_set_spacing" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <argument index="3" name="value" type="int" />
+ <description>
+ Sets extra spacing added between glyphs in pixels.
+ </description>
+ </method>
+ <method name="_font_set_texture_image" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="texture_index" type="int" />
+ <argument index="3" name="image" type="Image" />
+ <description>
+ Sets font cache texture image data.
+ </description>
+ </method>
+ <method name="_font_set_texture_offsets" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="texture_index" type="int" />
+ <argument index="3" name="offset" type="PackedInt32Array" />
+ <description>
+ Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
+ </description>
+ </method>
+ <method name="_font_set_underline_position" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="underline_position" type="float" />
+ <description>
+ Sets pixel offset of the underline below the baseline.
+ </description>
+ </method>
+ <method name="_font_set_underline_thickness" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="underline_thickness" type="float" />
+ <description>
+ Sets thickness of the underline in pixels.
+ </description>
+ </method>
+ <method name="_font_set_variation_coordinates" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="variation_coordinates" type="Dictionary" />
+ <description>
+ Sets variation coordinates for the specified font cache entry. See [method _font_supported_variation_list] for more info.
+ </description>
+ </method>
+ <method name="_font_supported_feature_list" qualifiers="virtual const">
+ <return type="Dictionary" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns the dictionary of the supported OpenType features.
+ </description>
+ </method>
+ <method name="_font_supported_variation_list" qualifiers="virtual const">
+ <return type="Dictionary" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns the dictionary of the supported OpenType variation coordinates.
+ </description>
+ </method>
+ <method name="_format_number" qualifiers="virtual const">
+ <return type="String" />
+ <argument index="0" name="string" type="String" />
+ <argument index="1" name="language" type="String" />
+ <description>
+ Converts a number from the Western Arabic (0..9) to the numeral systems used in [code]language[/code].
+ </description>
+ </method>
+ <method name="_free" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="rid" type="RID" />
+ <description>
+ Frees an object created by this [TextServer].
+ </description>
+ </method>
+ <method name="_get_features" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ Returns text server features, see [enum TextServer.Feature].
+ </description>
+ </method>
+ <method name="_get_hex_code_box_size" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="size" type="int" />
+ <argument index="1" name="index" type="int" />
+ <description>
+ Returns size of the replacement character (box with character hexadecimal code that is drawn in place of invalid characters).
+ </description>
+ </method>
+ <method name="_get_name" qualifiers="virtual const">
+ <return type="String" />
+ <description>
+ Returns the name of the server interface.
+ </description>
+ </method>
+ <method name="_get_support_data_filename" qualifiers="virtual 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="virtual const">
+ <return type="String" />
+ <description>
+ Returns TextServer database (e.g. ICU break iterators and dictionaries) description.
+ </description>
+ </method>
+ <method name="_has" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if [code]rid[/code] is valid resource owned by this text server.
+ </description>
+ </method>
+ <method name="_has_feature" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="feature" type="int" enum="TextServer.Feature" />
+ <description>
+ Returns [code]true[/code] if the server supports a feature.
+ </description>
+ </method>
+ <method name="_is_locale_right_to_left" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="locale" type="String" />
+ <description>
+ Returns [code]true[/code] if locale is right-to-left.
+ </description>
+ </method>
+ <method name="_load_support_data" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="filename" type="String" />
+ <description>
+ Loads optional TextServer database (e.g. ICU break iterators and dictionaries).
+ Note: This function should be called before any other TextServer functions used, otherwise it won't have any effect.
+ </description>
+ </method>
+ <method name="_name_to_tag" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ Converts readable feature, variation, script or language name to OpenType tag.
+ </description>
+ </method>
+ <method name="_parse_number" qualifiers="virtual const">
+ <return type="String" />
+ <argument index="0" name="string" type="String" />
+ <argument index="1" name="language" type="String" />
+ <description>
+ Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9).
+ </description>
+ </method>
+ <method name="_percent_sign" qualifiers="virtual const">
+ <return type="String" />
+ <argument index="0" name="language" type="String" />
+ <description>
+ Returns percent sign used in the [code]language[/code].
+ </description>
+ </method>
+ <method name="_save_support_data" qualifiers="virtual 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" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="key" type="Variant" />
+ <argument index="2" name="size" type="Vector2" />
+ <argument index="3" name="inline_align" type="int" enum="InlineAlign" />
+ <argument index="4" name="length" type="int" />
+ <description>
+ Adds inline object to the text buffer, [code]key[/code] must be unique. In the text, object is represented as [code]length[/code] object replacement characters.
+ </description>
+ </method>
+ <method name="_shaped_text_add_string" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="text" type="String" />
+ <argument index="2" name="fonts" type="Array" />
+ <argument index="3" name="size" type="int" />
+ <argument index="4" name="opentype_features" type="Dictionary" />
+ <argument index="5" name="language" type="String" />
+ <description>
+ Adds text span and font to draw it to the text buffer.
+ </description>
+ </method>
+ <method name="_shaped_text_clear" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Clears text buffer (removes text and inline objects).
+ </description>
+ </method>
+ <method name="_shaped_text_draw" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="canvas" type="RID" />
+ <argument index="2" name="pos" type="Vector2" />
+ <argument index="3" name="clip_l" type="float" />
+ <argument index="4" name="clip_r" type="float" />
+ <argument index="5" name="color" type="Color" />
+ <description>
+ Draw shaped text into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the leftmost point of the baseline (for horizontal layout) or topmost point of the baseline (for vertical layout).
+ </description>
+ </method>
+ <method name="_shaped_text_draw_outline" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="canvas" type="RID" />
+ <argument index="2" name="pos" type="Vector2" />
+ <argument index="3" name="clip_l" type="float" />
+ <argument index="4" name="clip_r" type="float" />
+ <argument index="5" name="outline_size" type="int" />
+ <argument index="6" name="color" type="Color" />
+ <description>
+ Draw the outline of the shaped text into a canvas item at a given position, with [code]color[/code]. [code]pos[/code] specifies the leftmost point of the baseline (for horizontal layout) or topmost point of the baseline (for vertical layout).
+ </description>
+ </method>
+ <method name="_shaped_text_fit_to_width" qualifiers="virtual">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="width" type="float" />
+ <argument index="2" name="jst_flags" type="int" />
+ <description>
+ Adjusts text with to fit to specified width, returns new text width
+ </description>
+ </method>
+ <method name="_shaped_text_get_ascent" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns the text ascent (number of pixels above the baseline for horizontal layout or to the left of baseline for vertical).
+ Note: overall ascent can be higher than font ascent, if some glyphs are displaced from the baseline.
+ </description>
+ </method>
+ <method name="_shaped_text_get_carets" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="position" type="int" />
+ <argument index="2" name="caret" type="CaretInfo*" />
+ <description>
+ Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle.
+ </description>
+ </method>
+ <method name="_shaped_text_get_descent" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns the text descent (number of pixels below the baseline for horizontal layout or to the right of baseline for vertical).
+ Note: overall descent can be higher than font descent, if some glyphs are displaced from the baseline.
+ </description>
+ </method>
+ <method name="_shaped_text_get_direction" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns direction of the text.
+ </description>
+ </method>
+ <method name="_shaped_text_get_dominant_direction_in_range" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="start" type="int" />
+ <argument index="2" name="end" type="int" />
+ <description>
+ Returns dominant direction of in the range of text.
+ </description>
+ </method>
+ <method name="_shaped_text_get_ellipsis_glyph_count" qualifiers="virtual 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="virtual const">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="r_glyphs" type="void*" />
+ <description>
+ Returns array of the glyphs in the ellipsis.
+ </description>
+ </method>
+ <method name="_shaped_text_get_ellipsis_pos" qualifiers="virtual 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="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns text glyphs count.
+ </description>
+ </method>
+ <method name="_shaped_text_get_glyphs" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="r_glyphs" type="void*" />
+ <description>
+ Copies text glyphs in the visual order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count].
+ </description>
+ </method>
+ <method name="_shaped_text_get_line_breaks" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="width" type="float" />
+ <argument index="2" name="start" type="int" />
+ <argument index="3" name="break_flags" type="int" />
+ <description>
+ Breaks text to the lines and returns character ranges for each line.
+ </description>
+ </method>
+ <method name="_shaped_text_get_line_breaks_adv" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="width" type="PackedFloat32Array" />
+ <argument index="2" name="start" type="int" />
+ <argument index="3" name="once" type="bool" />
+ <argument index="4" name="break_flags" type="int" />
+ <description>
+ Breaks text to the lines and columns. Returns character ranges for each segment.
+ </description>
+ </method>
+ <method name="_shaped_text_get_object_rect" qualifiers="virtual const">
+ <return type="Rect2" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="key" type="Variant" />
+ <description>
+ Returns bounding rectangle of the inline object.
+ </description>
+ </method>
+ <method name="_shaped_text_get_objects" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns array of inline objects.
+ </description>
+ </method>
+ <method name="_shaped_text_get_orientation" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns text orientation.
+ </description>
+ </method>
+ <method name="_shaped_text_get_parent" qualifiers="virtual const">
+ <return type="RID" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Sets text orientation.
+ </description>
+ </method>
+ <method name="_shaped_text_get_preserve_control" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns [code]true[/code] if text buffer is configured to display control characters.
+ </description>
+ </method>
+ <method name="_shaped_text_get_preserve_invalid" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns [code]true[/code] if text buffer is configured to display hexadecimal codes in place of invalid characters.
+ Note: If set to [code]false[/code], nothing is displayed in place of invalid characters.
+ </description>
+ </method>
+ <method name="_shaped_text_get_range" qualifiers="virtual const">
+ <return type="Vector2i" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns substring buffer character range in the parent buffer.
+ </description>
+ </method>
+ <method name="_shaped_text_get_selection" qualifiers="virtual const">
+ <return type="PackedVector2Array" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="start" type="int" />
+ <argument index="2" name="end" type="int" />
+ <description>
+ Returns selection rectangles for the specified character range.
+ </description>
+ </method>
+ <method name="_shaped_text_get_size" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns size of the text.
+ </description>
+ </method>
+ <method name="_shaped_text_get_trim_pos" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns ellipsis and trim positions.
+ </description>
+ </method>
+ <method name="_shaped_text_get_underline_position" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns pixel offset of the underline below the baseline.
+ </description>
+ </method>
+ <method name="_shaped_text_get_underline_thickness" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns thickness of the underline.
+ </description>
+ </method>
+ <method name="_shaped_text_get_width" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns width (for horizontal layout) or height (for vertical) of the text.
+ </description>
+ </method>
+ <method name="_shaped_text_get_word_breaks" qualifiers="virtual const">
+ <return type="PackedInt32Array" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="grapheme_flags" type="int" />
+ <description>
+ Breaks text into words and returns array of character ranges.
+ </description>
+ </method>
+ <method name="_shaped_text_hit_test_grapheme" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="coord" type="float" />
+ <description>
+ Returns grapheme index at the specified pixel offset at the baseline, or [code]-1[/code] if none is found.
+ </description>
+ </method>
+ <method name="_shaped_text_hit_test_position" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="coord" type="float" />
+ <description>
+ Returns caret character offset at the specified pixel offset at the baseline. This function always returns a valid position.
+ </description>
+ </method>
+ <method name="_shaped_text_is_ready" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Returns [code]true[/code] if buffer is successfully shaped.
+ </description>
+ </method>
+ <method name="_shaped_text_next_grapheme_pos" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="pos" type="int" />
+ <description>
+ Returns composite character end position closest to the [code]pos[/code].
+ </description>
+ </method>
+ <method name="_shaped_text_overrun_trim_to_width" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="width" type="float" />
+ <argument index="2" name="trim_flags" type="int" />
+ <description>
+ Trims text if it exceeds the given width.
+ </description>
+ </method>
+ <method name="_shaped_text_prev_grapheme_pos" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="pos" type="int" />
+ <description>
+ Returns composite character start position closest to the [code]pos[/code].
+ </description>
+ </method>
+ <method name="_shaped_text_resize_object" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="key" type="Variant" />
+ <argument index="2" name="size" type="Vector2" />
+ <argument index="3" name="inline_align" type="int" enum="InlineAlign" />
+ <description>
+ Sets new size and alignment of embedded object.
+ </description>
+ </method>
+ <method name="_shaped_text_set_bidi_override" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="override" type="Array" />
+ <description>
+ Overrides BiDi for the structured text.
+ Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately.
+ </description>
+ </method>
+ <method name="_shaped_text_set_direction" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="direction" type="int" enum="TextServer.Direction" />
+ <description>
+ Sets desired text direction. If set to [code]TEXT_DIRECTION_AUTO[/code], direction will be detected based on the buffer contents and current locale.
+ Note: Direction is ignored if server does not support [code]FEATURE_BIDI_LAYOUT[/code] feature.
+ </description>
+ </method>
+ <method name="_shaped_text_set_orientation" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="orientation" type="int" enum="TextServer.Orientation" />
+ <description>
+ Sets desired text orientation.
+ Note: Orientation is ignored if server does not support [code]FEATURE_VERTICAL_LAYOUT[/code] feature.
+ </description>
+ </method>
+ <method name="_shaped_text_set_preserve_control" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="enabled" type="bool" />
+ <description>
+ If set to [code]true[/code] text buffer will display control characters.
+ </description>
+ </method>
+ <method name="_shaped_text_set_preserve_invalid" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="enabled" type="bool" />
+ <description>
+ If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed.
+ </description>
+ </method>
+ <method name="_shaped_text_shape" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Shapes buffer if it's not shaped. Returns [code]true[/code] if the string is shaped successfully.
+ 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>
+ </method>
+ <method name="_shaped_text_sort_logical" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="r_glyphs" type="void*" />
+ <description>
+ Copies text glyphs in the logical order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count].
+ </description>
+ </method>
+ <method name="_shaped_text_substr" qualifiers="virtual const">
+ <return type="RID" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="start" type="int" />
+ <argument index="2" name="length" type="int" />
+ <description>
+ Returns text buffer for the substring of the text in the [code]shaped[/code] text buffer (including inline objects).
+ </description>
+ </method>
+ <method name="_shaped_text_tab_align" qualifiers="virtual">
+ <return type="float" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="tab_stops" type="PackedFloat32Array" />
+ <description>
+ Aligns shaped text to the given tab-stops.
+ </description>
+ </method>
+ <method name="_shaped_text_update_breaks" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Updates line and word breaks.
+ </description>
+ </method>
+ <method name="_shaped_text_update_justification_ops" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="shaped" type="RID" />
+ <description>
+ Updates justification opportunities (spaces, kashidas, etc.).
+ </description>
+ </method>
+ <method name="_tag_to_name" qualifiers="virtual const">
+ <return type="String" />
+ <argument index="0" name="tag" type="int" />
+ <description>
+ Converts OpenType tag to readable feature, variation, script or language name.
+ </description>
+ </method>
+ </methods>
+</class>
diff --git a/doc/classes/TextServerManager.xml b/doc/classes/TextServerManager.xml
index 0e7b6d15d3..aa2177c3b1 100644
--- a/doc/classes/TextServerManager.xml
+++ b/doc/classes/TextServerManager.xml
@@ -10,6 +10,13 @@
<tutorials>
</tutorials>
<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">
<return type="TextServer" />
<argument index="0" name="name" type="String" />
@@ -19,7 +26,7 @@
</method>
<method name="get_interface" qualifiers="const">
<return type="TextServer" />
- <argument index="0" name="index" type="int" />
+ <argument index="0" name="idx" type="int" />
<description>
Returns the interface registered at a given index.
</description>
@@ -30,20 +37,6 @@
Returns the number of interfaces currently registered.
</description>
</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">
<return type="Array" />
<description>
@@ -53,15 +46,36 @@
<method name="get_primary_interface" qualifiers="const">
<return type="TextServer" />
<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>
</method>
<method name="set_primary_interface">
- <return type="bool" />
- <argument index="0" name="index" type="int" />
+ <return type="void" />
+ <argument index="0" name="index" type="TextServer" />
<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>
</method>
</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>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 44825d2536..8bc87b7f81 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6221,12 +6221,12 @@ EditorNode::EditorNode() {
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
- scene_tabs->connect("right_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited));
+ scene_tabs->connect("tab_rmb_clicked", callable_mp(this, &EditorNode::_scene_tab_script_edited));
scene_tabs->connect("tab_closed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE));
scene_tabs->connect("tab_hovered", callable_mp(this, &EditorNode::_scene_tab_hovered));
scene_tabs->connect("mouse_exited", callable_mp(this, &EditorNode::_scene_tab_exit));
scene_tabs->connect("gui_input", callable_mp(this, &EditorNode::_scene_tab_input));
- scene_tabs->connect("reposition_active_tab_request", callable_mp(this, &EditorNode::_reposition_active_tab));
+ scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorNode::_reposition_active_tab));
scene_tabs->connect("resized", callable_mp(this, &EditorNode::_update_scene_tabs));
tabbar_container = memnew(HBoxContainer);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index c0dadc4484..2d4a3ac788 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3574,7 +3574,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
case Variant::PACKED_COLOR_ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
editor->setup(Variant::PACKED_COLOR_ARRAY);
-
+ return editor;
} break;
default: {
}
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 9cecb62c66..9b5dc8851c 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -429,6 +429,12 @@ void EditorPropertyArray::_button_draw() {
bool EditorPropertyArray::_is_drop_valid(const Dictionary &p_drag_data) const {
String allowed_type = Variant::get_type_name(subtype);
+ // When the subtype is of type Object, an additional subtype may be specified in the hint string
+ // (e.g. Resource, Texture2D, ShaderMaterial, etc). We want the allowed type to be that, not just "Object".
+ if (subtype == Variant::OBJECT && subtype_hint_string != "") {
+ allowed_type = subtype_hint_string;
+ }
+
Dictionary drag_data = p_drag_data;
if (drag_data.has("type") && String(drag_data["type"]) == "files") {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 25406055f2..f0e97a7787 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -73,14 +73,15 @@ bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value)
if (p_name == "shortcuts") {
Array arr = p_value;
- ERR_FAIL_COND_V(arr.size() && arr.size() & 1, true);
- for (int i = 0; i < arr.size(); i += 2) {
- String name = arr[i];
- Ref<InputEvent> shortcut = arr[i + 1];
+ for (int i = 0; i < arr.size(); i++) {
+ Dictionary dict = arr[i];
+ String name = dict["name"];
+
+ Array shortcut_events = dict["shortcuts"];
Ref<Shortcut> sc;
sc.instantiate();
- sc->set_event(shortcut);
+ sc->set_events(shortcut_events);
add_shortcut(name, sc);
}
@@ -138,11 +139,11 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
_THREAD_SAFE_METHOD_
if (p_name == "shortcuts") {
- Array arr;
- for (const KeyValue<String, Ref<Shortcut>> &E : shortcuts) {
- Ref<Shortcut> sc = E.value;
+ Array save_array;
+ for (const KeyValue<String, Ref<Shortcut>> &shortcut_definition : shortcuts) {
+ Ref<Shortcut> sc = shortcut_definition.value;
- if (builtin_action_overrides.has(E.key)) {
+ if (builtin_action_overrides.has(shortcut_definition.key)) {
// This shortcut was auto-generated from built in actions: don't save.
continue;
}
@@ -151,34 +152,57 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
if (!sc->has_meta("original")) {
continue; //this came from settings but is not any longer used
}
+ }
- Ref<InputEvent> original = sc->get_meta("original");
- if (sc->matches_event(original) || (original.is_null() && sc->get_event().is_null())) {
- continue; //not changed from default, don't save
- }
+ Array original_events = sc->get_meta("original");
+ Array shortcut_events = sc->get_events();
+
+ bool is_same = Shortcut::is_event_array_equal(original_events, shortcut_events);
+ if (is_same) {
+ continue; // Not changed from default; don't save.
}
- arr.push_back(E.key);
- arr.push_back(sc->get_event());
+ Dictionary dict;
+ dict["name"] = shortcut_definition.key;
+ dict["shortcuts"] = shortcut_events;
+
+ save_array.push_back(dict);
}
- r_ret = arr;
+ r_ret = save_array;
return true;
} else if (p_name == "builtin_action_overrides") {
Array actions_arr;
- for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtin_action_overrides) {
- List<Ref<InputEvent>> events = E.value;
+ for (const KeyValue<String, List<Ref<InputEvent>>> &action_override : builtin_action_overrides) {
+ List<Ref<InputEvent>> events = action_override.value;
- // TODO: skip actions which are the same as the builtin.
Dictionary action_dict;
- action_dict["name"] = E.key;
+ action_dict["name"] = action_override.key;
+ // Convert the list to an array, and only keep key events as this is for the editor.
Array events_arr;
- for (List<Ref<InputEvent>>::Element *I = events.front(); I; I = I->next()) {
- events_arr.push_back(I->get());
+ for (const Ref<InputEvent> &ie : events) {
+ Ref<InputEventKey> iek = ie;
+ if (iek.is_valid()) {
+ events_arr.append(iek);
+ }
}
- action_dict["events"] = events_arr;
+ Array defaults_arr;
+ List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins()[action_override.key];
+ for (const Ref<InputEvent> &default_input_event : defaults) {
+ if (default_input_event.is_valid()) {
+ defaults_arr.append(default_input_event);
+ }
+ }
+
+ bool same = Shortcut::is_event_array_equal(events_arr, defaults_arr);
+ // Don't save if same as default.
+ if (same) {
+ continue;
+ }
+
+ action_dict["events"] = events_arr;
actions_arr.push_back(action_dict);
}
@@ -1405,7 +1429,7 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const {
const Map<String, List<Ref<InputEvent>>>::Element *builtin_override = builtin_action_overrides.find(p_name);
if (builtin_override) {
sc.instantiate();
- sc->set_event(builtin_override->get().front()->get());
+ sc->set_events_list(&builtin_override->get());
sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
}
@@ -1414,7 +1438,7 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const {
const OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
if (builtin_default) {
sc.instantiate();
- sc->set_event(builtin_default.get().front()->get());
+ sc->set_events_list(&builtin_default.get());
sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
}
}
@@ -1450,52 +1474,91 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + ".");
+ PackedInt32Array arr;
+ arr.push_back(p_keycode);
+
+ ED_SHORTCUT_OVERRIDE_ARRAY(p_path, p_feature, arr);
+}
+
+void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes) {
+ Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+ ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + ".");
+
// Only add the override if the OS supports the provided feature.
- if (OS::get_singleton()->has_feature(p_feature)) {
- Ref<InputEventKey> ie;
- if (p_keycode) {
- ie = InputEventKey::create_reference(p_keycode);
+ if (!OS::get_singleton()->has_feature(p_feature)) {
+ return;
+ }
+
+ Array events;
+
+ for (int i = 0; i < p_keycodes.size(); i++) {
+ Key keycode = (Key)p_keycodes[i];
+
+#ifdef OSX_ENABLED
+ // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
+ if (keycode == KEY_DELETE) {
+ keycode = KEY_MASK_CMD | KEY_BACKSPACE;
}
+#endif
- // Directly override the existing shortcut.
- sc->set_event(ie);
- sc->set_meta("original", ie);
+ Ref<InputEventKey> ie;
+ if (keycode) {
+ ie = InputEventKey::create_reference(keycode);
+ events.push_back(ie);
+ }
}
+
+ // Directly override the existing shortcut.
+ sc->set_events(events);
+ sc->set_meta("original", events);
}
Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode) {
+ PackedInt32Array arr;
+ arr.push_back(p_keycode);
+ return ED_SHORTCUT_ARRAY(p_path, p_name, arr);
+}
+
+Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes) {
+ Array events;
+
+ for (int i = 0; i < p_keycodes.size(); i++) {
+ Key keycode = (Key)p_keycodes[i];
+
#ifdef OSX_ENABLED
- // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
- if (p_keycode == KEY_DELETE) {
- p_keycode = KEY_MASK_CMD | KEY_BACKSPACE;
- }
+ // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
+ if (keycode == KEY_DELETE) {
+ keycode = KEY_MASK_CMD | KEY_BACKSPACE;
+ }
#endif
- Ref<InputEventKey> ie;
- if (p_keycode) {
- ie = InputEventKey::create_reference(p_keycode);
+ Ref<InputEventKey> ie;
+ if (keycode) {
+ ie = InputEventKey::create_reference(keycode);
+ events.push_back(ie);
+ }
}
if (!EditorSettings::get_singleton()) {
Ref<Shortcut> sc;
sc.instantiate();
sc->set_name(p_name);
- sc->set_event(ie);
- sc->set_meta("original", ie);
+ sc->set_events(events);
+ sc->set_meta("original", events);
return sc;
}
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
if (sc.is_valid()) {
sc->set_name(p_name); //keep name (the ones that come from disk have no name)
- sc->set_meta("original", ie); //to compare against changes
+ sc->set_meta("original", events); //to compare against changes
return sc;
}
sc.instantiate();
sc->set_name(p_name);
- sc->set_event(ie);
- sc->set_meta("original", ie); //to compare against changes
+ sc->set_events(events);
+ sc->set_meta("original", events); //to compare against changes
EditorSettings::get_singleton()->add_shortcut(p_path, sc);
return sc;
@@ -1550,7 +1613,7 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr
// Update the shortcut (if it is used somewhere in the editor) to be the first event of the new list.
if (shortcuts.has(p_name)) {
- shortcuts[p_name]->set_event(event_list.front()->get());
+ shortcuts[p_name]->set_events_list(&event_list);
}
}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 9067539e29..04e227bc5c 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -201,7 +201,9 @@ Variant _EDITOR_GET(const String &p_setting);
#define ED_IS_SHORTCUT(p_name, p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name, p_ev))
Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode = KEY_NONE);
+Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes);
void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode = KEY_NONE);
+void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes);
Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path);
#endif // EDITOR_SETTINGS_H
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 1890814da9..ec90af1bcc 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -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);
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 = visual.size();
- const TextServer::Glyph *glyphs = visual.ptr();
+ int v_size = TS->shaped_text_get_glyph_count(num_rid);
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(num_rid);
for (int i = 0; i < v_size; i++) {
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)) {
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index de1d7b5706..0579fb4cbd 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -962,8 +962,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected);
theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected);
theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons"));
- theme->set_stylebox("button_pressed", "Tabs", style_menu);
- theme->set_stylebox("button", "Tabs", style_menu);
+ theme->set_stylebox("close_bg_pressed", "Tabs", style_menu);
+ theme->set_stylebox("close_bg_highlight", "Tabs", style_menu);
theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
diff --git a/editor/import/dynamicfont_import_settings.cpp b/editor/import/dynamicfont_import_settings.cpp
index 9a8abfa5c6..474c9d5296 100644
--- a/editor/import/dynamicfont_import_settings.cpp
+++ b/editor/import/dynamicfont_import_settings.cpp
@@ -1011,9 +1011,10 @@ void DynamicFontImportSettings::_glyph_text_selected() {
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_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) {
selected_glyphs.insert(gl[i].index);
}
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index dae3b6aaec..f179c01f89 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2483,8 +2483,14 @@ static bool is_shortcut_pressed(const String &p_path) {
if (shortcut.is_null()) {
return false;
}
- InputEventKey *k = Object::cast_to<InputEventKey>(shortcut->get_event().ptr());
- if (k == nullptr) {
+
+ const Array shortcuts = shortcut->get_events();
+ Ref<InputEventKey> k;
+ if (shortcuts.size() > 0) {
+ k = shortcuts.front();
+ }
+
+ if (k.is_null()) {
return false;
}
const Input &input = *Input::get_singleton();
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index f92f50f826..b1e104e680 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -43,6 +43,7 @@ void PhysicalBone3DEditor::_on_toggle_button_transform_joint(bool p_is_pressed)
void PhysicalBone3DEditor::_set_move_joint() {
if (selected) {
selected->_set_gizmo_move_joint(button_transform_joint->is_pressed());
+ Node3DEditor::get_singleton()->update_transform_gizmo();
}
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index a1591ce9d8..19e1b40a0d 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -3333,7 +3333,7 @@ ThemeEditor::ThemeEditor() {
preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
preview_tabbar_hb->add_child(preview_tabs);
preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab));
- preview_tabs->connect("right_button_pressed", callable_mp(this, &ThemeEditor::_remove_preview_tab));
+ preview_tabs->connect("tab_rmb_clicked", callable_mp(this, &ThemeEditor::_remove_preview_tab));
HBoxContainer *add_preview_button_hb = memnew(HBoxContainer);
preview_tabbar_hb->add_child(add_preview_button_hb);
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 9c579f3e9f..9062169e06 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -193,35 +193,25 @@ void EditorSettingsDialog::_event_config_confirmed() {
return;
}
- if (editing_action) {
- if (current_action_event_index == -1) {
- // Add new event
- current_action_events.push_back(k);
- } else {
- // Edit existing event
- current_action_events[current_action_event_index] = k;
- }
+ if (current_event_index == -1) {
+ // Add new event
+ current_events.push_back(k);
+ } else {
+ // Edit existing event
+ current_events[current_event_index] = k;
+ }
- _update_builtin_action(current_action, current_action_events);
+ if (is_editing_action) {
+ _update_builtin_action(current_edited_identifier, current_events);
} else {
- k = k->duplicate();
- Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(shortcut_being_edited);
-
- undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_being_edited + "'");
- undo_redo->add_do_method(current_sc.ptr(), "set_event", k);
- undo_redo->add_undo_method(current_sc.ptr(), "set_event", current_sc->get_event());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
+ _update_shortcut_events(current_edited_identifier, current_events);
}
}
void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) {
- Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(current_action);
+ Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name);
- undo_redo->create_action(TTR("Edit Built-in Action"));
+ undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'");
undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events);
undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array);
undo_redo->add_do_method(this, "_settings_changed");
@@ -231,15 +221,125 @@ void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Ar
_update_shortcuts();
}
+void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const Array &p_events) {
+ Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+
+ undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'");
+ undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events);
+ undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events());
+ undo_redo->add_do_method(this, "_update_shortcuts");
+ undo_redo->add_undo_method(this, "_update_shortcuts");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+}
+
+Array EditorSettingsDialog::_event_list_to_array_helper(List<Ref<InputEvent>> &p_events) {
+ Array events;
+
+ // Convert the list to an array, and only keep key events as this is for the editor.
+ for (List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) {
+ Ref<InputEventKey> k = E->get();
+ if (k.is_valid()) {
+ events.append(E->get());
+ }
+ }
+
+ return events;
+}
+
+void EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_action, bool p_is_collapsed) {
+ TreeItem *shortcut_item = shortcuts->create_item(p_parent);
+ shortcut_item->set_collapsed(p_is_collapsed);
+ shortcut_item->set_text(0, p_display);
+
+ Ref<InputEvent> primary = p_events.size() > 0 ? Ref<InputEvent>(p_events[0]) : Ref<InputEvent>();
+ Ref<InputEvent> secondary = p_events.size() > 1 ? Ref<InputEvent>(p_events[1]) : Ref<InputEvent>();
+
+ String sc_text = "None";
+ if (primary.is_valid()) {
+ sc_text = primary->as_text();
+
+ if (secondary.is_valid()) {
+ sc_text += ", " + secondary->as_text();
+
+ if (p_events.size() > 2) {
+ sc_text += " (+" + itos(p_events.size() - 2) + ")";
+ }
+ }
+ }
+
+ shortcut_item->set_text(1, sc_text);
+ if (sc_text == "None") {
+ // Fade out unassigned shortcut labels for easier visual grepping.
+ shortcut_item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5));
+ }
+
+ if (p_allow_revert) {
+ shortcut_item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), SHORTCUT_REVERT);
+ }
+
+ shortcut_item->add_button(1, shortcuts->get_theme_icon("Add", "EditorIcons"), SHORTCUT_ADD);
+ shortcut_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE);
+
+ shortcut_item->set_meta("is_action", p_is_action);
+ shortcut_item->set_meta("type", "shortcut");
+ shortcut_item->set_meta("shortcut_identifier", p_shortcut_identifier);
+ shortcut_item->set_meta("events", p_events);
+
+ // Shortcut Input Events
+ for (int i = 0; i < p_events.size(); i++) {
+ Ref<InputEvent> ie = p_events[i];
+ if (ie.is_null()) {
+ continue;
+ }
+
+ TreeItem *event_item = shortcuts->create_item(shortcut_item);
+
+ event_item->set_text(0, shortcut_item->get_child_count() == 1 ? "Primary" : "");
+ event_item->set_text(1, ie->as_text());
+
+ event_item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), SHORTCUT_EDIT);
+ event_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE);
+
+ event_item->set_custom_bg_color(0, shortcuts->get_theme_color("dark_color_3", "Editor"));
+ event_item->set_custom_bg_color(1, shortcuts->get_theme_color("dark_color_3", "Editor"));
+
+ event_item->set_meta("is_action", p_is_action);
+ event_item->set_meta("type", "event");
+ event_item->set_meta("event_index", i);
+ }
+}
+
void EditorSettingsDialog::_update_shortcuts() {
// Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated.
Map<String, bool> collapsed;
if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) {
- for (TreeItem *item = shortcuts->get_root()->get_first_child(); item; item = item->get_next()) {
- collapsed[item->get_text(0)] = item->is_collapsed();
+ TreeItem *ti = shortcuts->get_root()->get_first_child();
+ while (ti) {
+ // Not all items have valid or unique text in the first column - so if it has an identifier, use that, as it should be unique.
+ if (ti->get_first_child() && ti->has_meta("shortcut_identifier")) {
+ collapsed[ti->get_meta("shortcut_identifier")] = ti->is_collapsed();
+ } else {
+ collapsed[ti->get_text(0)] = ti->is_collapsed();
+ }
+
+ // Try go down tree
+ TreeItem *ti_next = ti->get_first_child();
+ // Try go across tree
+ if (!ti_next) {
+ ti_next = ti->get_next();
+ }
+ // Try go up tree, to next node
+ if (!ti_next) {
+ ti_next = ti->get_parent()->get_next();
+ }
+
+ ti = ti_next;
}
}
+
shortcuts->clear();
TreeItem *root = shortcuts->create_item();
@@ -247,7 +347,6 @@ void EditorSettingsDialog::_update_shortcuts() {
// Set up section for Common/Built-in actions
TreeItem *common_section = shortcuts->create_item(root);
-
sections["Common"] = common_section;
common_section->set_text(0, TTR("Common"));
common_section->set_selectable(0, false);
@@ -262,7 +361,6 @@ void EditorSettingsDialog::_update_shortcuts() {
OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map();
for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) {
String action_name = E.key();
-
InputMap::Action action = E.get();
Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
@@ -278,21 +376,6 @@ void EditorSettingsDialog::_update_shortcuts() {
}
}
- bool same_as_defaults = key_default_events.size() == action.inputs.size(); // Initially this is set to just whether the arrays are equal. Later we check the events if needed.
-
- int count = 0;
- for (List<Ref<InputEvent>>::Element *I = action.inputs.front(); I; I = I->next()) {
- // Add event and event text to respective arrays.
- events.push_back(I->get());
- event_strings.push_back(I->get()->as_text());
-
- // Only check if the events have been the same so far - once one fails, we don't need to check any more.
- if (same_as_defaults && !key_default_events[count]->is_match(I->get())) {
- same_as_defaults = false;
- }
- count++;
- }
-
// Join the text of the events with a delimiter so they can all be displayed in one cell.
String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings);
@@ -300,25 +383,12 @@ void EditorSettingsDialog::_update_shortcuts() {
continue;
}
- TreeItem *item = shortcuts->create_item(common_section);
- item->set_text(0, action_name);
- item->set_text(1, events_display_string);
-
- if (!same_as_defaults) {
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2);
- }
-
- if (events_display_string == "None") {
- // Fade out unassigned shortcut labels for easier visual grepping.
- item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5));
- }
+ Array action_events = _event_list_to_array_helper(action.inputs);
+ Array default_events = _event_list_to_array_helper(all_default_events);
+ bool same_as_defaults = Shortcut::is_event_array_equal(default_events, action_events);
+ bool collapse = !collapsed.has(action_name) || (collapsed.has(action_name) && collapsed[action_name]);
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1);
- item->set_tooltip(0, action_name);
- item->set_tooltip(1, events_display_string);
- item->set_metadata(0, "Common");
- item->set_metadata(1, events);
+ _create_shortcut_treeitem(common_section, action_name, action_name, action_events, !same_as_defaults, true, collapse);
}
// Editor Shortcuts
@@ -332,11 +402,10 @@ void EditorSettingsDialog::_update_shortcuts() {
continue;
}
- Ref<InputEvent> original = sc->get_meta("original");
-
- String section_name = E.get_slice("/", 0);
+ // Shortcut Section
TreeItem *section;
+ String section_name = E.get_slice("/", 0);
if (sections.has(section_name)) {
section = sections[section_name];
@@ -357,28 +426,18 @@ void EditorSettingsDialog::_update_shortcuts() {
sections[section_name] = section;
}
- // Don't match unassigned shortcuts when searching for assigned keys in search results.
- // This prevents all unassigned shortcuts from appearing when searching a string like "no".
- if (shortcut_filter.is_subsequence_ofi(sc->get_name()) || (sc->get_as_text() != "None" && shortcut_filter.is_subsequence_ofi(sc->get_as_text()))) {
- TreeItem *item = shortcuts->create_item(section);
-
- item->set_text(0, sc->get_name());
- item->set_text(1, sc->get_as_text());
+ // Shortcut Item
- if (!sc->matches_event(original) && !(sc->get_event().is_null() && original.is_null())) {
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), 2);
- }
+ if (!shortcut_filter.is_subsequence_ofi(sc->get_name())) {
+ continue;
+ }
- if (sc->get_as_text() == "None") {
- // Fade out unassigned shortcut labels for easier visual grepping.
- item->set_custom_color(1, shortcuts->get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.5));
- }
+ Array original = sc->get_meta("original");
+ Array shortcuts_array = sc->get_events();
+ bool same_as_defaults = Shortcut::is_event_array_equal(original, shortcuts_array);
+ bool collapse = !collapsed.has(E) || (collapsed.has(E) && collapsed[E]);
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
- item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1);
- item->set_tooltip(0, E);
- item->set_metadata(0, E);
- }
+ _create_shortcut_treeitem(section, E, sc->get_name(), shortcuts_array, !same_as_defaults, false, collapse);
}
// remove sections with no shortcuts
@@ -392,123 +451,130 @@ void EditorSettingsDialog::_update_shortcuts() {
void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx) {
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
- ERR_FAIL_COND(!ti);
-
- button_idx = p_idx;
+ ERR_FAIL_COND_MSG(!ti, "Object passed is not a TreeItem");
- if (ti->get_metadata(0) == "Common") {
- // Editing a Built-in action, which can have multiple bindings.
- editing_action = true;
- current_action = ti->get_text(0);
+ ShortcutButton button_idx = (ShortcutButton)p_idx;
- switch (button_idx) {
- case SHORTCUT_REVERT: {
- Array events;
- List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_action];
+ is_editing_action = ti->get_meta("is_action");
- // Convert the list to an array, and only keep key events as this is for the editor.
- for (const Ref<InputEvent> &k : defaults) {
- if (k.is_valid()) {
- events.append(k);
- }
- }
+ String type = ti->get_meta("type");
- _update_builtin_action(current_action, events);
- } break;
- case SHORTCUT_EDIT:
- case SHORTCUT_ERASE: {
- // For Edit end Delete, we will show a popup which displays each event so the user can select which one to edit/delete.
- current_action_events = ti->get_metadata(1);
- action_popup->clear();
-
- for (int i = 0; i < current_action_events.size(); i++) {
- Ref<InputEvent> ie = current_action_events[i];
- action_popup->add_item(ie->as_text());
- action_popup->set_item_metadata(i, ie);
- }
-
- if (button_idx == SHORTCUT_EDIT) {
- // If editing, add a button which can be used to add an additional event.
- action_popup->add_icon_item(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), TTR("Add"));
- }
+ if (type == "event") {
+ current_edited_identifier = ti->get_parent()->get_meta("shortcut_identifier");
+ current_events = ti->get_parent()->get_meta("events");
+ current_event_index = ti->get_meta("event_index");
+ } else { // Type is "shortcut"
+ current_edited_identifier = ti->get_meta("shortcut_identifier");
+ current_events = ti->get_meta("events");
+ current_event_index = -1;
+ }
- action_popup->set_position(get_position() + get_mouse_position());
- action_popup->take_mouse_focus();
- action_popup->popup();
- action_popup->set_as_minsize();
- } break;
- default:
- break;
- }
- } else {
- // Editing an Editor Shortcut, which can only have 1 binding.
- String item = ti->get_metadata(0);
- Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(item);
- editing_action = false;
-
- switch (button_idx) {
- case EditorSettingsDialog::SHORTCUT_EDIT:
- shortcut_editor->popup_and_configure(sc->get_event());
- shortcut_being_edited = item;
- break;
- case EditorSettingsDialog::SHORTCUT_ERASE: {
- if (!sc.is_valid()) {
- return; //pointless, there is nothing
+ switch (button_idx) {
+ case EditorSettingsDialog::SHORTCUT_ADD: {
+ // Only for "shortcut" types
+ shortcut_editor->popup_and_configure();
+ } break;
+ case EditorSettingsDialog::SHORTCUT_EDIT: {
+ // Only for "event" types
+ shortcut_editor->popup_and_configure(current_events[current_event_index]);
+ } break;
+ case EditorSettingsDialog::SHORTCUT_ERASE: {
+ if (type == "shortcut") {
+ if (is_editing_action) {
+ _update_builtin_action(current_edited_identifier, Array());
+ } else {
+ _update_shortcut_events(current_edited_identifier, Array());
}
+ } else if (type == "event") {
+ current_events.remove(current_event_index);
- undo_redo->create_action(TTR("Erase Shortcut"));
- undo_redo->add_do_method(sc.ptr(), "set_event", Ref<InputEvent>());
- undo_redo->add_undo_method(sc.ptr(), "set_event", sc->get_event());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
- } break;
- case EditorSettingsDialog::SHORTCUT_REVERT: {
- if (!sc.is_valid()) {
- return; //pointless, there is nothing
+ if (is_editing_action) {
+ _update_builtin_action(current_edited_identifier, current_events);
+ } else {
+ _update_shortcut_events(current_edited_identifier, current_events);
}
+ }
+ } break;
+ case EditorSettingsDialog::SHORTCUT_REVERT: {
+ // Only for "shortcut" types
+ if (is_editing_action) {
+ List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_edited_identifier];
+ Array events = _event_list_to_array_helper(defaults);
- Ref<InputEvent> original = sc->get_meta("original");
-
- undo_redo->create_action(TTR("Restore Shortcut"));
- undo_redo->add_do_method(sc.ptr(), "set_event", original);
- undo_redo->add_undo_method(sc.ptr(), "set_event", sc->get_event());
- undo_redo->add_do_method(this, "_update_shortcuts");
- undo_redo->add_undo_method(this, "_update_shortcuts");
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
- undo_redo->commit_action();
- } break;
- default:
- break;
- }
- }
-}
-
-void EditorSettingsDialog::_builtin_action_popup_index_pressed(int p_index) {
- switch (button_idx) {
- case SHORTCUT_EDIT: {
- if (p_index == action_popup->get_item_count() - 1) {
- // Selected last item in list (Add button), therefore add new
- current_action_event_index = -1;
- shortcut_editor->popup_and_configure();
+ _update_builtin_action(current_edited_identifier, events);
} else {
- // Configure existing
- current_action_event_index = p_index;
- shortcut_editor->popup_and_configure(action_popup->get_item_metadata(p_index));
+ Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(current_edited_identifier);
+ Array original = sc->get_meta("original");
+ _update_shortcut_events(current_edited_identifier, original);
}
} break;
- case SHORTCUT_ERASE: {
- current_action_events.remove(p_index);
- _update_builtin_action(current_action, current_action_events);
- } break;
default:
break;
}
}
+Variant EditorSettingsDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+ TreeItem *selected = shortcuts->get_selected();
+
+ // Only allow drag for events
+ if (!selected || !selected->has_meta("type") || selected->get_meta("type") != "event") {
+ return Variant();
+ }
+
+ String label_text = "Event " + itos(selected->get_meta("event_index"));
+ Label *label = memnew(Label(label_text));
+ label->set_modulate(Color(1, 1, 1, 1.0f));
+ shortcuts->set_drag_preview(label);
+
+ shortcuts->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+
+ return Dictionary(); // No data required
+}
+
+bool EditorSettingsDialog::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ TreeItem *selected = shortcuts->get_selected();
+ TreeItem *item = shortcuts->get_item_at_position(p_point);
+ if (!selected || !item || item == selected || !item->has_meta("type") || item->get_meta("type") != "event") {
+ return false;
+ }
+
+ // Don't allow moving an events in-between shortcuts.
+ if (selected->get_parent()->get_meta("shortcut_identifier") != item->get_parent()->get_meta("shortcut_identifier")) {
+ return false;
+ }
+
+ return true;
+}
+
+void EditorSettingsDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ if (!can_drop_data_fw(p_point, p_data, p_from)) {
+ return;
+ }
+
+ TreeItem *selected = shortcuts->get_selected();
+ TreeItem *target = shortcuts->get_item_at_position(p_point);
+
+ if (!target) {
+ return;
+ }
+
+ int target_event_index = target->get_meta("event_index");
+ int index_moving_from = selected->get_meta("event_index");
+
+ Array events = selected->get_parent()->get_meta("events");
+
+ Variant event_moved = events[index_moving_from];
+ events.remove(index_moving_from);
+ events.insert(target_event_index, event_moved);
+
+ String ident = selected->get_parent()->get_meta("shortcut_identifier");
+ if (selected->get_meta("is_action")) {
+ _update_builtin_action(ident, events);
+ } else {
+ _update_shortcut_events(ident, events);
+ }
+}
+
void EditorSettingsDialog::_tabs_tab_changed(int p_tab) {
_focus_current_search_box();
}
@@ -544,13 +610,13 @@ void EditorSettingsDialog::_editor_restart_close() {
void EditorSettingsDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts);
ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed);
+
+ ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &EditorSettingsDialog::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorSettingsDialog::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorSettingsDialog::drop_data_fw);
}
EditorSettingsDialog::EditorSettingsDialog() {
- action_popup = memnew(PopupMenu);
- action_popup->connect("index_pressed", callable_mp(this, &EditorSettingsDialog::_builtin_action_popup_index_pressed));
- add_child(action_popup);
-
set_title(TTR("Editor Settings"));
undo_redo = memnew(UndoRedo);
@@ -628,6 +694,8 @@ EditorSettingsDialog::EditorSettingsDialog() {
shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed));
tab_shortcuts->add_child(shortcuts);
+ shortcuts->set_drag_forwarding(this);
+
// Adding event dialog
shortcut_editor = memnew(InputEventConfigurationDialog);
shortcut_editor->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_event_config_confirmed));
diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h
index 2b6c9b3e1d..7317a014b2 100644
--- a/editor/settings_config_dialog.h
+++ b/editor/settings_config_dialog.h
@@ -53,29 +53,28 @@ class EditorSettingsDialog : public AcceptDialog {
LineEdit *shortcut_search_box;
SectionedInspector *inspector;
+ // Shortcuts
enum ShortcutButton {
+ SHORTCUT_ADD,
SHORTCUT_EDIT,
SHORTCUT_ERASE,
SHORTCUT_REVERT
};
- int button_idx;
- int current_action_event_index = -1;
- bool editing_action = false;
- String current_action;
- Array current_action_events;
- PopupMenu *action_popup;
+ Tree *shortcuts;
+ String shortcut_filter;
+
+ InputEventConfigurationDialog *shortcut_editor;
+
+ bool is_editing_action = false;
+ String current_edited_identifier;
+ Array current_events;
+ int current_event_index = -1;
Timer *timer;
UndoRedo *undo_redo;
- // Shortcuts
- String shortcut_filter;
- Tree *shortcuts;
- InputEventConfigurationDialog *shortcut_editor;
- String shortcut_being_edited;
-
virtual void cancel_pressed() override;
virtual void ok_pressed() override;
@@ -89,7 +88,14 @@ class EditorSettingsDialog : public AcceptDialog {
void _event_config_confirmed();
+ void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed);
+ Array _event_list_to_array_helper(List<Ref<InputEvent>> &p_events);
void _update_builtin_action(const String &p_name, const Array &p_events);
+ void _update_shortcut_events(const String &p_path, const Array &p_events);
+
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void _tabs_tab_changed(int p_tab);
void _focus_current_search_box();
diff --git a/main/main.cpp b/main/main.cpp
index 7d7c9d7374..5a2a088494 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -407,6 +407,7 @@ Error Main::test_setup() {
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
translation_server = memnew(TranslationServer);
+ tsman = memnew(TextServerManager);
register_core_extensions();
@@ -440,6 +441,9 @@ Error Main::test_setup() {
register_module_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);
_start_success = true;
@@ -459,6 +463,7 @@ void Main::test_cleanup() {
#ifdef TOOLS_ENABLED
EditorNode::unregister_editor_types();
#endif
+
unregister_module_types();
unregister_platform_apis();
unregister_scene_types();
@@ -469,6 +474,9 @@ void Main::test_cleanup() {
if (translation_server) {
memdelete(translation_server);
}
+ if (tsman) {
+ memdelete(tsman);
+ }
if (globals) {
memdelete(globals);
}
@@ -1461,6 +1469,8 @@ error:
}
Error Main::setup2(Thread::ID p_main_tid_override) {
+ tsman = memnew(TextServerManager);
+
preregister_module_types();
preregister_server_types();
@@ -1479,64 +1489,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
}
#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 */
input = memnew(Input);
@@ -1781,6 +1733,57 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
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");
register_scene_types();
@@ -1793,7 +1796,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#endif
- MAIN_PRINT("Main: Load Modules, Physics, Drivers, Scripts");
+ MAIN_PRINT("Main: Load Modules");
register_platform_apis();
register_module_types();
@@ -1817,6 +1820,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
camera_server = CameraServer::create();
+ MAIN_PRINT("Main: Load Physics, Drivers, Scripts");
+
initialize_physics();
initialize_navigation_server();
register_server_singletons();
@@ -2728,10 +2733,6 @@ void Main::cleanup(bool p_force) {
finalize_navigation_server();
finalize_display();
- if (tsman) {
- memdelete(tsman);
- }
-
if (input) {
memdelete(input);
}
@@ -2754,6 +2755,9 @@ void Main::cleanup(bool p_force) {
if (translation_server) {
memdelete(translation_server);
}
+ if (tsman) {
+ memdelete(tsman);
+ }
if (globals) {
memdelete(globals);
}
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index 94bda04d12..f7f21a433e 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -18,7 +18,6 @@ Export("env_gdnative")
SConscript("pluginscript/SCsub")
SConscript("videodecoder/SCsub")
-SConscript("text/SCsub")
import gdnative_builders
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 627883886c..cf1c7dc01f 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -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"
- ]
- ]
- }
- ]
}
]
}
diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py
index 4986b173cf..6c96e23426 100644
--- a/modules/gdnative/gdnative_builders.py
+++ b/modules/gdnative/gdnative_builders.py
@@ -22,7 +22,6 @@ def _build_gdnative_api_struct_header(api):
"#include <nativescript/godot_nativescript.h>",
"#include <pluginscript/godot_pluginscript.h>",
"#include <videodecoder/godot_videodecoder.h>",
- "#include <text/godot_text.h>",
"",
"#ifdef __cplusplus",
'extern "C" {',
diff --git a/modules/gdnative/include/text/godot_text.h b/modules/gdnative/include/text/godot_text.h
deleted file mode 100644
index 940cfd11f8..0000000000
--- a/modules/gdnative/include/text/godot_text.h
+++ /dev/null
@@ -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 */
diff --git a/modules/gdnative/text/SCsub b/modules/gdnative/text/SCsub
deleted file mode 100644
index 0b2db3b504..0000000000
--- a/modules/gdnative/text/SCsub
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-Import("env_gdnative")
-
-env_gdnative.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/gdnative/text/config.py b/modules/gdnative/text/config.py
deleted file mode 100644
index d22f9454ed..0000000000
--- a/modules/gdnative/text/config.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def can_build(env, platform):
- return True
-
-
-def configure(env):
- pass
diff --git a/modules/gdnative/text/register_types.cpp b/modules/gdnative/text/register_types.cpp
deleted file mode 100644
index 67385d2fbf..0000000000
--- a/modules/gdnative/text/register_types.cpp
+++ /dev/null
@@ -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() {}
diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp
deleted file mode 100644
index 39db8ae636..0000000000
--- a/modules/gdnative/text/text_server_gdnative.cpp
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*************************************************************************/
-/* text_server_gdnative.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 "text_server_gdnative.h"
-
-bool TextServerGDNative::has_feature(Feature p_feature) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->has_feature(data, (godot_int)p_feature);
-}
-
-String TextServerGDNative::get_name() const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->get_name(data);
- String name = *(String *)&result;
- godot_string_destroy(&result);
- return name;
-}
-
-void TextServerGDNative::free(RID p_rid) {
- ERR_FAIL_COND(interface == nullptr);
- interface->free(data, (godot_rid *)&p_rid);
-}
-
-bool TextServerGDNative::has(RID p_rid) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->has(data, (godot_rid *)&p_rid);
-}
-
-bool TextServerGDNative::load_support_data(const String &p_filename) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->load_support_data(data, (godot_string *)&p_filename);
-}
-
-#ifdef TOOLS_ENABLED
-
-String TextServerGDNative::get_support_data_filename() {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->get_support_data_filename(data);
- String name = *(String *)&result;
- godot_string_destroy(&result);
- return name;
-}
-
-String TextServerGDNative::get_support_data_info() {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->get_support_data_info(data);
- String info = *(String *)&result;
- godot_string_destroy(&result);
- return info;
-}
-
-bool TextServerGDNative::save_support_data(const String &p_filename) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->save_support_data(data, (godot_string *)&p_filename);
-}
-
-#endif
-
-bool TextServerGDNative::is_locale_right_to_left(const String &p_locale) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->is_locale_right_to_left(data, (godot_string *)&p_locale);
-}
-
-int32_t TextServerGDNative::name_to_tag(const String &p_name) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->name_to_tag(data, (godot_string *)&p_name);
-}
-
-String TextServerGDNative::tag_to_name(int32_t p_tag) const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->tag_to_name(data, p_tag);
- String name = *(String *)&result;
- godot_string_destroy(&result);
- return name;
-}
-
-/*************************************************************************/
-/* Font */
-/*************************************************************************/
-
-RID TextServerGDNative::create_font() {
- ERR_FAIL_COND_V(interface == nullptr, RID());
- godot_rid result = interface->create_font(data);
- RID rid = *(RID *)&result;
- return rid;
-}
-
-void TextServerGDNative::font_set_data(RID p_font_rid, const PackedByteArray &p_data) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_data(data, (godot_rid *)&p_font_rid, (const godot_packed_byte_array *)&p_data);
-}
-
-void TextServerGDNative::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_data_ptr(data, (godot_rid *)&p_font_rid, p_data_ptr, p_data_size);
-}
-
-void TextServerGDNative::font_set_antialiased(RID p_font_rid, bool p_antialiased) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_antialiased(data, (godot_rid *)&p_font_rid, p_antialiased);
-}
-
-bool TextServerGDNative::font_is_antialiased(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_is_antialiased(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_multichannel_signed_distance_field(data, (godot_rid *)&p_font_rid, p_msdf);
-}
-
-bool TextServerGDNative::font_is_multichannel_signed_distance_field(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_is_multichannel_signed_distance_field(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_msdf_pixel_range(data, (godot_rid *)&p_font_rid, p_msdf_pixel_range);
-}
-
-int TextServerGDNative::font_get_msdf_pixel_range(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->font_get_msdf_pixel_range(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_msdf_size(RID p_font_rid, int p_msdf_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_msdf_size(data, (godot_rid *)&p_font_rid, p_msdf_size);
-}
-
-int TextServerGDNative::font_get_msdf_size(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->font_get_msdf_size(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_fixed_size(RID p_font_rid, int p_fixed_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_fixed_size(data, (godot_rid *)&p_font_rid, p_fixed_size);
-}
-
-int TextServerGDNative::font_get_fixed_size(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->font_get_fixed_size(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_force_autohinter(data, (godot_rid *)&p_font_rid, p_force_autohinter);
-}
-
-bool TextServerGDNative::font_is_force_autohinter(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_is_force_autohinter(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_hinting(data, (godot_rid *)&p_font_rid, (godot_int)p_hinting);
-}
-
-TextServer::Hinting TextServerGDNative::font_get_hinting(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, TextServer::HINTING_NONE);
- return (TextServer::Hinting)interface->font_get_hinting(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_variation_coordinates(data, (godot_rid *)&p_font_rid, (const godot_dictionary *)&p_variation_coordinates);
-}
-
-Dictionary TextServerGDNative::font_get_variation_coordinates(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, Dictionary());
- godot_dictionary result = interface->font_get_variation_coordinates(data, (godot_rid *)&p_font_rid);
- Dictionary dict = *(Dictionary *)&result;
- godot_dictionary_destroy(&result);
- return dict;
-}
-
-void TextServerGDNative::font_set_oversampling(RID p_font_rid, real_t p_oversampling) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_oversampling(data, (godot_rid *)&p_font_rid, p_oversampling);
-}
-
-real_t TextServerGDNative::font_get_oversampling(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_oversampling(data, (godot_rid *)&p_font_rid);
-}
-
-Array TextServerGDNative::font_get_size_cache_list(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, Array());
- godot_array result = interface->font_get_size_cache_list(data, (godot_rid *)&p_font_rid);
- Array list = *(Array *)&result;
- godot_array_destroy(&result);
- return list;
-}
-
-void TextServerGDNative::font_clear_size_cache(RID p_font_rid) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_clear_size_cache(data, (godot_rid *)&p_font_rid);
-}
-
-void TextServerGDNative::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_size_cache(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size);
-}
-
-void TextServerGDNative::font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_ascent(data, (godot_rid *)&p_font_rid, p_size, p_ascent);
-}
-
-real_t TextServerGDNative::font_get_ascent(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_ascent(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_set_descent(RID p_font_rid, int p_size, real_t p_descent) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_descent(data, (godot_rid *)&p_font_rid, p_size, p_descent);
-}
-
-real_t TextServerGDNative::font_get_descent(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_descent(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_underline_position(data, (godot_rid *)&p_font_rid, p_size, p_underline_position);
-}
-
-real_t TextServerGDNative::font_get_underline_position(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_underline_position(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_underline_thickness(data, (godot_rid *)&p_font_rid, p_size, p_underline_thickness);
-}
-
-real_t TextServerGDNative::font_get_underline_thickness(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_underline_thickness(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_set_scale(RID p_font_rid, int p_size, real_t p_scale) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_scale(data, (godot_rid *)&p_font_rid, p_size, p_scale);
-}
-
-real_t TextServerGDNative::font_get_scale(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_scale(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_spacing(data, (godot_rid *)&p_font_rid, p_size, (godot_int)p_spacing, p_value);
-}
-
-int TextServerGDNative::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->font_get_spacing(data, (godot_rid *)&p_font_rid, p_size, (godot_int)p_spacing);
-}
-
-int TextServerGDNative::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, -1);
- return interface->font_get_texture_count(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size);
-}
-
-void TextServerGDNative::font_clear_textures(RID p_font_rid, const Vector2i &p_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_clear_textures(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size);
-}
-
-void TextServerGDNative::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_texture(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_texture_index);
-}
-
-void TextServerGDNative::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_texture_image(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_texture_index, (const godot_object *)p_image.ptr());
-}
-
-Ref<Image> TextServerGDNative::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
- ERR_FAIL_COND_V(interface == nullptr, Ref<Image>());
- godot_object *result = interface->font_get_texture_image(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_texture_index);
- return Ref<Image>((Image *)result);
-}
-
-void TextServerGDNative::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_texture_offsets(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_texture_index, (const godot_packed_int32_array *)&p_offset);
-}
-
-PackedInt32Array TextServerGDNative::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
- ERR_FAIL_COND_V(interface == nullptr, PackedInt32Array());
- godot_packed_int32_array result = interface->font_get_texture_offsets(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_texture_index);
- PackedInt32Array offset = *(PackedInt32Array *)&result;
- godot_packed_int32_array_destroy(&result);
- return offset;
-}
-
-Array TextServerGDNative::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, Array());
- godot_array result = interface->font_get_glyph_list(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size);
- Array list = *(Array *)&result;
- godot_array_destroy(&result);
- return list;
-}
-
-void TextServerGDNative::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_clear_glyphs(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size);
-}
-
-void TextServerGDNative::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_glyph(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph);
-}
-
-Vector2 TextServerGDNative::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector2());
- godot_vector2 result = interface->font_get_glyph_advance(data, (godot_rid *)&p_font_rid, p_size, p_glyph);
- Vector2 adv = *(Vector2 *)&result;
- return adv;
-}
-
-void TextServerGDNative::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_glyph_advance(data, (godot_rid *)&p_font_rid, p_size, p_glyph, (const godot_vector2 *)&p_advance);
-}
-
-Vector2 TextServerGDNative::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector2());
- godot_vector2 result = interface->font_get_glyph_offset(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph);
- Vector2 off = *(Vector2 *)&result;
- return off;
-}
-
-void TextServerGDNative::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_glyph_offset(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph, (const godot_vector2 *)&p_offset);
-}
-
-Vector2 TextServerGDNative::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector2());
- godot_vector2 result = interface->font_get_glyph_size(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph);
- Vector2 sz = *(Vector2 *)&result;
- return sz;
-}
-
-void TextServerGDNative::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_glyph_size(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph, (const godot_vector2 *)&p_gl_size);
-}
-
-Rect2 TextServerGDNative::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
- ERR_FAIL_COND_V(interface == nullptr, Rect2());
- godot_rect2 result = interface->font_get_glyph_uv_rect(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph);
- Rect2 uv = *(Rect2 *)&result;
- return uv;
-}
-
-void TextServerGDNative::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_glyph_uv_rect(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph, (const godot_rect2 *)&p_uv_rect);
-}
-
-int TextServerGDNative::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
- ERR_FAIL_COND_V(interface == nullptr, -1);
- return interface->font_get_glyph_texture_idx(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph);
-}
-
-void TextServerGDNative::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_glyph_texture_idx(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_glyph, p_texture_idx);
-}
-
-bool TextServerGDNative::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 {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_get_glyph_contours(data, (godot_rid *)&p_font_rid, p_size, p_index, (godot_packed_vector3_array *)&r_points, (godot_packed_int32_array *)&r_contours, &r_orientation);
-}
-
-Array TextServerGDNative::font_get_kerning_list(RID p_font_rid, int p_size) const {
- ERR_FAIL_COND_V(interface == nullptr, Array());
- godot_array result = interface->font_get_kerning_list(data, (godot_rid *)&p_font_rid, p_size);
- Array list = *(Array *)&result;
- godot_array_destroy(&result);
- return list;
-}
-
-void TextServerGDNative::font_clear_kerning_map(RID p_font_rid, int p_size) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_clear_kerning_map(data, (godot_rid *)&p_font_rid, p_size);
-}
-
-void TextServerGDNative::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_kerning(data, (godot_rid *)&p_font_rid, p_size, (const godot_vector2i *)&p_glyph_pair);
-}
-
-void TextServerGDNative::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_kerning(data, (godot_rid *)&p_font_rid, p_size, (const godot_vector2i *)&p_glyph_pair, (const godot_vector2 *)&p_kerning);
-}
-
-Vector2 TextServerGDNative::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector2());
- godot_vector2 result = interface->font_get_kerning(data, (godot_rid *)&p_font_rid, p_size, (const godot_vector2i *)&p_glyph_pair);
- Vector2 kern = *(Vector2 *)&result;
- return kern;
-}
-
-int32_t TextServerGDNative::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const {
- ERR_FAIL_COND_V(interface == nullptr, 0);
- return interface->font_get_glyph_index(data, (godot_rid *)&p_font_rid, p_size, p_char, p_variation_selector);
-}
-
-bool TextServerGDNative::font_has_char(RID p_font_rid, char32_t p_char) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_has_char(data, (godot_rid *)&p_font_rid, p_char);
-}
-
-String TextServerGDNative::font_get_supported_chars(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->font_get_supported_chars(data, (godot_rid *)&p_font_rid);
- String chars = *(String *)&result;
- godot_string_destroy(&result);
- return chars;
-}
-
-void TextServerGDNative::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_render_range(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_start, p_end);
-}
-
-void TextServerGDNative::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_render_glyph(data, (godot_rid *)&p_font_rid, (const godot_vector2i *)&p_size, p_index);
-}
-
-void TextServerGDNative::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_draw_glyph(data, (godot_rid *)&p_font_rid, (godot_rid *)&p_canvas, p_size, (const godot_vector2 *)&p_pos, p_index, (const godot_color *)&p_color);
-}
-
-void TextServerGDNative::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_draw_glyph_outline(data, (godot_rid *)&p_font_rid, (godot_rid *)&p_canvas, p_size, p_outline_size, (const godot_vector2 *)&p_pos, p_index, (const godot_color *)&p_color);
-}
-
-bool TextServerGDNative::font_is_language_supported(RID p_font_rid, const String &p_language) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_is_language_supported(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_language);
-}
-
-void TextServerGDNative::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_language_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_language, p_supported);
-}
-
-bool TextServerGDNative::font_get_language_support_override(RID p_font_rid, const String &p_language) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_get_language_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_language);
-}
-
-void TextServerGDNative::font_remove_language_support_override(RID p_font_rid, const String &p_language) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_language_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_language);
-}
-
-Vector<String> TextServerGDNative::font_get_language_support_overrides(RID p_font_rid) {
- ERR_FAIL_COND_V(interface == nullptr, PackedStringArray());
- godot_packed_string_array result = interface->font_get_language_support_overrides(data, (godot_rid *)&p_font_rid);
- PackedStringArray list = *(PackedStringArray *)&result;
- godot_packed_string_array_destroy(&result);
- return list;
-}
-
-bool TextServerGDNative::font_is_script_supported(RID p_font_rid, const String &p_script) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_is_script_supported(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_script);
-}
-
-void TextServerGDNative::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_script_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_script, p_supported);
-}
-
-bool TextServerGDNative::font_get_script_support_override(RID p_font_rid, const String &p_script) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->font_get_script_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_script);
-}
-
-void TextServerGDNative::font_remove_script_support_override(RID p_font_rid, const String &p_script) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_remove_script_support_override(data, (godot_rid *)&p_font_rid, (const godot_string *)&p_script);
-}
-
-Vector<String> TextServerGDNative::font_get_script_support_overrides(RID p_font_rid) {
- ERR_FAIL_COND_V(interface == nullptr, PackedStringArray());
- godot_packed_string_array result = interface->font_get_script_support_overrides(data, (godot_rid *)&p_font_rid);
- PackedStringArray list = *(PackedStringArray *)&result;
- godot_packed_string_array_destroy(&result);
- return list;
-}
-
-Dictionary TextServerGDNative::font_supported_feature_list(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, Dictionary());
- godot_dictionary result = interface->font_supported_feature_list(data, (godot_rid *)&p_font_rid);
- Dictionary dict = *(Dictionary *)&result;
- godot_dictionary_destroy(&result);
- return dict;
-}
-
-Dictionary TextServerGDNative::font_supported_variation_list(RID p_font_rid) const {
- ERR_FAIL_COND_V(interface == nullptr, Dictionary());
- godot_dictionary result = interface->font_supported_variation_list(data, (godot_rid *)&p_font_rid);
- Dictionary dict = *(Dictionary *)&result;
- godot_dictionary_destroy(&result);
- return dict;
-}
-
-real_t TextServerGDNative::font_get_global_oversampling() const {
- ERR_FAIL_COND_V(interface == nullptr, 0.0f);
- return interface->font_get_global_oversampling(data);
-}
-
-void TextServerGDNative::font_set_global_oversampling(real_t p_oversampling) {
- ERR_FAIL_COND(interface == nullptr);
- interface->font_set_global_oversampling(data, p_oversampling);
-}
-
-/*************************************************************************/
-/* Shaped text buffer interface */
-/*************************************************************************/
-
-RID TextServerGDNative::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
- ERR_FAIL_COND_V(interface == nullptr, RID());
- godot_rid result = interface->create_shaped_text(data, (godot_int)p_direction, (godot_int)p_orientation);
- RID rid = *(RID *)&result;
- return rid;
-}
-
-void TextServerGDNative::shaped_text_clear(RID p_shaped) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_clear(data, (godot_rid *)&p_shaped);
-}
-
-void TextServerGDNative::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_set_direction(data, (godot_rid *)&p_shaped, (godot_int)p_direction);
-}
-
-TextServer::Direction TextServerGDNative::shaped_text_get_direction(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, TextServer::DIRECTION_LTR);
- return (TextServer::Direction)interface->shaped_text_get_direction(data, (godot_rid *)&p_shaped);
-}
-
-void TextServerGDNative::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_set_orientation(data, (godot_rid *)&p_shaped, (godot_int)p_orientation);
-}
-
-TextServer::Orientation TextServerGDNative::shaped_text_get_orientation(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, TextServer::ORIENTATION_HORIZONTAL);
- return (TextServer::Orientation)interface->shaped_text_get_orientation(data, (godot_rid *)&p_shaped);
-}
-
-void TextServerGDNative::shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_set_bidi_override(data, (godot_rid *)&p_shaped, (const godot_packed_vector2i_array *)&p_override);
-}
-
-void TextServerGDNative::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_set_preserve_invalid(data, (godot_rid *)&p_shaped, p_enabled);
-}
-
-bool TextServerGDNative::shaped_text_get_preserve_invalid(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return (TextServer::Orientation)interface->shaped_text_get_preserve_invalid(data, (godot_rid *)&p_shaped);
-}
-
-void TextServerGDNative::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_set_preserve_control(data, (godot_rid *)&p_shaped, p_enabled);
-}
-
-bool TextServerGDNative::shaped_text_get_preserve_control(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return (TextServer::Orientation)interface->shaped_text_get_preserve_control(data, (godot_rid *)&p_shaped);
-}
-
-bool TextServerGDNative::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_add_string(data, (godot_rid *)&p_shaped, (const godot_string *)&p_text, (const godot_rid **)p_fonts.ptr(), p_size, (const godot_dictionary *)&p_opentype_features, (const godot_string *)&p_language);
-}
-
-bool TextServerGDNative::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_add_object(data, (godot_rid *)&p_shaped, (const godot_variant *)&p_key, (const godot_vector2 *)&p_size, (godot_int)p_inline_align, p_length);
-}
-
-bool TextServerGDNative::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_resize_object(data, (godot_rid *)&p_shaped, (const godot_variant *)&p_key, (const godot_vector2 *)&p_size, (godot_int)p_inline_align);
-}
-
-RID TextServerGDNative::shaped_text_substr(RID p_shaped, int p_start, int p_length) const {
- ERR_FAIL_COND_V(interface == nullptr, RID());
- godot_rid result = interface->shaped_text_substr(data, (godot_rid *)&p_shaped, (godot_int)p_start, (godot_int)p_length);
- RID rid = *(RID *)&result;
- return rid;
-}
-
-RID TextServerGDNative::shaped_text_get_parent(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, RID());
- godot_rid result = interface->shaped_text_get_parent(data, (godot_rid *)&p_shaped);
- RID rid = *(RID *)&result;
- return rid;
-}
-
-real_t TextServerGDNative::shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t p_jst_flags) {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_fit_to_width(data, (godot_rid *)&p_shaped, p_width, p_jst_flags);
-}
-
-real_t TextServerGDNative::shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_tab_align(data, (godot_rid *)&p_shaped, (godot_packed_float32_array *)&p_tab_stops);
-}
-
-bool TextServerGDNative::shaped_text_shape(RID p_shaped) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_shape(data, (godot_rid *)&p_shaped);
-}
-
-bool TextServerGDNative::shaped_text_update_breaks(RID p_shaped) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_update_breaks(data, (godot_rid *)&p_shaped);
-}
-
-bool TextServerGDNative::shaped_text_update_justification_ops(RID p_shaped) {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_update_justification_ops(data, (godot_rid *)&p_shaped);
-}
-
-void TextServerGDNative::shaped_text_overrun_trim_to_width(RID p_shaped_line, real_t p_width, uint8_t p_trim_flags) {
- ERR_FAIL_COND(interface == nullptr);
- interface->shaped_text_overrun_trim_to_width(data, (godot_rid *)&p_shaped_line, p_width, p_trim_flags);
-};
-
-bool TextServerGDNative::shaped_text_is_ready(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, false);
- return interface->shaped_text_is_ready(data, (godot_rid *)&p_shaped);
-}
-
-Vector<TextServer::Glyph> TextServerGDNative::shaped_text_get_glyphs(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector<TextServer::Glyph>());
- godot_packed_glyph_array result = interface->shaped_text_get_glyphs(data, (godot_rid *)&p_shaped);
- Vector<TextServer::Glyph> glyphs = *(Vector<TextServer::Glyph> *)&result;
- godot_packed_glyph_array_destroy(&result);
- return glyphs;
-}
-
-Vector2i TextServerGDNative::shaped_text_get_range(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector2i());
- godot_vector2i result = interface->shaped_text_get_range(data, (godot_rid *)&p_shaped);
- Vector2i range = *(Vector2i *)&result;
- return range;
-}
-
-Vector<TextServer::Glyph> TextServerGDNative::shaped_text_sort_logical(RID p_shaped) {
- ERR_FAIL_COND_V(interface == nullptr, Vector<TextServer::Glyph>());
- godot_packed_glyph_array result = interface->shaped_text_sort_logical(data, (godot_rid *)&p_shaped);
- Vector<TextServer::Glyph> glyphs = *(Vector<TextServer::Glyph> *)&result;
- godot_packed_glyph_array_destroy(&result);
- return glyphs;
-}
-
-Vector<Vector2i> TextServerGDNative::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start, bool p_once, uint8_t p_break_flags) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector<Vector2i>());
- if (interface->shaped_text_get_line_breaks_adv != nullptr) {
- godot_packed_vector2i_array result = interface->shaped_text_get_line_breaks_adv(data, (godot_rid *)&p_shaped, (godot_packed_float32_array *)&p_width, p_start, p_once, p_break_flags);
- Vector<Vector2i> breaks = *(Vector<Vector2i> *)&result;
- godot_packed_vector2i_array_destroy(&result);
- return breaks;
- } else {
- return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_break_flags);
- }
-}
-
-Vector<Vector2i> TextServerGDNative::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector<Vector2i>());
- if (interface->shaped_text_get_line_breaks != nullptr) {
- godot_packed_vector2i_array result = interface->shaped_text_get_line_breaks(data, (godot_rid *)&p_shaped, p_width, p_start, p_break_flags);
- Vector<Vector2i> breaks = *(Vector<Vector2i> *)&result;
- godot_packed_vector2i_array_destroy(&result);
- return breaks;
- } else {
- return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_break_flags);
- }
-}
-
-Vector<Vector2i> TextServerGDNative::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
- ERR_FAIL_COND_V(interface == nullptr, Vector<Vector2i>());
- if (interface->shaped_text_get_word_breaks != nullptr) {
- godot_packed_vector2i_array result = interface->shaped_text_get_word_breaks(data, (godot_rid *)&p_shaped, p_grapheme_flags);
- Vector<Vector2i> breaks = *(Vector<Vector2i> *)&result;
- godot_packed_vector2i_array_destroy(&result);
- return breaks;
- } else {
- return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
- }
-}
-
-Array TextServerGDNative::shaped_text_get_objects(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, Array());
- godot_array result = interface->shaped_text_get_objects(data, (godot_rid *)&p_shaped);
- Array rect = *(Array *)&result;
- return rect;
-}
-
-Rect2 TextServerGDNative::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const {
- ERR_FAIL_COND_V(interface == nullptr, Rect2());
- godot_rect2 result = interface->shaped_text_get_object_rect(data, (godot_rid *)&p_shaped, (const godot_variant *)&p_key);
- Rect2 rect = *(Rect2 *)&result;
- return rect;
-}
-
-Size2 TextServerGDNative::shaped_text_get_size(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, Size2());
- godot_vector2 result = interface->shaped_text_get_size(data, (godot_rid *)&p_shaped);
- Size2 size = *(Size2 *)&result;
- return size;
-}
-
-real_t TextServerGDNative::shaped_text_get_ascent(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_get_ascent(data, (godot_rid *)&p_shaped);
-}
-
-real_t TextServerGDNative::shaped_text_get_descent(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_get_descent(data, (godot_rid *)&p_shaped);
-}
-
-real_t TextServerGDNative::shaped_text_get_width(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_get_width(data, (godot_rid *)&p_shaped);
-}
-
-real_t TextServerGDNative::shaped_text_get_underline_position(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_get_underline_position(data, (godot_rid *)&p_shaped);
-}
-
-real_t TextServerGDNative::shaped_text_get_underline_thickness(RID p_shaped) const {
- ERR_FAIL_COND_V(interface == nullptr, 0.f);
- return interface->shaped_text_get_underline_thickness(data, (godot_rid *)&p_shaped);
-}
-
-String TextServerGDNative::format_number(const String &p_string, const String &p_language) const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- godot_string result = interface->format_number(data, (const godot_string *)&p_string, (const godot_string *)&p_language);
- if (interface->format_number == nullptr) {
- return p_string;
- }
- String ret = *(String *)&result;
- godot_string_destroy(&result);
- return ret;
-}
-
-String TextServerGDNative::parse_number(const String &p_string, const String &p_language) const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- if (interface->parse_number == nullptr) {
- return p_string;
- }
- godot_string result = interface->parse_number(data, (const godot_string *)&p_string, (const godot_string *)&p_language);
- String ret = *(String *)&result;
- godot_string_destroy(&result);
- return ret;
-}
-
-String TextServerGDNative::percent_sign(const String &p_language) const {
- ERR_FAIL_COND_V(interface == nullptr, String());
- if (interface->percent_sign == nullptr) {
- return "%";
- }
- godot_string result = interface->percent_sign(data, (const godot_string *)&p_language);
- String ret = *(String *)&result;
- godot_string_destroy(&result);
- return ret;
-}
-
-TextServer *TextServerGDNative::create_func(Error &r_error, void *p_user_data) {
- const godot_text_interface_gdnative *interface = (const godot_text_interface_gdnative *)p_user_data;
- r_error = OK;
-
- TextServerGDNative *server = memnew(TextServerGDNative());
- server->interface = interface;
- server->data = interface->constructor((godot_object *)server);
-
- return server;
-}
-
-TextServerGDNative::TextServerGDNative() {
- data = nullptr;
- interface = nullptr;
-}
-
-TextServerGDNative::~TextServerGDNative() {
- if (interface != nullptr) {
- interface->destructor(data);
- data = nullptr;
- interface = nullptr;
- }
-}
-
-/*************************************************************************/
-/* GDNative functions */
-/*************************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static_assert(sizeof(godot_glyph) == sizeof(TextServer::Glyph), "Glyph size mismatch");
-static_assert(sizeof(godot_packed_glyph_array) == sizeof(Vector<TextServer::Glyph>), "Vector<Glyph> size mismatch");
-
-void GDAPI godot_text_register_interface(const godot_text_interface_gdnative *p_interface, const godot_string *p_name, uint32_t p_features) {
- ERR_FAIL_COND(p_interface->version.major != 1);
- String name = *(String *)p_name;
- TextServerManager::register_create_function(name + "(GDNative)", p_features, TextServerGDNative::create_func, (void *)p_interface);
-}
-
-// Glyph
-
-void GDAPI godot_glyph_new(godot_glyph *r_dest) {
- TextServer::Glyph *dest = (TextServer::Glyph *)r_dest;
- *dest = TextServer::Glyph();
-}
-
-godot_vector2i GDAPI godot_glyph_get_range(const godot_glyph *p_self) {
- godot_vector2i dest;
- Vector2i *d = (Vector2i *)&dest;
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- d->x = self->start;
- d->y = self->end;
- return dest;
-}
-
-void GDAPI godot_glyph_set_range(godot_glyph *p_self, const godot_vector2i *p_range) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- const Vector2i *range = (const Vector2i *)p_range;
- self->start = range->x;
- self->end = range->y;
-}
-
-godot_int GDAPI godot_glyph_get_count(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->count;
-}
-
-void GDAPI godot_glyph_set_count(godot_glyph *p_self, godot_int p_count) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->count = p_count;
-}
-
-godot_int GDAPI godot_glyph_get_repeat(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->repeat;
-}
-
-void GDAPI godot_glyph_set_repeat(godot_glyph *p_self, godot_int p_repeat) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->repeat = p_repeat;
-}
-
-godot_int GDAPI godot_glyph_get_flags(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->flags;
-}
-
-void GDAPI godot_glyph_set_flags(godot_glyph *p_self, godot_int p_flags) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->flags = p_flags;
-}
-
-godot_vector2 GDAPI godot_glyph_get_offset(const godot_glyph *p_self) {
- godot_vector2 dest;
- Vector2 *d = (Vector2 *)&dest;
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- d->x = self->x_off;
- d->y = self->y_off;
- return dest;
-}
-
-void GDAPI godot_glyph_set_offset(godot_glyph *p_self, const godot_vector2 *p_offset) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- const Vector2 *offset = (const Vector2 *)p_offset;
- self->x_off = offset->x;
- self->y_off = offset->y;
-}
-
-godot_real_t GDAPI godot_glyph_get_advance(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->advance;
-}
-
-void GDAPI godot_glyph_set_advance(godot_glyph *p_self, godot_real_t p_advance) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->advance = p_advance;
-}
-
-godot_rid GDAPI godot_glyph_get_font(const godot_glyph *p_self) {
- godot_rid dest;
- RID *d = (RID *)&dest;
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- *d = self->font_rid;
- return dest;
-}
-
-void GDAPI godot_glyph_set_font(godot_glyph *p_self, godot_rid *p_font) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- const RID *font = (const RID *)p_font;
- self->font_rid = *font;
-}
-
-godot_int GDAPI godot_glyph_get_font_size(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->font_size;
-}
-
-void GDAPI godot_glyph_set_font_size(godot_glyph *p_self, godot_int p_size) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->font_size = p_size;
-}
-
-godot_int GDAPI godot_glyph_get_index(const godot_glyph *p_self) {
- const TextServer::Glyph *self = (const TextServer::Glyph *)p_self;
- return self->index;
-}
-
-void GDAPI godot_glyph_set_index(godot_glyph *p_self, godot_int p_index) {
- TextServer::Glyph *self = (TextServer::Glyph *)p_self;
- self->index = p_index;
-}
-
-// GlyphArray
-
-void GDAPI godot_packed_glyph_array_new(godot_packed_glyph_array *r_dest) {
- Vector<TextServer::Glyph> *dest = (Vector<TextServer::Glyph> *)r_dest;
- memnew_placement(dest, Vector<TextServer::Glyph>);
-}
-
-void GDAPI godot_packed_glyph_array_new_copy(godot_packed_glyph_array *r_dest, const godot_packed_glyph_array *p_src) {
- Vector<TextServer::Glyph> *dest = (Vector<TextServer::Glyph> *)r_dest;
- const Vector<TextServer::Glyph> *src = (const Vector<TextServer::Glyph> *)p_src;
- memnew_placement(dest, Vector<TextServer::Glyph>(*src));
-}
-
-const godot_glyph GDAPI *godot_packed_glyph_array_ptr(const godot_packed_glyph_array *p_self) {
- const Vector<TextServer::Glyph> *self = (const Vector<TextServer::Glyph> *)p_self;
- return (const godot_glyph *)self->ptr();
-}
-
-godot_glyph GDAPI *godot_packed_glyph_array_ptrw(godot_packed_glyph_array *p_self) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- return (godot_glyph *)self->ptrw();
-}
-
-void GDAPI godot_packed_glyph_array_append(godot_packed_glyph_array *p_self, const godot_glyph *p_data) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- TextServer::Glyph &s = *(TextServer::Glyph *)p_data;
- self->push_back(s);
-}
-
-void GDAPI godot_packed_glyph_array_append_array(godot_packed_glyph_array *p_self, const godot_packed_glyph_array *p_array) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- Vector<TextServer::Glyph> *array = (Vector<TextServer::Glyph> *)p_array;
- self->append_array(*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) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- TextServer::Glyph &s = *(TextServer::Glyph *)p_data;
- return (godot_error)self->insert(p_idx, s);
-}
-
-godot_bool GDAPI godot_packed_glyph_array_has(godot_packed_glyph_array *p_self, const godot_glyph *p_value) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- TextServer::Glyph &v = *(TextServer::Glyph *)p_value;
- return (godot_bool)self->has(v);
-}
-
-void GDAPI godot_packed_glyph_array_sort(godot_packed_glyph_array *p_self) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- self->sort();
-}
-
-void GDAPI godot_packed_glyph_array_reverse(godot_packed_glyph_array *p_self) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- self->reverse();
-}
-
-void GDAPI godot_packed_glyph_array_push_back(godot_packed_glyph_array *p_self, const godot_glyph *p_data) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- TextServer::Glyph &s = *(TextServer::Glyph *)p_data;
- self->push_back(s);
-}
-
-void GDAPI godot_packed_glyph_array_remove(godot_packed_glyph_array *p_self, const godot_int p_idx) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- self->remove(p_idx);
-}
-
-void GDAPI godot_packed_glyph_array_resize(godot_packed_glyph_array *p_self, const godot_int p_size) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- self->resize(p_size);
-}
-
-void GDAPI godot_packed_glyph_array_set(godot_packed_glyph_array *p_self, const godot_int p_idx, const godot_glyph *p_data) {
- Vector<TextServer::Glyph> *self = (Vector<TextServer::Glyph> *)p_self;
- TextServer::Glyph &s = *(TextServer::Glyph *)p_data;
- self->set(p_idx, s);
-}
-
-godot_glyph GDAPI godot_packed_glyph_array_get(const godot_packed_glyph_array *p_self, const godot_int p_idx) {
- const Vector<TextServer::Glyph> *self = (const Vector<TextServer::Glyph> *)p_self;
- godot_glyph v;
- TextServer::Glyph *s = (TextServer::Glyph *)&v;
- *s = self->get(p_idx);
- return v;
-}
-
-godot_int GDAPI godot_packed_glyph_array_size(const godot_packed_glyph_array *p_self) {
- const Vector<TextServer::Glyph> *self = (const Vector<TextServer::Glyph> *)p_self;
- return self->size();
-}
-
-godot_bool GDAPI godot_packed_glyph_array_is_empty(const godot_packed_glyph_array *p_self) {
- const Vector<TextServer::Glyph> *self = (const Vector<TextServer::Glyph> *)p_self;
- return self->is_empty();
-}
-
-void GDAPI godot_packed_glyph_array_destroy(godot_packed_glyph_array *p_self) {
- ((Vector<TextServer::Glyph> *)p_self)->~Vector();
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h
deleted file mode 100644
index f081637e23..0000000000
--- a/modules/gdnative/text/text_server_gdnative.h
+++ /dev/null
@@ -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
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 51b3452a3a..631ee4d895 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -176,7 +176,8 @@
<method name="range" qualifiers="vararg">
<return type="Array" />
<description>
- Returns an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment).
+ Returns an array with the given range. Range can be 1 argument [code]N[/code] (0 to [code]N[/code] - 1), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). Returns an empty array if the range isn't valid (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]).
+ Returns an array with the given range. [code]range()[/code] can have 1 argument N ([code]0[/code] to [code]N - 1[/code]), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). [code]increment[/code] can be negative. If [code]increment[/code] is negative, [code]final - 1[/code] will become [code]final + 1[/code]. Also, the initial value must be greater than the final value for the loop to run.
[codeblock]
print(range(4))
print(range(2, 5))
@@ -188,6 +189,20 @@
[2, 3, 4]
[0, 2, 4]
[/codeblock]
+ To iterate over an [Array] backwards, use:
+ [codeblock]
+ var array = [3, 6, 9]
+ var i := array.size() - 1
+ while i &gt;= 0:
+ print(array[i])
+ i -= 1
+ [/codeblock]
+ Output:
+ [codeblock]
+ 9
+ 6
+ 3
+ [/codeblock]
</description>
</method>
<method name="str" qualifiers="vararg">
diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py
index d22f9454ed..8c8df9b05e 100644
--- a/modules/text_server_adv/config.py
+++ b/modules/text_server_adv/config.py
@@ -4,3 +4,13 @@ def can_build(env, platform):
def configure(env):
pass
+
+
+def get_doc_classes():
+ return [
+ "TextServerAdvanced",
+ ]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/text_server_adv/doc_classes/TextServerAdvanced.xml b/modules/text_server_adv/doc_classes/TextServerAdvanced.xml
new file mode 100644
index 0000000000..eff4aa5fae
--- /dev/null
+++ b/modules/text_server_adv/doc_classes/TextServerAdvanced.xml
@@ -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>
diff --git a/modules/text_server_adv/register_types.cpp b/modules/text_server_adv/register_types.cpp
index abefa83b9b..b711d1561f 100644
--- a/modules/text_server_adv/register_types.cpp
+++ b/modules/text_server_adv/register_types.cpp
@@ -33,7 +33,12 @@
#include "text_server_adv.h"
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() {
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index b5b7342e87..f5d159040f 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -322,7 +322,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite";
uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | 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;
}
@@ -330,6 +330,10 @@ String TextServerAdvanced::get_name() const {
return interface_name;
}
+uint32_t TextServerAdvanced::get_features() const {
+ return interface_features;
+}
+
void TextServerAdvanced::free(RID p_rid) {
_THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) {
@@ -394,9 +398,23 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) {
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
+}
+
+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) {
+bool TextServerAdvanced::save_support_data(const String &p_filename) const {
_THREAD_SAFE_METHOD_
#ifdef ICU_STATIC_DATA
@@ -415,9 +433,7 @@ bool TextServerAdvanced::save_support_data(const String &p_filename) {
#endif
}
-#endif
-
-bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) {
+bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) const {
String l = p_locale.get_slicec('_', 0);
if ((l == "ar") || (l == "dv") || (l == "he") || (l == "fa") || (l == "ff") || (l == "ku") || (l == "ur")) {
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);
if (error) {
fd->glyph_map[p_glyph] = FontGlyph();
- ERR_FAIL_V_MSG(false, "FreeType: Failed to load glyph.");
+ return false;
}
if (!outline) {
@@ -1236,7 +1252,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
fd->oversampling = 1.0f;
fd->size.x = p_font_data->msdf_source_size;
} else if (p_font_data->oversampling <= 0.0f) {
- fd->oversampling = TS->font_get_global_oversampling();
+ fd->oversampling = font_get_global_oversampling();
} else {
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) {
int best_match = 0;
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++) {
int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width));
if (ndiff < diff) {
best_match = i;
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);
@@ -1786,7 +1802,7 @@ Dictionary TextServerAdvanced::font_get_variation_coordinates(RID p_font_rid) co
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);
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);
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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) {
case TextServer::SPACING_GLYPH: {
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 {
return fd->cache[size]->spacing_glyph;
}
} break;
case TextServer::SPACING_SPACE: {
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 {
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;
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 {
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;
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 {
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;
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 {
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;
}
-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);
- ERR_FAIL_COND_V(!fd, false);
+ ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
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
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();
- r_contours.clear();
+ points.clear();
+ contours.clear();
- real_t h = fd->cache[size]->ascent;
- real_t scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
+ float h = fd->cache[size]->ascent;
+ float scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
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++) {
- 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++) {
- 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
- return false;
+ return Dictionary();
#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 {
@@ -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 (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 {
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_Get_Kerning(fd->cache[size]->face, p_glyph_pair.x, p_glyph_pair.y, FT_KERNING_DEFAULT, &delta);
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 {
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();
if (fd->msdf) {
Point2 cpos = p_pos;
- cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size;
- Size2 csize = gl.rect.size * (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 * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else {
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();
if (fd->msdf) {
Point2 cpos = p_pos;
- cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size;
- Size2 csize = gl.rect.size * (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 * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else {
Point2i cpos = p_pos;
@@ -2694,7 +2718,7 @@ bool TextServerAdvanced::font_is_script_supported(RID p_font_rid, const String &
} else {
Vector2i size = _get_size(fd, 16);
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;
}
-real_t TextServerAdvanced::font_get_global_oversampling() const {
+float TextServerAdvanced::font_get_global_oversampling() const {
return oversampling;
}
-void TextServerAdvanced::font_set_global_oversampling(real_t p_oversampling) {
+void TextServerAdvanced::font_set_global_oversampling(float p_oversampling) {
_THREAD_SAFE_METHOD_
if (oversampling != p_oversampling) {
oversampling = p_oversampling;
@@ -2904,7 +2928,7 @@ TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped
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);
ERR_FAIL_COND(!sd);
@@ -2912,7 +2936,10 @@ void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Vecto
if (sd->parent != RID()) {
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);
}
@@ -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))) {
// Glyph not found, replace with hex code box.
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->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
+ sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} else {
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));
@@ -3108,8 +3134,8 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key,
}
// Align embedded objects to baseline.
- real_t full_ascent = sd->ascent;
- real_t full_descent = sd->descent;
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) {
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))) {
// Glyph not found, replace with hex code box.
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->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
+ new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} 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->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.
- real_t full_ascent = new_sd->ascent;
- real_t full_descent = new_sd->descent;
+ float full_ascent = new_sd->ascent;
+ float full_descent = new_sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
@@ -3378,7 +3403,7 @@ RID TextServerAdvanced::shaped_text_get_parent(RID p_shaped) const {
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);
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 (sd->overrun_trim_data.trim_pos >= 0) {
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)) {
- 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++) {
Glyph &gl = sd->glyphs.write[i];
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)) {
- 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++) {
Glyph &gl = sd->glyphs.write[i];
if (gl.count > 0) {
if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
- real_t old_adv = gl.advance;
- real_t new_advance;
+ float old_adv = gl.advance;
+ float new_advance;
if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
new_advance = MAX(gl.advance + delta_width_per_space, 0.f);
} else {
@@ -3514,7 +3539,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_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);
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;
- real_t off = 0.f;
+ float off = 0.f;
int start, end, delta;
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) {
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) {
tab_off += p_tab_stops[tab_index];
tab_index++;
@@ -3552,7 +3577,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
tab_index = 0;
}
}
- real_t old_adv = gl[i].advance;
+ float old_adv = gl[i].advance;
gl[i].advance = tab_off - off;
sd->width += gl[i].advance - old_adv;
off = 0;
@@ -3564,7 +3589,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real
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);
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;
- 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);
@@ -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)) {
// Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) {
- TextServer::Glyph gl;
+ Glyph gl;
gl.count = 1;
gl.advance = whitespace_adv.x;
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);
}
// Add ellipsis dots.
- TextServer::Glyph gl;
+ Glyph gl;
gl.count = 1;
gl.repeat = 3;
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);
+ ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid.");
+
+ MutexLock lock(sd->mutex);
+ 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, TrimData(), "ShapedTextDataAdvanced invalid.");
+ ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid.");
MutexLock lock(sd->mutex);
- return sd->overrun_trim_data;
+ 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) {
@@ -3783,7 +3832,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
if (is_whitespace(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT;
} else {
- TextServer::Glyph gl;
+ Glyph gl;
gl.start = sd_glyphs[i].start;
gl.end = sd_glyphs[i].end;
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;
} else {
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) {
gl.start = sd->glyphs[i].start;
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)) {
- TextServer::Glyph gl;
+ Glyph gl;
gl.start = sd->glyphs[i].start;
gl.end = sd->glyphs[i].end;
gl.count = 1;
@@ -4007,9 +4056,9 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) {
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);
- 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_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);
// Process glyphs.
- TextServer::Glyph gl;
+ Glyph gl;
if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) {
gl.flags |= TextServer::GRAPHEME_IS_RTL;
@@ -4034,7 +4083,7 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced
gl.font_size = p_font_size;
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) {
gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale));
} else {
@@ -4059,7 +4108,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
// Add fallback glyphs.
for (int i = p_start; i < p_end; 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.end = i + 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) {
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->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.25f));
+ p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y);
} else {
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));
@@ -4126,7 +4174,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
// Process glyphs.
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;
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;
- TextServer::Glyph &gl = w[i];
- gl = TextServer::Glyph();
+ Glyph &gl = w[i];
+ gl = Glyph();
gl.start = glyph_info[i].cluster;
gl.end = end;
@@ -4171,7 +4219,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
gl.index = glyph_info[i].codepoint;
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) {
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
} else {
@@ -4411,8 +4459,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
}
// Align embedded objects to baseline.
- real_t full_ascent = sd->ascent;
- real_t full_descent = sd->descent;
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
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;
}
-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);
- ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>());
+ ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex);
if (!sd->valid) {
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);
- ERR_FAIL_COND_V(!sd, Vector2i());
+ ERR_FAIL_COND_V(!sd, 0);
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);
- ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>());
+ ERR_FAIL_COND_V(!sd, nullptr);
MutexLock lock(sd->mutex);
if (!sd->valid) {
@@ -4516,11 +4567,19 @@ Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_sort_logical(RID p_sha
if (!sd->sort_valid) {
sd->glyphs_logical = sd->glyphs;
- sd->glyphs_logical.sort_custom<TextServer::GlyphCompare>();
+ sd->glyphs_logical.sort_custom<GlyphCompare>();
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 {
@@ -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);
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;
}
-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);
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;
}
-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);
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);
}
-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);
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;
}
-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);
ERR_FAIL_COND_V(!sd, 0.f);
@@ -4752,15 +4811,6 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
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() {
_insert_num_systems_lang();
_insert_feature_sets();
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index fc0e7a09a7..1feeada76d 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -115,12 +115,12 @@ class TextServerAdvanced : public TextServer {
};
struct FontDataForSizeAdvanced {
- real_t ascent = 0.f;
- real_t descent = 0.f;
- real_t underline_position = 0.f;
- real_t underline_thickness = 0.f;
- real_t scale = 1.f;
- real_t oversampling = 1.f;
+ float ascent = 0.f;
+ float descent = 0.f;
+ float underline_position = 0.f;
+ float underline_thickness = 0.f;
+ float scale = 1.f;
+ float oversampling = 1.f;
int spacing_glyph = 0;
int spacing_space = 0;
@@ -161,7 +161,7 @@ class TextServerAdvanced : public TextServer {
bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
Dictionary variation_coordinates;
- real_t oversampling = 0.f;
+ float oversampling = 0.f;
Map<Vector2i, FontDataForSizeAdvanced *> cache;
@@ -245,14 +245,14 @@ class TextServerAdvanced : public TextServer {
// Common data.
- real_t oversampling = 1.f;
+ float oversampling = 1.f;
mutable RID_PtrOwner<FontDataAdvanced> font_owner;
mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner;
int _convert_pos(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);
- 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.
@@ -284,20 +284,19 @@ protected:
void invalidate(ShapedTextDataAdvanced *p_shaped);
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 uint32_t get_features() 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 { return _MKSTR(ICU_DATA_NAME); };
- 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) override;
-#endif
+ 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;
- 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 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 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 void font_set_oversampling(RID p_font_rid, float p_oversampling) 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 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;
- 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_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;
- 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_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;
- 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_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;
- 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_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;
- 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_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;
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;
@@ -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 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 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_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;
+ virtual float font_get_global_oversampling() const override;
+ virtual void font_set_global_oversampling(float p_oversampling) override;
/* 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 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 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_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 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;
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 TrimData shaped_text_get_trim_data(RID p_shaped) const override;
+ 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;
+
+ 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 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 Vector<Glyph> shaped_text_sort_logical(RID p_shaped) 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 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;
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);
- static void register_server();
-
TextServerAdvanced();
~TextServerAdvanced();
};
diff --git a/modules/text_server_fb/config.py b/modules/text_server_fb/config.py
index 7a73080ae9..275c2b4d53 100644
--- a/modules/text_server_fb/config.py
+++ b/modules/text_server_fb/config.py
@@ -9,3 +9,13 @@ def configure(env):
def is_enabled():
# The module is disabled by default. Use module_text_server_fb_enabled=yes to enable it.
return False
+
+
+def get_doc_classes():
+ return [
+ "TextServerFallback",
+ ]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/text_server_fb/doc_classes/TextServerFallback.xml b/modules/text_server_fb/doc_classes/TextServerFallback.xml
new file mode 100644
index 0000000000..8aadf2b882
--- /dev/null
+++ b/modules/text_server_fb/doc_classes/TextServerFallback.xml
@@ -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>
diff --git a/modules/text_server_fb/register_types.cpp b/modules/text_server_fb/register_types.cpp
index 87cbd2ac2c..0b59040ce8 100644
--- a/modules/text_server_fb/register_types.cpp
+++ b/modules/text_server_fb/register_types.cpp
@@ -33,7 +33,12 @@
#include "text_server_fb.h"
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() {
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 62adf458aa..3d868d7be3 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -69,7 +69,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
String TextServerFallback::interface_name = "Fallback";
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;
}
@@ -77,6 +77,10 @@ String TextServerFallback::get_name() const {
return interface_name;
}
+uint32_t TextServerFallback::get_features() const {
+ return interface_features;
+}
+
void TextServerFallback::free(RID p_rid) {
_THREAD_SAFE_METHOD_
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.
}
-#ifdef TOOLS_ENABLED
-
-bool TextServerFallback::save_support_data(const String &p_filename) {
+bool TextServerFallback::save_support_data(const String &p_filename) const {
return false; // No extra data used.
}
-#endif
-
-bool TextServerFallback::is_locale_right_to_left(const String &p_locale) {
+bool TextServerFallback::is_locale_right_to_left(const String &p_locale) const {
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];
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.
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);
if (error) {
fd->glyph_map[p_glyph] = FontGlyph();
- ERR_FAIL_V_MSG(false, "FreeType: Failed to load glyph.");
+ return false;
}
if (!outline) {
@@ -714,7 +714,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
fd->oversampling = 1.0f;
fd->size.x = p_font_data->msdf_source_size;
} else if (p_font_data->oversampling <= 0.0f) {
- fd->oversampling = TS->font_get_global_oversampling();
+ fd->oversampling = font_get_global_oversampling();
} else {
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) {
int best_match = 0;
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++) {
int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width));
if (ndiff < diff) {
best_match = i;
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);
@@ -769,7 +769,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
for (FT_UInt i = 0; i < amaster->num_axis; i++) {
// Reset to default.
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;
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;
}
-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);
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);
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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);
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;
}
-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);
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);
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 {
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) {
case TextServer::SPACING_GLYPH: {
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 {
return fd->cache[size]->spacing_glyph;
}
} break;
case TextServer::SPACING_SPACE: {
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 {
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;
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 {
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;
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 {
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;
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 {
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;
}
-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);
- ERR_FAIL_COND_V(!fd, false);
+ ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
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
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();
- r_contours.clear();
+ points.clear();
+ contours.clear();
- real_t h = fd->cache[size]->ascent;
- real_t scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
+ float h = fd->cache[size]->ascent;
+ float scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
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++) {
- 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++) {
- 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
- return false;
+ return Dictionary();
#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 {
@@ -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 (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 {
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);
FT_Get_Kerning(fd->cache[size]->face, glyph_a, glyph_b, FT_KERNING_DEFAULT, &delta);
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 {
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();
if (fd->msdf) {
Point2 cpos = p_pos;
- cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size;
- Size2 csize = gl.rect.size * (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 * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else {
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();
if (fd->msdf) {
Point2 cpos = p_pos;
- cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size;
- Size2 csize = gl.rect.size * (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 * (float)p_size / (float)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else {
Point2i cpos = p_pos;
@@ -1922,11 +1930,11 @@ Dictionary TextServerFallback::font_supported_variation_list(RID p_font_rid) con
return fd->supported_varaitions;
}
-real_t TextServerFallback::font_get_global_oversampling() const {
+float TextServerFallback::font_get_global_oversampling() const {
return oversampling;
}
-void TextServerFallback::font_set_global_oversampling(real_t p_oversampling) {
+void TextServerFallback::font_set_global_oversampling(float p_oversampling) {
_THREAD_SAFE_METHOD_
if (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.
}
@@ -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))) {
// Glyph not found, replace with hex code box.
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->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
+ sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} else {
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));
@@ -2235,8 +2242,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
}
// Align embedded objects to baseline.
- real_t full_ascent = sd->ascent;
- real_t full_descent = sd->descent;
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) {
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))) {
// Glyph not found, replace with hex code box.
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->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
+ new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} 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->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.
- real_t full_ascent = new_sd->ascent;
- real_t full_descent = new_sd->descent;
+ float full_ascent = new_sd->ascent;
+ float full_descent = new_sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) {
if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
@@ -2466,7 +2472,7 @@ RID TextServerFallback::shaped_text_get_parent(RID p_shaped) const {
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);
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)) {
- 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++) {
Glyph &gl = sd->glyphs.write[i];
if (gl.count > 0) {
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));
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;
}
-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);
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;
- real_t off = 0.f;
+ float off = 0.f;
int start, end, delta;
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) {
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) {
tab_off += p_tab_stops[tab_index];
tab_index++;
@@ -2584,7 +2590,7 @@ real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<real
tab_index = 0;
}
}
- real_t old_adv = gl[i].advance;
+ float old_adv = gl[i].advance;
gl[i].advance = tab_off - off;
sd->width += gl[i].advance - old_adv;
off = 0;
@@ -2653,7 +2659,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(RID p_shaped) {
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);
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;
- real_t width = sd->width;
+ float width = sd->width;
int trim_pos = 0;
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)) {
// Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) {
- TextServer::Glyph gl;
+ Glyph gl;
gl.count = 1;
gl.advance = whitespace_adv.x;
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);
}
// Add ellipsis dots.
- TextServer::Glyph gl;
+ Glyph gl;
gl.count = 1;
gl.repeat = 3;
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);
+ ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid.");
+
+ MutexLock lock(sd->mutex);
+ 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, TrimData(), "ShapedTextDataFallback invalid.");
+ ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextData invalid.");
MutexLock lock(sd->mutex);
- return sd->overrun_trim_data;
+ return sd->overrun_trim_data.ellipsis_glyph_buf.size();
}
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.
if (sd->orientation == ORIENTATION_HORIZONTAL) {
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->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
+ sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y);
} else {
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));
@@ -2905,8 +2934,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
}
// Align embedded objects to baseline.
- real_t full_ascent = sd->ascent;
- real_t full_descent = sd->descent;
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) {
@@ -2980,35 +3009,46 @@ bool TextServerFallback::shaped_text_is_ready(RID p_shaped) const {
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);
- ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>());
+ 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;
+ return sd->glyphs.ptr();
}
-Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
+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, Vector2i());
+ ERR_FAIL_COND_V(!sd, 0);
MutexLock lock(sd->mutex);
- return Vector2(sd->start, sd->end);
+ if (!sd->valid) {
+ const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
+ }
+ return sd->glyphs.size();
}
-Vector<TextServer::Glyph> TextServerFallback::shaped_text_sort_logical(RID p_shaped) {
+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, Vector<TextServer::Glyph>());
+ 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; // Already in the logical order, return as is.
+ return sd->glyphs.ptr(); // Already in the logical order, return as is.
+}
+
+Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const {
+ const ShapedTextData *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 TextServerFallback::shaped_text_get_objects(RID p_shaped) const {
@@ -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);
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;
}
-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);
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;
}
-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);
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;
}
-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);
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;
}
-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);
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;
}
-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() {
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index fde75e7135..992ce5018f 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -93,12 +93,12 @@ class TextServerFallback : public TextServer {
};
struct FontDataForSizeFallback {
- real_t ascent = 0.f;
- real_t descent = 0.f;
- real_t underline_position = 0.f;
- real_t underline_thickness = 0.f;
- real_t scale = 1.f;
- real_t oversampling = 1.f;
+ float ascent = 0.f;
+ float descent = 0.f;
+ float underline_position = 0.f;
+ float underline_thickness = 0.f;
+ float scale = 1.f;
+ float oversampling = 1.f;
int spacing_glyph = 0;
int spacing_space = 0;
@@ -134,7 +134,7 @@ class TextServerFallback : public TextServer {
bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
Dictionary variation_coordinates;
- real_t oversampling = 0.f;
+ float oversampling = 0.f;
Map<Vector2i, FontDataForSizeFallback *> cache;
@@ -194,7 +194,7 @@ class TextServerFallback : public TextServer {
// Common data.
- real_t oversampling = 1.f;
+ float oversampling = 1.f;
mutable RID_PtrOwner<FontDataFallback> font_owner;
mutable RID_PtrOwner<ShapedTextData> shaped_owner;
@@ -205,20 +205,19 @@ protected:
void invalidate(ShapedTextData *p_shaped);
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 uint32_t get_features() 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 { return ""; };
- virtual String get_support_data_info() override { return "Not supported"; };
- virtual bool save_support_data(const String &p_filename) override;
-#endif
+ virtual String get_support_data_filename() const override { return ""; };
+ virtual String get_support_data_info() const override { return "Not supported"; };
+ virtual bool save_support_data(const String &p_filename) const override;
- 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 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 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 void font_set_oversampling(RID p_font_rid, float p_oversampling) 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 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_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;
- 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_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;
- 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_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;
- 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_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;
- 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_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;
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;
@@ -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 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 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_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;
+ virtual float font_get_global_oversampling() const override;
+ virtual void font_set_global_oversampling(float p_oversampling) override;
/* 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 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 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_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 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;
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 TrimData shaped_text_get_trim_data(RID p_shaped) const override;
+ 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;
+
+ 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 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 Vector<Glyph> shaped_text_sort_logical(RID p_shaped) 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;
-
- static TextServer *create_func(Error &r_error, void *p_user_data);
- static void register_server();
+ 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;
TextServerFallback();
~TextServerFallback();
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 66fcc8335d..f2cd336b39 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -2068,6 +2068,24 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const {
return ret;
}
+Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
+ unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK;
+ unsigned int xkeycode = KeyMappingX11::get_xlibcode((Key)keycode_no_mod);
+ KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0);
+ if (xkeysym >= 'a' && xkeysym <= 'z') {
+ xkeysym -= ('a' - 'A');
+ }
+
+ Key key = KeyMappingX11::get_keycode(xkeysym);
+ // If not found, fallback to QWERTY.
+ // This should match the behavior of the event pump
+ if (key == KEY_NONE) {
+ return p_keycode;
+ }
+ return (Key)(key | modifiers);
+}
+
DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) {
Atom actual_type = None;
int actual_format = 0;
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 052c6d6b7b..1887c7105b 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -372,6 +372,7 @@ public:
virtual void keyboard_set_current_layout(int p_index) override;
virtual String keyboard_get_layout_language(int p_index) const override;
virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
virtual void process_events() override;
diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp
index a1ef28234d..829feda40a 100644
--- a/platform/linuxbsd/key_mapping_x11.cpp
+++ b/platform/linuxbsd/key_mapping_x11.cpp
@@ -309,6 +309,18 @@ unsigned int KeyMappingX11::get_scancode(unsigned int p_code) {
return keycode;
}
+unsigned int KeyMappingX11::get_xlibcode(unsigned int p_keysym) {
+ unsigned int code = 0;
+ for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+ if (_scancode_to_keycode[i].keysym == p_keysym) {
+ code = _scancode_to_keycode[i].keycode;
+ break;
+ }
+ }
+
+ return code;
+}
+
Key KeyMappingX11::get_keycode(KeySym p_keysym) {
// kinda bruteforce.. could optimize.
diff --git a/platform/linuxbsd/key_mapping_x11.h b/platform/linuxbsd/key_mapping_x11.h
index 598db1c45a..d4f1554671 100644
--- a/platform/linuxbsd/key_mapping_x11.h
+++ b/platform/linuxbsd/key_mapping_x11.h
@@ -45,6 +45,7 @@ class KeyMappingX11 {
public:
static Key get_keycode(KeySym p_keysym);
+ static unsigned int get_xlibcode(unsigned int p_keysym);
static unsigned int get_scancode(unsigned int p_code);
static KeySym get_keysym(Key p_code);
static unsigned int get_unicode_from_keysym(KeySym p_keysym);
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 06b14f1c14..e8f2858489 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -305,6 +305,7 @@ public:
virtual void keyboard_set_current_layout(int p_index) override;
virtual String keyboard_get_layout_language(int p_index) const override;
virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
virtual void process_events() override;
virtual void force_process_and_drop_events() override;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index f037d75fbd..da6c45793a 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -930,146 +930,155 @@ static bool isNumpadKey(unsigned int key) {
return false;
}
+// Keyboard symbol translation table
+static const Key _osx_to_godot_table[128] = {
+ /* 00 */ KEY_A,
+ /* 01 */ KEY_S,
+ /* 02 */ KEY_D,
+ /* 03 */ KEY_F,
+ /* 04 */ KEY_H,
+ /* 05 */ KEY_G,
+ /* 06 */ KEY_Z,
+ /* 07 */ KEY_X,
+ /* 08 */ KEY_C,
+ /* 09 */ KEY_V,
+ /* 0a */ KEY_SECTION, /* ISO Section */
+ /* 0b */ KEY_B,
+ /* 0c */ KEY_Q,
+ /* 0d */ KEY_W,
+ /* 0e */ KEY_E,
+ /* 0f */ KEY_R,
+ /* 10 */ KEY_Y,
+ /* 11 */ KEY_T,
+ /* 12 */ KEY_1,
+ /* 13 */ KEY_2,
+ /* 14 */ KEY_3,
+ /* 15 */ KEY_4,
+ /* 16 */ KEY_6,
+ /* 17 */ KEY_5,
+ /* 18 */ KEY_EQUAL,
+ /* 19 */ KEY_9,
+ /* 1a */ KEY_7,
+ /* 1b */ KEY_MINUS,
+ /* 1c */ KEY_8,
+ /* 1d */ KEY_0,
+ /* 1e */ KEY_BRACERIGHT,
+ /* 1f */ KEY_O,
+ /* 20 */ KEY_U,
+ /* 21 */ KEY_BRACELEFT,
+ /* 22 */ KEY_I,
+ /* 23 */ KEY_P,
+ /* 24 */ KEY_ENTER,
+ /* 25 */ KEY_L,
+ /* 26 */ KEY_J,
+ /* 27 */ KEY_APOSTROPHE,
+ /* 28 */ KEY_K,
+ /* 29 */ KEY_SEMICOLON,
+ /* 2a */ KEY_BACKSLASH,
+ /* 2b */ KEY_COMMA,
+ /* 2c */ KEY_SLASH,
+ /* 2d */ KEY_N,
+ /* 2e */ KEY_M,
+ /* 2f */ KEY_PERIOD,
+ /* 30 */ KEY_TAB,
+ /* 31 */ KEY_SPACE,
+ /* 32 */ KEY_QUOTELEFT,
+ /* 33 */ KEY_BACKSPACE,
+ /* 34 */ KEY_UNKNOWN,
+ /* 35 */ KEY_ESCAPE,
+ /* 36 */ KEY_META,
+ /* 37 */ KEY_META,
+ /* 38 */ KEY_SHIFT,
+ /* 39 */ KEY_CAPSLOCK,
+ /* 3a */ KEY_ALT,
+ /* 3b */ KEY_CTRL,
+ /* 3c */ KEY_SHIFT,
+ /* 3d */ KEY_ALT,
+ /* 3e */ KEY_CTRL,
+ /* 3f */ KEY_UNKNOWN, /* Function */
+ /* 40 */ KEY_UNKNOWN, /* F17 */
+ /* 41 */ KEY_KP_PERIOD,
+ /* 42 */ KEY_UNKNOWN,
+ /* 43 */ KEY_KP_MULTIPLY,
+ /* 44 */ KEY_UNKNOWN,
+ /* 45 */ KEY_KP_ADD,
+ /* 46 */ KEY_UNKNOWN,
+ /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */
+ /* 48 */ KEY_VOLUMEUP, /* VolumeUp */
+ /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */
+ /* 4a */ KEY_VOLUMEMUTE, /* Mute */
+ /* 4b */ KEY_KP_DIVIDE,
+ /* 4c */ KEY_KP_ENTER,
+ /* 4d */ KEY_UNKNOWN,
+ /* 4e */ KEY_KP_SUBTRACT,
+ /* 4f */ KEY_UNKNOWN, /* F18 */
+ /* 50 */ KEY_UNKNOWN, /* F19 */
+ /* 51 */ KEY_EQUAL, /* KeypadEqual */
+ /* 52 */ KEY_KP_0,
+ /* 53 */ KEY_KP_1,
+ /* 54 */ KEY_KP_2,
+ /* 55 */ KEY_KP_3,
+ /* 56 */ KEY_KP_4,
+ /* 57 */ KEY_KP_5,
+ /* 58 */ KEY_KP_6,
+ /* 59 */ KEY_KP_7,
+ /* 5a */ KEY_UNKNOWN, /* F20 */
+ /* 5b */ KEY_KP_8,
+ /* 5c */ KEY_KP_9,
+ /* 5d */ KEY_YEN, /* JIS Yen */
+ /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */
+ /* 5f */ KEY_COMMA, /* JIS KeypadComma */
+ /* 60 */ KEY_F5,
+ /* 61 */ KEY_F6,
+ /* 62 */ KEY_F7,
+ /* 63 */ KEY_F3,
+ /* 64 */ KEY_F8,
+ /* 65 */ KEY_F9,
+ /* 66 */ KEY_UNKNOWN, /* JIS Eisu */
+ /* 67 */ KEY_F11,
+ /* 68 */ KEY_UNKNOWN, /* JIS Kana */
+ /* 69 */ KEY_F13,
+ /* 6a */ KEY_F16,
+ /* 6b */ KEY_F14,
+ /* 6c */ KEY_UNKNOWN,
+ /* 6d */ KEY_F10,
+ /* 6e */ KEY_MENU,
+ /* 6f */ KEY_F12,
+ /* 70 */ KEY_UNKNOWN,
+ /* 71 */ KEY_F15,
+ /* 72 */ KEY_INSERT, /* Really Help... */
+ /* 73 */ KEY_HOME,
+ /* 74 */ KEY_PAGEUP,
+ /* 75 */ KEY_DELETE,
+ /* 76 */ KEY_F4,
+ /* 77 */ KEY_END,
+ /* 78 */ KEY_F2,
+ /* 79 */ KEY_PAGEDOWN,
+ /* 7a */ KEY_F1,
+ /* 7b */ KEY_LEFT,
+ /* 7c */ KEY_RIGHT,
+ /* 7d */ KEY_DOWN,
+ /* 7e */ KEY_UP,
+ /* 7f */ KEY_UNKNOWN,
+};
+
// Translates a OS X keycode to a Godot keycode
-//
static Key translateKey(unsigned int key) {
- // Keyboard symbol translation table
- static const Key table[128] = {
- /* 00 */ KEY_A,
- /* 01 */ KEY_S,
- /* 02 */ KEY_D,
- /* 03 */ KEY_F,
- /* 04 */ KEY_H,
- /* 05 */ KEY_G,
- /* 06 */ KEY_Z,
- /* 07 */ KEY_X,
- /* 08 */ KEY_C,
- /* 09 */ KEY_V,
- /* 0a */ KEY_SECTION, /* ISO Section */
- /* 0b */ KEY_B,
- /* 0c */ KEY_Q,
- /* 0d */ KEY_W,
- /* 0e */ KEY_E,
- /* 0f */ KEY_R,
- /* 10 */ KEY_Y,
- /* 11 */ KEY_T,
- /* 12 */ KEY_1,
- /* 13 */ KEY_2,
- /* 14 */ KEY_3,
- /* 15 */ KEY_4,
- /* 16 */ KEY_6,
- /* 17 */ KEY_5,
- /* 18 */ KEY_EQUAL,
- /* 19 */ KEY_9,
- /* 1a */ KEY_7,
- /* 1b */ KEY_MINUS,
- /* 1c */ KEY_8,
- /* 1d */ KEY_0,
- /* 1e */ KEY_BRACERIGHT,
- /* 1f */ KEY_O,
- /* 20 */ KEY_U,
- /* 21 */ KEY_BRACELEFT,
- /* 22 */ KEY_I,
- /* 23 */ KEY_P,
- /* 24 */ KEY_ENTER,
- /* 25 */ KEY_L,
- /* 26 */ KEY_J,
- /* 27 */ KEY_APOSTROPHE,
- /* 28 */ KEY_K,
- /* 29 */ KEY_SEMICOLON,
- /* 2a */ KEY_BACKSLASH,
- /* 2b */ KEY_COMMA,
- /* 2c */ KEY_SLASH,
- /* 2d */ KEY_N,
- /* 2e */ KEY_M,
- /* 2f */ KEY_PERIOD,
- /* 30 */ KEY_TAB,
- /* 31 */ KEY_SPACE,
- /* 32 */ KEY_QUOTELEFT,
- /* 33 */ KEY_BACKSPACE,
- /* 34 */ KEY_UNKNOWN,
- /* 35 */ KEY_ESCAPE,
- /* 36 */ KEY_META,
- /* 37 */ KEY_META,
- /* 38 */ KEY_SHIFT,
- /* 39 */ KEY_CAPSLOCK,
- /* 3a */ KEY_ALT,
- /* 3b */ KEY_CTRL,
- /* 3c */ KEY_SHIFT,
- /* 3d */ KEY_ALT,
- /* 3e */ KEY_CTRL,
- /* 3f */ KEY_UNKNOWN, /* Function */
- /* 40 */ KEY_UNKNOWN, /* F17 */
- /* 41 */ KEY_KP_PERIOD,
- /* 42 */ KEY_UNKNOWN,
- /* 43 */ KEY_KP_MULTIPLY,
- /* 44 */ KEY_UNKNOWN,
- /* 45 */ KEY_KP_ADD,
- /* 46 */ KEY_UNKNOWN,
- /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */
- /* 48 */ KEY_VOLUMEUP, /* VolumeUp */
- /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */
- /* 4a */ KEY_VOLUMEMUTE, /* Mute */
- /* 4b */ KEY_KP_DIVIDE,
- /* 4c */ KEY_KP_ENTER,
- /* 4d */ KEY_UNKNOWN,
- /* 4e */ KEY_KP_SUBTRACT,
- /* 4f */ KEY_UNKNOWN, /* F18 */
- /* 50 */ KEY_UNKNOWN, /* F19 */
- /* 51 */ KEY_EQUAL, /* KeypadEqual */
- /* 52 */ KEY_KP_0,
- /* 53 */ KEY_KP_1,
- /* 54 */ KEY_KP_2,
- /* 55 */ KEY_KP_3,
- /* 56 */ KEY_KP_4,
- /* 57 */ KEY_KP_5,
- /* 58 */ KEY_KP_6,
- /* 59 */ KEY_KP_7,
- /* 5a */ KEY_UNKNOWN, /* F20 */
- /* 5b */ KEY_KP_8,
- /* 5c */ KEY_KP_9,
- /* 5d */ KEY_YEN, /* JIS Yen */
- /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */
- /* 5f */ KEY_COMMA, /* JIS KeypadComma */
- /* 60 */ KEY_F5,
- /* 61 */ KEY_F6,
- /* 62 */ KEY_F7,
- /* 63 */ KEY_F3,
- /* 64 */ KEY_F8,
- /* 65 */ KEY_F9,
- /* 66 */ KEY_UNKNOWN, /* JIS Eisu */
- /* 67 */ KEY_F11,
- /* 68 */ KEY_UNKNOWN, /* JIS Kana */
- /* 69 */ KEY_F13,
- /* 6a */ KEY_F16,
- /* 6b */ KEY_F14,
- /* 6c */ KEY_UNKNOWN,
- /* 6d */ KEY_F10,
- /* 6e */ KEY_MENU,
- /* 6f */ KEY_F12,
- /* 70 */ KEY_UNKNOWN,
- /* 71 */ KEY_F15,
- /* 72 */ KEY_INSERT, /* Really Help... */
- /* 73 */ KEY_HOME,
- /* 74 */ KEY_PAGEUP,
- /* 75 */ KEY_DELETE,
- /* 76 */ KEY_F4,
- /* 77 */ KEY_END,
- /* 78 */ KEY_F2,
- /* 79 */ KEY_PAGEDOWN,
- /* 7a */ KEY_F1,
- /* 7b */ KEY_LEFT,
- /* 7c */ KEY_RIGHT,
- /* 7d */ KEY_DOWN,
- /* 7e */ KEY_UP,
- /* 7f */ KEY_UNKNOWN,
- };
-
if (key >= 128) {
return KEY_UNKNOWN;
}
- return table[key];
+ return _osx_to_godot_table[key];
+}
+
+// Translates a Godot keycode back to a OSX keycode
+static unsigned int unmapKey(Key key) {
+ for (int i = 0; i <= 126; i++) {
+ if (_osx_to_godot_table[i] == key) {
+ return i;
+ }
+ }
+ return 127;
}
struct _KeyCodeMap {
@@ -3200,6 +3209,17 @@ String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
return kbd_layouts[p_index].name;
}
+Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ if (p_keycode == KEY_PAUSE) {
+ return p_keycode;
+ }
+
+ unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
+ unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK;
+ unsigned int osx_keycode = unmapKey((Key)keycode_no_mod);
+ return (Key)(remapKey(osx_keycode, 0) | modifiers);
+}
+
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
Ref<InputEvent> ev = p_event;
Input::get_singleton()->parse_input_event(ev);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 6ef1bdbd11..e9cb46ed21 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -314,17 +314,27 @@ String OS_OSX::get_name() const {
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) {
- String path = p_path;
+ String path = _get_framework_executable(p_path);
if (!FileAccess::exists(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());
+ // This code exists so gdnative can load .dylib files from within the executable path.
+ path = _get_framework_executable(get_executable_path().get_base_dir().plus_file(p_path.get_file()));
}
if (!FileAccess::exists(path)) {
- //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());
+ // This code exists so gdnative can load .dylib files from a standard macOS location.
+ 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);
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index a4be108c65..3100c0bd27 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1476,6 +1476,42 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const {
return String::utf16((const char16_t *)buf).substr(0, 2);
}
+Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
+ Key keycode_no_mod = (Key)(p_keycode & KEY_CODE_MASK);
+
+ if (keycode_no_mod == KEY_PRINT ||
+ keycode_no_mod == KEY_KP_ADD ||
+ keycode_no_mod == KEY_KP_5 ||
+ (keycode_no_mod >= KEY_0 && keycode_no_mod <= KEY_9)) {
+ return p_keycode;
+ }
+
+ unsigned int scancode = KeyMappingWindows::get_scancode(keycode_no_mod);
+ if (scancode == 0) {
+ return p_keycode;
+ }
+
+ HKL current_layout = GetKeyboardLayout(0);
+ UINT vk = MapVirtualKeyEx(scancode, MAPVK_VSC_TO_VK, current_layout);
+ if (vk == 0) {
+ return p_keycode;
+ }
+
+ UINT char_code = MapVirtualKeyEx(vk, MAPVK_VK_TO_CHAR, current_layout) & 0x7FFF;
+ // Unlike a similar Linux/BSD check which matches full Latin-1 range,
+ // we limit these to ASCII to fix some layouts, including Arabic ones
+ if (char_code >= 32 && char_code <= 127) {
+ // Godot uses 'braces' instead of 'brackets'
+ if (char_code == KEY_BRACKETLEFT || char_code == KEY_BRACKETRIGHT) {
+ char_code += 32;
+ }
+ return (Key)(char_code | modifiers);
+ }
+
+ return (Key)(KeyMappingWindows::get_keysym(vk) | modifiers);
+}
+
String _get_full_layout_name_from_registry(HKL p_layout) {
String id = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + String::num_int64((int64_t)p_layout, 16, false).lpad(8, "0");
String ret;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index c02a90c543..8b82288a40 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -543,6 +543,7 @@ public:
virtual void keyboard_set_current_layout(int p_index) override;
virtual String keyboard_get_layout_language(int p_index) const override;
virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
virtual int tablet_get_driver_count() const override;
virtual String tablet_get_driver_name(int p_driver) const override;
diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp
index db99d6c122..8016d20470 100644
--- a/platform/windows/key_mapping_windows.cpp
+++ b/platform/windows/key_mapping_windows.cpp
@@ -345,6 +345,16 @@ unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) {
return KEY_UNKNOWN;
}
+unsigned int KeyMappingWindows::get_scancode(Key p_keycode) {
+ for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+ if (_scancode_to_keycode[i].keysym == p_keycode) {
+ return _scancode_to_keycode[i].keycode;
+ }
+ }
+
+ return 0;
+}
+
unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) {
unsigned int keycode = KEY_UNKNOWN;
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
diff --git a/platform/windows/key_mapping_windows.h b/platform/windows/key_mapping_windows.h
index fb07227014..f260666a3e 100644
--- a/platform/windows/key_mapping_windows.h
+++ b/platform/windows/key_mapping_windows.h
@@ -42,6 +42,7 @@ class KeyMappingWindows {
public:
static unsigned int get_keysym(unsigned int p_code);
+ static unsigned int get_scancode(Key p_keycode);
static unsigned int get_scansym(unsigned int p_code, bool p_extended);
static bool is_extended_key(unsigned int p_code);
};
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 3c25f99ada..5f56f86029 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1131,6 +1131,8 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
bool sliding_enabled = !floor_stop_on_slope;
// Constant speed can be applied only the first time sliding is enabled.
bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
bool first_slide = true;
bool vel_dir_facing_up = motion_velocity.dot(up_direction) > 0;
Vector2 last_travel;
@@ -1147,6 +1149,19 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
motion_results.push_back(result);
_set_collision_direction(result);
+ // If we hit a ceiling platform, we set the vertical motion_velocity to at least the platform one.
+ if (on_ceiling && result.collider_velocity != Vector2() && result.collider_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (result.collision_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector2 ceiling_vertical_velocity = up_direction * up_direction.dot(result.collider_velocity);
+ Vector2 motion_vertical_velocity = up_direction * up_direction.dot(motion_velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ motion_velocity = ceiling_vertical_velocity + motion_velocity.slide(up_direction);
+ }
+ }
+ }
+
if (on_floor && floor_stop_on_slope && (motion_velocity.normalized() + up_direction).length() < 0.01) {
Transform2D gt = get_global_transform();
if (result.travel.length() <= margin + CMP_EPSILON) {
@@ -1200,7 +1215,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
}
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
+ else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
Vector2 slide_motion = result.remainder.slide(result.collision_normal);
if (slide_motion.dot(motion_velocity) > 0.0) {
motion = slide_motion;
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 4de67dd5dc..67f4a88228 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -369,6 +369,8 @@ void MeshInstance3D::create_debug_tangents() {
for (int i = 0; i < mesh->get_surface_count(); i++) {
Array arrays = mesh->surface_get_arrays(i);
+ ERR_CONTINUE(arrays.size() != Mesh::ARRAY_MAX);
+
Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX];
Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL];
if (norms.size() == 0) {
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 8603d15162..fc0df3650f 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -33,10 +33,6 @@
#include "core/core_string_names.h"
#include "scene/scene_string_names.h"
-#ifdef TOOLS_ENABLED
-#include "editor/plugins/node_3d_editor_plugin.h"
-#endif
-
void PhysicsBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_and_collide", "linear_velocity", "test_only", "safe_margin", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(1));
ClassDB::bind_method(D_METHOD("test_move", "from", "linear_velocity", "collision", "safe_margin", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(1));
@@ -1168,14 +1164,18 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
platform_rid = RID();
platform_velocity = Vector3();
+ platform_ceiling_velocity = Vector3();
floor_normal = Vector3();
wall_normal = Vector3();
+ ceiling_normal = Vector3();
// No sliding on first attempt to keep floor motion stable when possible,
// When stop on slope is enabled or when there is no up direction.
bool sliding_enabled = !floor_stop_on_slope;
// Constant speed can be applied only the first time sliding is enabled.
bool can_apply_constant_speed = sliding_enabled;
+ // If the platform's ceiling push down the body.
+ bool apply_ceiling_velocity = false;
bool first_slide = true;
bool vel_dir_facing_up = motion_velocity.dot(up_direction) > 0;
Vector3 total_travel;
@@ -1193,6 +1193,19 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
CollisionState result_state;
_set_collision_direction(result, result_state);
+ // If we hit a ceiling platform, we set the vertical motion_velocity to at least the platform one.
+ if (collision_state.ceiling && platform_ceiling_velocity != Vector3() && platform_ceiling_velocity.dot(up_direction) < 0) {
+ // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
+ if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (ceiling_normal + up_direction).length() < 0.01) {
+ apply_ceiling_velocity = true;
+ Vector3 ceiling_vertical_velocity = up_direction * up_direction.dot(platform_ceiling_velocity);
+ Vector3 motion_vertical_velocity = up_direction * up_direction.dot(motion_velocity);
+ if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
+ motion_velocity = ceiling_vertical_velocity + motion_velocity.slide(up_direction);
+ }
+ }
+ }
+
if (collision_state.floor && floor_stop_on_slope && (motion_velocity.normalized() + up_direction).length() < 0.01) {
Transform3D gt = get_global_transform();
if (result.travel.length() <= margin + CMP_EPSILON) {
@@ -1304,7 +1317,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
if (apply_default_sliding) {
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
- if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
+ if ((sliding_enabled || !collision_state.floor) && (!collision_state.ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
Vector3 slide_motion = result.remainder.slide(collision.normal);
@@ -1526,6 +1539,8 @@ void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResu
if (ceiling_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
r_state.ceiling = true;
if (p_apply_state.ceiling) {
+ platform_ceiling_velocity = collision.collider_velocity;
+ ceiling_normal = collision.normal;
collision_state.ceiling = true;
}
continue;
@@ -2998,14 +3013,11 @@ void PhysicalBone3D::_on_bone_parent_changed() {
_reload_joint();
}
-void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) {
#ifdef TOOLS_ENABLED
+void PhysicalBone3D::_set_gizmo_move_joint(bool p_move_joint) {
gizmo_move_joint = p_move_joint;
- Node3DEditor::get_singleton()->update_transform_gizmo();
-#endif
}
-#ifdef TOOLS_ENABLED
Transform3D PhysicalBone3D::get_global_gizmo_transform() const {
return gizmo_move_joint ? get_global_transform() * joint_offset : get_global_transform();
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 916b2cd464..fdda681350 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -392,8 +392,10 @@ private:
Vector3 motion_velocity;
Vector3 floor_normal;
Vector3 wall_normal;
+ Vector3 ceiling_normal;
Vector3 last_motion;
Vector3 platform_velocity;
+ Vector3 platform_ceiling_velocity;
Vector3 previous_position;
Vector3 real_velocity;
@@ -662,10 +664,9 @@ private:
public:
void _on_bone_parent_changed();
- void _set_gizmo_move_joint(bool p_move_joint);
-public:
#ifdef TOOLS_ENABLED
+ void _set_gizmo_move_joint(bool p_move_joint);
virtual Transform3D get_global_gizmo_transform() const override;
virtual Transform3D get_local_gizmo_transform() const override;
#endif
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 81411d5844..1b8b5e17ed 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -742,7 +742,7 @@ bool Control::has_point(const Point2 &p_point) const {
return Rect2(Point2(), get_size()).has_point(p_point);
}
-void Control::set_drag_forwarding(Control *p_target) {
+void Control::set_drag_forwarding(Node *p_target) {
if (p_target) {
data.drag_owner = p_target->get_instance_id();
} else {
@@ -754,8 +754,7 @@ Variant Control::get_drag_data(const Point2 &p_point) {
if (data.drag_owner.is_valid()) {
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
- Control *c = Object::cast_to<Control>(obj);
- return c->call("_get_drag_data_fw", p_point, this);
+ return obj->call("_get_drag_data_fw", p_point, this);
}
}
@@ -771,8 +770,7 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const
if (data.drag_owner.is_valid()) {
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
- Control *c = Object::cast_to<Control>(obj);
- return c->call("_can_drop_data_fw", p_point, p_data, this);
+ return obj->call("_can_drop_data_fw", p_point, p_data, this);
}
}
@@ -787,8 +785,7 @@ void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
if (data.drag_owner.is_valid()) {
Object *obj = ObjectDB::get_instance(data.drag_owner);
if (obj) {
- Control *c = Object::cast_to<Control>(obj);
- c->call("_drop_data_fw", p_point, p_data, this);
+ obj->call("_drop_data_fw", p_point, p_data, this);
return;
}
}
@@ -2452,8 +2449,8 @@ bool Control::is_text_field() const {
return false;
}
-Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const {
- Vector<Vector2i> ret;
+Array Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const {
+ Array ret;
switch (p_theme_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 9cec5d6e8d..87ff3918cb 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -283,7 +283,7 @@ protected:
//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 _get(const StringName &p_name, Variant &r_ret) const;
@@ -355,7 +355,7 @@ public:
virtual Size2 get_minimum_size() const;
virtual Size2 get_combined_minimum_size() const;
virtual bool has_point(const Point2 &p_point) const;
- virtual void set_drag_forwarding(Control *p_target);
+ virtual void set_drag_forwarding(Node *p_target);
virtual Variant get_drag_data(const Point2 &p_point);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 18cde25e55..b8cb618171 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -108,7 +108,7 @@ void Label::_shape() {
}
lines_rid.clear();
- uint8_t autowrap_flags = TextServer::BREAK_MANDATORY;
+ uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
switch (autowrap_mode) {
case AUTOWRAP_WORD_SMART:
autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
@@ -122,10 +122,10 @@ void Label::_shape() {
case AUTOWRAP_OFF:
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++) {
- RID line = TS->shaped_text_substr(text_rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x);
+ for (int i = 0; i < line_breaks.size(); i = i + 2) {
+ RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
lines_rid.push_back(line);
}
}
@@ -145,7 +145,7 @@ void Label::_shape() {
}
if (lines_dirty) {
- uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
+ uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS:
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()) {
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 {
@@ -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_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);
@@ -387,21 +387,25 @@ void Label::_notification(int p_what) {
} break;
}
- const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(lines_rid[i]);
- const TextServer::Glyph *glyphs = visual.ptr();
- int gl_size = visual.size();
- TextServer::TrimData trim_data = TS->shaped_text_get_trim_data(lines_rid[i]);
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
+ int gl_size = TS->shaped_text_get_glyph_count(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.
if (font_shadow_color.a > 0 || (font_outline_color.a != 0.0 && outline_size > 0)) {
Vector2 offset = ofs;
// Draw RTL ellipsis string when necessary.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ if (rtl && ellipsis_pos >= 0) {
+ for (int gl_idx = ellipsis_gl_size - 1; gl_idx >= 0; gl_idx--) {
+ for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//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);
- offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ 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 += 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 k = 0; k < glyphs[j].repeat; k++) {
// Trim when necessary.
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
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;
}
} 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;
}
}
@@ -428,12 +432,12 @@ void Label::_notification(int p_what) {
}
}
// Draw LTR ellipsis string when necessary.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int gl_idx = 0; gl_idx < ellipsis_gl_size; gl_idx++) {
+ for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//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);
- offset.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ 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 += 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 RTL ellipsis string when necessary.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int gl_idx = trim_data.ellipsis_glyph_buf.size() - 1; gl_idx >= 0; gl_idx--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ if (rtl && ellipsis_pos >= 0) {
+ for (int gl_idx = ellipsis_gl_size - 1; gl_idx >= 0; gl_idx--) {
+ for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow.
- draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs);
- ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ draw_glyph(ellipsis_glyphs[gl_idx], ci, font_color, ofs);
+ 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 k = 0; k < glyphs[j].repeat; k++) {
// Trim when necessary.
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
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;
}
} 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;
}
}
@@ -474,12 +478,12 @@ void Label::_notification(int p_what) {
}
}
// Draw LTR ellipsis string when necessary.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int gl_idx = 0; gl_idx < trim_data.ellipsis_glyph_buf.size(); gl_idx++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[gl_idx].repeat; j++) {
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int gl_idx = 0; gl_idx < ellipsis_gl_size; gl_idx++) {
+ for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
//Draw glyph outlines and shadow.
- draw_glyph(trim_data.ellipsis_glyph_buf[gl_idx], ci, font_color, ofs);
- ofs.x += trim_data.ellipsis_glyph_buf[gl_idx].advance;
+ draw_glyph(ellipsis_glyphs[gl_idx], ci, font_color, ofs);
+ ofs.x += ellipsis_glyphs[gl_idx].advance;
}
}
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 89fd9bfc88..2c1092d8f9 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -67,10 +67,10 @@ void LineEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
if (p_move_by_word) {
int cc = caret_column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < cc) {
+ cc = words[i];
break;
}
}
@@ -99,10 +99,10 @@ void LineEdit::_move_caret_right(bool p_select, bool p_move_by_word) {
if (p_move_by_word) {
int cc = caret_column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 1; i < words.size(); i = i + 2) {
+ if (words[i] > cc) {
+ cc = words[i];
break;
}
}
@@ -151,10 +151,10 @@ void LineEdit::_backspace(bool p_word, bool p_all_to_left) {
if (p_word) {
int cc = caret_column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < cc) {
+ cc = words[i];
break;
}
}
@@ -194,10 +194,10 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) {
if (p_word) {
int cc = caret_column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 1; i < words.size(); i = i + 2) {
+ if (words[i] > cc) {
+ cc = words[i];
break;
}
}
@@ -276,12 +276,12 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
// Double-click select word.
last_dblclk = OS::get_singleton()->get_ticks_msec();
last_dblclk_pos = b->get_position();
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text_rid);
- for (int i = 0; i < words.size(); i++) {
- if ((words[i].x < caret_column && words[i].y > caret_column) || (i == words.size() - 1 && caret_column == words[i].y)) {
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text_rid);
+ for (int i = 0; i < words.size(); i = i + 2) {
+ if ((words[i] < caret_column && words[i + 1] > caret_column) || (i == words.size() - 2 && caret_column == words[i + 1])) {
selection.enabled = true;
- selection.begin = words[i].x;
- selection.end = words[i].y;
+ selection.begin = words[i];
+ selection.end = words[i + 1];
selection.double_click = true;
caret_column = selection.end;
break;
@@ -737,9 +737,8 @@ void LineEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, rect, selection_color);
}
}
- const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(text_rid);
- const TextServer::Glyph *glyphs = visual.ptr();
- int gl_size = visual.size();
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(text_rid);
+ int gl_size = TS->shaped_text_get_glyph_count(text_rid);
// Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid);
@@ -783,38 +782,36 @@ void LineEdit::_notification(int p_what) {
if (draw_caret) {
if (ime_text.length() == 0) {
// Normal caret.
- Rect2 l_caret, t_caret;
- TextServer::Direction l_dir, t_dir;
- TS->shaped_text_get_carets(text_rid, caret_column, l_caret, l_dir, t_caret, t_dir);
+ CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column);
- if (l_caret == Rect2() && t_caret == Rect2()) {
+ if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
// No carets, add one at the start.
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;
if (rtl) {
- l_dir = TextServer::DIRECTION_RTL;
- l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
+ caret.l_dir = TextServer::DIRECTION_RTL;
+ caret.l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
} else {
- l_dir = TextServer::DIRECTION_LTR;
- l_caret = Rect2(Vector2(x_ofs, y), Size2(caret_width, h));
+ caret.l_dir = TextServer::DIRECTION_LTR;
+ 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 {
- 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.
- 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;
RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color);
}
- l_caret.position += ofs;
- l_caret.size.x = caret_width;
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, l_caret, caret_color);
+ caret.l_caret.position += ofs;
+ caret.l_caret.size.x = caret_width;
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.l_caret, caret_color);
- t_caret.position += ofs;
- t_caret.size.x = caret_width;
+ caret.t_caret.position += ofs;
+ 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 {
{
@@ -1114,32 +1111,31 @@ Vector2i LineEdit::get_caret_pixel_pos() {
}
Vector2i ret;
- Rect2 l_caret, t_caret;
- TextServer::Direction l_dir, t_dir;
+ CaretInfo caret;
// Get position of the start of caret.
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 {
- 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())) {
- ret.x = x_ofs + l_caret.position.x + scroll_offset;
+ 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 + caret.l_caret.position.x + scroll_offset;
} 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.
if (ime_text.length() != 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 {
- 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())) {
- ret.y = x_ofs + l_caret.position.x + scroll_offset;
+ 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 + caret.l_caret.position.x + scroll_offset;
} else {
- ret.y = x_ofs + t_caret.position.x + scroll_offset;
+ ret.y = x_ofs + caret.t_caret.position.x + scroll_offset;
}
} else {
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);
text = pre + p_text + post;
_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) {
input_direction = (TextDirection)dir;
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 277026cc28..bc25177275 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -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 TextServer::Glyph *glyphs = visual.ptr();
- int gl_size = visual.size();
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(rid);
+ int gl_size = TS->shaped_text_get_glyph_count(rid);
Vector2 gloff = off;
// Draw oulines and shadow.
@@ -1593,18 +1592,18 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (c_frame) {
const Line &l = c_frame->lines[c_line];
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(l.text_buf->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if (c_index >= words[i].x && c_index < words[i].y) {
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(l.text_buf->get_rid());
+ for (int i = 0; i < words.size(); i = i + 2) {
+ if (c_index >= words[i] && c_index < words[i + 1]) {
selection.from_frame = c_frame;
selection.from_line = c_line;
selection.from_item = c_item;
- selection.from_char = words[i].x;
+ selection.from_char = words[i];
selection.to_frame = c_frame;
selection.to_line = c_line;
selection.to_item = c_item;
- selection.to_char = words[i].y;
+ selection.to_char = words[i + 1];
selection.active = true;
update();
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index ef34bec347..ba8dba847c 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -164,7 +164,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (rb_hover != -1) {
//pressed
- emit_signal(SNAME("right_button_pressed"), rb_hover);
+ emit_signal(SNAME("tab_rmb_clicked"), rb_hover);
}
rb_pressing = false;
@@ -401,7 +401,7 @@ void Tabs::_notification(int p_what) {
w += tabs[i].size_text;
if (tabs[i].right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
Ref<Texture2D> rb = tabs[i].right_button;
w += get_theme_constant(SNAME("hseparation"));
@@ -433,7 +433,7 @@ void Tabs::_notification(int p_what) {
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button"));
+ Ref<StyleBox> style = get_theme_stylebox(SNAME("close_bg_highlight"));
Ref<Texture2D> cb = close;
w += get_theme_constant(SNAME("hseparation"));
@@ -449,7 +449,7 @@ void Tabs::_notification(int p_what) {
if (!tabs[i].disabled && cb_hover == i) {
if (cb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
+ get_theme_stylebox(SNAME("close_bg_pressed"))->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
@@ -886,7 +886,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
hover_now = get_tab_count() - 1;
}
move_tab(tab_from_id, hover_now);
- emit_signal(SNAME("reposition_active_tab_request"), hover_now);
+ emit_signal(SNAME("active_tab_rearranged"), hover_now);
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
// drag and drop between Tabs
@@ -1165,10 +1165,10 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &Tabs::get_select_with_rmb);
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
- ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_rmb_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_closed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_hovered", PropertyInfo(Variant::INT, "tab")));
- ADD_SIGNAL(MethodInfo("reposition_active_tab_request", PropertyInfo(Variant::INT, "idx_to")));
+ ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to")));
ADD_SIGNAL(MethodInfo("tab_clicked", PropertyInfo(Variant::INT, "tab")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 5e165be15e..e2ddc761b8 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -186,7 +186,7 @@ void TextEdit::Text::_calculate_max_line_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());
if (font.is_null() || font_size <= 0) {
@@ -278,14 +278,14 @@ void TextEdit::Text::invalidate_all() {
void TextEdit::Text::clear() {
text.clear();
- insert(0, "", Vector<Vector2i>());
+ insert(0, "", Array());
}
int TextEdit::Text::get_max_width() const {
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());
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);
}
-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.gutters.resize(gutter_count);
line.hidden = false;
@@ -1076,9 +1076,8 @@ void TextEdit::_notification(int p_what) {
ofs_y += (row_height - text_height) / 2;
- const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(rid);
- const TextServer::Glyph *glyphs = visual.ptr();
- int gl_size = visual.size();
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(rid);
+ int gl_size = TS->shaped_text_get_glyph_count(rid);
ofs_y += ldata->get_line_ascent(line_wrap_index);
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);
if (ime_text.length() == 0) {
- Rect2 l_caret, t_caret;
- TextServer::Direction l_dir, t_dir;
+ CaretInfo ts_caret;
if (str.length() != 0) {
// 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 {
// No carets, add one at the start.
int h = font->get_height(font_size);
if (rtl) {
- 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_dir = TextServer::DIRECTION_RTL;
+ ts_caret.l_caret = Rect2(Vector2(xmargin_end - char_margin + ofs_x, -h / 2), Size2(caret_width * 4, h));
} else {
- l_dir = TextServer::DIRECTION_LTR;
- l_caret = Rect2(Vector2(char_ofs, -h / 2), Size2(caret_width * 4, h));
+ ts_caret.l_dir = TextServer::DIRECTION_LTR;
+ 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())) {
- caret.draw_pos.x = char_margin + ofs_x + l_caret.position.x;
+ 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 + ts_caret.l_caret.position.x;
} 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) {
@@ -1215,64 +1213,64 @@ void TextEdit::_notification(int p_what) {
//Block or underline caret, draw trailing carets at full height.
int h = font->get_height(font_size);
- if (t_caret != Rect2()) {
+ if (ts_caret.t_caret != Rect2()) {
if (overtype_mode) {
- t_caret.position.y = TS->shaped_text_get_descent(rid);
- t_caret.size.y = caret_width;
+ ts_caret.t_caret.position.y = TS->shaped_text_get_descent(rid);
+ ts_caret.t_caret.size.y = caret_width;
} else {
- t_caret.position.y = -TS->shaped_text_get_ascent(rid);
- t_caret.size.y = h;
+ ts_caret.t_caret.position.y = -TS->shaped_text_get_ascent(rid);
+ ts_caret.t_caret.size.y = h;
}
- t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- draw_rect(t_caret, caret_color, overtype_mode);
+ ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ draw_rect(ts_caret.t_caret, caret_color, overtype_mode);
- if (l_caret != Rect2() && l_dir != t_dir) {
- l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- l_caret.size.x = caret_width;
- draw_rect(l_caret, caret_color * Color(1, 1, 1, 0.5));
+ if (ts_caret.l_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) {
+ ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ ts_caret.l_caret.size.x = caret_width;
+ draw_rect(ts_caret.l_caret, caret_color * Color(1, 1, 1, 0.5));
}
} else { // End of the line.
if (gl_size > 0) {
// Adjust for actual line dimensions.
if (overtype_mode) {
- l_caret.position.y = TS->shaped_text_get_descent(rid);
- l_caret.size.y = caret_width;
+ ts_caret.l_caret.position.y = TS->shaped_text_get_descent(rid);
+ ts_caret.l_caret.size.y = caret_width;
} else {
- l_caret.position.y = -TS->shaped_text_get_ascent(rid);
- l_caret.size.y = h;
+ ts_caret.l_caret.position.y = -TS->shaped_text_get_ascent(rid);
+ ts_caret.l_caret.size.y = h;
}
} else if (overtype_mode) {
- l_caret.position.y += l_caret.size.y;
- l_caret.size.y = caret_width;
+ ts_caret.l_caret.position.y += ts_caret.l_caret.size.y;
+ ts_caret.l_caret.size.y = caret_width;
}
- if (l_caret.position.x >= TS->shaped_text_get_size(rid).x) {
- l_caret.size.x = font->get_char_size('m', 0, font_size).x;
+ if (ts_caret.l_caret.position.x >= TS->shaped_text_get_size(rid).x) {
+ ts_caret.l_caret.size.x = font->get_char_size('m', 0, font_size).x;
} 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);
- if (l_dir == TextServer::DIRECTION_RTL) {
- l_caret.position.x -= l_caret.size.x;
+ ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ if (ts_caret.l_dir == TextServer::DIRECTION_RTL) {
+ 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 {
// 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.
- 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);
RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color);
}
- l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
- l_caret.size.x = caret_width;
+ ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ 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);
- t_caret.size.x = caret_width;
+ ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y);
+ 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_column(text[caret.line].length());
} else {
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < cc) {
- cc = words[i].x;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < cc) {
+ cc = words[i];
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_column(0);
} else {
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > cc) {
- cc = words[i].y;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
+ for (int i = 1; i < words.size(); i = i + 2) {
+ if (words[i] > cc) {
+ cc = words[i];
break;
}
}
@@ -2214,10 +2212,10 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
int line = caret.line;
int column = caret.column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = words.size() - 1; i >= 0; i--) {
- if (words[i].x < column) {
- column = words[i].x;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < column) {
+ column = words[i];
break;
}
}
@@ -2257,10 +2255,10 @@ void TextEdit::_delete(bool p_word, bool p_all_to_right) {
int line = caret.line;
int column = caret.column;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if (words[i].y > column) {
- column = words[i].y;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
+ for (int i = 1; i < words.size(); i = i + 2) {
+ if (words[i] > column) {
+ column = words[i];
break;
}
}
@@ -3631,10 +3629,10 @@ int TextEdit::get_caret_wrap_index() 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());
- for (int i = 0; i < words.size(); i++) {
- if (words[i].x <= caret.column && words[i].y > caret.column) {
- return text[caret.line].substr(words[i].x, words[i].y - words[i].x);
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
+ for (int i = 0; i < words.size(); i = i + 2) {
+ if (words[i] <= caret.column && words[i + 1] > caret.column) {
+ return text[caret.line].substr(words[i], words[i + 1] - words[i]);
}
}
return "";
@@ -3718,11 +3716,11 @@ void TextEdit::select_word_under_caret() {
int begin = 0;
int end = 0;
- const Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if ((words[i].x < caret.column && words[i].y > caret.column) || (i == words.size() - 1 && caret.column == words[i].y)) {
- begin = words[i].x;
- end = words[i].y;
+ 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 = i + 2) {
+ if ((words[i] < caret.column && words[i + 1] > caret.column) || (i == words.size() - 2 && caret.column == words[i + 1])) {
+ begin = words[i];
+ end = words[i + 1];
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);
- TS->shaped_text_get_carets(text_rid, caret.column, l_caret, l_dir, t_caret, t_dir);
- if ((l_caret != Rect2() && (l_dir == TextServer::DIRECTION_AUTO || l_dir == (TextServer::Direction)input_direction)) || (t_caret == Rect2())) {
- return l_caret.position.x;
+ CaretInfo ts_caret = TS->shaped_text_get_carets(text_rid, caret.column);
+ 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 ts_caret.l_caret.position.x;
} 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 beg = caret_pos;
int end = beg;
- Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = 0; i < words.size(); i++) {
- if ((words[i].x < caret_pos && words[i].y > caret_pos) || (i == words.size() - 1 && caret_pos == words[i].y)) {
- beg = words[i].x;
- end = words[i].y;
+ PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
+ for (int i = 0; i < words.size(); i = i + 2) {
+ if ((words[i] < caret_pos && words[i + 1] > caret_pos) || (i == words.size() - 2 && caret_pos == words[i + 1])) {
+ beg = words[i];
+ end = words[i + 1];
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_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) {
input_direction = (TextDirection)dir;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index db16d09c58..07e585847a 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -139,7 +139,7 @@ private:
Vector<Gutter> gutters;
String data;
- Vector<Vector2i> bidi_override;
+ Array bidi_override;
Ref<TextParagraph> data_buf;
Color background_color = Color(0, 0, 0, 0);
@@ -194,7 +194,7 @@ private:
Vector<Vector2i> get_line_wrap_ranges(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) {
text.write[p_line].hidden = p_hidden;
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; }
- 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);
int size() const { return text.size(); }
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_lines();
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 64b169b1fb..916833c9a7 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -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);
}
-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(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);
}
-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(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);
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 01ed47d4dc..ba9f47119d 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -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_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_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_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), 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;
void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 492e0512e4..94cf826477 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -790,8 +790,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("tab_selected", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2));
theme->set_stylebox("tab_unselected", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3));
theme->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3));
- theme->set_stylebox("button_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4));
- theme->set_stylebox("button", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4));
+ theme->set_stylebox("close_bg_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4));
+ theme->set_stylebox("close_bg_highlight", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4));
theme->set_icon("increment", "Tabs", make_icon(scroll_button_right_png));
theme->set_icon("increment_highlight", "Tabs", make_icon(scroll_button_right_hl_png));
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 9b403a18f0..c1d42dff09 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -502,6 +502,11 @@ void FontData::set_data(const PackedByteArray &p_data) {
}
PackedByteArray FontData::get_data() const {
+ if (unlikely((size_t)data.size() != data_size)) {
+ PackedByteArray *data_w = const_cast<PackedByteArray *>(&data);
+ data_w->resize(data_size);
+ memcpy(data_w->ptrw(), data_ptr, data_size);
+ }
return data;
}
@@ -1399,7 +1404,7 @@ real_t Font::get_underline_thickness(int p_size) const {
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());
int size = (p_size <= 0) ? base_size : p_size;
@@ -1426,7 +1431,7 @@ Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, re
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());
int size = (p_size <= 0) ? base_size : p_size;
@@ -1465,7 +1470,7 @@ Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int
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());
int size = (p_size <= 0) ? base_size : p_size;
@@ -1507,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);
}
-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());
int size = (p_size <= 0) ? base_size : p_size;
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 9a34edce64..e65fdb0751 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -266,11 +266,11 @@ public:
virtual real_t get_underline_thickness(int p_size = -1) const;
// 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_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_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, 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_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_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), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
// Helper functions.
virtual bool has_char(char32_t p_char) const;
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index d0e0f15ef6..d87056f55d 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -41,6 +41,8 @@ void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) {
continue;
}
Array arr = p_mesh->surface_get_arrays(i);
+ ERR_CONTINUE(arr.size() != Mesh::ARRAY_MAX);
+
Vector<Vector3> varr = arr[Mesh::ARRAY_VERTEX];
Vector<int> iarr = arr[Mesh::ARRAY_INDEX];
if (varr.size() == 0 || iarr.size() == 0) {
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index d2f38ba836..0094518967 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -53,7 +53,7 @@ void TextLine::_bind_methods() {
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_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);
}
- uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
+ uint16_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING;
if (overrun_behavior != OVERRUN_NO_TRIMMING) {
switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS:
@@ -195,15 +195,7 @@ TextServer::Orientation TextLine::get_orientation() const {
return TS->shaped_text_get_orientation(rid);
}
-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) {
+void TextLine::set_bidi_override(const Array &p_override) {
TS->shaped_text_set_bidi_override(rid, p_override);
dirty = true;
}
@@ -256,14 +248,14 @@ void TextLine::tab_align(const Vector<float> &p_tab_stops) {
dirty = true;
}
-void TextLine::set_flags(uint8_t p_flags) {
+void TextLine::set_flags(uint16_t p_flags) {
if (flags != p_flags) {
flags = p_flags;
dirty = true;
}
}
-uint8_t TextLine::get_flags() const {
+uint16_t TextLine::get_flags() const {
return flags;
}
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index 9ed9c2f177..43739f27ec 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -56,7 +56,7 @@ private:
bool dirty = true;
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;
OverrunBehavior overrun_behavior = OVERRUN_TRIM_ELLIPSIS;
@@ -75,7 +75,7 @@ public:
void set_direction(TextServer::Direction p_direction);
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);
TextServer::Orientation get_orientation() const;
@@ -95,8 +95,8 @@ public:
void tab_align(const Vector<float> &p_tab_stops);
- void set_flags(uint8_t p_flags);
- uint8_t get_flags() const;
+ void set_flags(uint16_t p_flags);
+ uint16_t get_flags() const;
void set_text_overrun_behavior(OverrunBehavior p_behavior);
OverrunBehavior get_text_overrun_behavior() const;
@@ -120,8 +120,6 @@ public:
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();
~TextLine();
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 62949b9b98..b2e18e2451 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -53,7 +53,7 @@ void TextParagraph::_bind_methods() {
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("clear_dropcap"), &TextParagraph::clear_dropcap);
@@ -158,9 +158,9 @@ void TextParagraph::_shape_lines() {
if (h_offset > 0) {
// Dropcap, flow around.
- Vector<Vector2i> line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags);
- for (int i = 0; i < line_breaks.size(); i++) {
- RID line = TS->shaped_text_substr(rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x);
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width - h_offset, 0, flags);
+ for (int i = 0; i < line_breaks.size(); i = i + 2) {
+ 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;
if (v_offset < h) {
TS->free(line);
@@ -171,21 +171,21 @@ void TextParagraph::_shape_lines() {
}
dropcap_lines++;
v_offset -= h;
- start = line_breaks[i].y;
+ start = line_breaks[i + 1];
lines_rid.push_back(line);
}
}
// Use fixed for the rest of lines.
- Vector<Vector2i> line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags);
- for (int i = 0; i < line_breaks.size(); i++) {
- RID line = TS->shaped_text_substr(rid, line_breaks[i].x, line_breaks[i].y - line_breaks[i].x);
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(rid, width, start, flags);
+ for (int i = 0; i < line_breaks.size(); i = i + 2) {
+ RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
if (!tab_stops.is_empty()) {
TS->shaped_text_tab_align(line, tab_stops);
}
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) {
switch (overrun_behavior) {
case OVERRUN_TRIM_WORD_ELLIPSIS:
@@ -347,15 +347,7 @@ int TextParagraph::get_spacing_bottom() const {
return spacing_bottom;
}
-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) {
+void TextParagraph::set_bidi_override(const Array &p_override) {
TS->shaped_text_set_bidi_override(rid, p_override);
lines_dirty = true;
}
@@ -392,14 +384,14 @@ void TextParagraph::tab_align(const Vector<float> &p_tab_stops) {
lines_dirty = true;
}
-void TextParagraph::set_flags(uint8_t p_flags) {
+void TextParagraph::set_flags(uint16_t p_flags) {
if (flags != p_flags) {
flags = p_flags;
lines_dirty = true;
}
}
-uint8_t TextParagraph::get_flags() const {
+uint16_t TextParagraph::get_flags() const {
return flags;
}
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index ee7bbab9c5..69c50559df 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -63,7 +63,7 @@ private:
float width = -1.0;
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;
HAlign align = HALIGN_LEFT;
@@ -94,7 +94,7 @@ public:
void set_preserve_control(bool p_enabled);
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 = "");
void clear_dropcap();
@@ -108,8 +108,8 @@ public:
void tab_align(const Vector<float> &p_tab_stops);
- void set_flags(uint8_t p_flags);
- uint8_t get_flags() const;
+ void set_flags(uint16_t p_flags);
+ uint16_t get_flags() const;
void set_text_overrun_behavior(OverrunBehavior p_behavior);
OverrunBehavior get_text_overrun_behavior() const;
@@ -153,8 +153,6 @@ public:
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();
~TextParagraph();
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 42b82957fb..2b4929b3df 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -646,7 +646,7 @@ private:
};
Vector2 linear_velocity;
- float angular_velocity;
+ float angular_velocity = 0.0;
Vector<PolygonShapeTileData> polygons;
};
Vector<PhysicsLayerTileData> physics;
diff --git a/servers/SCsub b/servers/SCsub
index 121990f2e1..76c11724d3 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -11,6 +11,7 @@ SConscript("physics_3d/SCsub")
SConscript("physics_2d/SCsub")
SConscript("rendering/SCsub")
SConscript("audio/SCsub")
+SConscript("text/SCsub")
lib = env.add_library("servers", env.servers_sources)
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index cdf892094d..3897e5e7c2 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -285,6 +285,10 @@ String DisplayServer::keyboard_get_layout_name(int p_index) const {
return "Not supported";
}
+Key DisplayServer::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ ERR_FAIL_V_MSG(p_keycode, "Not supported by this display server.");
+}
+
void DisplayServer::force_process_and_drop_events() {
}
@@ -452,6 +456,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_current_layout);
ClassDB::bind_method(D_METHOD("keyboard_get_layout_language", "index"), &DisplayServer::keyboard_get_layout_language);
ClassDB::bind_method(D_METHOD("keyboard_get_layout_name", "index"), &DisplayServer::keyboard_get_layout_name);
+ ClassDB::bind_method(D_METHOD("keyboard_get_keycode_from_physical", "keycode"), &DisplayServer::keyboard_get_keycode_from_physical);
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
diff --git a/servers/display_server.h b/servers/display_server.h
index 788206768c..f411a72aa3 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -343,6 +343,7 @@ public:
virtual void keyboard_set_current_layout(int p_index);
virtual String keyboard_get_layout_language(int p_index) const;
virtual String keyboard_get_layout_name(int p_index) const;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const;
virtual int tablet_get_driver_count() const { return 1; };
virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 41c8b45113..d5eccce88e 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -70,6 +70,7 @@
#include "rendering/rendering_device_binds.h"
#include "rendering_server.h"
#include "servers/rendering/shader_types.h"
+#include "text/text_server_extension.h"
#include "text_server.h"
#include "xr/xr_interface.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() {
shader_types = memnew(ShaderTypes);
- GLOBAL_DEF("internationalization/rendering/text_driver", "");
- String text_driver_options;
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- if (i > 0) {
- text_driver_options += ",";
- }
- 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));
+ GDREGISTER_CLASS(TextServerManager);
+ GDREGISTER_VIRTUAL_CLASS(TextServer);
+ GDREGISTER_CLASS(TextServerExtension);
+
+ Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
}
void register_server_types() {
@@ -125,8 +122,6 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_CLASS(TextServerManager);
- GDREGISTER_VIRTUAL_CLASS(TextServer);
TextServer::initialize_hex_code_box_fonts();
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("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("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
Engine::get_singleton()->add_singleton(Engine::Singleton("XRServer", XRServer::get_singleton(), "XRServer"));
Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton(), "CameraServer"));
}
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index bed6ade1f6..62390f9d4d 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -45,6 +45,9 @@ int RenderingServerDefault::changes = 0;
/* FREE */
void RenderingServerDefault::_free(RID p_rid) {
+ if (unlikely(p_rid.is_null())) {
+ return;
+ }
if (RSG::storage->free(p_rid)) {
return;
}
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 1b10e4dcbe..58e99f0e91 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -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_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_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_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));
diff --git a/servers/text/SCsub b/servers/text/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/text/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
new file mode 100644
index 0000000000..a44fee7c95
--- /dev/null
+++ b/servers/text/text_server_extension.cpp
@@ -0,0 +1,1281 @@
+/*************************************************************************/
+/* text_server_extension.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 "text_server_extension.h"
+
+void TextServerExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_has_feature, "feature");
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_get_features);
+
+ GDVIRTUAL_BIND(_free, "rid");
+ GDVIRTUAL_BIND(_has, "rid");
+ GDVIRTUAL_BIND(_load_support_data, "filename");
+
+ GDVIRTUAL_BIND(_get_support_data_filename);
+ GDVIRTUAL_BIND(_get_support_data_info);
+ GDVIRTUAL_BIND(_save_support_data, "filename");
+
+ GDVIRTUAL_BIND(_is_locale_right_to_left, "locale");
+
+ GDVIRTUAL_BIND(_name_to_tag, "name");
+ GDVIRTUAL_BIND(_tag_to_name, "tag");
+
+ /* Font interface */
+
+ GDVIRTUAL_BIND(_create_font);
+
+ GDVIRTUAL_BIND(_font_set_data, "font_rid", "data");
+ GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+
+ GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased");
+ GDVIRTUAL_BIND(_font_is_antialiased, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_multichannel_signed_distance_field, "font_rid", "msdf");
+ GDVIRTUAL_BIND(_font_is_multichannel_signed_distance_field, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
+ GDVIRTUAL_BIND(_font_get_msdf_pixel_range, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_msdf_size, "font_rid", "msdf_size");
+ GDVIRTUAL_BIND(_font_get_msdf_size, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
+ GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter");
+ GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
+ GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
+ GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_oversampling, "font_rid", "oversampling");
+ GDVIRTUAL_BIND(_font_get_oversampling, "font_rid");
+
+ GDVIRTUAL_BIND(_font_get_size_cache_list, "font_rid");
+ GDVIRTUAL_BIND(_font_clear_size_cache, "font_rid");
+ GDVIRTUAL_BIND(_font_remove_size_cache, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_ascent, "font_rid", "size", "ascent");
+ GDVIRTUAL_BIND(_font_get_ascent, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_descent, "font_rid", "size", "descent");
+ GDVIRTUAL_BIND(_font_get_descent, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_underline_position, "font_rid", "size", "underline_position");
+ GDVIRTUAL_BIND(_font_get_underline_position, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_underline_thickness, "font_rid", "size", "underline_thickness");
+ GDVIRTUAL_BIND(_font_get_underline_thickness, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_scale, "font_rid", "size", "scale");
+ GDVIRTUAL_BIND(_font_get_scale, "font_rid", "size");
+
+ GDVIRTUAL_BIND(_font_set_spacing, "font_rid", "size", "spacing", "value");
+ GDVIRTUAL_BIND(_font_get_spacing, "font_rid", "size", "spacing");
+
+ GDVIRTUAL_BIND(_font_get_texture_count, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_textures, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_texture, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_set_texture_image, "font_rid", "size", "texture_index", "image");
+ GDVIRTUAL_BIND(_font_get_texture_image, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
+ GDVIRTUAL_BIND(_font_get_texture_offsets, "font_rid", "size", "texture_index");
+
+ GDVIRTUAL_BIND(_font_get_glyph_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_glyphs, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_glyph, "font_rid", "size", "glyph");
+
+ GDVIRTUAL_BIND(_font_get_glyph_advance, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
+
+ GDVIRTUAL_BIND(_font_get_glyph_offset, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
+
+ GDVIRTUAL_BIND(_font_get_glyph_size, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
+
+ GDVIRTUAL_BIND(_font_get_glyph_uv_rect, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
+
+ GDVIRTUAL_BIND(_font_get_glyph_texture_idx, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
+
+ GDVIRTUAL_BIND(_font_get_glyph_contours, "font_rid", "size", "index");
+
+ GDVIRTUAL_BIND(_font_get_kerning_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_kerning_map, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_kerning, "font_rid", "size", "glyph_pair");
+
+ GDVIRTUAL_BIND(_font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
+ GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair");
+
+ GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
+
+ GDVIRTUAL_BIND(_font_has_char, "font_rid", "char");
+ GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid");
+
+ GDVIRTUAL_BIND(_font_render_range, "font_rid", "size", "start", "end");
+ GDVIRTUAL_BIND(_font_render_glyph, "font_rid", "size", "index");
+
+ GDVIRTUAL_BIND(_font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(_font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
+
+ GDVIRTUAL_BIND(_font_is_language_supported, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_set_language_support_override, "font_rid", "language", "supported");
+ GDVIRTUAL_BIND(_font_get_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_remove_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_get_language_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(_font_is_script_supported, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_set_script_support_override, "font_rid", "script", "supported");
+ GDVIRTUAL_BIND(_font_get_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid");
+
+ GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid");
+ GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid");
+
+ GDVIRTUAL_BIND(_font_get_global_oversampling);
+ GDVIRTUAL_BIND(_font_set_global_oversampling, "oversampling");
+
+ GDVIRTUAL_BIND(_get_hex_code_box_size, "size", "index");
+ GDVIRTUAL_BIND(_draw_hex_code_box, "canvas", "size", "pos", "index", "color");
+
+ /* Shaped text buffer interface */
+
+ GDVIRTUAL_BIND(_create_shaped_text, "direction", "orientation");
+
+ GDVIRTUAL_BIND(_shaped_text_clear, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction");
+ GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
+
+ GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
+ GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_invalid, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_invalid, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_control, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_control, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language");
+ GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
+ GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align");
+
+ GDVIRTUAL_BIND(_shaped_text_substr, "shaped", "start", "length");
+ GDVIRTUAL_BIND(_shaped_text_get_parent, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_fit_to_width, "shaped", "width", "jst_flags");
+ GDVIRTUAL_BIND(_shaped_text_tab_align, "shaped", "tab_stops");
+
+ GDVIRTUAL_BIND(_shaped_text_shape, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_breaks, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_justification_ops, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped", "r_glyphs");
+ GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped", "r_glyphs");
+ GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_range, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags");
+
+ GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped", "r_glyphs");
+
+ GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
+
+ GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key");
+
+ GDVIRTUAL_BIND(_shaped_text_get_size, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_descent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_width, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_position, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_thickness, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
+
+ GDVIRTUAL_BIND(_shaped_text_get_carets, "shaped", "position", "caret");
+ GDVIRTUAL_BIND(_shaped_text_get_selection, "shaped", "start", "end");
+
+ GDVIRTUAL_BIND(_shaped_text_hit_test_grapheme, "shaped", "coord");
+ GDVIRTUAL_BIND(_shaped_text_hit_test_position, "shaped", "coord");
+
+ GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
+ GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
+
+ GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos");
+
+ GDVIRTUAL_BIND(_format_number, "string", "language");
+ GDVIRTUAL_BIND(_parse_number, "string", "language");
+ GDVIRTUAL_BIND(_percent_sign, "language");
+}
+
+bool TextServerExtension::has_feature(Feature p_feature) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_feature, p_feature, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::get_name() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_name, ret)) {
+ return ret;
+ }
+ return "Unknown";
+}
+
+uint32_t TextServerExtension::get_features() const {
+ uint32_t ret;
+ if (GDVIRTUAL_CALL(_get_features, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::free(RID p_rid) {
+ GDVIRTUAL_CALL(_free, p_rid);
+}
+
+bool TextServerExtension::has(RID p_rid) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has, p_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::load_support_data(const String &p_filename) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_load_support_data, p_filename, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::get_support_data_filename() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_support_data_filename, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+String TextServerExtension::get_support_data_info() const {
+ String ret;
+ if (GDVIRTUAL_CALL(_get_support_data_info, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+bool TextServerExtension::save_support_data(const String &p_filename) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_save_support_data, p_filename, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_locale_right_to_left, p_locale, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+int32_t TextServerExtension::name_to_tag(const String &p_name) const {
+ int32_t ret;
+ if (GDVIRTUAL_CALL(_name_to_tag, p_name, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+String TextServerExtension::tag_to_name(int32_t p_tag) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_tag_to_name, p_tag, ret)) {
+ return ret;
+ }
+ return "";
+}
+
+/*************************************************************************/
+/* Font */
+/*************************************************************************/
+
+RID TextServerExtension::create_font() {
+ RID ret;
+ if (GDVIRTUAL_CALL(_create_font, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+void TextServerExtension::font_set_data(RID p_font_rid, const PackedByteArray &p_data) {
+ GDVIRTUAL_CALL(_font_set_data, p_font_rid, p_data);
+}
+
+void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) {
+ GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
+}
+
+void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) {
+ GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased);
+}
+
+bool TextServerExtension::font_is_antialiased(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_antialiased, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) {
+ GDVIRTUAL_CALL(_font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
+}
+
+bool TextServerExtension::font_is_multichannel_signed_distance_field(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_multichannel_signed_distance_field, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) {
+ GDVIRTUAL_CALL(_font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
+}
+
+int TextServerExtension::font_get_msdf_pixel_range(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_msdf_pixel_range, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_msdf_size(RID p_font_rid, int p_msdf_size) {
+ GDVIRTUAL_CALL(_font_set_msdf_size, p_font_rid, p_msdf_size);
+}
+
+int TextServerExtension::font_get_msdf_size(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_msdf_size, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_fixed_size(RID p_font_rid, int p_fixed_size) {
+ GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
+}
+
+int TextServerExtension::font_get_fixed_size(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) {
+ GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter);
+}
+
+bool TextServerExtension::font_is_force_autohinter(RID p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_force_autohinter, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) {
+ GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting);
+}
+
+TextServer::Hinting TextServerExtension::font_get_hinting(RID p_font_rid) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret)) {
+ return (TextServer::Hinting)ret;
+ }
+ return TextServer::Hinting::HINTING_NONE;
+}
+
+void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
+ GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
+}
+
+Dictionary TextServerExtension::font_get_variation_coordinates(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_get_variation_coordinates, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+void TextServerExtension::font_set_oversampling(RID p_font_rid, float p_oversampling) {
+ GDVIRTUAL_CALL(_font_set_oversampling, p_font_rid, p_oversampling);
+}
+
+float TextServerExtension::font_get_oversampling(RID p_font_rid) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_oversampling, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+Array TextServerExtension::font_get_size_cache_list(RID p_font_rid) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_size_cache(RID p_font_rid) {
+ GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid);
+}
+
+void TextServerExtension::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) {
+ GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
+}
+
+float TextServerExtension::font_get_ascent(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_descent(RID p_font_rid, int p_size, float p_descent) {
+ GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
+}
+
+float TextServerExtension::font_get_descent(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) {
+ GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
+}
+
+float TextServerExtension::font_get_underline_position(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) {
+ GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
+}
+
+float TextServerExtension::font_get_underline_thickness(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_scale(RID p_font_rid, int p_size, float p_scale) {
+ GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
+}
+
+float TextServerExtension::font_get_scale(RID p_font_rid, int p_size) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) {
+ GDVIRTUAL_CALL(_font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
+}
+
+int TextServerExtension::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextServerExtension::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_clear_textures(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) {
+ GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
+}
+
+void TextServerExtension::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
+ GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
+}
+
+Ref<Image> TextServerExtension::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+ Ref<Image> ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) {
+ return ret;
+ }
+ return Ref<Image>();
+}
+
+void TextServerExtension::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
+ GDVIRTUAL_CALL(_font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
+}
+
+PackedInt32Array TextServerExtension::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) {
+ return ret;
+ }
+ return PackedInt32Array();
+}
+
+Array TextServerExtension::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) {
+ GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) {
+ GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
+}
+
+Vector2 TextServerExtension::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
+ GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
+}
+
+Vector2 TextServerExtension::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
+ GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
+}
+
+Vector2 TextServerExtension::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+void TextServerExtension::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
+ GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
+}
+
+Rect2 TextServerExtension::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Rect2();
+}
+
+void TextServerExtension::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
+ GDVIRTUAL_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
+}
+
+int TextServerExtension::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
+ GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+}
+
+Dictionary TextServerExtension::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+Array TextServerExtension::font_get_kerning_list(RID p_font_rid, int p_size) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_font_get_kerning_list, p_font_rid, p_size, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+void TextServerExtension::font_clear_kerning_map(RID p_font_rid, int p_size) {
+ GDVIRTUAL_CALL(_font_clear_kerning_map, p_font_rid, p_size);
+}
+
+void TextServerExtension::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) {
+ GDVIRTUAL_CALL(_font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
+}
+
+void TextServerExtension::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
+ GDVIRTUAL_CALL(_font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
+}
+
+Vector2 TextServerExtension::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) {
+ return ret;
+ }
+ return Vector2();
+}
+
+int32_t TextServerExtension::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const {
+ int32_t ret;
+ if (GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+bool TextServerExtension::font_has_char(RID p_font_rid, char32_t p_char) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+String TextServerExtension::font_get_supported_chars(RID p_font_rid) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+void TextServerExtension::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
+ GDVIRTUAL_CALL(_font_render_range, p_font_rid, p_size, p_start, p_end);
+}
+
+void TextServerExtension::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) {
+ GDVIRTUAL_CALL(_font_render_glyph, p_font_rid, p_size, p_index);
+}
+
+void TextServerExtension::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
+}
+
+void TextServerExtension::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const {
+ GDVIRTUAL_CALL(_font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
+}
+
+bool TextServerExtension::font_is_language_supported(RID p_font_rid, const String &p_language) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_language_supported, p_font_rid, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) {
+ GDVIRTUAL_CALL(_font_set_language_support_override, p_font_rid, p_language, p_supported);
+}
+
+bool TextServerExtension::font_get_language_support_override(RID p_font_rid, const String &p_language) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_get_language_support_override, p_font_rid, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_remove_language_support_override(RID p_font_rid, const String &p_language) {
+ GDVIRTUAL_CALL(_font_remove_language_support_override, p_font_rid, p_language);
+}
+
+Vector<String> TextServerExtension::font_get_language_support_overrides(RID p_font_rid) {
+ Vector<String> ret;
+ if (GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret)) {
+ return ret;
+ }
+ return Vector<String>();
+}
+
+bool TextServerExtension::font_is_script_supported(RID p_font_rid, const String &p_script) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_is_script_supported, p_font_rid, p_script, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) {
+ GDVIRTUAL_CALL(_font_set_script_support_override, p_font_rid, p_script, p_supported);
+}
+
+bool TextServerExtension::font_get_script_support_override(RID p_font_rid, const String &p_script) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_font_get_script_support_override, p_font_rid, p_script, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::font_remove_script_support_override(RID p_font_rid, const String &p_script) {
+ GDVIRTUAL_CALL(_font_remove_script_support_override, p_font_rid, p_script);
+}
+
+Vector<String> TextServerExtension::font_get_script_support_overrides(RID p_font_rid) {
+ Vector<String> ret;
+ if (GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret)) {
+ return ret;
+ }
+ return Vector<String>();
+}
+
+Dictionary TextServerExtension::font_supported_feature_list(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+Dictionary TextServerExtension::font_supported_variation_list(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_supported_variation_list, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
+float TextServerExtension::font_get_global_oversampling() const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_global_oversampling, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_global_oversampling(float p_oversampling) {
+ GDVIRTUAL_CALL(_font_set_global_oversampling, p_oversampling);
+}
+
+Vector2 TextServerExtension::get_hex_code_box_size(int p_size, char32_t p_index) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_get_hex_code_box_size, p_size, p_index, ret)) {
+ return ret;
+ }
+ return TextServer::get_hex_code_box_size(p_size, p_index);
+}
+
+void TextServerExtension::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_pos, char32_t p_index, const Color &p_color) const {
+ if (!GDVIRTUAL_CALL(_draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
+ TextServer::draw_hex_code_box(p_canvas, p_size, p_pos, p_index, p_color);
+ }
+}
+
+/*************************************************************************/
+/* Shaped text buffer interface */
+/*************************************************************************/
+
+RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
+ RID ret;
+ if (GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+void TextServerExtension::shaped_text_clear(RID p_shaped) {
+ GDVIRTUAL_CALL(_shaped_text_clear, p_shaped);
+}
+
+void TextServerExtension::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) {
+ GDVIRTUAL_CALL(_shaped_text_set_direction, p_shaped, p_direction);
+}
+
+TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret)) {
+ return (TextServer::Direction)ret;
+ }
+ return TextServer::Direction::DIRECTION_AUTO;
+}
+
+void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
+ GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation);
+}
+
+TextServer::Orientation TextServerExtension::shaped_text_get_orientation(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret)) {
+ return (TextServer::Orientation)ret;
+ }
+ return TextServer::Orientation::ORIENTATION_HORIZONTAL;
+}
+
+void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
+ GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
+}
+
+void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
+}
+
+bool TextServerExtension::shaped_text_get_preserve_invalid(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_preserve_invalid, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void TextServerExtension::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) {
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_control, p_shaped, p_enabled);
+}
+
+bool TextServerExtension::shaped_text_get_preserve_control(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_preserve_control, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) {
+ bool ret;
+ Array fonts;
+ for (int i = 0; i < p_fonts.size(); i++) {
+ fonts.push_back(p_fonts[i]);
+ }
+ if (GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, fonts, p_size, p_opentype_features, p_language, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+RID TextServerExtension::shaped_text_substr(RID p_shaped, int p_start, int p_length) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+RID TextServerExtension::shaped_text_get_parent(RID p_shaped) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+float TextServerExtension::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t p_jst_flags) {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_tab_align, p_shaped, p_tab_stops, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+bool TextServerExtension::shaped_text_shape(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_update_breaks(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_update_breaks, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_update_justification_ops(RID p_shaped) {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_update_justification_ops, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool TextServerExtension::shaped_text_is_ready(RID p_shaped) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+const Glyph *TextServerExtension::shaped_text_get_glyphs(RID p_shaped) const {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+const Glyph *TextServerExtension::shaped_text_sort_logical(RID p_shaped) {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+int TextServerExtension::shaped_text_get_glyph_count(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Vector2i TextServerExtension::shaped_text_get_range(RID p_shaped) const {
+ Vector2i ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret)) {
+ return ret;
+ }
+ return Vector2i();
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t p_break_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t p_break_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
+}
+
+PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+ PackedInt32Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
+}
+
+int TextServerExtension::shaped_text_get_trim_pos(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+int TextServerExtension::shaped_text_get_ellipsis_pos(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(RID p_shaped) const {
+ const Glyph *ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, &ret)) {
+ return ret;
+ }
+ return nullptr;
+}
+
+int TextServerExtension::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) {
+ return ret;
+ }
+ return -1;
+}
+
+void TextServerExtension::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) {
+ GDVIRTUAL_CALL(_shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
+}
+
+Array TextServerExtension::shaped_text_get_objects(RID p_shaped) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+Rect2 TextServerExtension::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret)) {
+ return ret;
+ }
+ return Rect2();
+}
+
+Size2 TextServerExtension::shaped_text_get_size(RID p_shaped) const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret)) {
+ return ret;
+ }
+ return Size2();
+}
+
+float TextServerExtension::shaped_text_get_ascent(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_descent(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_width(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_underline_position(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+float TextServerExtension::shaped_text_get_underline_thickness(RID p_shaped) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
+ return (TextServer::Direction)ret;
+ }
+ return TextServer::shaped_text_get_dominant_direction_in_range(p_shaped, p_start, p_end);
+}
+
+CaretInfo TextServerExtension::shaped_text_get_carets(RID p_shaped, int p_position) const {
+ CaretInfo ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_carets, p_shaped, p_position, &ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_carets(p_shaped, p_position);
+}
+
+Vector<Vector2> TextServerExtension::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
+ Vector<Vector2> ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_selection(p_shaped, p_start, p_end);
+}
+
+int TextServerExtension::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_hit_test_grapheme(p_shaped, p_coords);
+}
+
+int TextServerExtension::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_hit_test_position(p_shaped, p_coords);
+}
+
+void TextServerExtension::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(_shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
+ return;
+ }
+ TextServer::shaped_text_draw(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color);
+}
+
+void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
+ if (GDVIRTUAL_CALL(_shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
+ return;
+ }
+ shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
+}
+
+int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_next_grapheme_pos(p_shaped, p_pos);
+}
+
+int TextServerExtension::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_prev_grapheme_pos(p_shaped, p_pos);
+}
+
+String TextServerExtension::format_number(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::format_number(p_string, p_language);
+}
+
+String TextServerExtension::parse_number(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::parse_number(p_string, p_language);
+}
+
+String TextServerExtension::percent_sign(const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_percent_sign, p_language, ret)) {
+ return ret;
+ }
+ return TextServer::percent_sign(p_language);
+}
+
+TextServerExtension::TextServerExtension() {
+ //NOP
+}
+
+TextServerExtension::~TextServerExtension() {
+ //NOP
+}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
new file mode 100644
index 0000000000..88a8c0cb0c
--- /dev/null
+++ b/servers/text/text_server_extension.h
@@ -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
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 4886a6f582..a365fde64a 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -32,122 +32,108 @@
#include "scene/main/canvas_item.h"
TextServerManager *TextServerManager::singleton = nullptr;
-TextServer *TextServerManager::server = nullptr;
-TextServerManager::TextServerCreate TextServerManager::server_create_functions[TextServerManager::MAX_SERVERS];
-int TextServerManager::server_create_count = 0;
void TextServerManager::_bind_methods() {
- ClassDB::bind_method(D_METHOD("get_interface_count"), &TextServerManager::_get_interface_count);
- ClassDB::bind_method(D_METHOD("get_interface_name", "index"), &TextServerManager::_get_interface_name);
- ClassDB::bind_method(D_METHOD("get_interface_features", "index"), &TextServerManager::_get_interface_features);
- ClassDB::bind_method(D_METHOD("get_interface", "index"), &TextServerManager::_get_interface);
- ClassDB::bind_method(D_METHOD("get_interfaces"), &TextServerManager::_get_interfaces);
- ClassDB::bind_method(D_METHOD("find_interface", "name"), &TextServerManager::_find_interface);
-
- ClassDB::bind_method(D_METHOD("set_primary_interface", "index"), &TextServerManager::_set_primary_interface);
+ ClassDB::bind_method(D_METHOD("add_interface", "interface"), &TextServerManager::add_interface);
+ ClassDB::bind_method(D_METHOD("get_interface_count"), &TextServerManager::get_interface_count);
+ ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &TextServerManager::remove_interface);
+ ClassDB::bind_method(D_METHOD("get_interface", "idx"), &TextServerManager::get_interface);
+ ClassDB::bind_method(D_METHOD("get_interfaces"), &TextServerManager::get_interfaces);
+ ClassDB::bind_method(D_METHOD("find_interface", "name"), &TextServerManager::find_interface);
+
+ ClassDB::bind_method(D_METHOD("set_primary_interface", "index"), &TextServerManager::set_primary_interface);
ClassDB::bind_method(D_METHOD("get_primary_interface"), &TextServerManager::_get_primary_interface);
-}
-void TextServerManager::register_create_function(const String &p_name, uint32_t p_features, TextServerManager::CreateFunction p_function, void *p_user_data) {
- ERR_FAIL_COND(server_create_count == MAX_SERVERS);
- server_create_functions[server_create_count].name = p_name;
- server_create_functions[server_create_count].create_function = p_function;
- server_create_functions[server_create_count].user_data = p_user_data;
- server_create_functions[server_create_count].features = p_features;
- server_create_count++;
+ ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name")));
+ ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name")));
}
-int TextServerManager::get_interface_count() {
- return server_create_count;
-}
+void TextServerManager::add_interface(const Ref<TextServer> &p_interface) {
+ ERR_FAIL_COND(p_interface.is_null());
-String TextServerManager::get_interface_name(int p_index) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, String());
- return server_create_functions[p_index].name;
-}
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i] == p_interface) {
+ ERR_PRINT("TextServer: Interface was already added.");
+ return;
+ };
+ };
-uint32_t TextServerManager::get_interface_features(int p_index) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, 0);
- return server_create_functions[p_index].features;
+ interfaces.push_back(p_interface);
+ print_verbose("TextServer: Added interface \"" + p_interface->get_name() + "\"");
+ emit_signal(SNAME("interface_added"), p_interface->get_name());
}
-TextServer *TextServerManager::initialize(int p_index, Error &r_error) {
- ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- if (server_create_functions[p_index].instance == nullptr) {
- server_create_functions[p_index].instance = server_create_functions[p_index].create_function(r_error, server_create_functions[p_index].user_data);
- if (server_create_functions[p_index].instance != nullptr) {
- server_create_functions[p_index].instance->load_support_data(""); // Try loading default data.
- }
- }
- if (server_create_functions[p_index].instance != nullptr) {
- server = server_create_functions[p_index].instance;
- if (OS::get_singleton()->get_main_loop()) {
- OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED);
- }
- }
- return server_create_functions[p_index].instance;
-}
+void TextServerManager::remove_interface(const Ref<TextServer> &p_interface) {
+ ERR_FAIL_COND(p_interface.is_null());
+ ERR_FAIL_COND_MSG(p_interface == primary_interface, "TextServer: Can't remove primary interface.");
-TextServer *TextServerManager::get_primary_interface() {
- return server;
-}
+ int idx = -1;
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i] == p_interface) {
+ idx = i;
+ break;
+ };
+ };
-int TextServerManager::_get_interface_count() const {
- return server_create_count;
+ ERR_FAIL_COND(idx == -1);
+ print_verbose("TextServer: Removed interface \"" + p_interface->get_name() + "\"");
+ emit_signal(SNAME("interface_removed"), p_interface->get_name());
+ interfaces.remove(idx);
}
-String TextServerManager::_get_interface_name(int p_index) const {
- return get_interface_name(p_index);
+int TextServerManager::get_interface_count() const {
+ return interfaces.size();
}
-uint32_t TextServerManager::_get_interface_features(int p_index) const {
- return get_interface_features(p_index);
+Ref<TextServer> TextServerManager::get_interface(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, interfaces.size(), nullptr);
+ return interfaces[p_index];
}
-TextServer *TextServerManager::_get_interface(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- if (server_create_functions[p_index].instance == nullptr) {
- Error error;
- server_create_functions[p_index].instance = server_create_functions[p_index].create_function(error, server_create_functions[p_index].user_data);
- if (server_create_functions[p_index].instance != nullptr) {
- server_create_functions[p_index].instance->load_support_data(""); // Try loading default data.
- }
- }
- return server_create_functions[p_index].instance;
-}
+Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
+ int idx = -1;
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (interfaces[i]->get_name() == p_name) {
+ idx = i;
+ break;
+ };
+ };
-TextServer *TextServerManager::_find_interface(const String &p_name) const {
- for (int i = 0; i < server_create_count; i++) {
- if (server_create_functions[i].name == p_name) {
- return _get_interface(i);
- }
- }
- return nullptr;
+ ERR_FAIL_COND_V(idx == -1, nullptr);
+ return interfaces[idx];
}
-Array TextServerManager::_get_interfaces() const {
+Array TextServerManager::get_interfaces() const {
Array ret;
- for (int i = 0; i < server_create_count; i++) {
+ for (int i = 0; i < interfaces.size(); i++) {
Dictionary iface_info;
iface_info["id"] = i;
- iface_info["name"] = server_create_functions[i].name;
+ iface_info["name"] = interfaces[i]->get_name();
ret.push_back(iface_info);
};
return ret;
-};
+}
-bool TextServerManager::_set_primary_interface(int p_index) {
- Error error;
- TextServerManager::initialize(p_index, error);
- return (error == OK);
+Ref<TextServer> TextServerManager::_get_primary_interface() const {
+ return primary_interface;
}
-TextServer *TextServerManager::_get_primary_interface() const {
- return server;
+void TextServerManager::set_primary_interface(const Ref<TextServer> &p_primary_interface) {
+ if (p_primary_interface.is_null()) {
+ print_verbose("TextServer: Clearing primary interface");
+ primary_interface.unref();
+ } else {
+ primary_interface = p_primary_interface;
+ print_verbose("TextServer: Primary interface set to: \"" + primary_interface->get_name() + "\".");
+
+ if (OS::get_singleton()->get_main_loop()) {
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED);
+ }
+ }
}
TextServerManager::TextServerManager() {
@@ -155,29 +141,29 @@ TextServerManager::TextServerManager() {
}
TextServerManager::~TextServerManager() {
- singleton = nullptr;
- for (int i = 0; i < server_create_count; i++) {
- if (server_create_functions[i].instance != nullptr) {
- memdelete(server_create_functions[i].instance);
- server_create_functions[i].instance = nullptr;
- }
+ if (primary_interface.is_valid()) {
+ primary_interface.unref();
}
+ while (interfaces.size() > 0) {
+ interfaces.remove(0);
+ }
+ singleton = nullptr;
}
/*************************************************************************/
-bool TextServer::Glyph::operator==(const Glyph &p_a) const {
+bool Glyph::operator==(const Glyph &p_a) const {
return (p_a.index == index) && (p_a.font_rid == font_rid) && (p_a.font_size == font_size) && (p_a.start == start);
}
-bool TextServer::Glyph::operator!=(const Glyph &p_a) const {
+bool Glyph::operator!=(const Glyph &p_a) const {
return (p_a.index != index) || (p_a.font_rid != font_rid) || (p_a.font_size != font_size) || (p_a.start != start);
}
-bool TextServer::Glyph::operator<(const Glyph &p_a) const {
+bool Glyph::operator<(const Glyph &p_a) const {
if (p_a.start == start) {
if (p_a.count == count) {
- if ((p_a.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
+ if ((p_a.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
return true;
} else {
return false;
@@ -188,10 +174,10 @@ bool TextServer::Glyph::operator<(const Glyph &p_a) const {
return p_a.start < start;
}
-bool TextServer::Glyph::operator>(const Glyph &p_a) const {
+bool Glyph::operator>(const Glyph &p_a) const {
if (p_a.start == start) {
if (p_a.count == count) {
- if ((p_a.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) {
+ if ((p_a.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
return false;
} else {
return true;
@@ -205,8 +191,13 @@ bool TextServer::Glyph::operator>(const Glyph &p_a) const {
void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &TextServer::has_feature);
ClassDB::bind_method(D_METHOD("get_name"), &TextServer::get_name);
+ ClassDB::bind_method(D_METHOD("get_features"), &TextServer::get_features);
ClassDB::bind_method(D_METHOD("load_support_data", "filename"), &TextServer::load_support_data);
+ ClassDB::bind_method(D_METHOD("get_support_data_filename"), &TextServer::get_support_data_filename);
+ ClassDB::bind_method(D_METHOD("get_support_data_info"), &TextServer::get_support_data_info);
+ ClassDB::bind_method(D_METHOD("save_support_data", "filename"), &TextServer::save_support_data);
+
ClassDB::bind_method(D_METHOD("is_locale_right_to_left", "locale"), &TextServer::is_locale_right_to_left);
ClassDB::bind_method(D_METHOD("name_to_tag", "name"), &TextServer::name_to_tag);
@@ -219,7 +210,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_font"), &TextServer::create_font);
- ClassDB::bind_method(D_METHOD("font_set_data", "data"), &TextServer::font_set_data);
+ ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
@@ -299,7 +290,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_get_glyph_texture_idx", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_idx);
ClassDB::bind_method(D_METHOD("font_set_glyph_texture_idx", "font_rid", "size", "glyph", "texture_idx"), &TextServer::font_set_glyph_texture_idx);
- ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::_font_get_glyph_contours);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::font_get_glyph_contours);
ClassDB::bind_method(D_METHOD("font_get_kerning_list", "font_rid", "size"), &TextServer::font_get_kerning_list);
ClassDB::bind_method(D_METHOD("font_clear_kerning_map", "font_rid", "size"), &TextServer::font_clear_kerning_map);
@@ -349,7 +340,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_direction", "shaped", "direction"), &TextServer::shaped_text_set_direction, DEFVAL(DIRECTION_AUTO));
ClassDB::bind_method(D_METHOD("shaped_text_get_direction", "shaped"), &TextServer::shaped_text_get_direction);
- ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::_shaped_text_set_bidi_override);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override);
ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation);
@@ -372,12 +363,19 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_shape", "shaped"), &TextServer::shaped_text_shape);
ClassDB::bind_method(D_METHOD("shaped_text_is_ready", "shaped"), &TextServer::shaped_text_is_ready);
- ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs", "shaped"), &TextServer::_shaped_text_get_glyphs);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs", "shaped"), &TextServer::_shaped_text_get_glyphs_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_sort_logical", "shaped"), &TextServer::_shaped_text_sort_logical_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_glyph_count", "shaped"), &TextServer::shaped_text_get_glyph_count);
ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range);
- ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::_shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::_shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped"), &TextServer::_shaped_text_get_word_breaks);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks);
+
+ ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyphs", "shaped"), &TextServer::_shaped_text_get_ellipsis_glyphs_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyph_count", "shaped"), &TextServer::shaped_text_get_ellipsis_glyph_count);
ClassDB::bind_method(D_METHOD("shaped_text_overrun_trim_to_width", "shaped", "width", "overrun_trim_flags"), &TextServer::shaped_text_overrun_trim_to_width, DEFVAL(0), DEFVAL(OVERRUN_NO_TRIMMING));
@@ -391,8 +389,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_underline_position", "shaped"), &TextServer::shaped_text_get_underline_position);
ClassDB::bind_method(D_METHOD("shaped_text_get_underline_thickness", "shaped"), &TextServer::shaped_text_get_underline_thickness);
- ClassDB::bind_method(D_METHOD("shaped_text_get_carets", "shaped", "position"), &TextServer::_shaped_text_get_carets);
- ClassDB::bind_method(D_METHOD("shaped_text_get_selection", "shaped", "start", "end"), &TextServer::_shaped_text_get_selection);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_carets", "shaped", "position"), &TextServer::_shaped_text_get_carets_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_selection", "shaped", "start", "end"), &TextServer::shaped_text_get_selection);
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_grapheme", "shaped", "coords"), &TextServer::shaped_text_hit_test_grapheme);
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_position", "shaped", "coords"), &TextServer::shaped_text_hit_test_position);
@@ -403,7 +401,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_draw", "shaped", "canvas", "pos", "clip_l", "clip_r", "color"), &TextServer::shaped_text_draw, DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("shaped_text_draw_outline", "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color"), &TextServer::shaped_text_draw_outline, DEFVAL(-1), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direciton_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direciton_in_range);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direction_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direction_in_range);
ClassDB::bind_method(D_METHOD("format_number", "number", "language"), &TextServer::format_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
@@ -424,12 +422,14 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND);
BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES);
BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB);
+ BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
/* LineBreakFlag */
BIND_ENUM_CONSTANT(BREAK_NONE);
BIND_ENUM_CONSTANT(BREAK_MANDATORY);
BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
+ BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE);
/* TextOverrunFlag */
BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
@@ -437,8 +437,10 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
+ BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE);
/* GraphemeFlag */
+ BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID);
BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE);
@@ -578,6 +580,9 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
int fnt = (p_size < 20) ? 0 : 1;
ERR_FAIL_COND(hex_code_box_font_tex[fnt].is_null());
+ if (p_index == 0) {
+ return;
+ }
uint8_t a = p_index & 0x0F;
uint8_t b = (p_index >> 4) & 0x0F;
@@ -592,12 +597,12 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
real_t w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)) * hex_code_box_font_size[fnt].x;
real_t h = 2 * hex_code_box_font_size[fnt].y;
- pos.y -= Math::floor((h + 3 + hex_code_box_font_size[fnt].z) * 0.75);
+ pos.y -= Math::floor((h + 3 + hex_code_box_font_size[fnt].z));
RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(1, h + 2 + 2 * hex_code_box_font_size[fnt].z)), p_color);
RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(w + 2, 0), Size2(1, h + 2 + 2 * hex_code_box_font_size[fnt].z)), p_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(w + 2, 1)), p_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, h + 2 + 2 * hex_code_box_font_size[fnt].z), Size2(w + 2, 1)), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, 0), Size2(w + 3, 1)), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(p_canvas, Rect2(pos + Point2(0, h + 2 + 2 * hex_code_box_font_size[fnt].z), Size2(w + 3, 1)), p_color);
pos += Point2(2, 2);
if (p_index <= 0xFF) {
@@ -630,13 +635,12 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
}
}
-Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start, bool p_once, uint8_t /*TextBreakFlag*/ p_break_flags) const {
- Vector<Vector2i> lines;
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+ PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
real_t width = 0.f;
@@ -644,8 +648,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
int last_safe_break = -1;
int chunk = 0;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
@@ -653,7 +657,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if (l_gl[i].count > 0) {
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
- lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
line_start = l_gl[last_safe_break].end;
i = last_safe_break;
last_safe_break = -1;
@@ -669,7 +674,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(Vector2i(line_start, l_gl[i].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
line_start = l_gl[i].end;
last_safe_break = -1;
width = 0;
@@ -693,27 +699,31 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
}
if (l_size > 0) {
- lines.push_back(Vector2i(line_start, range.y));
+ if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
+ lines.push_back(line_start);
+ lines.push_back(range.y);
+ }
} else {
- lines.push_back(Vector2i(0, 0));
+ lines.push_back(0);
+ lines.push_back(0);
}
return lines;
}
-Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t /*TextBreakFlag*/ p_break_flags) const {
- Vector<Vector2i> lines;
+PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+ PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
real_t width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
int word_count = 0;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
@@ -721,7 +731,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_
}
if (l_gl[i].count > 0) {
if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
- lines.push_back(Vector2i(line_start, l_gl[last_safe_break].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
line_start = l_gl[last_safe_break].end;
i = last_safe_break;
last_safe_break = -1;
@@ -731,7 +742,8 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_
}
if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(Vector2i(line_start, l_gl[i].end));
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
line_start = l_gl[i].end;
last_safe_break = -1;
width = 0;
@@ -755,51 +767,49 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1].y < range.y) {
- lines.push_back(Vector2i(line_start, range.y));
+ if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
+ lines.push_back(line_start);
+ lines.push_back(range.y);
}
} else {
- lines.push_back(Vector2i(0, 0));
+ lines.push_back(0);
+ lines.push_back(0);
}
return lines;
}
-Vector<Vector2i> TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
- Vector<Vector2i> words;
+PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const {
+ PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
- const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
int word_start = range.x;
- int l_size = logical.size();
- const Glyph *l_gl = logical.ptr();
+ int l_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].count > 0) {
if ((l_gl[i].flags & p_grapheme_flags) != 0) {
- words.push_back(Vector2i(word_start, l_gl[i].start));
+ words.push_back(word_start);
+ words.push_back(l_gl[i].start);
word_start = l_gl[i].end;
}
}
}
if (l_size > 0) {
- words.push_back(Vector2i(word_start, range.y));
+ words.push_back(word_start);
+ words.push_back(range.y);
}
return words;
}
-TextServer::TrimData TextServer::shaped_text_get_trim_data(RID p_shaped) const {
- WARN_PRINT("Getting overrun data not supported by this TextServer.");
- return TrimData();
-}
-
-void TextServer::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 {
+CaretInfo TextServer::shaped_text_get_carets(RID p_shaped, int p_position) const {
Vector<Rect2> carets;
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
const Vector2 &range = shaped_text_get_range(p_shaped);
real_t ascent = shaped_text_get_ascent(p_shaped);
@@ -807,11 +817,12 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
real_t height = (ascent + descent) / 2;
real_t off = 0.0f;
- p_leading_dir = DIRECTION_AUTO;
- p_trailing_dir = DIRECTION_AUTO;
+ CaretInfo caret;
+ caret.l_dir = DIRECTION_AUTO;
+ caret.t_dir = DIRECTION_AUTO;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (glyphs[i].count > 0) {
@@ -827,13 +838,13 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.y = -ascent;
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- p_trailing_dir = DIRECTION_RTL;
+ caret.t_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_trailing_dir = DIRECTION_LTR;
+ caret.t_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
}
@@ -847,19 +858,19 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.x = -ascent;
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- p_trailing_dir = DIRECTION_RTL;
+ caret.t_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_trailing_dir = DIRECTION_LTR;
+ caret.t_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
}
}
}
- p_trailing_caret = cr;
+ caret.t_caret = cr;
}
// Caret after grapheme (bottom / right).
if (p_position == glyphs[i].end && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
@@ -874,13 +885,13 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
}
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
- p_leading_dir = DIRECTION_LTR;
+ caret.l_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_leading_dir = DIRECTION_RTL;
+ caret.l_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
}
@@ -896,19 +907,19 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
}
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
- p_leading_dir = DIRECTION_LTR;
+ caret.l_dir = DIRECTION_LTR;
for (int j = 0; j < glyphs[i].count; j++) {
cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
}
} else {
- p_leading_dir = DIRECTION_RTL;
+ caret.l_dir = DIRECTION_RTL;
for (int j = 0; j < glyphs[i].count; j++) {
cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
}
}
}
- p_leading_caret = cr;
+ caret.l_caret = cr;
}
// Caret inside grapheme (middle).
if (p_position > glyphs[i].start && p_position < glyphs[i].end && (glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL) {
@@ -937,17 +948,29 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l
cr.position.y = off + char_adv * (p_position - glyphs[i].start);
}
}
- p_trailing_caret = cr;
- p_leading_caret = cr;
+ caret.t_caret = cr;
+ caret.l_caret = cr;
}
}
off += glyphs[i].advance * glyphs[i].repeat;
}
+ return caret;
}
-TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RID p_shaped, int p_start, int p_end) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
+Dictionary TextServer::_shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const {
+ Dictionary ret;
+
+ CaretInfo caret = shaped_text_get_carets(p_shaped, p_position);
+
+ ret["leading_rect"] = caret.l_caret;
+ ret["leading_direction"] = caret.l_dir;
+ ret["trailing_rect"] = caret.t_caret;
+ ret["trailing_direction"] = caret.t_dir;
+
+ return ret;
+}
+TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const {
if (p_start == p_end) {
return DIRECTION_AUTO;
}
@@ -958,8 +981,8 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RI
int rtl = 0;
int ltr = 0;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if ((glyphs[i].end > start) && (glyphs[i].start < end)) {
@@ -983,7 +1006,6 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direciton_in_range(RI
Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
Vector<Vector2> ranges;
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
if (p_start == p_end) {
return ranges;
@@ -992,8 +1014,8 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
int start = MIN(p_start, p_end);
int end = MAX(p_start, p_end);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
real_t off = 0.0f;
for (int i = 0; i < v_size; i++) {
@@ -1076,13 +1098,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
-
// Exact grapheme hit test, return -1 if missed.
real_t off = 0.0f;
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
for (int j = 0; j < glyphs[i].repeat; j++) {
@@ -1096,10 +1116,8 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) con
}
int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
-
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
// Cursor placement hit test.
@@ -1165,10 +1183,9 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) con
return 0;
}
-int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (p_pos >= glyphs[i].start && p_pos < glyphs[i].end) {
return glyphs[i].end;
@@ -1177,10 +1194,9 @@ int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) {
return p_pos;
}
-int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
for (int i = 0; i < v_size; i++) {
if (p_pos > glyphs[i].start && p_pos <= glyphs[i].end) {
return glyphs[i].start;
@@ -1191,26 +1207,30 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) {
}
void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, const Color &p_color) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped);
bool rtl = shaped_text_get_direction(p_shaped) == DIRECTION_RTL;
- TrimData trim_data = shaped_text_get_trim_data(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
+ int trim_pos = shaped_text_get_trim_pos(p_shaped);
+
+ const Glyph *ellipsis_glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int ellipsis_gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
Vector2 ofs = p_pos;
// Draw RTL ellipsis string when needed.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (rtl && ellipsis_pos >= 0) {
+ for (int i = ellipsis_gl_size - 1; i >= 0; i--) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
@@ -1244,13 +1264,13 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
}
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
if (rtl) {
- if (i < trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i < trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
continue;
}
} else {
- if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break;
}
}
@@ -1269,14 +1289,14 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
// Draw LTR ellipsis string when needed.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int i = 0; i < ellipsis_gl_size; i++) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
@@ -1284,24 +1304,28 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, int p_outline_size, const Color &p_color) const {
- const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped);
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool rtl = (shaped_text_get_direction(p_shaped) == DIRECTION_RTL);
- TrimData trim_data = shaped_text_get_trim_data(p_shaped);
- int v_size = visual.size();
- const Glyph *glyphs = visual.ptr();
+ int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
+ int trim_pos = shaped_text_get_trim_pos(p_shaped);
+
+ const Glyph *ellipsis_glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int ellipsis_gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
Vector2 ofs = p_pos;
// Draw RTL ellipsis string when needed.
- if (rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = trim_data.ellipsis_glyph_buf.size() - 1; i >= 0; i--) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (rtl && ellipsis_pos >= 0) {
+ for (int i = ellipsis_gl_size - 1; i >= 0; i--) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
@@ -1335,13 +1359,13 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
}
- if (trim_data.trim_pos >= 0) {
+ if (trim_pos >= 0) {
if (rtl) {
- if (i < trim_data.trim_pos) {
+ if (i < trim_pos) {
continue;
}
} else {
- if (i >= trim_data.trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
break;
}
}
@@ -1357,48 +1381,26 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
// Draw LTR ellipsis string when needed.
- if (!rtl && trim_data.ellipsis_pos >= 0) {
- for (int i = 0; i < trim_data.ellipsis_glyph_buf.size(); i++) {
- for (int j = 0; j < trim_data.ellipsis_glyph_buf[i].repeat; j++) {
- font_draw_glyph(trim_data.ellipsis_glyph_buf[i].font_rid, p_canvas, trim_data.ellipsis_glyph_buf[i].font_size, ofs + Vector2(trim_data.ellipsis_glyph_buf[i].x_off, trim_data.ellipsis_glyph_buf[i].y_off), trim_data.ellipsis_glyph_buf[i].index, p_color);
+ if (!rtl && ellipsis_pos >= 0) {
+ for (int i = 0; i < ellipsis_gl_size; i++) {
+ for (int j = 0; j < ellipsis_glyphs[i].repeat; j++) {
+ font_draw_glyph(ellipsis_glyphs[i].font_rid, p_canvas, ellipsis_glyphs[i].font_size, ofs + Vector2(ellipsis_glyphs[i].x_off, ellipsis_glyphs[i].y_off), ellipsis_glyphs[i].index, p_color);
if (orientation == ORIENTATION_HORIZONTAL) {
- ofs.x += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.x += ellipsis_glyphs[i].advance;
} else {
- ofs.y += trim_data.ellipsis_glyph_buf[i].advance;
+ ofs.y += ellipsis_glyphs[i].advance;
}
}
}
}
}
-Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const {
- Vector<Vector3> points;
- Vector<int32_t> contours;
- bool orientation;
- bool ok = font_get_glyph_contours(p_font, p_size, p_index, points, contours, orientation);
- Dictionary out;
-
- if (ok) {
- out["points"] = points;
- out["contours"] = contours;
- out["orientation"] = orientation;
- }
- return out;
-}
-
-void TextServer::_shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
- Vector<Vector2i> overrides;
- for (int i = 0; i < p_override.size(); i++) {
- overrides.push_back(p_override[i]);
- }
- shaped_text_set_bidi_override(p_shaped, overrides);
-}
-
-Array TextServer::_shaped_text_get_glyphs(RID p_shaped) const {
+Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const {
Array ret;
- Vector<Glyph> glyphs = shaped_text_get_glyphs(p_shaped);
- for (int i = 0; i < glyphs.size(); i++) {
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
+ int gl_size = shaped_text_get_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
Dictionary glyph;
glyph["start"] = glyphs[i].start;
@@ -1418,60 +1420,51 @@ Array TextServer::_shaped_text_get_glyphs(RID p_shaped) const {
return ret;
}
-Array TextServer::_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 TextServer::_shaped_text_sort_logical_wrapper(RID p_shaped) {
Array ret;
- Vector<Vector2i> lines = shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
- for (int i = 0; i < lines.size(); i++) {
- ret.push_back(lines[i]);
- }
-
- return ret;
-}
+ const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
+ int gl_size = shaped_text_get_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
+ Dictionary glyph;
-Array TextServer::_shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const {
- Array ret;
+ glyph["start"] = glyphs[i].start;
+ glyph["end"] = glyphs[i].end;
+ glyph["repeat"] = glyphs[i].repeat;
+ glyph["count"] = glyphs[i].count;
+ glyph["flags"] = glyphs[i].flags;
+ glyph["offset"] = Vector2(glyphs[i].x_off, glyphs[i].y_off);
+ glyph["advance"] = glyphs[i].advance;
+ glyph["font_rid"] = glyphs[i].font_rid;
+ glyph["font_size"] = glyphs[i].font_size;
+ glyph["index"] = glyphs[i].index;
- Vector<Vector2i> lines = shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
- for (int i = 0; i < lines.size(); i++) {
- ret.push_back(lines[i]);
+ ret.push_back(glyph);
}
return ret;
}
-Array TextServer::_shaped_text_get_word_breaks(RID p_shaped) const {
+Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const {
Array ret;
- Vector<Vector2i> words = shaped_text_get_word_breaks(p_shaped);
- for (int i = 0; i < words.size(); i++) {
- ret.push_back(words[i]);
- }
-
- return ret;
-}
-
-Dictionary TextServer::_shaped_text_get_carets(RID p_shaped, int p_position) const {
- Dictionary ret;
-
- Rect2 l_caret, t_caret;
- Direction l_dir, t_dir;
- shaped_text_get_carets(p_shaped, p_position, l_caret, l_dir, t_caret, t_dir);
-
- ret["leading_rect"] = l_caret;
- ret["leading_direction"] = l_dir;
- ret["trailing_rect"] = t_caret;
- ret["trailing_direction"] = t_dir;
-
- return ret;
-}
+ const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
+ int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
+ for (int i = 0; i < gl_size; i++) {
+ Dictionary glyph;
-Array TextServer::_shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const {
- Array ret;
+ glyph["start"] = glyphs[i].start;
+ glyph["end"] = glyphs[i].end;
+ glyph["repeat"] = glyphs[i].repeat;
+ glyph["count"] = glyphs[i].count;
+ glyph["flags"] = glyphs[i].flags;
+ glyph["offset"] = Vector2(glyphs[i].x_off, glyphs[i].y_off);
+ glyph["advance"] = glyphs[i].advance;
+ glyph["font_rid"] = glyphs[i].font_rid;
+ glyph["font_size"] = glyphs[i].font_size;
+ glyph["index"] = glyphs[i].index;
- Vector<Vector2> ranges = shaped_text_get_selection(p_shaped, p_start, p_end);
- for (int i = 0; i < ranges.size(); i++) {
- ret.push_back(ranges[i]);
+ ret.push_back(glyph);
}
return ret;
diff --git a/servers/text_server.h b/servers/text_server.h
index 90ad9b493b..da62ff8ef4 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -34,13 +34,17 @@
#include "core/object/ref_counted.h"
#include "core/os/os.h"
#include "core/templates/rid.h"
+#include "core/variant/native_ptr.h"
#include "core/variant/variant.h"
#include "scene/resources/texture.h"
class CanvasTexture;
-class TextServer : public Object {
- GDCLASS(TextServer, Object);
+struct Glyph;
+struct CaretInfo;
+
+class TextServer : public RefCounted {
+ GDCLASS(TextServer, RefCounted);
public:
enum Direction {
@@ -63,12 +67,12 @@ public:
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_MANDATORY = 1 << 4,
- BREAK_WORD_BOUND = 1 << 5,
- BREAK_GRAPHEME_BOUND = 1 << 6,
- BREAK_WORD_BOUND_ADAPTIVE = 1 << 5 | 1 << 7,
+ BREAK_MANDATORY = 1 << 5,
+ BREAK_WORD_BOUND = 1 << 6,
+ BREAK_GRAPHEME_BOUND = 1 << 7,
+ BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8,
};
enum TextOverrunFlag {
@@ -124,50 +128,11 @@ public:
SPACING_BOTTOM,
};
- 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.
-
- 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;
- }
- }
- };
-
+protected:
struct TrimData {
int trim_pos = -1;
int ellipsis_pos = -1;
- Vector<TextServer::Glyph> ellipsis_glyph_buf;
+ Vector<Glyph> ellipsis_glyph_buf;
};
struct ShapedTextData {
@@ -215,22 +180,21 @@ public:
bool preserve_invalid = true; // Draw hex code box instead of missing characters.
bool preserve_control = false; // Draw control characters.
- real_t 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.
- real_t width = 0.f; // Width for horizontal layout, height for vertical.
- real_t width_trimmed = 0.f;
+ float ascent = 0.f; // Ascent for horizontal layout, 1/2 of width for vertical.
+ float descent = 0.f; // Descent for horizontal layout, 1/2 of width for vertical.
+ float width = 0.f; // Width for horizontal layout, height for vertical.
+ float width_trimmed = 0.f;
- real_t upos = 0.f;
- real_t uthk = 0.f;
+ float upos = 0.f;
+ float uthk = 0.f;
TrimData overrun_trim_data;
bool fit_width_minimum_reached = false;
- Vector<TextServer::Glyph> glyphs;
- Vector<TextServer::Glyph> glyphs_logical;
+ Vector<Glyph> glyphs;
+ Vector<Glyph> glyphs_logical;
};
-protected:
static void _bind_methods();
static Vector3 hex_code_box_font_size[2];
@@ -240,20 +204,19 @@ public:
static void initialize_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 uint32_t get_features() const = 0;
virtual void free(RID p_rid) = 0;
virtual bool has(RID p_rid) = 0;
virtual bool load_support_data(const String &p_filename) = 0;
-#ifdef TOOLS_ENABLED
- virtual String get_support_data_filename() = 0;
- virtual String get_support_data_info() = 0;
- virtual bool save_support_data(const String &p_filename) = 0;
-#endif
+ virtual String get_support_data_filename() const = 0;
+ virtual String get_support_data_info() const = 0;
+ virtual bool save_support_data(const String &p_filename) const = 0;
- 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 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 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 TextServer::Hinting font_get_hinting(RID p_font_rid) const = 0;
+ virtual void font_set_hinting(RID p_font_rid, Hinting p_hinting) = 0;
+ virtual Hinting font_get_hinting(RID p_font_rid) const = 0;
virtual void font_set_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 void font_set_oversampling(RID p_font_rid, real_t p_oversampling) = 0;
- virtual real_t font_get_oversampling(RID p_font_rid) const = 0;
+ virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) = 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 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_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) = 0;
- virtual real_t font_get_ascent(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) = 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 real_t font_get_descent(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) = 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 real_t font_get_underline_position(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) = 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 real_t font_get_underline_thickness(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) = 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 real_t font_get_scale(RID p_font_rid, int p_size) const = 0;
+ virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) = 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 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 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 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_variation_list(RID p_font_rid) const = 0;
- virtual real_t font_get_global_oversampling() const = 0;
- virtual void font_set_global_oversampling(real_t p_oversampling) = 0;
+ virtual float font_get_global_oversampling() const = 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;
- 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 Vector2 get_hex_code_box_size(int p_size, char32_t p_index) 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 */
@@ -392,7 +355,7 @@ public:
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 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 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_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 real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) = 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 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_update_breaks(RID p_shaped) = 0;
@@ -419,66 +382,109 @@ public:
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 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 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 Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+ virtual int shaped_text_get_trim_pos(RID p_shaped) const = 0;
+ virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const = 0;
+ 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 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 real_t shaped_text_get_ascent(RID p_shaped) const = 0;
- virtual real_t shaped_text_get_descent(RID p_shaped) const = 0;
- virtual real_t shaped_text_get_width(RID p_shaped) const = 0;
- virtual real_t 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_ascent(RID p_shaped) const = 0;
+ virtual float shaped_text_get_descent(RID p_shaped) const = 0;
+ virtual float shaped_text_get_width(RID p_shaped) const = 0;
+ virtual float shaped_text_get_underline_position(RID p_shaped) const = 0;
+ virtual float shaped_text_get_underline_thickness(RID p_shaped) const = 0;
+
+ virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const;
- virtual Direction shaped_text_get_dominant_direciton_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 int shaped_text_hit_test_grapheme(RID p_shaped, real_t 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_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index.
+ 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_prev_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) const;
// 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_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(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, 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.
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 percent_sign(const String &p_language = "") const { return "%"; };
- /* GDScript wrappers */
- RID _create_font_memory(const PackedByteArray &p_data, int p_base_size = 16);
+ TextServer();
+ ~TextServer();
+};
+
+/*************************************************************************/
- Dictionary _font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const;
+struct Glyph {
+ int start = -1; // Start offset in the source string.
+ int end = -1; // End offset in the source string.
- Array _shaped_text_get_glyphs(RID p_shaped) const;
- Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const;
+ 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.
- void _shaped_text_set_bidi_override(RID p_shaped, const Array &p_override);
+ 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).
- 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;
+ 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).
- Array _shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const;
+ bool operator==(const Glyph &p_a) const;
+ bool operator!=(const Glyph &p_a) const;
- TextServer();
- ~TextServer();
+ 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;
+ }
+ }
};
/*************************************************************************/
@@ -486,52 +492,32 @@ public:
class TextServerManager : public Object {
GDCLASS(TextServerManager, Object);
-public:
- typedef TextServer *(*CreateFunction)(Error &r_error, void *p_user_data);
-
protected:
static void _bind_methods();
private:
static TextServerManager *singleton;
- static TextServer *server;
- enum {
- MAX_SERVERS = 64
- };
- struct TextServerCreate {
- String name;
- 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;
+ Ref<TextServer> primary_interface;
+ Vector<Ref<TextServer>> interfaces;
public:
_FORCE_INLINE_ static TextServerManager *get_singleton() {
return singleton;
}
- static void register_create_function(const String &p_name, uint32_t p_features, CreateFunction p_function, void *p_user_data);
- static int get_interface_count();
- static String get_interface_name(int p_index);
- static uint32_t get_interface_features(int p_index);
- static TextServer *initialize(int p_index, Error &r_error);
- static TextServer *get_primary_interface();
-
- /* GDScript wrappers */
- int _get_interface_count() const;
- String _get_interface_name(int p_index) const;
- uint32_t _get_interface_features(int p_index) const;
- TextServer *_get_interface(int p_index) const;
- Array _get_interfaces() const;
- TextServer *_find_interface(const String &p_name) const;
+ void add_interface(const Ref<TextServer> &p_interface);
+ void remove_interface(const Ref<TextServer> &p_interface);
+ int get_interface_count() const;
+ Ref<TextServer> get_interface(int p_index) const;
+ Ref<TextServer> find_interface(const String &p_name) const;
+ Array get_interfaces() const;
- bool _set_primary_interface(int p_index);
- TextServer *_get_primary_interface() const;
+ _FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
+ return primary_interface;
+ }
+ Ref<TextServer> _get_primary_interface() const;
+ void set_primary_interface(const Ref<TextServer> &p_primary_interface);
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::Orientation);
@@ -552,4 +538,8 @@ VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
+GDVIRTUAL_NATIVE_PTR(Glyph);
+GDVIRTUAL_NATIVE_PTR(Glyph *);
+GDVIRTUAL_NATIVE_PTR(CaretInfo);
+
#endif // TEXT_SERVER_H
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index e4aa4c38ff..341fb1af61 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -174,10 +174,8 @@ struct GodotTestCaseListener : public doctest::IReporter {
memnew(MessageQueue);
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);
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (String("headless") == DisplayServer::get_create_function_name(i)) {
@@ -224,10 +222,6 @@ struct GodotTestCaseListener : public doctest::IReporter {
clear_default_theme();
- if (TextServerManager::get_singleton()) {
- memdelete(TextServerManager::get_singleton());
- }
-
if (navigation_3d_server) {
memdelete(navigation_3d_server);
navigation_3d_server = nullptr;
diff --git a/tests/test_text_server.h b/tests/test_text_server.h
index b8ed4f89d0..af3df7bc79 100644
--- a/tests/test_text_server.h
+++ b/tests/test_text_server.h
@@ -41,19 +41,10 @@ namespace TestTextServer {
TEST_SUITE("[[TextServer]") {
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") {
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- TextServer *ts = TextServerManager::initialize(i, err);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
+ TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font = ts->create_font();
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") {
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- TextServer *ts = TextServerManager::initialize(i, err);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
+ TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font1 = ts->create_font();
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);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
- Vector<TextServer::Glyph> glyphs = ts->shaped_text_get_glyphs(ctx);
- TEST_FAIL_COND(glyphs.size() == 0, "Shaping failed");
- for (int j = 0; j < glyphs.size(); j++) {
+ const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
+ int gl_size = ts->shaped_text_get_glyph_count(ctx);
+ TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+ for (int j = 0; j < gl_size; j++) {
if (glyphs[j].start < 6) {
TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected.");
}
@@ -110,8 +103,9 @@ TEST_SUITE("[[TextServer]") {
}
SUBCASE("[TextServer] Text layout: BiDi") {
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- TextServer *ts = TextServerManager::initialize(i, err);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ 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)) {
continue;
@@ -134,9 +128,10 @@ TEST_SUITE("[[TextServer]") {
bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
- Vector<TextServer::Glyph> glyphs = ts->shaped_text_get_glyphs(ctx);
- TEST_FAIL_COND(glyphs.size() == 0, "Shaping failed");
- for (int j = 0; j < glyphs.size(); j++) {
+ const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
+ int gl_size = ts->shaped_text_get_glyph_count(ctx);
+ TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+ for (int j = 0; j < gl_size; j++) {
if (glyphs[j].count > 0) {
if (glyphs[j].start < 7) {
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") {
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- TextServer *ts = TextServerManager::initialize(i, err);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ 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";
// 5^ 10^
@@ -180,12 +176,17 @@ TEST_SUITE("[[TextServer]") {
bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
- Vector<Vector2i> brks = ts->shaped_text_get_line_breaks(ctx, 1);
- TEST_FAIL_COND(brks.size() != 3, "Invalid line breaks number.");
- if (brks.size() == 3) {
- TEST_FAIL_COND(brks[0] != Vector2i(0, 5), "Invalid line break position.");
- TEST_FAIL_COND(brks[1] != Vector2i(5, 10), "Invalid line break position.");
- TEST_FAIL_COND(brks[2] != Vector2i(10, 14), "Invalid line break position.");
+ PackedInt32Array brks = ts->shaped_text_get_line_breaks(ctx, 1);
+ TEST_FAIL_COND(brks.size() != 6, "Invalid line breaks number.");
+ if (brks.size() == 6) {
+ TEST_FAIL_COND(brks[0] != 0, "Invalid line break position.");
+ TEST_FAIL_COND(brks[1] != 5, "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);
@@ -198,8 +199,9 @@ TEST_SUITE("[[TextServer]") {
}
SUBCASE("[TextServer] Text layout: Justification") {
- for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
- TextServer *ts = TextServerManager::initialize(i, err);
+ for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
+ Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
+ TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
RID font1 = ts->create_font();
ts->font_set_data_ptr(font1, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
@@ -263,7 +265,6 @@ TEST_SUITE("[[TextServer]") {
font.clear();
}
}
- memdelete(tsman);
}
}
}; // namespace TestTextServer
diff --git a/tests/test_vector.h b/tests/test_vector.h
index 02c56e59f6..bfdf389aa7 100644
--- a/tests/test_vector.h
+++ b/tests/test_vector.h
@@ -472,6 +472,19 @@ TEST_CASE("[Vector] Sort custom") {
CHECK(vector[7] == "World");
}
+TEST_CASE("[Vector] Search") {
+ Vector<int> vector;
+ vector.push_back(1);
+ vector.push_back(2);
+ vector.push_back(3);
+ vector.push_back(5);
+ vector.push_back(8);
+ CHECK(vector.bsearch(2, true) == 1);
+ CHECK(vector.bsearch(2, false) == 2);
+ CHECK(vector.bsearch(5, true) == 3);
+ CHECK(vector.bsearch(5, false) == 4);
+}
+
TEST_CASE("[Vector] Operators") {
Vector<int> vector;
vector.push_back(2);