Add font LCD sub-pixel anti-aliasing support.

This commit is contained in:
bruvzg 2022-08-12 14:03:28 +03:00
parent 230225d360
commit bcc3643989
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
49 changed files with 933 additions and 303 deletions

View File

@ -107,6 +107,23 @@
After submitting all animations slices via [method draw_animation_slice], this function can be used to revert drawing to its default state (all subsequent drawing commands will be visible). If you don't care about this particular use case, usage of this function after submitting the slices is not required. After submitting all animations slices via [method draw_animation_slice], this function can be used to revert drawing to its default state (all subsequent drawing commands will be visible). If you don't care about this particular use case, usage of this function after submitting the slices is not required.
</description> </description>
</method> </method>
<method name="draw_lcd_texture_rect_region">
<return type="void" />
<param index="0" name="texture" type="Texture2D" />
<param index="1" name="rect" type="Rect2" />
<param index="2" name="src_rect" type="Rect2" />
<param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<description>
Draws a textured rectangle region of the font texture with LCD sub-pixel anti-aliasing at a given position, optionally modulated by a color.
Texture is drawn using the following blend operation, blend mode of the [CanvasItemMaterial] is ignored:
[codeblock]
dst.r = texture.r * modulate.r * modulate.a + dst.r * (1.0 - texture.r * modulate.a);
dst.g = texture.g * modulate.g * modulate.a + dst.g * (1.0 - texture.g * modulate.a);
dst.b = texture.b * modulate.b * modulate.a + dst.b * (1.0 - texture.b * modulate.a);
dst.a = modulate.a + dst.a * (1.0 - modulate.a);
[/codeblock]
</description>
</method>
<method name="draw_line"> <method name="draw_line">
<return type="void" /> <return type="void" />
<param index="0" name="from" type="Vector2" /> <param index="0" name="from" type="Vector2" />

View File

@ -495,8 +495,8 @@
The language to use for the editor interface. The language to use for the editor interface.
Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url] Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url]
</member> </member>
<member name="interface/editor/font_antialiased" type="bool" setter="" getter=""> <member name="interface/editor/font_antialiasing" type="int" setter="" getter="">
If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. FreeType's font anti-aliasing mode used to render the editor fonts. Most fonts are not designed to look good with anti-aliasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font.
</member> </member>
<member name="interface/editor/font_hinting" type="int" setter="" getter=""> <member name="interface/editor/font_hinting" type="int" setter="" getter="">
The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes: The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes:

View File

@ -543,8 +543,8 @@
</method> </method>
</methods> </methods>
<members> <members>
<member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. Font anti-aliasing mode.
</member> </member>
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file. Contents of the dynamic font source file.

View File

@ -651,8 +651,8 @@
<member name="gui/theme/custom_font" type="String" setter="" getter="" default="&quot;&quot;"> <member name="gui/theme/custom_font" type="String" setter="" getter="" default="&quot;&quot;">
Path to a custom [Font] resource to use as default for all GUI elements of the project. Path to a custom [Font] resource to use as default for all GUI elements of the project.
</member> </member>
<member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true"> <member name="gui/theme/default_font_antialiasing" type="int" setter="" getter="" default="1">
If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontFile.antialiased]. Font anti-aliasing mode. See [member FontFile.antialiasing],
</member> </member>
<member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false"> <member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false">
If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps). If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps).
@ -672,6 +672,9 @@
</member> </member>
<member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0"> <member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0">
</member> </member>
<member name="gui/theme/lcd_subpixel_layout" type="int" setter="" getter="" default="1">
LCD sub-pixel layout used for font anti-aliasing. See [enum TextServer.FontLCDSubpixelLayout].
</member>
<member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000"> <member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000">
Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds). Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds).
</member> </member>

View File

@ -227,6 +227,14 @@
<description> <description>
</description> </description>
</method> </method>
<method name="draw_list_set_blend_constants">
<return type="void" />
<param index="0" name="draw_list" type="int" />
<param index="1" name="color" type="Color" />
<description>
Sets blend constants for draw list, blend constants are used only if the graphics pipeline is created with [code]DYNAMIC_STATE_BLEND_CONSTANTS[/code] flag set.
</description>
</method>
<method name="draw_list_set_push_constant"> <method name="draw_list_set_push_constant">
<return type="void" /> <return type="void" />
<param index="0" name="draw_list" type="int" /> <param index="0" name="draw_list" type="int" />

View File

@ -176,6 +176,16 @@
<description> <description>
</description> </description>
</method> </method>
<method name="canvas_item_add_lcd_texture_rect_region">
<return type="void" />
<param index="0" name="item" type="RID" />
<param index="1" name="rect" type="Rect2" />
<param index="2" name="texture" type="RID" />
<param index="3" name="src_rect" type="Rect2" />
<param index="4" name="modulate" type="Color" />
<description>
</description>
</method>
<method name="canvas_item_add_line"> <method name="canvas_item_add_line">
<return type="void" /> <return type="void" />
<param index="0" name="item" type="RID" /> <param index="0" name="item" type="RID" />

View File

@ -13,8 +13,8 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<members> <members>
<member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1">
If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. Font anti-aliasing mode.
</member> </member>
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]"> <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
Array of fallback [Font]s. Array of fallback [Font]s.

View File

