diff options
author | K. S. Ernest (iFire) Lee <fire@users.noreply.github.com> | 2021-08-27 08:51:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-27 08:51:37 -0700 |
commit | 90a35dac489bcbe39de35af661367519b411cb98 (patch) | |
tree | 8b6b4535556be521f9fbbadaebdea04e5316582c /servers | |
parent | ca4f20529c0b6588464f88fc0b0680a8df0fc77f (diff) | |
parent | 4c3f7d1290311456519ca2416590c7e62465b7f2 (diff) |
Merge pull request #51908 from bruvzg/msdf_fonts2
Make FontData importable resource. Add multi-channel SDF font rendering.
Diffstat (limited to 'servers')
-rw-r--r-- | servers/rendering/renderer_canvas_cull.cpp | 34 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_cull.h | 1 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_render.h | 5 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp | 8 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.h | 8 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas.glsl | 37 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl | 2 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.h | 1 | ||||
-rw-r--r-- | servers/rendering_server.h | 1 | ||||
-rw-r--r-- | servers/text_server.cpp | 223 | ||||
-rw-r--r-- | servers/text_server.h | 221 |
11 files changed, 370 insertions, 171 deletions
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index fd7d5b91fa..efa3a457d3 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -806,6 +806,40 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p rect->texture = p_texture; } +void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range) { + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + + rect->texture = p_texture; + + rect->source = p_src_rect; + rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_MSDF; + + if (p_rect.size.x < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_src_rect.size.x < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (p_rect.size.y < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_src_rect.size.y < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } + rect->outline = p_outline_size; + rect->px_range = p_px_range; +} + void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 79b5450d14..5e343dcf02 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -222,6 +222,7 @@ public: void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); + void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()); diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 8afe9ef410..04ddae4089 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -45,6 +45,7 @@ public: CANVAS_RECT_TRANSPOSE = 16, CANVAS_RECT_CLIP_UV = 32, CANVAS_RECT_IS_GROUP = 64, + CANVAS_RECT_MSDF = 128, }; struct Light { @@ -193,11 +194,15 @@ public: Color modulate; Rect2 source; uint8_t flags; + float outline; + float px_range; RID texture; CommandRect() { flags = 0; + outline = 0; + px_range = 1; type = TYPE_RECT; } }; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 3af5047854..6267f684e3 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -541,6 +541,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend src_rect = Rect2(0, 0, 1, 1); } + if (rect->flags & CANVAS_RECT_MSDF) { + push_constant.flags |= FLAGS_USE_MSDF; + push_constant.msdf[0] = rect->px_range; // Pixel range. + push_constant.msdf[1] = rect->outline; // Outline size. + push_constant.msdf[2] = 0.f; // Reserved. + push_constant.msdf[3] = 0.f; // Reserved. + } + push_constant.modulation[0] = rect->modulate.r * base_color.r; push_constant.modulation[1] = rect->modulate.g * base_color.g; push_constant.modulation[2] = rect->modulate.b * base_color.b; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 7c4f62832c..ec7d7e2854 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -84,8 +84,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_LIGHT_COUNT_SHIFT = 20, FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27) + FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), + FLAGS_USE_MSDF = (1 << 28), }; enum { @@ -388,7 +389,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender { //rect struct { float modulation[4]; - float ninepatch_margins[4]; + union { + float msdf[4]; + float ninepatch_margins[4]; + }; float dst_rect[4]; float src_rect[4]; float pad[2]; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index a443bcdcb8..2911e8b731 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -458,6 +458,14 @@ void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) { #endif +float msdf_median(float r, float g, float b, float a) { + return min(max(min(r, g), min(max(r, g), b)), a); +} + +vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) { + return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min); +} + void main() { vec4 color = color_interp; vec2 uv = uv_interp; @@ -485,7 +493,34 @@ void main() { #endif - color *= texture(sampler2D(color_texture, texture_sampler), uv); +#ifndef USE_PRIMITIVE + if (bool(draw_data.flags & FLAGS_USE_MSDF)) { + float px_range = draw_data.ninepatch_margins.x; + float outline_thickness = draw_data.ninepatch_margins.y; + //float reserved1 = draw_data.ninepatch_margins.z; + //float reserved2 = draw_data.ninepatch_margins.w; + + vec4 msdf_sample = texture(sampler2D(color_texture, texture_sampler), uv); + vec2 msdf_size = vec2(textureSize(sampler2D(color_texture, texture_sampler), 0)); + vec2 dest_size = vec2(1.0) / fwidth(uv); + float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0); + float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b, msdf_sample.a) - 0.5; + + if (outline_thickness > 0) { + float cr = clamp(outline_thickness, 0.0, px_range / 2) / px_range; + float a = clamp((d + cr) * px_size, 0.0, 1.0); + color.a = a * color.a; + } else { + float a = clamp(d * px_size + 0.5, 0.0, 1.0); + color.a = a * color.a; + } + + } else { +#else + { +#endif + color *= texture(sampler2D(color_texture, texture_sampler), uv); + } uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights bool using_light = light_count > 0 || canvas_data.directional_light_count > 0; diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 451f9b0089..0cff505cae 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -24,6 +24,8 @@ #define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) +#define FLAGS_USE_MSDF (1 << 28) + #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 #define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 3386b99f53..56e79b62f2 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -763,6 +763,7 @@ public: FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) + FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 6f80b52faa..8fbf231d9b 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1258,6 +1258,7 @@ public: virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0; + virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0; virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index e51e229418..c05ff78718 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -216,83 +216,130 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("free_rid", "rid"), &TextServer::free); // shouldn't conflict with Object::free() /* Font Interface */ - ClassDB::bind_method(D_METHOD("create_font_system", "name", "base_size"), &TextServer::create_font_system, DEFVAL(16)); - ClassDB::bind_method(D_METHOD("create_font_resource", "filename", "base_size"), &TextServer::create_font_resource, DEFVAL(16)); - ClassDB::bind_method(D_METHOD("create_font_memory", "data", "type", "base_size"), &TextServer::_create_font_memory, DEFVAL(16)); - ClassDB::bind_method(D_METHOD("create_font_bitmap", "height", "ascent", "base_size"), &TextServer::create_font_bitmap); - ClassDB::bind_method(D_METHOD("font_bitmap_add_texture", "font", "texture"), &TextServer::font_bitmap_add_texture); - ClassDB::bind_method(D_METHOD("font_bitmap_add_char", "font", "char", "texture_idx", "rect", "align", "advance"), &TextServer::font_bitmap_add_char); - ClassDB::bind_method(D_METHOD("font_bitmap_add_kerning_pair", "font", "A", "B", "kerning"), &TextServer::font_bitmap_add_kerning_pair); + ClassDB::bind_method(D_METHOD("create_font"), &TextServer::create_font); - ClassDB::bind_method(D_METHOD("font_get_height", "font", "size"), &TextServer::font_get_height); - ClassDB::bind_method(D_METHOD("font_get_ascent", "font", "size"), &TextServer::font_get_ascent); - ClassDB::bind_method(D_METHOD("font_get_descent", "font", "size"), &TextServer::font_get_descent); + ClassDB::bind_method(D_METHOD("font_set_data", "data"), &TextServer::font_set_data); - ClassDB::bind_method(D_METHOD("font_get_underline_position", "font", "size"), &TextServer::font_get_underline_position); - ClassDB::bind_method(D_METHOD("font_get_underline_thickness", "font", "size"), &TextServer::font_get_underline_thickness); + 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); - ClassDB::bind_method(D_METHOD("font_get_spacing_space", "font"), &TextServer::font_get_spacing_space); - ClassDB::bind_method(D_METHOD("font_set_spacing_space", "font", "value"), &TextServer::font_set_spacing_space); + ClassDB::bind_method(D_METHOD("font_set_multichannel_signed_distance_field", "font_rid", "msdf"), &TextServer::font_set_multichannel_signed_distance_field); + ClassDB::bind_method(D_METHOD("font_is_multichannel_signed_distance_field", "font_rid"), &TextServer::font_is_multichannel_signed_distance_field); - ClassDB::bind_method(D_METHOD("font_get_spacing_glyph", "font"), &TextServer::font_get_spacing_glyph); - ClassDB::bind_method(D_METHOD("font_set_spacing_glyph", "font", "value"), &TextServer::font_set_spacing_glyph); + ClassDB::bind_method(D_METHOD("font_set_msdf_pixel_range", "font_rid", "msdf_pixel_range"), &TextServer::font_set_msdf_pixel_range); + ClassDB::bind_method(D_METHOD("font_get_msdf_pixel_range", "font_rid"), &TextServer::font_get_msdf_pixel_range); - ClassDB::bind_method(D_METHOD("font_set_antialiased", "font", "antialiased"), &TextServer::font_set_antialiased); - ClassDB::bind_method(D_METHOD("font_get_antialiased", "font"), &TextServer::font_get_antialiased); + ClassDB::bind_method(D_METHOD("font_set_msdf_size", "font_rid", "msdf_size"), &TextServer::font_set_msdf_size); + ClassDB::bind_method(D_METHOD("font_get_msdf_size", "font_rid"), &TextServer::font_get_msdf_size); - ClassDB::bind_method(D_METHOD("font_get_feature_list", "font"), &TextServer::font_get_feature_list); - ClassDB::bind_method(D_METHOD("font_get_variation_list", "font"), &TextServer::font_get_variation_list); + ClassDB::bind_method(D_METHOD("font_set_fixed_size", "font_rid", "fixed_size"), &TextServer::font_set_fixed_size); + ClassDB::bind_method(D_METHOD("font_get_fixed_size", "font_rid"), &TextServer::font_get_fixed_size); - ClassDB::bind_method(D_METHOD("font_set_variation", "font", "tag", "value"), &TextServer::font_set_variation); - ClassDB::bind_method(D_METHOD("font_get_variation", "font", "tag"), &TextServer::font_get_variation); + ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font_rid", "force_autohinter"), &TextServer::font_set_force_autohinter); + ClassDB::bind_method(D_METHOD("font_is_force_autohinter", "font_rid"), &TextServer::font_is_force_autohinter); - ClassDB::bind_method(D_METHOD("font_set_hinting", "font", "hinting"), &TextServer::font_set_hinting); - ClassDB::bind_method(D_METHOD("font_get_hinting", "font"), &TextServer::font_get_hinting); + ClassDB::bind_method(D_METHOD("font_set_hinting", "font_rid", "_hinting"), &TextServer::font_set_hinting); + ClassDB::bind_method(D_METHOD("font_get_hinting", "font_rid"), &TextServer::font_get_hinting); - ClassDB::bind_method(D_METHOD("font_set_distance_field_hint", "font", "distance_field"), &TextServer::font_set_distance_field_hint); - ClassDB::bind_method(D_METHOD("font_get_distance_field_hint", "font"), &TextServer::font_get_distance_field_hint); + ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates); + ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates); - ClassDB::bind_method(D_METHOD("font_set_force_autohinter", "font", "enabeld"), &TextServer::font_set_force_autohinter); - ClassDB::bind_method(D_METHOD("font_get_force_autohinter", "font"), &TextServer::font_get_force_autohinter); + ClassDB::bind_method(D_METHOD("font_set_oversampling", "font_rid", "oversampling"), &TextServer::font_set_oversampling); + ClassDB::bind_method(D_METHOD("font_get_oversampling", "font_rid"), &TextServer::font_get_oversampling); - ClassDB::bind_method(D_METHOD("font_has_char", "font", "char"), &TextServer::font_has_char); - ClassDB::bind_method(D_METHOD("font_get_supported_chars", "font"), &TextServer::font_get_supported_chars); + ClassDB::bind_method(D_METHOD("font_get_size_cache_list", "font_rid"), &TextServer::font_get_size_cache_list); + ClassDB::bind_method(D_METHOD("font_clear_size_cache", "font_rid"), &TextServer::font_clear_size_cache); + ClassDB::bind_method(D_METHOD("font_remove_size_cache", "font_rid", "size"), &TextServer::font_remove_size_cache); - ClassDB::bind_method(D_METHOD("font_has_outline", "font"), &TextServer::font_has_outline); - ClassDB::bind_method(D_METHOD("font_get_base_size", "font"), &TextServer::font_get_base_size); + ClassDB::bind_method(D_METHOD("font_set_ascent", "font_rid", "size", "ascent"), &TextServer::font_set_ascent); + ClassDB::bind_method(D_METHOD("font_get_ascent", "font_rid", "size"), &TextServer::font_get_ascent); - ClassDB::bind_method(D_METHOD("font_is_language_supported", "font", "language"), &TextServer::font_is_language_supported); - ClassDB::bind_method(D_METHOD("font_set_language_support_override", "font", "language", "supported"), &TextServer::font_set_language_support_override); + ClassDB::bind_method(D_METHOD("font_set_descent", "font_rid", "size", "descent"), &TextServer::font_set_descent); + ClassDB::bind_method(D_METHOD("font_get_descent", "font_rid", "size"), &TextServer::font_get_descent); - ClassDB::bind_method(D_METHOD("font_get_language_support_override", "font", "language"), &TextServer::font_get_language_support_override); - ClassDB::bind_method(D_METHOD("font_remove_language_support_override", "font", "language"), &TextServer::font_remove_language_support_override); - ClassDB::bind_method(D_METHOD("font_get_language_support_overrides", "font"), &TextServer::font_get_language_support_overrides); + ClassDB::bind_method(D_METHOD("font_set_underline_position", "font_rid", "size", "underline_position"), &TextServer::font_set_underline_position); + ClassDB::bind_method(D_METHOD("font_get_underline_position", "font_rid", "size"), &TextServer::font_get_underline_position); - ClassDB::bind_method(D_METHOD("font_is_script_supported", "font", "script"), &TextServer::font_is_script_supported); - ClassDB::bind_method(D_METHOD("font_set_script_support_override", "font", "script", "supported"), &TextServer::font_set_script_support_override); + ClassDB::bind_method(D_METHOD("font_set_underline_thickness", "font_rid", "size", "underline_thickness"), &TextServer::font_set_underline_thickness); + ClassDB::bind_method(D_METHOD("font_get_underline_thickness", "font_rid", "size"), &TextServer::font_get_underline_thickness); - ClassDB::bind_method(D_METHOD("font_get_script_support_override", "font", "script"), &TextServer::font_get_script_support_override); - ClassDB::bind_method(D_METHOD("font_remove_script_support_override", "font", "script"), &TextServer::font_remove_script_support_override); - ClassDB::bind_method(D_METHOD("font_get_script_support_overrides", "font"), &TextServer::font_get_script_support_overrides); + ClassDB::bind_method(D_METHOD("font_set_scale", "font_rid", "size", "scale"), &TextServer::font_set_scale); + ClassDB::bind_method(D_METHOD("font_get_scale", "font_rid", "size"), &TextServer::font_get_scale); - ClassDB::bind_method(D_METHOD("font_get_glyph_index", "font", "char", "variation_selector"), &TextServer::font_get_glyph_index, DEFVAL(0x0000)); - ClassDB::bind_method(D_METHOD("font_get_glyph_advance", "font", "index", "size"), &TextServer::font_get_glyph_advance); - ClassDB::bind_method(D_METHOD("font_get_glyph_kerning", "font", "index_a", "index_b", "size"), &TextServer::font_get_glyph_kerning); + ClassDB::bind_method(D_METHOD("font_set_spacing", "font_rid", "size", "spacing", "value"), &TextServer::font_set_spacing); + ClassDB::bind_method(D_METHOD("font_get_spacing", "font_rid", "size", "spacing"), &TextServer::font_get_spacing); - ClassDB::bind_method(D_METHOD("font_draw_glyph", "font", "canvas", "size", "pos", "index", "color"), &TextServer::font_draw_glyph, DEFVAL(Color(1, 1, 1))); - ClassDB::bind_method(D_METHOD("font_draw_glyph_outline", "font", "canvas", "size", "outline_size", "pos", "index", "color"), &TextServer::font_draw_glyph_outline, DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("font_get_texture_count", "font_rid", "size"), &TextServer::font_get_texture_count); + ClassDB::bind_method(D_METHOD("font_clear_textures", "font_rid", "size"), &TextServer::font_clear_textures); + ClassDB::bind_method(D_METHOD("font_remove_texture", "font_rid", "size", "texture_index"), &TextServer::font_remove_texture); - ClassDB::bind_method(D_METHOD("font_get_oversampling"), &TextServer::font_get_oversampling); - ClassDB::bind_method(D_METHOD("font_set_oversampling", "oversampling"), &TextServer::font_set_oversampling); + ClassDB::bind_method(D_METHOD("font_set_texture_image", "font_rid", "size", "texture_index", "image"), &TextServer::font_set_texture_image); + ClassDB::bind_method(D_METHOD("font_get_texture_image", "font_rid", "size", "texture_index"), &TextServer::font_get_texture_image); - ClassDB::bind_method(D_METHOD("get_system_fonts"), &TextServer::get_system_fonts); + ClassDB::bind_method(D_METHOD("font_set_texture_offsets", "font_rid", "size", "texture_index", "offset"), &TextServer::font_set_texture_offsets); + ClassDB::bind_method(D_METHOD("font_get_texture_offsets", "font_rid", "size", "texture_index"), &TextServer::font_get_texture_offsets); - ClassDB::bind_method(D_METHOD("get_hex_code_box_size", "size", "index"), &TextServer::get_hex_code_box_size); - ClassDB::bind_method(D_METHOD("draw_hex_code_box", "canvas", "size", "pos", "index", "color"), &TextServer::draw_hex_code_box); + ClassDB::bind_method(D_METHOD("font_get_glyph_list", "font_rid", "size"), &TextServer::font_get_glyph_list); + ClassDB::bind_method(D_METHOD("font_clear_glyphs", "font_rid", "size"), &TextServer::font_clear_glyphs); + ClassDB::bind_method(D_METHOD("font_remove_glyph", "font_rid", "size", "glyph"), &TextServer::font_remove_glyph); + + ClassDB::bind_method(D_METHOD("font_get_glyph_advance", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_advance); + ClassDB::bind_method(D_METHOD("font_set_glyph_advance", "font_rid", "size", "glyph", "advance"), &TextServer::font_set_glyph_advance); + + ClassDB::bind_method(D_METHOD("font_get_glyph_offset", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_offset); + ClassDB::bind_method(D_METHOD("font_set_glyph_offset", "font_rid", "size", "glyph", "offset"), &TextServer::font_set_glyph_offset); + + ClassDB::bind_method(D_METHOD("font_get_glyph_size", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_size); + ClassDB::bind_method(D_METHOD("font_set_glyph_size", "font_rid", "size", "glyph", "size"), &TextServer::font_set_glyph_size); + + ClassDB::bind_method(D_METHOD("font_get_glyph_uv_rect", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_uv_rect); + ClassDB::bind_method(D_METHOD("font_set_glyph_uv_rect", "font_rid", "size", "glyph", "uv_rect"), &TextServer::font_set_glyph_uv_rect); + + 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_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); + ClassDB::bind_method(D_METHOD("font_remove_kerning", "font_rid", "size", "glyph_pair"), &TextServer::font_remove_kerning); + + ClassDB::bind_method(D_METHOD("font_set_kerning", "font_rid", "size", "glyph_pair", "kerning"), &TextServer::font_set_kerning); + ClassDB::bind_method(D_METHOD("font_get_kerning", "font_rid", "size", "glyph_pair"), &TextServer::font_get_kerning); + + ClassDB::bind_method(D_METHOD("font_get_glyph_index", "font_rid", "size", "char", "variation_selector"), &TextServer::font_get_glyph_index); + + ClassDB::bind_method(D_METHOD("font_has_char", "font_rid", "char"), &TextServer::font_has_char); + ClassDB::bind_method(D_METHOD("font_get_supported_chars", "font_rid"), &TextServer::font_get_supported_chars); + + ClassDB::bind_method(D_METHOD("font_render_range", "font_rid", "size", "start", "end"), &TextServer::font_render_range); + ClassDB::bind_method(D_METHOD("font_render_glyph", "font_rid", "size", "index"), &TextServer::font_render_glyph); + + ClassDB::bind_method(D_METHOD("font_draw_glyph", "font_rid", "canvas", "size", "pos", "index", "color"), &TextServer::font_draw_glyph, DEFVAL(Color(1, 1, 1))); + ClassDB::bind_method(D_METHOD("font_draw_glyph_outline", "font_rid", "canvas", "size", "outline_size", "pos", "index", "color"), &TextServer::font_draw_glyph_outline, DEFVAL(Color(1, 1, 1))); + + ClassDB::bind_method(D_METHOD("font_is_language_supported", "font_rid", "language"), &TextServer::font_is_language_supported); + ClassDB::bind_method(D_METHOD("font_set_language_support_override", "font_rid", "language", "supported"), &TextServer::font_set_language_support_override); + ClassDB::bind_method(D_METHOD("font_get_language_support_override", "font_rid", "language"), &TextServer::font_get_language_support_override); + ClassDB::bind_method(D_METHOD("font_remove_language_support_override", "font_rid", "language"), &TextServer::font_remove_language_support_override); + ClassDB::bind_method(D_METHOD("font_get_language_support_overrides", "font_rid"), &TextServer::font_get_language_support_overrides); + + ClassDB::bind_method(D_METHOD("font_is_script_supported", "font_rid", "script"), &TextServer::font_is_script_supported); + ClassDB::bind_method(D_METHOD("font_set_script_support_override", "font_rid", "script", "supported"), &TextServer::font_set_script_support_override); + ClassDB::bind_method(D_METHOD("font_get_script_support_override", "font_rid", "script"), &TextServer::font_get_script_support_override); + ClassDB::bind_method(D_METHOD("font_remove_script_support_override", "font_rid", "script"), &TextServer::font_remove_script_support_override); + ClassDB::bind_method(D_METHOD("font_get_script_support_overrides", "font_rid"), &TextServer::font_get_script_support_overrides); + + ClassDB::bind_method(D_METHOD("font_supported_feature_list", "font_rid"), &TextServer::font_supported_feature_list); + ClassDB::bind_method(D_METHOD("font_supported_variation_list", "font_rid"), &TextServer::font_supported_variation_list); + + ClassDB::bind_method(D_METHOD("font_get_global_oversampling"), &TextServer::font_get_global_oversampling); + ClassDB::bind_method(D_METHOD("font_set_global_oversampling", "oversampling"), &TextServer::font_set_global_oversampling); + + ClassDB::bind_method(D_METHOD("get_hex_code_box_size", "size", "index"), &TextServer::get_hex_code_box_size); + ClassDB::bind_method(D_METHOD("draw_hex_code_box", "canvas", "size", "pos", "index", "color"), &TextServer::draw_hex_code_box); + /* Shaped text buffer interface */ ClassDB::bind_method(D_METHOD("create_shaped_text", "direction", "orientation"), &TextServer::create_shaped_text, DEFVAL(DIRECTION_AUTO), DEFVAL(ORIENTATION_HORIZONTAL)); @@ -420,6 +467,12 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON); BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC); BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC); + + /* Font Spacing*/ + BIND_ENUM_CONSTANT(SPACING_GLYPH); + BIND_ENUM_CONSTANT(SPACING_SPACE); + BIND_ENUM_CONSTANT(SPACING_TOP); + BIND_ENUM_CONSTANT(SPACING_BOTTOM); } Vector3 TextServer::hex_code_box_font_size[2] = { Vector3(5, 5, 1), Vector3(10, 10, 2) }; @@ -514,8 +567,8 @@ void TextServer::finish_hex_code_box_fonts() { Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const { int fnt = (p_size < 20) ? 0 : 1; - float w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)) * hex_code_box_font_size[fnt].x; - float h = 2 * hex_code_box_font_size[fnt].y; + 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; return Vector2(w + 4, h + 3 + 2 * hex_code_box_font_size[fnt].z); } @@ -534,8 +587,8 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po Vector2 pos = p_pos; Rect2 dest = Rect2(Vector2(), Vector2(hex_code_box_font_size[fnt].x, hex_code_box_font_size[fnt].y)); - float w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3)) * hex_code_box_font_size[fnt].x; - float h = 2 * hex_code_box_font_size[fnt].y; + 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); @@ -575,7 +628,7 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po } } -Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start, bool p_once, uint8_t /*TextBreakFlag*/ p_break_flags) const { +Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start, bool p_once, uint8_t /*TextBreakFlag*/ p_break_flags) const { Vector<Vector2i> lines; ERR_FAIL_COND_V(p_width.is_empty(), lines); @@ -584,7 +637,7 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); const Vector2i &range = shaped_text_get_range(p_shaped); - float width = 0.f; + real_t width = 0.f; int line_start = MAX(p_start, range.x); int last_safe_break = -1; int chunk = 0; @@ -646,14 +699,14 @@ Vector<Vector2i> TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const return lines; } -Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint8_t /*TextBreakFlag*/ p_break_flags) const { +Vector<Vector2i> TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t /*TextBreakFlag*/ p_break_flags) const { Vector<Vector2i> lines; const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped); const Vector<Glyph> &logical = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); const Vector2i &range = shaped_text_get_range(p_shaped); - float width = 0.f; + real_t width = 0.f; int line_start = MAX(p_start, range.x); int last_safe_break = -1; int word_count = 0; @@ -747,11 +800,11 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped); TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); const Vector2 &range = shaped_text_get_range(p_shaped); - float ascent = shaped_text_get_ascent(p_shaped); - float descent = shaped_text_get_descent(p_shaped); - float height = (ascent + descent) / 2; + real_t ascent = shaped_text_get_ascent(p_shaped); + real_t descent = shaped_text_get_descent(p_shaped); + real_t height = (ascent + descent) / 2; - float off = 0.0f; + real_t off = 0.0f; p_leading_dir = DIRECTION_AUTO; p_trailing_dir = DIRECTION_AUTO; @@ -857,11 +910,11 @@ void TextServer::shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_l } // Caret inside grapheme (middle). if (p_position > glyphs[i].start && p_position < glyphs[i].end && (glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance * glyphs[i + j].repeat; } - float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start); + real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start); Rect2 cr; if (orientation == ORIENTATION_HORIZONTAL) { cr.size.x = 1.0f; @@ -940,14 +993,14 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, int v_size = visual.size(); const Glyph *glyphs = visual.ptr(); - float off = 0.0f; + real_t off = 0.0f; for (int i = 0; i < v_size; i++) { for (int k = 0; k < glyphs[i].repeat; k++) { if ((glyphs[i].count > 0) && ((glyphs[i].index != 0) || ((glyphs[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE))) { if (glyphs[i].start < end && glyphs[i].end > start) { // Grapheme fully in selection range. if (glyphs[i].start >= start && glyphs[i].end <= end) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance; } @@ -955,11 +1008,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, } // Only start of grapheme is in selection range. if (glyphs[i].start >= start && glyphs[i].end > end) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance; } - float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start); + real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start); if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) { ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + advance)); } else { @@ -968,11 +1021,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, } // Only end of grapheme is in selection range. if (glyphs[i].start < start && glyphs[i].end <= end) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance; } - float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start); + real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start); if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) { ranges.push_back(Vector2(off, off + char_adv * (start - glyphs[i].start))); } else { @@ -981,11 +1034,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, } // Selection range is within grapheme. if (glyphs[i].start < start && glyphs[i].end > end) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance; } - float char_adv = advance / (float)(glyphs[i].end - glyphs[i].start); + real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start); if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) { ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start))); } else { @@ -1020,11 +1073,11 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, return ranges; } -int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const { +int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) const { const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped); // Exact grapheme hit test, return -1 if missed. - float off = 0.0f; + real_t off = 0.0f; int v_size = visual.size(); const Glyph *glyphs = visual.ptr(); @@ -1040,7 +1093,7 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) cons return -1; } -int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) const { +int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) const { const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped); int v_size = visual.size(); @@ -1074,10 +1127,10 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) cons } } - float off = 0.0f; + real_t off = 0.0f; for (int i = 0; i < v_size; i++) { if (glyphs[i].count > 0) { - float advance = 0.f; + real_t advance = 0.f; for (int j = 0; j < glyphs[i].count; j++) { advance += glyphs[i + j].advance * glyphs[i + j].repeat; } @@ -1135,7 +1188,7 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) { return p_pos; } -void TextServer::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 { +void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, const Color &p_color) const { const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped); TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped); @@ -1228,7 +1281,7 @@ 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, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const { +void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, int p_outline_size, const Color &p_color) const { const Vector<TextServer::Glyph> visual = shaped_text_get_glyphs(p_shaped); TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped); @@ -1316,11 +1369,7 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect } } -RID TextServer::_create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size) { - return create_font_memory(p_data.ptr(), p_data.size(), p_type, p_base_size); -} - -Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const { +Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const { Vector<Vector3> points; Vector<int32_t> contours; bool orientation; @@ -1378,7 +1427,7 @@ Array TextServer::_shaped_text_get_line_breaks_adv(RID p_shaped, const PackedFlo return ret; } -Array TextServer::_shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint8_t p_break_flags) const { +Array TextServer::_shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint8_t p_break_flags) const { Array ret; Vector<Vector2i> lines = shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags); diff --git a/servers/text_server.h b/servers/text_server.h index 26993838a3..62e02e3c97 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -116,6 +116,13 @@ public: CONTOUR_CURVE_TAG_OFF_CUBIC = 0x02 }; + enum SpacingType { + SPACING_GLYPH, + SPACING_SPACE, + SPACING_TOP, + SPACING_BOTTOM, + }; + struct Glyph { int start = -1; // Start offset in the source string. int end = -1; // End offset in the source string. @@ -124,13 +131,13 @@ public: 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). + 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; - uint32_t index = 0; // Glyph index (font specific) or UTF-32 codepoint (for the invalid glyphs). + 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; @@ -163,6 +170,8 @@ public: }; struct ShapedTextData { + Mutex mutex; + /* Source data */ RID parent; // Substring parent ShapedTextData. @@ -205,13 +214,13 @@ public: bool preserve_invalid = true; // Draw hex code box instead of missing characters. bool preserve_control = false; // Draw control characters. - 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 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 upos = 0.f; - float uthk = 0.f; + real_t upos = 0.f; + real_t uthk = 0.f; TrimData overrun_trim_data; bool fit_width_minimum_reached = false; @@ -245,85 +254,134 @@ public: virtual bool is_locale_right_to_left(const String &p_locale) = 0; - virtual int32_t name_to_tag(const String &p_name) { return 0; }; - virtual String tag_to_name(int32_t p_tag) { return ""; }; + virtual int32_t name_to_tag(const String &p_name) const { return 0; }; + virtual String tag_to_name(int32_t p_tag) const { return ""; }; /* Font interface */ - virtual RID create_font_system(const String &p_name, int p_base_size = 16) = 0; - virtual RID create_font_resource(const String &p_filename, int p_base_size = 16) = 0; - virtual RID create_font_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16) = 0; - virtual RID create_font_bitmap(float p_height, float p_ascent, int p_base_size = 16) = 0; + virtual RID create_font() = 0; + + virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0; + virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0; + + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0; + virtual bool font_is_antialiased(RID p_font_rid) const = 0; + + virtual void font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) = 0; + virtual bool font_is_multichannel_signed_distance_field(RID p_font_rid) const = 0; + + virtual void font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) = 0; + virtual int font_get_msdf_pixel_range(RID p_font_rid) const = 0; + + virtual void font_set_msdf_size(RID p_font_rid, int p_msdf_size) = 0; + virtual int font_get_msdf_size(RID p_font_rid) const = 0; + + virtual void font_set_fixed_size(RID p_font_rid, int p_fixed_size) = 0; + virtual int font_get_fixed_size(RID p_font_rid) const = 0; + + virtual void font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) = 0; + virtual bool font_is_force_autohinter(RID p_font_rid) const = 0; + + virtual 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_bitmap_add_texture(RID p_font, const Ref<Texture> &p_texture) = 0; - virtual void font_bitmap_add_char(RID p_font, char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) = 0; - virtual void font_bitmap_add_kerning_pair(RID p_font, char32_t p_A, char32_t p_B, int p_kerning) = 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 float font_get_height(RID p_font, int p_size) const = 0; - virtual float font_get_ascent(RID p_font, int p_size) const = 0; - virtual float font_get_descent(RID p_font, int p_size) 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 int font_get_spacing_space(RID p_font) const = 0; - virtual void font_set_spacing_space(RID p_font, int p_value) = 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 int font_get_spacing_glyph(RID p_font) const = 0; - virtual void font_set_spacing_glyph(RID p_font, int p_value) = 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 float font_get_underline_position(RID p_font, int p_size) const = 0; - virtual float font_get_underline_thickness(RID p_font, 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_antialiased(RID p_font, bool p_antialiased) = 0; - virtual bool font_get_antialiased(RID p_font) 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 Dictionary font_get_feature_list(RID p_font) const { return Dictionary(); }; - virtual Dictionary font_get_variation_list(RID p_font) const { return Dictionary(); }; + 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_variation(RID p_font, const String &p_name, double p_value){}; - virtual double font_get_variation(RID p_font, const String &p_name) const { return 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_distance_field_hint(RID p_font, bool p_distance_field) = 0; - virtual bool font_get_distance_field_hint(RID p_font) 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; - virtual void font_set_hinting(RID p_font, Hinting p_hinting) = 0; - virtual Hinting font_get_hinting(RID p_font) const = 0; + virtual int font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const = 0; + virtual void font_clear_textures(RID p_font_rid, const Vector2i &p_size) = 0; + virtual void font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) = 0; - virtual void font_set_force_autohinter(RID p_font, bool p_enabeld) = 0; - virtual bool font_get_force_autohinter(RID p_font) const = 0; + virtual void font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) = 0; + virtual Ref<Image> font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0; - virtual bool font_has_char(RID p_font, char32_t p_char) const = 0; - virtual String font_get_supported_chars(RID p_font) const = 0; + virtual void font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) = 0; + virtual PackedInt32Array font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const = 0; - virtual bool font_has_outline(RID p_font) const = 0; - virtual float font_get_base_size(RID p_font) const = 0; + virtual Array font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const = 0; + virtual void font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) = 0; + virtual void font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) = 0; - virtual bool font_is_language_supported(RID p_font, const String &p_language) const = 0; - virtual void font_set_language_support_override(RID p_font, const String &p_language, bool p_supported) = 0; - virtual bool font_get_language_support_override(RID p_font, const String &p_language) = 0; - virtual void font_remove_language_support_override(RID p_font, const String &p_language) = 0; - virtual Vector<String> font_get_language_support_overrides(RID p_font) = 0; + virtual Vector2 font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const = 0; + virtual void font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) = 0; - virtual bool font_is_script_supported(RID p_font, const String &p_script) const = 0; - virtual void font_set_script_support_override(RID p_font, const String &p_script, bool p_supported) = 0; - virtual bool font_get_script_support_override(RID p_font, const String &p_script) = 0; - virtual void font_remove_script_support_override(RID p_font, const String &p_script) = 0; - virtual Vector<String> font_get_script_support_overrides(RID p_font) = 0; + virtual Vector2 font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; + virtual void font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) = 0; - virtual uint32_t font_get_glyph_index(RID p_font, char32_t p_char, char32_t p_variation_selector = 0x0000) const = 0; - virtual Vector2 font_get_glyph_advance(RID p_font, uint32_t p_index, int p_size) const = 0; - virtual Vector2 font_get_glyph_kerning(RID p_font, uint32_t p_index_a, uint32_t p_index_b, int p_size) const = 0; + virtual Vector2 font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; + virtual void font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) = 0; - virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; - virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0; + virtual Rect2 font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; + virtual void font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) = 0; - virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const = 0; + virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const = 0; + virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) = 0; - virtual float font_get_oversampling() const = 0; - virtual void font_set_oversampling(float p_oversampling) = 0; + virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const = 0; + + virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const = 0; + virtual void font_clear_kerning_map(RID p_font_rid, int p_size) = 0; + virtual void font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) = 0; + + virtual void font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) = 0; + virtual Vector2 font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const = 0; + + virtual int32_t font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const = 0; + + virtual bool font_has_char(RID p_font_rid, char32_t p_char) const = 0; + virtual String font_get_supported_chars(RID p_font_rid) const = 0; + + virtual void font_render_range(RID p_font, const Vector2i &p_size, char32_t p_start, char32_t p_end) = 0; + virtual void font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) = 0; + + 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 = 0; + 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 = 0; + + virtual bool font_is_language_supported(RID p_font_rid, const String &p_language) const = 0; + virtual void font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) = 0; + virtual bool font_get_language_support_override(RID p_font_rid, const String &p_language) = 0; + virtual void font_remove_language_support_override(RID p_font_rid, const String &p_language) = 0; + virtual Vector<String> font_get_language_support_overrides(RID p_font_rid) = 0; + + virtual bool font_is_script_supported(RID p_font_rid, const String &p_script) const = 0; + virtual void font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) = 0; + virtual bool font_get_script_support_override(RID p_font_rid, const String &p_script) = 0; + virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) = 0; + virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) = 0; + + virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0; + virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0; + + virtual real_t font_get_global_oversampling() const = 0; + virtual void font_set_global_oversampling(real_t 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 Vector<String> get_system_fonts() const = 0; - /* Shaped text buffer interface */ virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; @@ -351,8 +409,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 float shaped_text_fit_to_width(RID p_shaped, float p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; - virtual float shaped_text_tab_align(RID p_shaped, const Vector<float> &p_tab_stops) = 0; + virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0; + virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) = 0; virtual bool shaped_text_shape(RID p_shaped) = 0; virtual bool shaped_text_update_breaks(RID p_shaped) = 0; @@ -366,36 +424,36 @@ public: virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) = 0; - virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<float> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual Vector<Vector2i> shaped_text_get_line_breaks_adv(RID p_shaped, const Vector<real_t> &p_width, int p_start = 0, bool p_once = true, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; + virtual Vector<Vector2i> shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start = 0, uint8_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; virtual Vector<Vector2i> shaped_text_get_word_breaks(RID p_shaped, int p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; virtual TrimData shaped_text_get_trim_data(RID p_shaped) const; - virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint8_t p_trim_flags) = 0; + 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 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 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 Direction shaped_text_get_dominant_direciton_in_range(RID p_shaped, int p_start, int p_end) const; virtual void shaped_text_get_carets(RID p_shaped, int p_position, Rect2 &p_leading_caret, Direction &p_leading_dir, Rect2 &p_trailing_caret, Direction &p_trailing_dir) const; virtual Vector<Vector2> shaped_text_get_selection(RID p_shaped, int p_start, int p_end) const; - virtual int shaped_text_hit_test_grapheme(RID p_shaped, 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_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_next_grapheme_pos(RID p_shaped, int p_pos); virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos); // 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, 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; + 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; // Number conversion. virtual String format_number(const String &p_string, const String &p_language = "") const { return p_string; }; @@ -403,9 +461,9 @@ public: virtual String percent_sign(const String &p_language = "") const { return "%"; }; /* GDScript wrappers */ - RID _create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16); + RID _create_font_memory(const PackedByteArray &p_data, int p_base_size = 16); - Dictionary _font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const; + 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; @@ -413,7 +471,7 @@ public: 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, float p_width, int p_start, 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; @@ -491,5 +549,6 @@ VARIANT_ENUM_CAST(TextServer::GraphemeFlag); VARIANT_ENUM_CAST(TextServer::Hinting); VARIANT_ENUM_CAST(TextServer::Feature); VARIANT_ENUM_CAST(TextServer::ContourPointTag); +VARIANT_ENUM_CAST(TextServer::SpacingType); #endif // TEXT_SERVER_H |