summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2022-08-26 11:59:07 +0200
committerGitHub <noreply@github.com>2022-08-26 11:59:07 +0200
commit7013c68619dcd42d03497b538f141ad585535e08 (patch)
tree168fee4498bfc27ca64b4e1e517333b11de89655 /modules
parent354123a207e737fd6014b6ff17445ab66aa28787 (diff)
parentbcc3643989762a6814f1f0c5a4b63a0e66d6286c (diff)
Merge pull request #64422 from bruvzg/make_fonts_unbearably_ugly_2.0
Diffstat (limited to 'modules')
-rw-r--r--modules/text_server_adv/text_server_adv.cpp278
-rw-r--r--modules/text_server_adv/text_server_adv.h8
-rw-r--r--modules/text_server_fb/text_server_fb.cpp266
-rw-r--r--modules/text_server_fb/text_server_fb.h8
4 files changed, 466 insertions, 94 deletions
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index e80eb43369..366e1ba604 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -29,12 +29,12 @@
/*************************************************************************/
#include "text_server_adv.h"
-#include "core/object/worker_thread_pool.h"
#ifdef GDEXTENSION
// Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file.hpp>
+#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp>
#include <godot_cpp/core/error_macros.hpp>
@@ -44,8 +44,10 @@ using namespace godot;
#else
// Headers for building as built-in module.
+#include "core/config/project_settings.h"
#include "core/core_bind.h"
#include "core/error/error_macros.h"
+#include "core/object/worker_thread_pool.h"
#include "core/string/print_string.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++) {
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.
continue;
}
@@ -1082,9 +1088,28 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
#endif
#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 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 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(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;
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 + 3] = bitmap.buffer[ofs_color + 3];
} 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:
ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + ".");
break;
@@ -1230,9 +1282,44 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data,
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 (!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;
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!");
#endif
} 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 {
@@ -1264,11 +1351,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data,
if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) {
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;
}
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:
FT_Done_Glyph(glyph);
@@ -1925,23 +2012,23 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const {
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);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
- if (fd->antialiased != p_antialiased) {
+ if (fd->antialiasing != p_antialiasing) {
_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);
- ERR_FAIL_COND_V(!fd, false);
+ ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE);
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) {
@@ -2514,7 +2601,16 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_
Vector2i size = _get_size(fd, p_size);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -2986,16 +3136,18 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i
if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx);
} else {
- 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 | (0 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
- } else {
- _ensure_glyph(fd, size, (int32_t)idx);
+ for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
+ 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 | (0 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
+ } 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) {
_ensure_glyph(fd, size, (int32_t)idx);
} else {
- 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 | (0 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
- } else {
- _ensure_glyph(fd, size, (int32_t)idx);
+ for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
+ 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 | (0 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
+ } 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));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
+ bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED
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)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
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) {
Color modulate = p_color;
#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;
}
#endif
@@ -3103,7 +3267,11 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
}
cpos += gl.rect.position;
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));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
+ bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED
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)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
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;
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_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.
if (glyph_count > 0) {
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;
if (gl.index != 0) {
- _ensure_glyph(fd, fss, gl.index);
+ _ensure_glyph(fd, fss, gl.index | mod);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
if (subpos) {
gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea;
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 6c3e8dbdcb..02abc31c55 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -223,7 +223,7 @@ class TextServerAdvanced : public TextServerExtension {
struct FontAdvanced {
Mutex mutex;
- bool antialiased = true;
+ TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false;
bool msdf = false;
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;
#endif
#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
_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;
@@ -498,8 +498,8 @@ public:
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 void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
- virtual bool font_is_antialiased(const RID &p_font_rid) const override;
+ virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) 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 bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 016bcfc886..53b303cb20 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -34,6 +34,7 @@
// Headers for building as GDExtension plug-in.
#include <godot_cpp/classes/file.hpp>
+#include <godot_cpp/classes/project_settings.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/translation_server.hpp>
#include <godot_cpp/core/error_macros.hpp>
@@ -43,6 +44,7 @@ using namespace godot;
#else
// Headers for building as built-in module.
+#include "core/config/project_settings.h"
#include "core/error/error_macros.h"
#include "core/string/print_string.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++) {
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.
continue;
}
@@ -500,9 +506,28 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
#endif
#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 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 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(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;
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 + 3] = bitmap.buffer[ofs_color + 3];
} 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:
ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + ".");
break;
@@ -650,9 +702,44 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data,
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 (!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;
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!");
#endif
} 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 {
@@ -684,11 +771,11 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data,
if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) {
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;
}
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:
FT_Done_Glyph(glyph);
@@ -1014,23 +1101,23 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const {
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);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
- if (fd->antialiased != p_antialiased) {
+ if (fd->antialiasing != p_antialiasing) {
_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);
- ERR_FAIL_COND_V(!fd, false);
+ ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE);
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) {
@@ -1589,7 +1676,16 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_
Vector2i size = _get_size(fd, p_size);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -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);
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.
}
@@ -2043,16 +2193,18 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i
if (fd->msdf) {
_ensure_glyph(fd, size, (int32_t)idx);
} else {
- 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 | (0 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
- } else {
- _ensure_glyph(fd, size, (int32_t)idx);
+ for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
+ 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 | (0 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
+ } 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) {
_ensure_glyph(fd, size, (int32_t)idx);
} else {
- 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 | (0 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (2 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27));
- _ensure_glyph(fd, size, (int32_t)idx | (0 << 27));
- } else {
- _ensure_glyph(fd, size, (int32_t)idx);
+ for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) {
+ 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 | (0 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (3 << 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 | (1 << 27) | (aa << 24));
+ _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24));
+ } 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));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
+ bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED
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)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
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) {
Color modulate = p_color;
#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;
}
#endif
@@ -2160,7 +2324,11 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
}
cpos += gl.rect.position;
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));
int32_t index = p_index & 0xffffff; // Remove subpixel shifts.
+ bool lcd_aa = false;
#ifdef MODULE_FREETYPE_ENABLED
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)) {
int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125));
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;
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);
+ }
}
}
}
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 8e81433a2a..940c57a354 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -179,7 +179,7 @@ class TextServerFallback : public TextServerExtension {
struct FontFallback {
Mutex mutex;
- bool antialiased = true;
+ TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
bool mipmaps = false;
bool msdf = false;
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;
#endif
#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
_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;
@@ -378,8 +378,8 @@ public:
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 void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
- virtual bool font_is_antialiased(const RID &p_font_rid) const override;
+ virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) 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 bool font_get_generate_mipmaps(const RID &p_font_rid) const override;