@ -98,6 +98,13 @@
[b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
</description> </description>
</method> </method>
<method name="font_get_antialiasing" qualifiers="const">
<return type="int" enum="TextServer.FontAntialiasing" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns font anti-aliasing mode.
</description>
</method>
<method name="font_get_ascent" qualifiers="const"> <method name="font_get_ascent" qualifiers="const">
<return type="float" /> <return type="float" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
@ -447,13 +454,6 @@
Returns [code]true[/code] if a Unicode [param char] is available in the font. Returns [code]true[/code] if a Unicode [param char] is available in the font.
</description> </description>
</method> </method>
<method name="font_is_antialiased" qualifiers="const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled.
</description>
</method>
<method name="font_is_force_autohinter" qualifiers="const"> <method name="font_is_force_autohinter" qualifiers="const">
<return type="bool" /> <return type="bool" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
@ -556,12 +556,12 @@
Renders the range of characters to the font cache texture. Renders the range of characters to the font cache texture.
</description> </description>
</method> </method>
<method name="font_set_antialiased"> <method name="font_set_antialiasing">
<return type="void" /> <return type="void" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
<param index="1" name="antialiased" type="bool" /> <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" />
<description> <description>
If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. Sets font anti-aliasing mode.
</description> </description>
</method> </method>
<method name="font_set_ascent"> <method name="font_set_ascent">
@ -1539,6 +1539,32 @@
</method> </method>
</methods> </methods>
<constants> <constants>
<constant name="FONT_ANTIALIASING_NONE" value="0" enum="FontAntialiasing">
Font glyphs are rasterized as 1-bit bitmaps.
</constant>
<constant name="FONT_ANTIALIASING_GRAY" value="1" enum="FontAntialiasing">
Font glyphs are rasterized as 8-bit grayscale anti-aliased bitmaps.
</constant>
<constant name="FONT_ANTIALIASING_LCD" value="2" enum="FontAntialiasing">
Font glyphs are rasterized for LCD screens.
LCD sub-pixel layout is determined by the value of [code]gui/theme/lcd_subpixel_layout[/code] project settings.
LCD sub-pixel anti-aliasing mode is suitable only for rendering horizontal, unscaled text in 2D.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_NONE" value="0" enum="FontLCDSubpixelLayout">
Unknown or unsupported sub-pixel layout, LCD sub-pixel anti-aliasing is disabled.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_HRGB" value="1" enum="FontLCDSubpixelLayout">
Horizontal RGB sub-pixel layout.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_HBGR" value="2" enum="FontLCDSubpixelLayout">
Horizontal BGR sub-pixel layout.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_VRGB" value="3" enum="FontLCDSubpixelLayout">
Vertical RGB sub-pixel layout.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_VBGR" value="4" enum="FontLCDSubpixelLayout">
Vertical BGR sub-pixel layout.
</constant>
<constant name="DIRECTION_AUTO" value="0" enum="Direction"> <constant name="DIRECTION_AUTO" value="0" enum="Direction">
Text direction is determined based on contents and current locale. Text direction is determined based on contents and current locale.
</constant> </constant>

View File

@ -91,6 +91,13 @@
Draws single glyph outline of size [param outline_size] into a canvas item at the position, using [param font_rid] at the size [param size]. Draws single glyph outline of size [param outline_size] into a canvas item at the position, using [param font_rid] at the size [param size].
</description> </description>
</method> </method>
<method name="font_get_antialiasing" qualifiers="virtual const">
<return type="int" enum="TextServer.FontAntialiasing" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns font anti-aliasing mode.
</description>
</method>
<method name="font_get_ascent" qualifiers="virtual const"> <method name="font_get_ascent" qualifiers="virtual const">
<return type="float" /> <return type="float" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
@ -437,13 +444,6 @@
Returns [code]true[/code] if a Unicode [param char] is available in the font. Returns [code]true[/code] if a Unicode [param char] is available in the font.
</description> </description>
</method> </method>
<method name="font_is_antialiased" qualifiers="virtual const">
<return type="bool" />
<param index="0" name="font_rid" type="RID" />
<description>
Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled.
</description>
</method>
<method name="font_is_force_autohinter" qualifiers="virtual const"> <method name="font_is_force_autohinter" qualifiers="virtual const">
<return type="bool" /> <return type="bool" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
@ -544,12 +544,12 @@
Renders the range of characters to the font cache texture. Renders the range of characters to the font cache texture.
</description> </description>
</method> </method>
<method name="font_set_antialiased" qualifiers="virtual"> <method name="font_set_antialiasing" qualifiers="virtual">
<return type="void" /> <return type="void" />
<param index="0" name="font_rid" type="RID" /> <param index="0" name="font_rid" type="RID" />
<param index="1" name="antialiased" type="bool" /> <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" />
<description> <description>
If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. Sets font anti-aliasing mode.
</description> </description>
</method> </method>
<method name="font_set_ascent" qualifiers="virtual"> <method name="font_set_ascent" qualifiers="virtual">

View File

@ -322,6 +322,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
RID prev_material; RID prev_material;
uint32_t index = 0; uint32_t index = 0;
GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX; GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX;
Color last_blend_color;
GLES3::CanvasShaderData *shader_data_cache = nullptr; GLES3::CanvasShaderData *shader_data_cache = nullptr;
state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE);
@ -378,75 +379,13 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX; GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
if (last_blend_mode != blend_mode) { _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index, blend_mode, last_blend_mode, last_blend_color);
if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
// re-enable it
glEnable(GL_BLEND);
} else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
// disable it
glDisable(GL_BLEND);
}
switch (blend_mode) {
case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: {
// Nothing to do here.
} break;
case GLES3::CanvasShaderData::BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
} else {
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_PMALPHA: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
} break;
}
last_blend_mode = blend_mode;
}
_render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index);
} }
// Render last command // Render last command
_render_batch(index); _render_batch(index);
} }
void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index) { void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color) {
// Used by Polygon and Mesh. // Used by Polygon and Mesh.
static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP };
@ -499,6 +438,92 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode;
Color blend_color;
if (c->type == Item::Command::TYPE_RECT) {
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
if (rect->flags & CANVAS_RECT_LCD) {
blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD;
blend_color = rect->modulate;
}
}
if (r_last_blend_mode != blend_mode || r_last_blend_color != blend_color) {
_render_batch(r_index);
if (r_last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
// re-enable it
glEnable(GL_BLEND);
} else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) {
// disable it
glDisable(GL_BLEND);
}
switch (blend_mode) {
case GLES3::CanvasShaderData::BLEND_MODE_DISABLED: {
// Nothing to do here.
} break;
case GLES3::CanvasShaderData::BLEND_MODE_LCD: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE);
}
glBlendColor(blend_color.r, blend_color.g, blend_color.b, blend_color.a);
} break;
case GLES3::CanvasShaderData::BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_SRC_ALPHA, GL_ONE);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
} else {
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
}
} break;
case GLES3::CanvasShaderData::BLEND_MODE_PMALPHA: {
glBlendEquation(GL_FUNC_ADD);
if (state.transparent_render_target) {
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
}
} break;
}
r_last_blend_mode = blend_mode;
r_last_blend_color = blend_color;
}
switch (c->type) { switch (c->type) {
case Item::Command::TYPE_RECT: { case Item::Command::TYPE_RECT: {
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
@ -569,6 +594,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size. state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size.
state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved.
state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved.
} else if (rect->flags & CANVAS_RECT_LCD) {
state.instance_data_array[r_index].flags |= FLAGS_USE_LCD;
} }
state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r; state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r;

View File

@ -73,6 +73,7 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
FLAGS_USE_MSDF = (1 << 28), FLAGS_USE_MSDF = (1 << 28),
FLAGS_USE_LCD = (1 << 29),
}; };
enum { enum {
@ -249,7 +250,7 @@ public:
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override; void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override;
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index); void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color);
void _render_batch(uint32_t &p_max_index); void _render_batch(uint32_t &p_max_index);
void _bind_instance_data_buffer(uint32_t p_max_index); void _bind_instance_data_buffer(uint32_t p_max_index);
void _allocate_instance_data_buffer(); void _allocate_instance_data_buffer();

View File

@ -473,7 +473,13 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0); float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a; color.a = a * color.a;
} }
} else if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_LCD)) {
vec4 lcd_sample = texture(color_texture, uv);
if (lcd_sample.a == 1.0) {
color.rgb = lcd_sample.rgb * color.a;
} else {
color = vec4(0.0, 0.0, 0.0, 0.0);
}
} else { } else {
#else #else
{ {

View File

@ -25,6 +25,7 @@
#define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27) #define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27)
#define FLAGS_USE_MSDF uint(1 << 28) #define FLAGS_USE_MSDF uint(1 << 28)
#define FLAGS_USE_LCD uint(1 << 29)
// must be always 128 bytes long // must be always 128 bytes long
struct DrawData { struct DrawData {

View File

@ -142,6 +142,7 @@ struct CanvasShaderData : public ShaderData {
BLEND_MODE_MUL, BLEND_MODE_MUL,
BLEND_MODE_PMALPHA, BLEND_MODE_PMALPHA,
BLEND_MODE_DISABLED, BLEND_MODE_DISABLED,
BLEND_MODE_LCD,
}; };
bool valid; bool valid;

View File

@ -7543,6 +7543,16 @@ RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawL
} }
} }
void RenderingDeviceVulkan::draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
vkCmdSetBlendConstants(dl->command_buffer, p_color.components);
}
void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) { void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) {
DrawList *dl = _get_draw_list_ptr(p_list); DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl); ERR_FAIL_COND(!dl);

View File

@ -1155,6 +1155,7 @@ public:
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color);
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline);
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index); virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index);
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array); virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array);

View File

