1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-08 12:40:44 +00:00

Merge pull request #67409 from bruvzg/fix_oversampling_rounding

[TextServer] Do not round glyph advances / coordinates if font oversampling or bitmap glyph scaling is used.
This commit is contained in:
Rémi Verschelde
2022-10-31 14:21:56 +01:00
2 changed files with 47 additions and 36 deletions

View File

@@ -2630,9 +2630,10 @@ Vector2 TextServerAdvanced::_font_get_glyph_advance(const RID &p_font_rid, int64
ea.x = fd->embolden * double(size.x) / 64.0; ea.x = fd->embolden * double(size.x) / 64.0;
} }
double scale = _font_get_scale(p_font_rid, p_size);
if (fd->msdf) { if (fd->msdf) {
return (gl[p_glyph | mod].advance + ea) * (double)p_size / (double)fd->msdf_source_size; return (gl[p_glyph | mod].advance + ea) * (double)p_size / (double)fd->msdf_source_size;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((scale == 1.0) && ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE))) {
return (gl[p_glyph | mod].advance + ea).round(); return (gl[p_glyph | mod].advance + ea).round();
} else { } else {
return gl[p_glyph | mod].advance + ea; return gl[p_glyph | mod].advance + ea;
@@ -3261,13 +3262,15 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size; Size2 csize = gl.rect.size * (double)p_size / (double)fd->msdf_source_size;
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else { } else {
double scale = _font_get_scale(p_font_rid, p_size);
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos.y = Math::floor(cpos.y);
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)) {
cpos.x = ((int)Math::floor(cpos.x + 0.125)); cpos.x = cpos.x + 0.125;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
cpos.x = ((int)Math::floor(cpos.x + 0.25)); cpos.x = cpos.x + 0.25;
} else { }
if (scale == 1.0) {
cpos.y = Math::floor(cpos.y);
cpos.x = Math::floor(cpos.x); cpos.x = Math::floor(cpos.x);
} }
cpos += gl.rect.position; cpos += gl.rect.position;
@@ -3352,12 +3355,14 @@ void TextServerAdvanced::_font_draw_glyph_outline(const RID &p_font_rid, const R
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else { } else {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos.y = Math::floor(cpos.y); double scale = _font_get_scale(p_font_rid, p_size);
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)) {
cpos.x = ((int)Math::floor(cpos.x + 0.125)); cpos.x = cpos.x + 0.125;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
cpos.x = ((int)Math::floor(cpos.x + 0.25)); cpos.x = cpos.x + 0.25;
} else { }
if (scale == 1.0) {
cpos.y = Math::floor(cpos.y);
cpos.x = Math::floor(cpos.x); cpos.x = Math::floor(cpos.x);
} }
cpos += gl.rect.position; cpos += gl.rect.position;
@@ -4975,7 +4980,8 @@ bool TextServerAdvanced::_shaped_text_update_justification_ops(const RID &p_shap
Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, const RID &p_font, int64_t p_font_size) { Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, const RID &p_font, int64_t p_font_size) {
hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size); hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size);
bool subpos = (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_AUTO && p_font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); double scale = _font_get_scale(p_font, p_font_size);
bool subpos = (scale != 1.0) || (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(p_font) == SUBPIXEL_POSITIONING_AUTO && p_font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
ERR_FAIL_COND_V(hb_font == nullptr, Glyph()); ERR_FAIL_COND_V(hb_font == nullptr, Glyph());
hb_buffer_clear_contents(p_sd->hb_buffer); hb_buffer_clear_contents(p_sd->hb_buffer);
@@ -5001,25 +5007,24 @@ Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char
gl.font_size = p_font_size; gl.font_size = p_font_size;
if (glyph_count > 0) { if (glyph_count > 0) {
double scale = _font_get_scale(p_font, p_font_size);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
if (subpos) { if (subpos) {
gl.advance = glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size); gl.advance = (double)glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size);
} else { } else {
gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size)); gl.advance = Math::round((double)glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size));
} }
} else { } else {
gl.advance = -Math::round(glyph_pos[0].y_advance / (64.0 / scale)); gl.advance = -Math::round((double)glyph_pos[0].y_advance / (64.0 / scale));
} }
gl.count = 1; gl.count = 1;
gl.index = glyph_info[0].codepoint; gl.index = glyph_info[0].codepoint;
if (subpos) { if (subpos) {
gl.x_off = glyph_pos[0].x_offset / (64.0 / scale); gl.x_off = (double)glyph_pos[0].x_offset / (64.0 / scale);
} else { } else {
gl.x_off = Math::round(glyph_pos[0].x_offset / (64.0 / scale)); gl.x_off = Math::round((double)glyph_pos[0].x_offset / (64.0 / scale));
} }
gl.y_off = -Math::round(glyph_pos[0].y_offset / (64.0 / scale)); gl.y_off = -Math::round((double)glyph_pos[0].y_offset / (64.0 / scale));
if ((glyph_info[0].codepoint != 0) || !u_isgraph(p_char)) { if ((glyph_info[0].codepoint != 0) || !u_isgraph(p_char)) {
gl.flags |= GRAPHEME_IS_VALID; gl.flags |= GRAPHEME_IS_VALID;
@@ -5092,7 +5097,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
double sp_gl = p_sd->extra_spacing[SPACING_GLYPH]; double sp_gl = p_sd->extra_spacing[SPACING_GLYPH];
bool last_run = (p_sd->end == p_end); bool last_run = (p_sd->end == p_end);
double ea = _get_extra_advance(f, fs); double ea = _get_extra_advance(f, fs);
bool subpos = (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); bool subpos = (scale != 1.0) || (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
ERR_FAIL_COND(hb_font == nullptr); ERR_FAIL_COND(hb_font == nullptr);
hb_buffer_clear_contents(p_sd->hb_buffer); hb_buffer_clear_contents(p_sd->hb_buffer);
@@ -5193,19 +5198,19 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
_ensure_glyph(fd, fss, gl.index | mod); _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 = (double)glyph_pos[i].x_advance / (64.0 / scale) + ea;
} else { } else {
gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale) + ea); gl.advance = Math::round((double)glyph_pos[i].x_advance / (64.0 / scale) + ea);
} }
} else { } else {
gl.advance = -Math::round(glyph_pos[i].y_advance / (64.0 / scale)); gl.advance = -Math::round((double)glyph_pos[i].y_advance / (64.0 / scale));
} }
if (subpos) { if (subpos) {
gl.x_off = glyph_pos[i].x_offset / (64.0 / scale); gl.x_off = (double)glyph_pos[i].x_offset / (64.0 / scale);
} else { } else {
gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / scale)); gl.x_off = Math::round((double)glyph_pos[i].x_offset / (64.0 / scale));
} }
gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale)); gl.y_off = -Math::round((double)glyph_pos[i].y_offset / (64.0 / scale));
} }
if (!last_run || i < glyph_count - 1) { if (!last_run || i < glyph_count - 1) {
// Do not add extra spacing to the last glyph of the string. // Do not add extra spacing to the last glyph of the string.

View File

@@ -1711,9 +1711,10 @@ Vector2 TextServerFallback::_font_get_glyph_advance(const RID &p_font_rid, int64
ea.x = fd->embolden * double(size.x) / 64.0; ea.x = fd->embolden * double(size.x) / 64.0;
} }
double scale = _font_get_scale(p_font_rid, p_size);
if (fd->msdf) { if (fd->msdf) {
return (gl[p_glyph | mod].advance + ea) * (double)p_size / (double)fd->msdf_source_size; return (gl[p_glyph | mod].advance + ea) * (double)p_size / (double)fd->msdf_source_size;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((scale == 1.0) && ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE))) {
return (gl[p_glyph | mod].advance + ea).round(); return (gl[p_glyph | mod].advance + ea).round();
} else { } else {
return gl[p_glyph | mod].advance + ea; return gl[p_glyph | mod].advance + ea;
@@ -2325,12 +2326,14 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range);
} else { } else {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos.y = Math::floor(cpos.y); double scale = _font_get_scale(p_font_rid, p_size);
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)) {
cpos.x = ((int)Math::floor(cpos.x + 0.125)); cpos.x = cpos.x + 0.125;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
cpos.x = ((int)Math::floor(cpos.x + 0.25)); cpos.x = cpos.x + 0.25;
} else { }
if (scale == 1.0) {
cpos.y = Math::floor(cpos.y);
cpos.x = Math::floor(cpos.x); cpos.x = Math::floor(cpos.x);
} }
cpos += gl.rect.position; cpos += gl.rect.position;
@@ -2415,12 +2418,14 @@ void TextServerFallback::_font_draw_glyph_outline(const RID &p_font_rid, const R
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range);
} else { } else {
Point2 cpos = p_pos; Point2 cpos = p_pos;
cpos.y = Math::floor(cpos.y); double scale = _font_get_scale(p_font_rid, p_size);
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)) {
cpos.x = ((int)Math::floor(cpos.x + 0.125)); cpos.x = cpos.x + 0.125;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
cpos.x = ((int)Math::floor(cpos.x + 0.25)); cpos.x = cpos.x + 0.25;
} else { }
if (scale == 1.0) {
cpos.y = Math::floor(cpos.y);
cpos.x = Math::floor(cpos.x); cpos.x = Math::floor(cpos.x);
} }
cpos += gl.rect.position; cpos += gl.rect.position;
@@ -3643,17 +3648,18 @@ bool TextServerFallback::_shaped_text_shape(const RID &p_shaped) {
} }
} }
double scale = _font_get_scale(gl.font_rid, gl.font_size);
if (gl.font_rid.is_valid()) { if (gl.font_rid.is_valid()) {
bool subpos = (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_AUTO && gl.font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); bool subpos = (scale != 1.0) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_AUTO && gl.font_size <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
if (sd->text[j - sd->start] != 0 && !is_linebreak(sd->text[j - sd->start])) { if (sd->text[j - sd->start] != 0 && !is_linebreak(sd->text[j - sd->start])) {
if (sd->orientation == ORIENTATION_HORIZONTAL) { if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x); gl.advance = _font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x;
gl.x_off = 0; gl.x_off = 0;
gl.y_off = 0; gl.y_off = 0;
sd->ascent = MAX(sd->ascent, _font_get_ascent(gl.font_rid, gl.font_size)); sd->ascent = MAX(sd->ascent, _font_get_ascent(gl.font_rid, gl.font_size));
sd->descent = MAX(sd->descent, _font_get_descent(gl.font_rid, gl.font_size)); sd->descent = MAX(sd->descent, _font_get_descent(gl.font_rid, gl.font_size));
} else { } else {
gl.advance = Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).y); gl.advance = _font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).y;
gl.x_off = -Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5); gl.x_off = -Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5);
gl.y_off = _font_get_ascent(gl.font_rid, gl.font_size); gl.y_off = _font_get_ascent(gl.font_rid, gl.font_size);
sd->ascent = MAX(sd->ascent, Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); sd->ascent = MAX(sd->ascent, Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));