From 0c0b5c84b06e64de6cab301994ac9cd1f845dd35 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Sat, 28 Aug 2021 00:19:51 +0300 Subject: [PATCH] Implement TextServer GDExtension interface, remove TextServer GDNative interface. --- core/extension/extension_api_dump.cpp | 17 + doc/classes/CanvasItem.xml | 2 +- doc/classes/Font.xml | 4 +- doc/classes/OS.xml | 2 +- doc/classes/RenderingServer.xml | 12 + doc/classes/TextParagraph.xml | 2 +- doc/classes/TextServer.xml | 118 +- doc/classes/TextServerExtension.xml | 1262 ++++++++++++++++ doc/classes/TextServerManager.xml | 52 +- editor/editor_spin_slider.cpp | 5 +- editor/import/dynamicfont_import_settings.cpp | 5 +- main/main.cpp | 130 +- modules/gdnative/SCsub | 1 - modules/gdnative/gdnative_api.json | 483 ------- modules/gdnative/gdnative_builders.py | 1 - modules/gdnative/include/text/godot_text.h | 283 ---- modules/gdnative/text/SCsub | 6 - modules/gdnative/text/config.py | 6 - modules/gdnative/text/register_types.cpp | 36 - modules/gdnative/text/register_types.h | 37 - .../gdnative/text/text_server_gdnative.cpp | 1086 -------------- modules/gdnative/text/text_server_gdnative.h | 254 ---- modules/text_server_adv/config.py | 10 + .../doc_classes/TextServerAdvanced.xml | 10 + modules/text_server_adv/register_types.cpp | 7 +- modules/text_server_adv/text_server_adv.cpp | 296 ++-- modules/text_server_adv/text_server_adv.h | 94 +- modules/text_server_fb/config.py | 10 + .../doc_classes/TextServerFallback.xml | 10 + modules/text_server_fb/register_types.cpp | 7 +- modules/text_server_fb/text_server_fb.cpp | 257 ++-- modules/text_server_fb/text_server_fb.h | 92 +- platform/osx/os_osx.mm | 20 +- scene/gui/control.cpp | 4 +- scene/gui/control.h | 2 +- scene/gui/label.cpp | 78 +- scene/gui/line_edit.cpp | 104 +- scene/gui/rich_text_label.cpp | 15 +- scene/gui/text_edit.cpp | 168 ++- scene/gui/text_edit.h | 8 +- scene/main/canvas_item.cpp | 4 +- scene/main/canvas_item.h | 4 +- scene/resources/font.cpp | 8 +- scene/resources/font.h | 8 +- scene/resources/text_line.cpp | 18 +- scene/resources/text_line.h | 10 +- scene/resources/text_paragraph.cpp | 32 +- scene/resources/text_paragraph.h | 10 +- servers/SCsub | 1 + servers/register_server_types.cpp | 18 +- servers/rendering_server.cpp | 1 + servers/text/SCsub | 5 + servers/text/text_server_extension.cpp | 1281 +++++++++++++++++ servers/text/text_server_extension.h | 426 ++++++ servers/text_server.cpp | 577 ++++---- servers/text_server.h | 302 ++-- tests/test_main.cpp | 8 +- tests/test_text_server.h | 67 +- 58 files changed, 4388 insertions(+), 3388 deletions(-) create mode 100644 doc/classes/TextServerExtension.xml delete mode 100644 modules/gdnative/include/text/godot_text.h delete mode 100644 modules/gdnative/text/SCsub delete mode 100644 modules/gdnative/text/config.py delete mode 100644 modules/gdnative/text/register_types.cpp delete mode 100644 modules/gdnative/text/register_types.h delete mode 100644 modules/gdnative/text/text_server_gdnative.cpp delete mode 100644 modules/gdnative/text/text_server_gdnative.h create mode 100644 modules/text_server_adv/doc_classes/TextServerAdvanced.xml create mode 100644 modules/text_server_fb/doc_classes/TextServerFallback.xml create mode 100644 servers/text/SCsub create mode 100644 servers/text/text_server_extension.cpp create mode 100644 servers/text/text_server_extension.h 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/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 @@ - + 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. 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 @@ - + 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 @@ - + 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 @@ - 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]. 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 @@ + + + + + + + + + + + + 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 @@ Text writing direction. - + Line breaking and alignment rules. For more info see [TextServer]. 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 @@ - + Interface for the fonts and complex text layouts. @@ -487,8 +487,8 @@ - - + + Sets font source data, e.g contents of the dynamic font source file. @@ -714,12 +714,14 @@ + Returns the dictionary of the supported OpenType features. + Returns the dictionary of the supported OpenType variation coordinates. @@ -737,6 +739,12 @@ Frees an object created by this [TextServer]. + + + + Returns text server features, see [enum Feature]. + + @@ -751,6 +759,18 @@ Returns the name of the server interface. + + + + Returns default TextServer database (e.g. ICU break iterators and dictionaries) filename. + + + + + + Returns TextServer database (e.g. ICU break iterators and dictionaries) description. + + @@ -758,14 +778,14 @@ Returns [code]true[/code] if [code]rid[/code] is valid resource owned by this text server. - + Returns [code]true[/code] if the server supports a feature. - + @@ -802,6 +822,14 @@ Returns percent sign used in the [code]language[/code]. + + + + + 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. + + @@ -898,7 +926,7 @@ Returns direction of the text. - + @@ -907,30 +935,58 @@ Returns dominant direction of in the range of text. + + + + + Returns number of glyphs in the ellipsis. + + + + + + + Returns array of the glyphs in the ellipsis. + + + + + + + Returns position of the ellipsis. + + + + + + + Returns number of glyphs in the buffer. + + - Returns text glyphs. + Returns text glyphs in the visual order. - + - + Breaks text to the lines and returns character ranges for each line. - + - + Breaks text to the lines and columns. Returns character ranges for each segment. @@ -987,7 +1043,7 @@ - + @@ -1002,6 +1058,13 @@ Returns size of the text. + + + + + Returns position of the trim. + + @@ -1024,8 +1087,9 @@ - + + Breaks text into words and returns array of character ranges. @@ -1053,7 +1117,7 @@ Returns [code]true[/code] if buffer is successfully shaped. - + @@ -1070,7 +1134,7 @@ Trims text if it exceeds the given width. - + @@ -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. + + + + + Returns text glyphs in the logical order. + + @@ -1196,18 +1267,24 @@ Only apply justification to the part of the text after the last tab. + + Apply justification to the trimmed line with ellipsis. + Do not break the line. - + Break the line at the line mandatory break characters (e.g. [code]"\n"[/code]). - + Break the line between the words. - + Break the line between any unconnected graphemes. + + Break the line between the words, or any unconnected graphemes if line is too short to fit the whole word. + No trimming is performed. @@ -1223,6 +1300,11 @@ Determines whether the ellipsis at the end of the text is enforced and may not be hidden. + + + + Grapheme is supprted by the font, and can be drawn. + Grapheme is part of right-to-left or bottom-to-top run. 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 @@ + + + + Base class for TextServer custom implementations (plugins). + + + External TextServer implementations should inherit from this class. + + + + + + + + Creates new, empty font cache entry resource. To free the resulting resourec, use [method _free] method. + + + + + + + + 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. + + + + + + + + + + + Draws box displaying character hexadecimal code. Used for replacing missing characters. + + + + + + + + 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. + + + + + + + + Removes all kerning overrides. + + + + + + + Removes all font sizes from the cache entry + + + + + + + + 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. + + + + + + + + + + + + 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]. + + + + + + + + + + + + + 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]. + + + + + + + + Returns the font ascent (number of pixels above the baseline). + + + + + + + + Returns the font descent (number of pixels below the baseline). + + + + + + + Returns bitmap font fixed size. + + + + + + Returns the font oversampling factor, shared by all fonts in the TextServer. + + + + + + + + + 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. + + + + + + + + + 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. + + + + + + + + + + Returns the glyph index of a [code]char[/code], optionally modified by the [code]variation_selector[/code]. + + + + + + + + Returns list of rendered glyphs in the cache entry. + + + + + + + + + Returns glyph offset from the baseline. + + + + + + + + + Returns size of the glyph. + + + + + + + + + Returns index of the cache texture containing the glyph. + + + + + + + + + Returns rectangle in the cache texture containing the glyph. + + + + + + + Returns the font hinting mode. Used by dynamic fonts only. + + + + + + + + + Returns kerning for the pair of glyphs. + + + + + + + + Returns list of the kerning overrides. + + + + + + + + Returns [code]true[/code] if support override is enabled for the [code]language[/code]. + + + + + + + Returns list of language support overrides. + + + + + + + Return the width of the range around the shape between the minimum and maximum representable signed distance. + + + + + + + Returns source font size used to generate MSDF textures. + + + + + + + Returns font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. Used by dynamic fonts only. + + + + + + + + Returns scaling factor of the color bitmap font. + + + + + + + + Returns [code]true[/code] if support override is enabled for the [code]script[/code]. + + + + + + + Returns list of script support overrides. + + + + + + + Return list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size. + + + + + + + + + Returns extra spacing added between glyphs in pixels. + + + + + + + Returns a string containing all the characters available in the font. + + + + + + + + Returns number of textures used by font cache entry. + + + + + + + + + Returns font cache texture image data. + + + + + + + + + Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. + + + + + + + + Returns pixel offset of the underline below the baseline. + + + + + + + + Returns thickness of the underline in pixels. + + + + + + + Returns variation coordinates for the specified font cache entry. See [method _font_supported_variation_list] for more info. + + + + + + + + Return [code]true[/code] if a Unicode [code]char[/code] is available in the font. + + + + + + + Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled. + + + + + + + Returns [code]true[/code] if auto-hinting is supported and preffered over font built-in hinting. Used by dynamic fonts only. + + + + + + + + Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code). + + + + + + + Returns [code]true[/code] if glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data. + + + + + + + + Returns [code]true[/code], if font supports given script (ISO 15924 code). + + + + + + + + + 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. + + + + + + + + + Removes kerning override for the pair of glyphs. + + + + + + + + Remove language support override. + + + + + + + + Removes script support override. + + + + + + + + Removes specified font size from the cache entry. + + + + + + + + + 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]. + + + + + + + + + Renders specified glyph the the font cache texture. + + + + + + + + + + Renders the range of characters to the font cache texture. + + + + + + + + If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. + + + + + + + + + Sets the font ascent (number of pixels above the baseline). + + + + + + + + Sets font source data, e.g contents of the dynamic font source file. + + + + + + + + + Sets the font descent (number of pixels below the baseline). + + + + + + + + + Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes. + + + + + + + + If set to [code]true[/code] auto-hinting is preffered over font built-in hinting. + + + + + + + + + + + + + + Sets oversampling factor, shared by all font in the TextServer. + Note: This value can be automaticaly changed by display server. + + + + + + + + + + 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. + + + + + + + + + + Sets glyph offset from the baseline. + + + + + + + + + + Sets size of the glyph. + + + + + + + + + + Sets index of the cache texture containing the glyph. + + + + + + + + + + Sets rectangle in the cache texture containing the glyph. + + + + + + + + Sets font hinting mode. Used by dynamic fonts only. + + + + + + + + + + Sets kerning for the pair of glyphs. + + + + + + + + + Adds override for [method _font_is_language_supported]. + + + + + + + + Sets the width of the range around the shape between the minimum and maximum representable signed distance. + + + + + + + + Sets source font size used to generate MSDF textures. + + + + + + + + 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. + + + + + + + + Sets font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. Used by dynamic fonts only. + + + + + + + + + Sets scaling factor of the color bitmap font. + + + + + + + + + Adds override for [method _font_is_script_supported]. + + + + + + + + + + Sets extra spacing added between glyphs in pixels. + + + + + + + + + + Sets font cache texture image data. + + + + + + + + + + Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. + + + + + + + + + Sets pixel offset of the underline below the baseline. + + + + + + + + + Sets thickness of the underline in pixels. + + + + + + + + Sets variation coordinates for the specified font cache entry. See [method _font_supported_variation_list] for more info. + + + + + + + Returns the dictionary of the supported OpenType features. + + + + + + + Returns the dictionary of the supported OpenType variation coordinates. + + + + + + + + Converts a number from the Western Arabic (0..9) to the numeral systems used in [code]language[/code]. + + + + + + + Frees an object created by this [TextServer]. + + + + + + Returns text server features, see [enum TextServer.Feature]. + + + + + + + + Returns size of the replacement character (box with character hexadecimal code that is drawn in place of invalid characters). + + + + + + Returns the name of the server interface. + + + + + + Returns default TextServer database (e.g. ICU break iterators and dictionaries) filename. + + + + + + Returns TextServer database (e.g. ICU break iterators and dictionaries) description. + + + + + + + Returns [code]true[/code] if [code]rid[/code] is valid resource owned by this text server. + + + + + + + Returns [code]true[/code] if the server supports a feature. + + + + + + + Returns [code]true[/code] if locale is right-to-left. + + + + + + + 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. + + + + + + + Converts readable feature, variation, script or language name to OpenType tag. + + + + + + + + Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9). + + + + + + + Returns percent sign used in the [code]language[/code]. + + + + + + + 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. + + + + + + + + + + + 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. + + + + + + + + + + + + Adds text span and font to draw it to the text buffer. + + + + + + + Clears text buffer (removes text and inline objects). + + + + + + + + + + + + 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). + + + + + + + + + + + + + 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). + + + + + + + + + Adjusts text with to fit to specified width, returns new text width + + + + + + + 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. + + + + + + + + + Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle. + + + + + + + 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. + + + + + + + Returns direction of the text. + + + + + + + + + Returns dominant direction of in the range of text. + + + + + + + Returns number of glyphs in the ellipsis. + + + + + + + + Returns array of the glyphs in the ellipsis. + + + + + + + Returns position of the ellipsis. + + + + + + + Returns text glyphs count. + + + + + + + + Copies text glyphs in the visual order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count]. + + + + + + + + + + Breaks text to the lines and returns character ranges for each line. + + + + + + + + + + + Breaks text to the lines and columns. Returns character ranges for each segment. + + + + + + + + Returns bounding rectangle of the inline object. + + + + + + + Returns array of inline objects. + + + + + + + Returns text orientation. + + + + + + + Sets text orientation. + + + + + + + Returns [code]true[/code] if text buffer is configured to display control characters. + + + + + + + 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. + + + + + + + Returns substring buffer character range in the parent buffer. + + + + + + + + + Returns selection rectangles for the specified character range. + + + + + + + Returns size of the text. + + + + + + + Returns ellipsis and trim positions. + + + + + + + Returns pixel offset of the underline below the baseline. + + + + + + + Returns thickness of the underline. + + + + + + + Returns width (for horizontal layout) or height (for vertical) of the text. + + + + + + + + Breaks text into words and returns array of character ranges. + + + + + + + + Returns grapheme index at the specified pixel offset at the baseline, or [code]-1[/code] if none is found. + + + + + + + + Returns caret character offset at the specified pixel offset at the baseline. This function always returns a valid position. + + + + + + + Returns [code]true[/code] if buffer is successfully shaped. + + + + + + + + Returns composite character end position closest to the [code]pos[/code]. + + + + + + + + + Trims text if it exceeds the given width. + + + + + + + + Returns composite character start position closest to the [code]pos[/code]. + + + + + + + + + + Sets new size and alignment of embedded object. + + + + + + + + Overrides BiDi for the structured text. + Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately. + + + + + + + + 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. + + + + + + + + Sets desired text orientation. + Note: Orientation is ignored if server does not support [code]FEATURE_VERTICAL_LAYOUT[/code] feature. + + + + + + + + If set to [code]true[/code] text buffer will display control characters. + + + + + + + + If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed. + + + + + + + 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. + + + + + + + + Copies text glyphs in the logical order, into preallocated array of the size returned by [method _shaped_text_get_glyph_count]. + + + + + + + + + Returns text buffer for the substring of the text in the [code]shaped[/code] text buffer (including inline objects). + + + + + + + + Aligns shaped text to the given tab-stops. + + + + + + + Updates line and word breaks. + + + + + + + Updates justification opportunities (spaces, kashidas, etc.). + + + + + + + Converts OpenType tag to readable feature, variation, script or language name. + + + + 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 @@ + + + + + Registers an [TextServer] interface. + + @@ -19,7 +26,7 @@ - + Returns the interface registered at a given index. @@ -30,20 +37,6 @@ Returns the number of interfaces currently registered. - - - - - Returns text server supported features (binary OR). - - - - - - - Returns the interface name registered at a given index. - - @@ -53,15 +46,36 @@ - Returns the primary [TextServer] interface. + Returns the primary [TextServer] interface currently in use. + + + + + + + Removes interface. All fonts and shaped text caches should be freed before removing interface. - - + + - 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. + + + + + Emitted when a new interface has been added. + + + + + + Emitted when an interface is removed. + + + 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 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/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 &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/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 ", "#include ", "#include ", - "#include ", "", "#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 - -#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/register_types.h b/modules/gdnative/text/register_types.h deleted file mode 100644 index cd4f2a3089..0000000000 --- a/modules/gdnative/text/register_types.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************/ -/* register_types.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TEXT_REGISTER_TYPES_H -#define TEXT_REGISTER_TYPES_H - -void register_text_server_gdn_types(); -void unregister_text_server_gdn_types(); - -#endif // TEXT_REGISTER_TYPES_H 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 &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 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()); - 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 *)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 &r_points, Vector &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 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 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 &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 &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 &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 TextServerGDNative::shaped_text_get_glyphs(RID p_shaped) const { - ERR_FAIL_COND_V(interface == nullptr, Vector()); - godot_packed_glyph_array result = interface->shaped_text_get_glyphs(data, (godot_rid *)&p_shaped); - Vector glyphs = *(Vector *)&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 TextServerGDNative::shaped_text_sort_logical(RID p_shaped) { - ERR_FAIL_COND_V(interface == nullptr, Vector()); - godot_packed_glyph_array result = interface->shaped_text_sort_logical(data, (godot_rid *)&p_shaped); - Vector glyphs = *(Vector *)&result; - godot_packed_glyph_array_destroy(&result); - return glyphs; -} - -Vector TextServerGDNative::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector &p_width, int p_start, bool p_once, uint8_t p_break_flags) const { - ERR_FAIL_COND_V(interface == nullptr, Vector()); - 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 breaks = *(Vector *)&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 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()); - 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 breaks = *(Vector *)&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 TextServerGDNative::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const { - ERR_FAIL_COND_V(interface == nullptr, Vector()); - 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 breaks = *(Vector *)&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), "Vector 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 *dest = (Vector *)r_dest; - memnew_placement(dest, Vector); -} - -void GDAPI godot_packed_glyph_array_new_copy(godot_packed_glyph_array *r_dest, const godot_packed_glyph_array *p_src) { - Vector *dest = (Vector *)r_dest; - const Vector *src = (const Vector *)p_src; - memnew_placement(dest, Vector(*src)); -} - -const godot_glyph GDAPI *godot_packed_glyph_array_ptr(const godot_packed_glyph_array *p_self) { - const Vector *self = (const Vector *)p_self; - return (const godot_glyph *)self->ptr(); -} - -godot_glyph GDAPI *godot_packed_glyph_array_ptrw(godot_packed_glyph_array *p_self) { - Vector *self = (Vector *)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 *self = (Vector *)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 *self = (Vector *)p_self; - Vector *array = (Vector *)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 *self = (Vector *)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 *self = (Vector *)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 *self = (Vector *)p_self; - self->sort(); -} - -void GDAPI godot_packed_glyph_array_reverse(godot_packed_glyph_array *p_self) { - Vector *self = (Vector *)p_self; - self->reverse(); -} - -void GDAPI godot_packed_glyph_array_push_back(godot_packed_glyph_array *p_self, const godot_glyph *p_data) { - Vector *self = (Vector *)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 *self = (Vector *)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 *self = (Vector *)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 *self = (Vector *)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 *self = (const Vector *)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 *self = (const Vector *)p_self; - return self->size(); -} - -godot_bool GDAPI godot_packed_glyph_array_is_empty(const godot_packed_glyph_array *p_self) { - const Vector *self = (const Vector *)p_self; - return self->is_empty(); -} - -void GDAPI godot_packed_glyph_array_destroy(godot_packed_glyph_array *p_self) { - ((Vector *)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 &p_image) override; - virtual Ref 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 &r_points, Vector &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 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 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 &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 &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 &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 shaped_text_get_glyphs(RID p_shaped) const override; - - virtual Vector2i shaped_text_get_range(RID p_shaped) const override; - - virtual Vector shaped_text_sort_logical(RID p_shaped) override; - virtual Vector shaped_text_get_line_breaks_adv(RID p_shaped, const Vector &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 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 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/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 @@ + + + + Text Server using HarfBuzz, ICU and SIL Graphite to support BiDi, complex text layouts and contextual OpenType features. + + + + + + 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 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 +} -bool TextServerAdvanced::save_support_data(const String &p_filename) { +String TextServerAdvanced::get_support_data_info() const { +#ifdef ICU_STATIC_DATA + return String("ICU break iteration data (") + _MKSTR(ICU_DATA_NAME) + String(")."); +#else + return String(); +#endif +} + +bool TextServerAdvanced::save_support_data(const String &p_filename) const { _THREAD_SAFE_METHOD_ #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 &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 &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 &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 &r_points, Vector &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 points; + Vector 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 &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 &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 &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 &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 Vectorpara_direction == DIRECTION_LTR) { @@ -3544,7 +3569,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vectorwidth += gl[i].advance - old_adv; off = 0; @@ -3564,7 +3589,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vectorwidth; + 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, 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.trim_pos; +} + +int TextServerAdvanced::shaped_text_get_ellipsis_pos(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_pos; +} + +const Glyph *TextServerAdvanced::shaped_text_get_ellipsis_glyphs(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_glyph_buf.ptr(); +} + +int TextServerAdvanced::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_glyph_buf.size(); } bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { @@ -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 &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 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()); + ERR_FAIL_COND_V(!sd, nullptr); MutexLock lock(sd->mutex); if (!sd->valid) { const_cast(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(this)->shaped_text_shape(p_shaped); + } + return sd->glyphs.size(); } -Vector 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()); + ERR_FAIL_COND_V(!sd, nullptr); MutexLock lock(sd->mutex); if (!sd->valid) { @@ -4516,11 +4567,19 @@ Vector TextServerAdvanced::shaped_text_sort_logical(RID p_sha if (!sd->sort_valid) { sd->glyphs_logical = sd->glyphs; - sd->glyphs_logical.sort_custom(); + sd->glyphs_logical.sort_custom(); 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 cache; @@ -245,14 +245,14 @@ class TextServerAdvanced : public TextServer { // Common data. - real_t oversampling = 1.f; + float oversampling = 1.f; mutable RID_PtrOwner font_owner; mutable RID_PtrOwner 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 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 &r_points, Vector &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 &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 &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 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 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 @@ + + + + Fallback implementation of the Text Server, without BiDi and complex text layout support. + + + + + + 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 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 image(w, h); // Texture size. + msdfgen::Bitmap 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 &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 &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 &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 &r_points, Vector &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 points; + Vector 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 &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 &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 &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 &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 Vectorpara_direction == DIRECTION_LTR) { @@ -2576,7 +2582,7 @@ real_t TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vectorwidth += 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, TrimData(), "ShapedTextDataFallback invalid."); + ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid."); MutexLock lock(sd->mutex); - return sd->overrun_trim_data; + return sd->overrun_trim_data.trim_pos; +} + +int TextServerFallback::shaped_text_get_ellipsis_pos(RID p_shaped) const { + ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextData invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_pos; +} + +const Glyph *TextServerFallback::shaped_text_get_ellipsis_glyphs(RID p_shaped) const { + ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextData invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_glyph_buf.ptr(); +} + +int TextServerFallback::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const { + ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextData invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_glyph_buf.size(); } bool TextServerFallback::shaped_text_shape(RID p_shaped) { @@ -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 &E : sd->objects) { if (sd->orientation == ORIENTATION_HORIZONTAL) { switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { @@ -2980,15 +3009,38 @@ bool TextServerFallback::shaped_text_is_ready(RID p_shaped) const { return sd->valid; } -Vector 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()); + ERR_FAIL_COND_V(!sd, nullptr); MutexLock lock(sd->mutex); if (!sd->valid) { const_cast(this)->shaped_text_shape(p_shaped); } - return sd->glyphs; + return sd->glyphs.ptr(); +} + +int TextServerFallback::shaped_text_get_glyph_count(RID p_shaped) const { + const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, 0); + + MutexLock lock(sd->mutex); + if (!sd->valid) { + const_cast(this)->shaped_text_shape(p_shaped); + } + return sd->glyphs.size(); +} + +const Glyph *TextServerFallback::shaped_text_sort_logical(RID p_shaped) { + const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, nullptr); + + MutexLock lock(sd->mutex); + if (!sd->valid) { + const_cast(this)->shaped_text_shape(p_shaped); + } + + return sd->glyphs.ptr(); // Already in the logical order, return as is. } Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const { @@ -2999,18 +3051,6 @@ Vector2i TextServerFallback::shaped_text_get_range(RID p_shaped) const { return Vector2(sd->start, sd->end); } -Vector TextServerFallback::shaped_text_sort_logical(RID p_shaped) { - const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); - ERR_FAIL_COND_V(!sd, Vector()); - - MutexLock lock(sd->mutex); - if (!sd->valid) { - const_cast(this)->shaped_text_shape(p_shaped); - } - - return sd->glyphs; // Already in the logical order, return as is. -} - Array TextServerFallback::shaped_text_get_objects(RID p_shaped) const { Array ret; const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); @@ -3051,7 +3091,7 @@ Size2 TextServerFallback::shaped_text_get_size(RID p_shaped) const { } } -real_t TextServerFallback::shaped_text_get_ascent(RID p_shaped) const { +float TextServerFallback::shaped_text_get_ascent(RID p_shaped) const { const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); 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 cache; @@ -194,7 +194,7 @@ class TextServerFallback : public TextServer { // Common data. - real_t oversampling = 1.f; + float oversampling = 1.f; mutable RID_PtrOwner font_owner; mutable RID_PtrOwner 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 &r_points, Vector &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 &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 &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 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 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/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/scene/gui/control.cpp b/scene/gui/control.cpp index ea82a0d131..1b8b5e17ed 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2449,8 +2449,8 @@ bool Control::is_text_field() const { return false; } -Vector Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String p_text) const { - Vector 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 e6ec741d99..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 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; 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 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 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 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 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 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 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 &p_event) { // Double-click select word. last_dblclk = OS::get_singleton()->get_ticks_msec(); last_dblclk_pos = b->get_position(); - Vector 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 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 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 &p_event) { if (c_frame) { const Line &l = c_frame->lines[c_line]; - Vector 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/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 &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()); + 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 &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 &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 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 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 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 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 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 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 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 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 gutters; String data; - Vector bidi_override; + Array bidi_override; Ref data_buf; Color background_color = Color(0, 0, 0, 0); @@ -194,7 +194,7 @@ private: Vector get_line_wrap_ranges(int p_line) const; const Ref get_line_data(int p_line) const; - void set(int p_line, const String &p_text, const Vector &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 &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 &p_bidi_override = Vector()); + 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 &p_multimesh, const Refcanvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid); } -void CanvasItem::draw_string(const Ref &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 &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 &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 &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 &p_mesh, const Ref &p_texture, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1)); void draw_multimesh(const Ref &p_multimesh, const Ref &p_texture); - void draw_string(const Ref &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 &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 &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 &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 &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/font.cpp b/scene/resources/font.cpp index de561bb852..c1d42dff09 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1404,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; @@ -1431,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; @@ -1470,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; @@ -1512,7 +1512,7 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t buffer->draw(p_canvas_item, ofs, p_modulate); } -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/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 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 &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 &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 &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 &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 &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 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 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 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 &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 &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 &p_override); + void set_bidi_override(const Array &p_override); bool set_dropcap(const String &p_text, const Ref &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 &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 &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/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/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_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 &p_image) { + GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image); +} + +Ref TextServerExtension::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const { + Ref ret; + if (GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) { + return ret; + } + return Ref(); +} + +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 TextServerExtension::font_get_language_support_overrides(RID p_font_rid) { + Vector ret; + if (GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret)) { + return ret; + } + return Vector(); +} + +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 TextServerExtension::font_get_script_support_overrides(RID p_font_rid) { + Vector ret; + if (GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret)) { + return ret; + } + return Vector(); +} + +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 &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 TextServerExtension::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const { + Vector 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, 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 &p_image) override; + virtual Ref 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 &); + GDVIRTUAL3RC(Ref, _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 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, _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 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, _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 &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); + GDVIRTUAL2(_shaped_text_sort_logical, RID, GDNativePtr); + 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); + 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 shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const override; + GDVIRTUAL3C(_shaped_text_get_carets, RID, int, GDNativePtr); + GDVIRTUAL3RC(Vector, _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("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("set_primary_interface", "index"), &TextServerManager::set_primary_interface); ClassDB::bind_method(D_METHOD("get_primary_interface"), &TextServerManager::_get_primary_interface); + + ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name"))); + ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name"))); } -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++; +void TextServerManager::add_interface(const Ref &p_interface) { + ERR_FAIL_COND(p_interface.is_null()); + + for (int i = 0; i < interfaces.size(); i++) { + if (interfaces[i] == p_interface) { + ERR_PRINT("TextServer: Interface was already added."); + return; + }; + }; + + interfaces.push_back(p_interface); + print_verbose("TextServer: Added interface \"" + p_interface->get_name() + "\""); + emit_signal(SNAME("interface_added"), p_interface->get_name()); } -int TextServerManager::get_interface_count() { - return server_create_count; +void TextServerManager::remove_interface(const Ref &p_interface) { + ERR_FAIL_COND(p_interface.is_null()); + ERR_FAIL_COND_MSG(p_interface == primary_interface, "TextServer: Can't remove primary interface."); + + int idx = -1; + for (int i = 0; i < interfaces.size(); i++) { + if (interfaces[i] == p_interface) { + idx = i; + break; + }; + }; + + 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) { - ERR_FAIL_INDEX_V(p_index, server_create_count, String()); - return server_create_functions[p_index].name; +int TextServerManager::get_interface_count() const { + return interfaces.size(); } -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; +Ref TextServerManager::get_interface(int p_index) const { + ERR_FAIL_INDEX_V(p_index, interfaces.size(), nullptr); + return interfaces[p_index]; } -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; +Ref 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; + }; + }; + + ERR_FAIL_COND_V(idx == -1, nullptr); + return interfaces[idx]; } -TextServer *TextServerManager::get_primary_interface() { - return server; -} - -int TextServerManager::_get_interface_count() const { - return server_create_count; -} - -String TextServerManager::_get_interface_name(int p_index) const { - return get_interface_name(p_index); -} - -uint32_t TextServerManager::_get_interface_features(int p_index) const { - return get_interface_features(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; -} - -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; -} - -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); } -TextServer *TextServerManager::_get_primary_interface() const { - return server; +Ref TextServerManager::_get_primary_interface() const { + return primary_interface; +} + +void TextServerManager::set_primary_interface(const Ref &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 TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector &p_width, int p_start, bool p_once, uint8_t /*TextBreakFlag*/ p_break_flags) const { - Vector 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(this)->shaped_text_update_breaks(p_shaped); - const Vector &logical = const_cast(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 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(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 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 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 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 TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t /*TextBreakFlag*/ p_break_flags) const { - Vector 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(this)->shaped_text_update_breaks(p_shaped); - const Vector &logical = const_cast(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(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 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 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 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 TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const { - Vector words; +PackedInt32Array TextServer::shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags) const { + PackedInt32Array words; const_cast(this)->shaped_text_update_justification_ops(p_shaped); - const Vector &logical = const_cast(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(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 carets; - const Vector 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 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 TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const { Vector ranges; - const Vector visual = shaped_text_get_glyphs(p_shaped); if (p_start == p_end) { return ranges; @@ -992,8 +1014,8 @@ Vector 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 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 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 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 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 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 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 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 points; - Vector 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 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 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 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]); + 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; + + 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; + + ret.push_back(glyph); } return ret; } -Array TextServer::_shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const { +Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const { Array ret; - Vector 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]); - } + 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; - return 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; -Array TextServer::_shaped_text_get_word_breaks(RID p_shaped) const { - Array ret; - - Vector 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; -} - -Array TextServer::_shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const { - Array ret; - - Vector 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 ellipsis_glyph_buf; + Vector 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 glyphs; - Vector glyphs_logical; + Vector glyphs; + Vector 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 &r_points, Vector &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 &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 &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,119 +382,142 @@ public: virtual bool shaped_text_is_ready(RID p_shaped) const = 0; - virtual Vector 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 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 shaped_text_get_line_breaks_adv(RID p_shaped, const Vector &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual Vector 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 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_direciton_in_range(RID p_shaped, int p_start, int p_end) const; + virtual Direction shaped_text_get_dominant_direction_in_range(RID p_shaped, int p_start, int p_end) const; + + virtual CaretInfo shaped_text_get_carets(RID p_shaped, int p_position) const; + Dictionary _shaped_text_get_carets_wrapper(RID p_shaped, int p_position) const; - virtual void shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const; virtual Vector 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); - - Dictionary _font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const; - - Array _shaped_text_get_glyphs(RID p_shaped) const; - Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const; - - void _shaped_text_set_bidi_override(RID p_shaped, const Array &p_override); - - Array _shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFloat32Array &p_width, int p_start, bool p_once, uint8_t p_break_flags) const; - Array _shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const; - Array _shaped_text_get_word_breaks(RID p_shaped) const; - - Array _shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const; - TextServer(); ~TextServer(); }; /*************************************************************************/ +struct Glyph { + int start = -1; // Start offset in the source string. + int end = -1; // End offset in the source string. + + uint8_t count = 0; // Number of glyphs in the grapheme, set in the first glyph only. + uint8_t repeat = 1; // Draw multiple times in the row. + uint16_t flags = 0; // Grapheme flags (valid, rtl, virtual), set in the first glyph only. + + float x_off = 0.f; // Offset from the origin of the glyph on baseline. + float y_off = 0.f; + float advance = 0.f; // Advance to the next glyph along baseline(x for horizontal layout, y for vertical). + + RID font_rid; // Font resource. + int font_size = 0; // Font size; + int32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs). + + bool operator==(const Glyph &p_a) const; + bool operator!=(const Glyph &p_a) const; + + bool operator<(const Glyph &p_a) const; + bool operator>(const Glyph &p_a) const; +}; + +struct CaretInfo { + Rect2 l_caret; + Rect2 t_caret; + TextServer::Direction l_dir; + TextServer::Direction t_dir; +}; + +struct GlyphCompare { // For line breaking reordering. + _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const { + if (l.start == r.start) { + if (l.count == r.count) { + if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) { + return false; + } else { + return true; + } + } + return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant. + } else { + return l.start < r.start; + } + } +}; + +/*************************************************************************/ + class TextServerManager : public Object { 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 primary_interface; + Vector> 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(); + void add_interface(const Ref &p_interface); + void remove_interface(const Ref &p_interface); + int get_interface_count() const; + Ref get_interface(int p_index) const; + Ref find_interface(const String &p_name) const; + Array get_interfaces() const; - /* 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; - - bool _set_primary_interface(int p_index); - TextServer *_get_primary_interface() const; + _FORCE_INLINE_ Ref get_primary_interface() const { + return primary_interface; + } + Ref _get_primary_interface() const; + void set_primary_interface(const Ref &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 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 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 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 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 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 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 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 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