@ -37,7 +37,7 @@
#include "scene/resources/default_theme/default_theme.h" #include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/font.h" #include "scene/resources/font.h"
Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
Ref<FontFile> font; Ref<FontFile> font;
font.instantiate(); font.instantiate();
@ -45,7 +45,7 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin
font->set_data(data); font->set_data(data);
font->set_multichannel_signed_distance_field(p_msdf); font->set_multichannel_signed_distance_field(p_msdf);
font->set_antialiased(p_aa); font->set_antialiasing(p_aa);
font->set_hinting(p_hinting); font->set_hinting(p_hinting);
font->set_force_autohinter(p_autohint); font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning); font->set_subpixel_positioning(p_font_subpixel_positioning);
@ -57,13 +57,13 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin
return font; return font;
} }
Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
Ref<FontFile> font; Ref<FontFile> font;
font.instantiate(); font.instantiate();
font->set_data_ptr(p_data, p_size); font->set_data_ptr(p_data, p_size);
font->set_multichannel_signed_distance_field(p_msdf); font->set_multichannel_signed_distance_field(p_msdf);
font->set_antialiased(p_aa); font->set_antialiasing(p_aa);
font->set_hinting(p_hinting); font->set_hinting(p_hinting);
font->set_force_autohinter(p_autohint); font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning); font->set_subpixel_positioning(p_font_subpixel_positioning);
@ -91,7 +91,7 @@ Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, Ty
void editor_register_fonts(Ref<Theme> p_theme) { void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased"); TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EditorSettings::get_singleton()->get("interface/editor/font_antialiasing");
int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting"); int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting");
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning"); TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning");
@ -123,47 +123,47 @@ void editor_register_fonts(Ref<Theme> p_theme) {
const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE; const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
const float embolden_strength = 0.6; const float embolden_strength = 0.6;
Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false);
Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true);
TypedArray<Font> fallbacks; TypedArray<Font> fallbacks;
Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks);
default_font->set_fallbacks(fallbacks); default_font->set_fallbacks(fallbacks);
default_font_msdf->set_fallbacks(fallbacks); default_font_msdf->set_fallbacks(fallbacks);
Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false);
Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true);
TypedArray<Font> fallbacks_bold; TypedArray<Font> fallbacks_bold;
Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold);
Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold); Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold);
Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold); Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold);
default_font_bold->set_fallbacks(fallbacks_bold); default_font_bold->set_fallbacks(fallbacks_bold);
default_font_bold_msdf->set_fallbacks(fallbacks_bold); default_font_bold_msdf->set_fallbacks(fallbacks_bold);
Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning);
default_font_mono->set_fallbacks(fallbacks); default_font_mono->set_fallbacks(fallbacks);
// Init base font configs and load custom fonts. // Init base font configs and load custom fonts.
@ -174,7 +174,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontVariation> default_fc; Ref<FontVariation> default_fc;
default_fc.instantiate(); default_fc.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font); fallback_custom.push_back(default_font);
@ -191,7 +191,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontVariation> default_fc_msdf; Ref<FontVariation> default_fc_msdf;
default_fc_msdf.instantiate(); default_fc_msdf.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_msdf); fallback_custom.push_back(default_font_msdf);
@ -208,7 +208,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontVariation> bold_fc; Ref<FontVariation> bold_fc;
bold_fc.instantiate(); bold_fc.instantiate();
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold); fallback_custom.push_back(default_font_bold);
@ -216,7 +216,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
} }
bold_fc->set_base_font(custom_font); bold_fc->set_base_font(custom_font);
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold); fallback_custom.push_back(default_font_bold);
@ -234,7 +234,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontVariation> bold_fc_msdf; Ref<FontVariation> bold_fc_msdf;
bold_fc_msdf.instantiate(); bold_fc_msdf.instantiate();
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold_msdf); fallback_custom.push_back(default_font_bold_msdf);
@ -242,7 +242,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
} }
bold_fc_msdf->set_base_font(custom_font); bold_fc_msdf->set_base_font(custom_font);
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_bold_msdf); fallback_custom.push_back(default_font_bold_msdf);
@ -260,7 +260,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontVariation> mono_fc; Ref<FontVariation> mono_fc;
mono_fc.instantiate(); mono_fc.instantiate();
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) { if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiasing, true, font_subpixel_positioning);
{ {
TypedArray<Font> fallback_custom; TypedArray<Font> fallback_custom;
fallback_custom.push_back(default_font_mono); fallback_custom.push_back(default_font_mono);

View File

@ -172,6 +172,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["k1"] = "K1"; capitalize_string_remaps["k1"] = "K1";
capitalize_string_remaps["k2"] = "K2"; capitalize_string_remaps["k2"] = "K2";
capitalize_string_remaps["kb"] = "(KB)"; // Unit. capitalize_string_remaps["kb"] = "(KB)"; // Unit.
capitalize_string_remaps["lcd"] = "LCD";
capitalize_string_remaps["ldr"] = "LDR"; capitalize_string_remaps["ldr"] = "LDR";
capitalize_string_remaps["lod"] = "LOD"; capitalize_string_remaps["lod"] = "LOD";
capitalize_string_remaps["lowpass"] = "Low-pass"; capitalize_string_remaps["lowpass"] = "Low-pass";

View File

@ -414,7 +414,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set")
_initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_opentype_features", "");
_initial_set("interface/editor/code_font_custom_variations", ""); _initial_set("interface/editor/code_font_custom_variations", "");
_initial_set("interface/editor/font_antialiased", true); EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD sub-pixel")
#ifdef MACOS_ENABLED #ifdef MACOS_ENABLED
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal")
#else #else

View File

@ -449,8 +449,8 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
// Update font preview. // Update font preview.
if (font_preview.is_valid()) { if (font_preview.is_valid()) {
if (p_edited_property == "antialiased") { if (p_edited_property == "antialiasing") {
font_preview->set_antialiased(import_settings_data->get("antialiased")); font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int());
} else if (p_edited_property == "generate_mipmaps") { } else if (p_edited_property == "generate_mipmaps") {
font_preview->set_generate_mipmaps(import_settings_data->get("generate_mipmaps")); font_preview->set_generate_mipmaps(import_settings_data->get("generate_mipmaps"));
} else if (p_edited_property == "multichannel_signed_distance_field") { } else if (p_edited_property == "multichannel_signed_distance_field") {
@ -574,6 +574,12 @@ void DynamicFontImportSettings::_variations_validate() {
} }
} }
} }
if ((TextServer::FontAntialiasing)(int)import_settings_data->get("antialiasing") == TextServer::FONT_ANTIALIASING_LCD) {
warn += "\n" + TTR("Note: LCD sub-pixel anti-aliasing is selected, each of the glyphs will be pre-rendered for all supported sub-pixel layouts (5x).");
}
if ((TextServer::SubpixelPositioning)(int)import_settings_data->get("subpixel_positioning") != TextServer::SUBPIXEL_POSITIONING_DISABLED) {
warn += "\n" + TTR("Note: Sub-pixel positioning is selected, each of the glyphs might be pre-rendered for multiple sub-pixel offsets (up to 4x).");
}
if (warn.is_empty()) { if (warn.is_empty()) {
label_warn->set_text(""); label_warn->set_text("");
label_warn->hide(); label_warn->hide();
@ -881,7 +887,7 @@ void DynamicFontImportSettings::_re_import() {
HashMap<StringName, Variant> main_settings; HashMap<StringName, Variant> main_settings;
main_settings["face_index"] = import_settings_data->get("face_index"); main_settings["face_index"] = import_settings_data->get("face_index");
main_settings["antialiased"] = import_settings_data->get("antialiased"); main_settings["antialiasing"] = import_settings_data->get("antialiasing");
main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps"); main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps");
main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field"); main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field");
main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range"); main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range");
@ -1079,7 +1085,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
import_settings_data->notify_property_list_changed(); import_settings_data->notify_property_list_changed();
if (font_preview.is_valid()) { if (font_preview.is_valid()) {
font_preview->set_antialiased(import_settings_data->get("antialiased")); font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int());
font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field")); font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range")); font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
font_preview->set_msdf_size(import_settings_data->get("msdf_size")); font_preview->set_msdf_size(import_settings_data->get("msdf_size"));
@ -1108,7 +1114,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));

View File

@ -105,7 +105,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));
@ -139,7 +139,7 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) {
Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing dynamic font from: " + p_source_file); print_verbose("Importing dynamic font from: " + p_source_file);
bool antialiased = p_options["antialiased"]; int antialiasing = p_options["antialiasing"];
bool generate_mipmaps = p_options["generate_mipmaps"]; bool generate_mipmaps = p_options["generate_mipmaps"];
bool msdf = p_options["multichannel_signed_distance_field"]; bool msdf = p_options["multichannel_signed_distance_field"];
int px_range = p_options["msdf_pixel_range"]; int px_range = p_options["msdf_pixel_range"];
@ -159,7 +159,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
Ref<FontFile> font; Ref<FontFile> font;
font.instantiate(); font.instantiate();
font->set_data(data); font->set_data(data);
font->set_antialiased(antialiased); font->set_antialiasing((TextServer::FontAntialiasing)antialiasing);
font->set_generate_mipmaps(generate_mipmaps); font->set_generate_mipmaps(generate_mipmaps);
font->set_multichannel_signed_distance_field(msdf); font->set_multichannel_signed_distance_field(msdf);
font->set_msdf_pixel_range(px_range); font->set_msdf_pixel_range(px_range);

View File

@ -99,7 +99,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
Ref<FontFile> font; Ref<FontFile> font;
font.instantiate(); font.instantiate();
font->set_antialiased(false); font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE);
font->set_generate_mipmaps(false); font->set_generate_mipmaps(false);
font->set_multichannel_signed_distance_field(false); font->set_multichannel_signed_distance_field(false);
font->set_fixed_size(base_size); font->set_fixed_size(base_size);

View File

@ -29,12 +29,12 @@
/*************************************************************************/ /*************************************************************************/
#include "text_server_adv.h" #include "text_server_adv.h"
#include "core/object/worker_thread_pool.h"
#ifdef GDEXTENSION #ifdef GDEXTENSION
// Headers for building as GDExtension plug-in. // Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file.hpp> #include <godot_cpp/classes/file.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/classes/translation_server.hpp>
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
@ -44,8 +44,10 @@ using namespace godot;
#else #else
// Headers for building as built-in module. // Headers for building as built-in module.
#include "core/config/project_settings.h"
#include "core/core_bind.h" #include "core/core_bind.h"
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/object/worker_thread_pool.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "core/string/translation.h" #include "core/string/translation.h"
@ -791,6 +793,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
for (int i = 0; i < p_data->textures.size(); i++) { for (int i = 0; i < p_data->textures.size(); i++) {
const FontTexture &ct = p_data->textures[i]; const FontTexture &ct = p_data->textures[i];
if (p_image_format != ct.format) {
continue;
}
if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture.
continue; continue;
} }
@ -1082,9 +1088,28 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
#endif #endif
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const {
int w = bitmap.width; int w = bitmap.width;
int h = bitmap.rows; int h = bitmap.rows;
int color_size = 2;
switch (bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO:
case FT_PIXEL_MODE_GRAY: {
color_size = 2;
} break;
case FT_PIXEL_MODE_BGRA: {
color_size = 4;
} break;
case FT_PIXEL_MODE_LCD: {
color_size = 4;
w /= 3;
} break;
case FT_PIXEL_MODE_LCD_V: {
color_size = 4;
h /= 3;
} break;
}
int mw = w + p_rect_margin * 4; int mw = w + p_rect_margin * 4;
int mh = h + p_rect_margin * 4; int mh = h + p_rect_margin * 4;
@ -1092,7 +1117,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
@ -1127,6 +1151,34 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 0] = bitmap.buffer[ofs_color + 2];
wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3];
} break; } break;
case FT_PIXEL_MODE_LCD: {
int ofs_color = i * bitmap.pitch + (j * 3);
if (p_bgra) {
wr[ofs + 0] = bitmap.buffer[ofs_color + 0];
wr[ofs + 1] = bitmap.buffer[ofs_color + 1];
wr[ofs + 2] = bitmap.buffer[ofs_color + 2];
wr[ofs + 3] = 255;
} else {
wr[ofs + 0] = bitmap.buffer[ofs_color + 2];
wr[ofs + 1] = bitmap.buffer[ofs_color + 1];
wr[ofs + 2] = bitmap.buffer[ofs_color + 0];
wr[ofs + 3] = 255;
}
} break;
case FT_PIXEL_MODE_LCD_V: {
int ofs_color = i * bitmap.pitch * 3 + j;
if (p_bgra) {
wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2];
wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch];
wr[ofs + 2] = bitmap.buffer[ofs_color + 0];
wr[ofs + 3] = 255;
} else {
wr[ofs + 0] = bitmap.buffer[ofs_color + 0];
wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch];
wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2];
wr[ofs + 3] = 255;
}
} break;
default: default:
ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + ".");
break; break;
@ -1230,9 +1282,44 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data,
FT_Outline_Transform(&fd->face->glyph->outline, &mat); FT_Outline_Transform(&fd->face->glyph->outline, &mat);
} }
FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL;
bool bgra = false;
switch (p_font_data->antialiasing) {
case FONT_ANTIALIASING_NONE: {
aa_mode = FT_RENDER_MODE_MONO;
} break;
case FONT_ANTIALIASING_GRAY: {
aa_mode = FT_RENDER_MODE_NORMAL;
} break;
case FONT_ANTIALIASING_LCD: {
int aa_layout = (int)((p_glyph >> 24) & 7);
switch (aa_layout) {
case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: {
aa_mode = FT_RENDER_MODE_LCD;
bgra = false;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: {
aa_mode = FT_RENDER_MODE_LCD;
bgra = true;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: {
aa_mode = FT_RENDER_MODE_LCD_V;
bgra = false;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: {
aa_mode = FT_RENDER_MODE_LCD_V;
bgra = true;
} break;
default: {
aa_mode = FT_RENDER_MODE_NORMAL;
} break;
}
} break;
}
if (!outline) { if (!outline) {
if (!p_font_data->msdf) { if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); error = FT_Render_Glyph(fd->face->glyph, aa_mode);
} }
FT_GlyphSlot slot = fd->face->glyph; FT_GlyphSlot slot = fd->face->glyph;
if (!error) { if (!error) {
@ -1244,7 +1331,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data,
ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!");
#endif #endif
} else { } else {
gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra);
} }
} }
} else { } else {
@ -1264,11 +1351,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data,
if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) {
goto cleanup_glyph; goto cleanup_glyph;
} }
if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) {
goto cleanup_glyph; goto cleanup_glyph;
} }
glyph_bitmap = (FT_BitmapGlyph)glyph; glyph_bitmap = (FT_BitmapGlyph)glyph;
gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra);
cleanup_glyph: cleanup_glyph:
FT_Done_Glyph(glyph); FT_Done_Glyph(glyph);
@ -1925,23 +2012,23 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const {
return fd->font_name; return fd->font_name;
} }
void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { void TextServerAdvanced::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) {
FontAdvanced *fd = font_owner.get_or_null(p_font_rid); FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
if (fd->antialiased != p_antialiased) { if (fd->antialiasing != p_antialiasing) {
_font_clear_cache(fd); _font_clear_cache(fd);
fd->antialiased = p_antialiased; fd->antialiasing = p_antialiasing;
} }
} }
bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { TextServer::FontAntialiasing TextServerAdvanced::font_get_antialiasing(RID p_font_rid) const {
FontAdvanced *fd = font_owner.get_or_null(p_font_rid); FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
return fd->antialiased; return fd->antialiasing;
} }
void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
@ -2514,7 +2601,16 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_
Vector2i size = _get_size(fd, p_size); Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2557,7 +2653,16 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const V
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2593,7 +2698,16 @@ Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vec
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2629,7 +2743,16 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Rect2(); // Invalid or non graphicl glyph, do not display errors. return Rect2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2660,7 +2783,16 @@ int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, co
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1);
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return -1; // Invalid or non graphicl glyph, do not display errors. return -1; // Invalid or non graphicl glyph, do not display errors.
} }
@ -2691,7 +2823,16 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return RID(); // Invalid or non graphicl glyph, do not display errors. return RID(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2730,7 +2871,16 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Size2(); // Invalid or non graphicl glyph, do not display errors. return Size2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2986,16 +3136,18 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i
if (fd->msdf) { if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx); _ensure_glyph(fd, size, (int32_t)idx);
} else { } else {
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
} else { _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx); } else {
_ensure_glyph(fd, size, (int32_t)idx | (aa << 24));
}
} }
} }
} }
@ -3016,16 +3168,18 @@ void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i
if (fd->msdf) { if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx); _ensure_glyph(fd, size, (int32_t)idx);
} else { } else {
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
} else { _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx); } else {
_ensure_glyph(fd, size, (int32_t)idx | (aa << 24));
}
} }
} }
} }
@ -3041,9 +3195,19 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts. int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (!fd->msdf && fd->cache[size]->face) { if (!fd->msdf && fd->cache[size]->face) {
// LCD layout, bits 24, 25, 26
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
lcd_aa = true;
index = index | (layout << 24);
}
}
// Subpixel X-shift, bits 27, 28
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
index = index | (xshift << 27); index = index | (xshift << 27);
@ -3065,7 +3229,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
if (gl.texture_idx != -1) { if (gl.texture_idx != -1) {
Color modulate = p_color; Color modulate = p_color;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) {
modulate.r = modulate.g = modulate.b = 1.0; modulate.r = modulate.g = modulate.b = 1.0;
} }
#endif #endif
@ -3103,7 +3267,11 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
} }
cpos += gl.rect.position; cpos += gl.rect.position;
Size2 csize = gl.rect.size; Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); if (lcd_aa) {
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate);
} else {
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
} }
} }
} }
@ -3119,9 +3287,19 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts. int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (!fd->msdf && fd->cache[size]->face) { if (!fd->msdf && fd->cache[size]->face) {
// LCD layout, bits 24, 25, 26
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
lcd_aa = true;
index = index | (layout << 24);
}
}
// Subpixel X-shift, bits 27, 28
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
index = index | (xshift << 27); index = index | (xshift << 27);
@ -3181,7 +3359,11 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
} }
cpos += gl.rect.position; cpos += gl.rect.position;
Size2 csize = gl.rect.size; Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); if (lcd_aa) {
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate);
} else {
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
} }
} }
} }
@ -4947,6 +5129,14 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(p_sd->hb_buffer, &glyph_count); hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(p_sd->hb_buffer, &glyph_count);
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count);
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
// Process glyphs. // Process glyphs.
if (glyph_count > 0) { if (glyph_count > 0) {
Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph)); Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph));
@ -5000,7 +5190,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
gl.index = glyph_info[i].codepoint; gl.index = glyph_info[i].codepoint;
if (gl.index != 0) { if (gl.index != 0) {
_ensure_glyph(fd, fss, gl.index); _ensure_glyph(fd, fss, gl.index | mod);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
if (subpos) { if (subpos) {
gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea; gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea;

View File

@ -223,7 +223,7 @@ class TextServerAdvanced : public TextServerExtension {
struct FontAdvanced { struct FontAdvanced {
Mutex mutex; Mutex mutex;
bool antialiased = true; TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false; bool mipmaps = false;
bool msdf = false; bool msdf = false;
int msdf_range = 14; int msdf_range = 14;
@ -271,7 +271,7 @@ class TextServerAdvanced : public TextServerExtension {
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif #endif
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const;
#endif #endif
_FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const;
@ -498,8 +498,8 @@ public:
virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual void font_set_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_name(const RID &p_font_rid) const override; virtual String font_get_name(const RID &p_font_rid) const override;
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
virtual bool font_is_antialiased(const RID &p_font_rid) const override; virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override;
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;

View File

@ -34,6 +34,7 @@
// Headers for building as GDExtension plug-in. // Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file.hpp> #include <godot_cpp/classes/file.hpp>
#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/classes/translation_server.hpp>
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
@ -43,6 +44,7 @@ using namespace godot;
#else #else
// Headers for building as built-in module. // Headers for building as built-in module.
#include "core/config/project_settings.h"
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "core/string/ucaps.h" #include "core/string/ucaps.h"
@ -209,6 +211,10 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
for (int i = 0; i < p_data->textures.size(); i++) { for (int i = 0; i < p_data->textures.size(); i++) {
const FontTexture &ct = p_data->textures[i]; const FontTexture &ct = p_data->textures[i];
if (p_image_format != ct.format) {
continue;
}
if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture.
continue; continue;
} }
@ -500,9 +506,28 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
#endif #endif
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const {
int w = bitmap.width; int w = bitmap.width;
int h = bitmap.rows; int h = bitmap.rows;
int color_size = 2;
switch (bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO:
case FT_PIXEL_MODE_GRAY: {
color_size = 2;
} break;
case FT_PIXEL_MODE_BGRA: {
color_size = 4;
} break;
case FT_PIXEL_MODE_LCD: {
color_size = 4;
w /= 3;
} break;
case FT_PIXEL_MODE_LCD_V: {
color_size = 4;
h /= 3;
} break;
}
int mw = w + p_rect_margin * 4; int mw = w + p_rect_margin * 4;
int mh = h + p_rect_margin * 4; int mh = h + p_rect_margin * 4;
@ -510,7 +535,6 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
@ -545,6 +569,34 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 0] = bitmap.buffer[ofs_color + 2];
wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3];
} break; } break;
case FT_PIXEL_MODE_LCD: {
int ofs_color = i * bitmap.pitch + (j * 3);
if (p_bgra) {
wr[ofs + 0] = bitmap.buffer[ofs_color + 0];
wr[ofs + 1] = bitmap.buffer[ofs_color + 1];
wr[ofs + 2] = bitmap.buffer[ofs_color + 2];
wr[ofs + 3] = 255;
} else {
wr[ofs + 0] = bitmap.buffer[ofs_color + 2];
wr[ofs + 1] = bitmap.buffer[ofs_color + 1];
wr[ofs + 2] = bitmap.buffer[ofs_color + 0];
wr[ofs + 3] = 255;
}
} break;
case FT_PIXEL_MODE_LCD_V: {
int ofs_color = i * bitmap.pitch * 3 + j;
if (p_bgra) {
wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2];
wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch];
wr[ofs + 2] = bitmap.buffer[ofs_color + 0];
wr[ofs + 3] = 255;
} else {
wr[ofs + 0] = bitmap.buffer[ofs_color + 0];
wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch];
wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2];
wr[ofs + 3] = 255;
}
} break;
default: default:
ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + ".");
break; break;
@ -650,9 +702,44 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data,
FT_Outline_Transform(&fd->face->glyph->outline, &mat); FT_Outline_Transform(&fd->face->glyph->outline, &mat);
} }
FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL;
bool bgra = false;
switch (p_font_data->antialiasing) {
case FONT_ANTIALIASING_NONE: {
aa_mode = FT_RENDER_MODE_MONO;
} break;
case FONT_ANTIALIASING_GRAY: {
aa_mode = FT_RENDER_MODE_NORMAL;
} break;
case FONT_ANTIALIASING_LCD: {
int aa_layout = (int)((p_glyph >> 24) & 7);
switch (aa_layout) {
case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: {
aa_mode = FT_RENDER_MODE_LCD;
bgra = false;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: {
aa_mode = FT_RENDER_MODE_LCD;
bgra = true;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: {
aa_mode = FT_RENDER_MODE_LCD_V;
bgra = false;
} break;
case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: {
aa_mode = FT_RENDER_MODE_LCD_V;
bgra = true;
} break;
default: {
aa_mode = FT_RENDER_MODE_NORMAL;
} break;
}
} break;
}
if (!outline) { if (!outline) {
if (!p_font_data->msdf) { if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); error = FT_Render_Glyph(fd->face->glyph, aa_mode);
} }
FT_GlyphSlot slot = fd->face->glyph; FT_GlyphSlot slot = fd->face->glyph;
if (!error) { if (!error) {
@ -664,7 +751,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data,
ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!");
#endif #endif
} else { } else {
gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra);
} }
} }
} else { } else {
@ -684,11 +771,11 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data,
if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) {
goto cleanup_glyph; goto cleanup_glyph;
} }
if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) {
goto cleanup_glyph; goto cleanup_glyph;
} }
glyph_bitmap = (FT_BitmapGlyph)glyph; glyph_bitmap = (FT_BitmapGlyph)glyph;
gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra);
cleanup_glyph: cleanup_glyph:
FT_Done_Glyph(glyph); FT_Done_Glyph(glyph);
@ -1014,23 +1101,23 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const {
return fd->font_name; return fd->font_name;
} }
void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { void TextServerFallback::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) {
FontFallback *fd = font_owner.get_or_null(p_font_rid); FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
if (fd->antialiased != p_antialiased) { if (fd->antialiasing != p_antialiasing) {
_font_clear_cache(fd); _font_clear_cache(fd);
fd->antialiased = p_antialiased; fd->antialiasing = p_antialiasing;
} }
} }
bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { TextServer::FontAntialiasing TextServerFallback::font_get_antialiasing(RID p_font_rid) const {
FontFallback *fd = font_owner.get_or_null(p_font_rid); FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
return fd->antialiased; return fd->antialiasing;
} }
void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
@ -1589,7 +1676,16 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_
Vector2i size = _get_size(fd, p_size); Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -1632,7 +1728,16 @@ Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const V
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -1668,7 +1773,16 @@ Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vec
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Vector2(); // Invalid or non graphicl glyph, do not display errors. return Vector2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -1704,7 +1818,16 @@ Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Rect2(); // Invalid or non graphicl glyph, do not display errors. return Rect2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -1735,7 +1858,16 @@ int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, co
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1);
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return -1; // Invalid or non graphicl glyph, do not display errors. return -1; // Invalid or non graphicl glyph, do not display errors.
} }
@ -1766,7 +1898,16 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return RID(); // Invalid or non graphicl glyph, do not display errors. return RID(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -1805,7 +1946,16 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con
Vector2i size = _get_size_outline(fd, p_size); Vector2i size = _get_size_outline(fd, p_size);
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2());
if (!_ensure_glyph(fd, size, p_glyph)) {
int mod = 0;
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
mod = (layout << 24);
}
}
if (!_ensure_glyph(fd, size, p_glyph | mod)) {
return Size2(); // Invalid or non graphicl glyph, do not display errors. return Size2(); // Invalid or non graphicl glyph, do not display errors.
} }
@ -2043,16 +2193,18 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i
if (fd->msdf) { if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx); _ensure_glyph(fd, size, (int32_t)idx);
} else { } else {
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
} else { _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx); } else {
_ensure_glyph(fd, size, (int32_t)idx | (aa << 24));
}
} }
} }
} }
@ -2073,16 +2225,18 @@ void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i
if (fd->msdf) { if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx); _ensure_glyph(fd, size, (int32_t)idx);
} else { } else {
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
_ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
} else { _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
_ensure_glyph(fd, size, (int32_t)idx); } else {
_ensure_glyph(fd, size, (int32_t)idx | (aa << 24));
}
} }
} }
} }
@ -2098,9 +2252,19 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts. int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (!fd->msdf && fd->cache[size]->face) { if (!fd->msdf && fd->cache[size]->face) {
// LCD layout, bits 24, 25, 26
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
lcd_aa = true;
index = index | (layout << 24);
}
}
// Subpixel X-shift, bits 27, 28
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
index = index | (xshift << 27); index = index | (xshift << 27);
@ -2122,7 +2286,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
if (gl.texture_idx != -1) { if (gl.texture_idx != -1) {
Color modulate = p_color; Color modulate = p_color;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) {
modulate.r = modulate.g = modulate.b = 1.0; modulate.r = modulate.g = modulate.b = 1.0;
} }
#endif #endif
@ -2160,7 +2324,11 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
} }
cpos += gl.rect.position; cpos += gl.rect.position;
Size2 csize = gl.rect.size; Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); if (lcd_aa) {
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate);
} else {
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
} }
} }
} }
@ -2176,9 +2344,19 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts. int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
if (!fd->msdf && fd->cache[size]->face) { if (!fd->msdf && fd->cache[size]->face) {
// LCD layout, bits 24, 25, 26
if (fd->antialiasing == FONT_ANTIALIASING_LCD) {
TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout");
if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) {
lcd_aa = true;
index = index | (layout << 24);
}
}
// Subpixel X-shift, bits 27, 28
if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
index = index | (xshift << 27); index = index | (xshift << 27);
@ -2238,7 +2416,11 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
} }
cpos += gl.rect.position; cpos += gl.rect.position;
Size2 csize = gl.rect.size; Size2 csize = gl.rect.size;
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); if (lcd_aa) {
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate);
} else {
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false);
}
} }
} }
} }

View File

@ -179,7 +179,7 @@ class TextServerFallback : public TextServerExtension {
struct FontFallback { struct FontFallback {
Mutex mutex; Mutex mutex;
bool antialiased = true; TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false; bool mipmaps = false;
bool msdf = false; bool msdf = false;
int msdf_range = 14; int msdf_range = 14;
@ -225,7 +225,7 @@ class TextServerFallback : public TextServerExtension {
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif #endif
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const;
#endif #endif
_FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
_FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const;
@ -378,8 +378,8 @@ public:
virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual void font_set_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_name(const RID &p_font_rid) const override; virtual String font_get_name(const RID &p_font_rid) const override;
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
virtual bool font_is_antialiased(const RID &p_font_rid) const override; virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override;
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;

View File

@ -587,6 +587,12 @@ void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture,
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range);
} }
void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_texture.is_null());
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate);
}
void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@ -919,6 +925,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0)); ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0));
ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box); ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>())); ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));

View File

@ -226,6 +226,7 @@ public:
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0); void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0);
void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1); void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1);
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>()); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());

View File

@ -1130,8 +1130,8 @@ void initialize_theme() {
String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", "");
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true); TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT); TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
@ -1142,6 +1142,10 @@ void initialize_theme() {
const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false); const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false);
const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false); const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false);
GLOBAL_DEF_RST("gui/theme/lcd_subpixel_layout", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/lcd_subpixel_layout", PropertyInfo(Variant::INT, "gui/theme/lcd_subpixel_layout", PROPERTY_HINT_ENUM, "Disabled,Horizontal RGB,Horizontal BGR,Vertical RGB,Vertical BGR"));
ProjectSettings::get_singleton()->set_restart_if_changed("gui/theme/lcd_subpixel_layout", false);
Ref<Font> font; Ref<Font> font;
if (!font_path.is_empty()) { if (!font_path.is_empty()) {
font = ResourceLoader::load(font_path); font = ResourceLoader::load(font_path);
@ -1152,7 +1156,7 @@ void initialize_theme() {
// Always make the default theme to avoid invalid default font/icon/style in the given theme. // Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) { if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased, font_msdf, font_generate_mipmaps); make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiasing, font_msdf, font_generate_mipmaps);
} }
if (!theme_path.is_empty()) { if (!theme_path.is_empty()) {

View File

@ -1053,7 +1053,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2);
} }
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, bool p_font_antialiased, bool p_font_msdf, bool p_font_generate_mipmaps) { void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, TextServer::FontAntialiasing p_font_antialiasing, bool p_font_msdf, bool p_font_generate_mipmaps) {
Ref<Theme> t; Ref<Theme> t;
t.instantiate(); t.instantiate();
@ -1077,7 +1077,7 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
dynamic_font->set_subpixel_positioning(p_font_subpixel); dynamic_font->set_subpixel_positioning(p_font_subpixel);
dynamic_font->set_hinting(p_font_hinting); dynamic_font->set_hinting(p_font_hinting);
dynamic_font->set_antialiased(p_font_antialiased); dynamic_font->set_antialiasing(p_font_antialiasing);
dynamic_font->set_multichannel_signed_distance_field(p_font_msdf); dynamic_font->set_multichannel_signed_distance_field(p_font_msdf);
dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps); dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps);

View File

@ -36,7 +36,7 @@
const int default_font_size = 16; const int default_font_size = 16;
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false);
void clear_default_theme(); void clear_default_theme();
#endif // DEFAULT_THEME_H #endif // DEFAULT_THEME_H

View File

@ -576,7 +576,7 @@ _FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index) const {
if (unlikely(!cache[p_cache_index].is_valid())) { if (unlikely(!cache[p_cache_index].is_valid())) {
cache.write[p_cache_index] = TS->create_font(); cache.write[p_cache_index] = TS->create_font();
TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size); TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
TS->font_set_antialiased(cache[p_cache_index], antialiased); TS->font_set_antialiasing(cache[p_cache_index], antialiasing);
TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps); TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf); TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range); TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range);
@ -875,8 +875,8 @@ void FontFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name); ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name);
ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style); ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style);
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontFile::set_antialiased); ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &FontFile::set_antialiasing);
ClassDB::bind_method(D_METHOD("is_antialiased"), &FontFile::is_antialiased); ClassDB::bind_method(D_METHOD("get_antialiasing"), &FontFile::get_antialiasing);
ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps);
@ -996,7 +996,7 @@ void FontFile::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased"); ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
@ -1318,7 +1318,7 @@ void FontFile::reset_state() {
data_size = 0; data_size = 0;
cache.clear(); cache.clear();
antialiased = true; antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
mipmaps = false; mipmaps = false;
msdf = false; msdf = false;
force_autohinter = false; force_autohinter = false;
@ -1337,7 +1337,7 @@ void FontFile::reset_state() {
Error FontFile::load_bitmap_font(const String &p_path) { Error FontFile::load_bitmap_font(const String &p_path) {
reset_state(); reset_state();
antialiased = false; antialiasing = TextServer::FONT_ANTIALIASING_NONE;
mipmaps = false; mipmaps = false;
msdf = false; msdf = false;
force_autohinter = false; force_autohinter = false;
@ -1864,19 +1864,19 @@ void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) {
TS->font_set_style(cache[0], p_style); TS->font_set_style(cache[0], p_style);
} }
void FontFile::set_antialiased(bool p_antialiased) { void FontFile::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) {
if (antialiased != p_antialiased) { if (antialiasing != p_antialiasing) {
antialiased = p_antialiased; antialiasing = p_antialiasing;
for (int i = 0; i < cache.size(); i++) { for (int i = 0; i < cache.size(); i++) {
_ensure_rid(i); _ensure_rid(i);
TS->font_set_antialiased(cache[i], antialiased); TS->font_set_antialiasing(cache[i], antialiasing);
} }
emit_changed(); emit_changed();
} }
} }
bool FontFile::is_antialiased() const { TextServer::FontAntialiasing FontFile::get_antialiasing() const {
return antialiased; return antialiasing;
} }
void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) { void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) {
@ -2699,8 +2699,8 @@ FontVariation::~FontVariation() {
/*************************************************************************/ /*************************************************************************/
void SystemFont::_bind_methods() { void SystemFont::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased); ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &SystemFont::set_antialiasing);
ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased); ClassDB::bind_method(D_METHOD("get_antialiasing"), &SystemFont::get_antialiasing);
ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps);
@ -2727,7 +2727,7 @@ void SystemFont::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased"); ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
@ -2804,7 +2804,7 @@ void SystemFont::_update_base_font() {
} }
// Apply font rendering settings. // Apply font rendering settings.
file->set_antialiased(antialiased); file->set_antialiasing(antialiasing);
file->set_generate_mipmaps(mipmaps); file->set_generate_mipmaps(mipmaps);
file->set_force_autohinter(force_autohinter); file->set_force_autohinter(force_autohinter);
file->set_hinting(hinting); file->set_hinting(hinting);
@ -2841,7 +2841,7 @@ void SystemFont::reset_state() {
ftr_weight = 0; ftr_weight = 0;
ftr_italic = 0; ftr_italic = 0;
style = 0; style = 0;
antialiased = true; antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
mipmaps = false; mipmaps = false;
force_autohinter = false; force_autohinter = false;
hinting = TextServer::HINTING_LIGHT; hinting = TextServer::HINTING_LIGHT;
@ -2907,18 +2907,18 @@ Ref<Font> SystemFont::_get_base_font_or_default() const {
return Ref<Font>(); return Ref<Font>();
} }
void SystemFont::set_antialiased(bool p_antialiased) { void SystemFont::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) {
if (antialiased != p_antialiased) { if (antialiasing != p_antialiasing) {
antialiased = p_antialiased; antialiasing = p_antialiasing;
if (base_font.is_valid()) { if (base_font.is_valid()) {
base_font->set_antialiased(antialiased); base_font->set_antialiasing(antialiasing);
} }
emit_changed(); emit_changed();
} }
} }
bool SystemFont::is_antialiased() const { TextServer::FontAntialiasing SystemFont::get_antialiasing() const {
return antialiased; return antialiasing;
} }
void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) { void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) {

View File

@ -141,7 +141,7 @@ class FontFile : public Font {
size_t data_size = 0; size_t data_size = 0;
PackedByteArray data; PackedByteArray data;
bool antialiased = true; TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false; bool mipmaps = false;
bool msdf = false; bool msdf = false;
int msdf_pixel_range = 16; int msdf_pixel_range = 16;
@ -192,8 +192,8 @@ public:
virtual void set_font_style_name(const String &p_name); virtual void set_font_style_name(const String &p_name);
virtual void set_font_style(BitField<TextServer::FontStyle> p_style); virtual void set_font_style(BitField<TextServer::FontStyle> p_style);
virtual void set_antialiased(bool p_antialiased); virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing);
virtual bool is_antialiased() const; virtual TextServer::FontAntialiasing get_antialiasing() const;
virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual void set_generate_mipmaps(bool p_generate_mipmaps);
virtual bool get_generate_mipmaps() const; virtual bool get_generate_mipmaps() const;
@ -398,7 +398,7 @@ class SystemFont : public Font {
int ftr_weight = 0; int ftr_weight = 0;
int ftr_italic = 0; int ftr_italic = 0;
bool antialiased = true; TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false; bool mipmaps = false;
bool force_autohinter = false; bool force_autohinter = false;
TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
@ -417,8 +417,8 @@ protected:
public: public:
virtual Ref<Font> _get_base_font_or_default() const; virtual Ref<Font> _get_base_font_or_default() const;
virtual void set_antialiased(bool p_antialiased); virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing);
virtual bool is_antialiased() const; virtual TextServer::FontAntialiasing get_antialiasing() const;
virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual void set_generate_mipmaps(bool p_generate_mipmaps);
virtual bool get_generate_mipmaps() const; virtual bool get_generate_mipmaps() const;

View File

@ -1183,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->px_range = p_px_range; rect->px_range = p_px_range;
} }
void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) {
Item *canvas_item = canvas_item_owner.get_or_null(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_LCD;
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;
}
}
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) { 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.get_or_null(p_item); Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item); ERR_FAIL_COND(!canvas_item);

View File

@ -225,6 +225,7 @@ public:
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(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_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_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_lcd_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));
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_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_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()); 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());

View File

@ -46,6 +46,7 @@ public:
CANVAS_RECT_CLIP_UV = 32, CANVAS_RECT_CLIP_UV = 32,
CANVAS_RECT_IS_GROUP = 64, CANVAS_RECT_IS_GROUP = 64,
CANVAS_RECT_MSDF = 128, CANVAS_RECT_MSDF = 128,
CANVAS_RECT_LCD = 256,
}; };
struct Light { struct Light {
@ -193,7 +194,7 @@ public:
Rect2 rect; Rect2 rect;
Color modulate; Color modulate;
Rect2 source; Rect2 source;
uint8_t flags; uint16_t flags;
float outline; float outline;
float px_range; float px_range;

View File

@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
} }
//bind pipeline //bind pipeline
{ if (rect->flags & CANVAS_RECT_LCD) {
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate);
} else {
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
} }
@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.msdf[1] = rect->outline; // Outline size. push_constant.msdf[1] = rect->outline; // Outline size.
push_constant.msdf[2] = 0.f; // Reserved. push_constant.msdf[2] = 0.f; // Reserved.
push_constant.msdf[3] = 0.f; // Reserved. push_constant.msdf[3] = 0.f; // Reserved.
} else if (rect->flags & CANVAS_RECT_LCD) {
push_constant.flags |= FLAGS_USE_LCD;
} }
push_constant.modulation[0] = rect->modulate.r * base_color.r; push_constant.modulation[0] = rect->modulate.r * base_color.r;
@ -2113,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::PipelineColorBlendState blend_state; RD::PipelineColorBlendState blend_state;
blend_state.attachments.push_back(attachment); blend_state.attachments.push_back(attachment);
RD::PipelineColorBlendState::Attachment attachment_lcd;
attachment_lcd.enable_blend = true;
attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
RD::PipelineColorBlendState blend_state_lcd;
blend_state_lcd.attachments.push_back(attachment_lcd);
//update pipelines //update pipelines
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
@ -2128,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS, RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_TRIANGLES,
}; };
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
{ //non lit {
//non lit
SHADER_VARIANT_QUAD, SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE, SHADER_VARIANT_PRIMITIVE,
@ -2141,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES_POINTS }, SHADER_VARIANT_ATTRIBUTES_POINTS,
{ //lit SHADER_VARIANT_QUAD,
},
{
//lit
SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT,
@ -2152,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
SHADER_VARIANT_QUAD_LIGHT,
},
}; };
RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
} else {
pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
}
} }
} }
@ -2363,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
blend_state.attachments.push_back(blend_attachment); blend_state.attachments.push_back(blend_attachment);
RD::PipelineColorBlendState::Attachment attachment_lcd;
attachment_lcd.enable_blend = true;
attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
RD::PipelineColorBlendState blend_state_lcd;
blend_state_lcd.attachments.push_back(attachment_lcd);
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@ -2376,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS, RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_TRIANGLES,
}; };
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
{ //non lit {
//non lit
SHADER_VARIANT_QUAD, SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE, SHADER_VARIANT_PRIMITIVE,
@ -2389,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES_POINTS }, SHADER_VARIANT_ATTRIBUTES_POINTS,
{ //lit SHADER_VARIANT_QUAD,
},
{
//lit
SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT,
@ -2400,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
SHADER_VARIANT_QUAD_LIGHT,
},
}; };
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
} else {
shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
}
} }
} }
} }

View File

@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
FLAGS_USE_MSDF = (1 << 28), FLAGS_USE_MSDF = (1 << 28),
FLAGS_USE_LCD = (1 << 29),
}; };
enum { enum {
@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES,
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_POINTS,
PIPELINE_VARIANT_QUAD_LCD_BLEND,
PIPELINE_VARIANT_MAX PIPELINE_VARIANT_MAX
}; };
enum PipelineLightMode { enum PipelineLightMode {

View File

@ -509,7 +509,13 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0); float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a; color.a = a * color.a;
} }
} else if (bool(draw_data.flags & FLAGS_USE_LCD)) {
vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv);
if (lcd_sample.a == 1.0) {
color.rgb = lcd_sample.rgb * color.a;
} else {
color = vec4(0.0, 0.0, 0.0, 0.0);
}
} else { } else {
#else #else
{ {

View File

@ -25,6 +25,7 @@
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
#define FLAGS_USE_MSDF (1 << 28) #define FLAGS_USE_MSDF (1 << 28)
#define FLAGS_USE_LCD (1 << 29)
#define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1 #define SAMPLER_LINEAR_CLAMP 1

View File

@ -429,6 +429,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants);
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array); ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);

View File

@ -1129,6 +1129,7 @@ public:
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0;
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0;

View File

@ -831,6 +831,7 @@ public:
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) 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_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) FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) 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) 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) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)

View File

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

View File

@ -1323,6 +1323,7 @@ public:
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(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_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_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_lcd_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)) = 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_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_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; 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;

View File

@ -69,8 +69,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style"); GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style");
GDVIRTUAL_BIND(font_get_style_name, "font_rid"); GDVIRTUAL_BIND(font_get_style_name, "font_rid");
GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); GDVIRTUAL_BIND(font_set_antialiasing, "font_rid", "antialiasing");
GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); GDVIRTUAL_BIND(font_get_antialiasing, "font_rid");
GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps"); GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid"); GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid");
@ -478,16 +478,16 @@ String TextServerExtension::font_get_name(const RID &p_font_rid) const {
return String(); return String();
} }
void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { void TextServerExtension::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) {
GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased); GDVIRTUAL_CALL(font_set_antialiasing, p_font_rid, p_antialiasing);
} }
bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(RID p_font_rid) const {
bool ret; TextServer::FontAntialiasing ret;
if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) { if (GDVIRTUAL_CALL(font_get_antialiasing, p_font_rid, ret)) {
return ret; return ret;
} }
return false; return TextServer::FONT_ANTIALIASING_NONE;
} }
void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {

View File

@ -107,10 +107,10 @@ public:
GDVIRTUAL2(font_set_style_name, RID, const String &); GDVIRTUAL2(font_set_style_name, RID, const String &);
GDVIRTUAL1RC(String, font_get_style_name, RID); GDVIRTUAL1RC(String, font_get_style_name, RID);
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
virtual bool font_is_antialiased(const RID &p_font_rid) const override; virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override;
GDVIRTUAL2(font_set_antialiased, RID, bool); GDVIRTUAL2(font_set_antialiasing, RID, TextServer::FontAntialiasing);
GDVIRTUAL1RC(bool, font_is_antialiased, RID); GDVIRTUAL1RC(TextServer::FontAntialiasing, font_get_antialiasing, RID);
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;

View File

@ -222,8 +222,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps); ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps); ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
@ -457,6 +457,17 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
/* Font AA */
BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE);
BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY);
BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD);
BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE);
BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB);
BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR);
BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB);
BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR);
/* Direction */ /* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR); BIND_ENUM_CONSTANT(DIRECTION_LTR);

View File

@ -44,6 +44,21 @@ class TextServer : public RefCounted {
GDCLASS(TextServer, RefCounted); GDCLASS(TextServer, RefCounted);
public: public:
enum FontAntialiasing {
FONT_ANTIALIASING_NONE,
FONT_ANTIALIASING_GRAY,
FONT_ANTIALIASING_LCD,
};
enum FontLCDSubpixelLayout {
FONT_LCD_SUBPIXEL_LAYOUT_NONE,
FONT_LCD_SUBPIXEL_LAYOUT_HRGB,
FONT_LCD_SUBPIXEL_LAYOUT_HBGR,
FONT_LCD_SUBPIXEL_LAYOUT_VRGB,
FONT_LCD_SUBPIXEL_LAYOUT_VBGR,
FONT_LCD_SUBPIXEL_LAYOUT_MAX,
};
enum Direction { enum Direction {
DIRECTION_AUTO, DIRECTION_AUTO,
DIRECTION_LTR, DIRECTION_LTR,
@ -230,8 +245,8 @@ public:
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0; virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0;
virtual String font_get_style_name(const RID &p_font_rid) const = 0; virtual String font_get_style_name(const RID &p_font_rid) const = 0;
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; virtual void font_set_antialiasing(RID p_font_rid, FontAntialiasing p_antialiasing) = 0;
virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; virtual FontAntialiasing font_get_antialiasing(RID p_font_rid) const = 0;
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0;
@ -569,6 +584,8 @@ VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_ENUM_CAST(TextServer::SpacingType);
VARIANT_BITFIELD_CAST(TextServer::FontStyle); VARIANT_BITFIELD_CAST(TextServer::FontStyle);
VARIANT_ENUM_CAST(TextServer::StructuredTextParser); VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
VARIANT_ENUM_CAST(TextServer::FontAntialiasing);
VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout);
GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo); GDVIRTUAL_NATIVE_PTR(CaretInfo);