Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Complex Text Layouts] Adds missing Font::SPACING_* to the controls, align glyphs to pixel grid. #43981

Merged
merged 5 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions modules/text_server_adv/bitmap_font_adv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ static hb_bool_t hb_bmp_get_font_h_extents(hb_font_t *font, void *font_data, hb_
return true;
}

static hb_font_funcs_t *_hb_bmp_get_font_funcs() {
hb_font_funcs_t *funcs = hb_font_funcs_create();
static hb_font_funcs_t *funcs = nullptr;
void hb_bmp_create_font_funcs() {
funcs = hb_font_funcs_create();

hb_font_funcs_set_font_h_extents_func(funcs, hb_bmp_get_font_h_extents, nullptr, nullptr);
//hb_font_funcs_set_font_v_extents_func (funcs, hb_bmp_get_font_v_extents, nullptr, nullptr);
Expand All @@ -194,12 +195,17 @@ static hb_font_funcs_t *_hb_bmp_get_font_funcs() {
//hb_font_funcs_set_glyph_from_name_func (funcs, hb_bmp_get_glyph_from_name, nullptr, nullptr);

hb_font_funcs_make_immutable(funcs);
}

return funcs;
void hb_bmp_free_font_funcs() {
if (funcs != nullptr) {
hb_font_funcs_destroy(funcs);
funcs = nullptr;
}
}

static void _hb_bmp_font_set_funcs(hb_font_t *p_font, BitmapFontDataAdvanced *p_face, int p_size, bool p_unref) {
hb_font_set_funcs(p_font, _hb_bmp_get_font_funcs(), _hb_bmp_font_create(p_face, p_size, p_unref), _hb_bmp_font_destroy);
hb_font_set_funcs(p_font, funcs, _hb_bmp_font_create(p_face, p_size, p_unref), _hb_bmp_font_destroy);
}

hb_font_t *hb_bmp_font_create(BitmapFontDataAdvanced *p_face, int p_size, hb_destroy_func_t p_destroy) {
Expand Down
3 changes: 3 additions & 0 deletions modules/text_server_adv/bitmap_font_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@

#include "font_adv.h"

void hb_bmp_create_font_funcs();
void hb_bmp_free_font_funcs();

struct BitmapFontDataAdvanced : public FontDataAdvanced {
_THREAD_SAFE_CLASS_

Expand Down
3 changes: 2 additions & 1 deletion modules/text_server_adv/script_iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length
int paren_sp = -1;
int start_sp = paren_sp;
UErrorCode err = U_ZERO_ERROR;
const char32_t *str = p_string.ptr();

do {
script_code = USCRIPT_COMMON;
for (script_start = script_end; script_end < p_length; script_end++) {
UChar32 ch = p_string[script_end];
UChar32 ch = str[script_end];
UScriptCode sc = uscript_getScript(ch, &err);
if (U_FAILURE(err)) {
ERR_FAIL_MSG(u_errorName(err));
Expand Down
183 changes: 105 additions & 78 deletions modules/text_server_adv/text_server_adv.cpp

Large diffs are not rendered by default.

106 changes: 60 additions & 46 deletions modules/text_server_fb/text_server_fb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,11 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
sd->width = 0;
sd->upos = 0;
sd->uthk = 0;
for (int i = 0; i < sd->glyphs.size(); i++) {
int sd_size = sd->glyphs.size();
const FontDataFallback *fd = nullptr;
RID prev_rid = RID();

for (int i = 0; i < sd_size; i++) {
Glyph gl = sd->glyphs[i];
Variant key;
if (gl.count == 1) {
Expand All @@ -645,8 +649,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y);
} break;
case VALIGN_CENTER: {
sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y / 2);
sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y / 2);
sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.y / 2));
sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.y / 2));
} break;
case VALIGN_BOTTOM: {
sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y);
Expand All @@ -661,8 +665,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x);
} break;
case VALIGN_CENTER: {
sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x / 2);
sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x / 2);
sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.x / 2));
sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.x / 2));
} break;
case VALIGN_BOTTOM: {
sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x);
Expand All @@ -671,25 +675,28 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
sd->glyphs.write[i].advance = sd->objects[key].rect.size.y;
}
} else {
const FontDataFallback *fd = font_owner.getornull(gl.font_rid);
if (prev_rid != gl.font_rid) {
fd = font_owner.getornull(gl.font_rid);
prev_rid = gl.font_rid;
}
if (fd != nullptr) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->ascent = MAX(sd->ascent, fd->get_ascent(gl.font_size));
sd->descent = MAX(sd->descent, fd->get_descent(gl.font_size));
} else {
sd->ascent = MAX(sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
sd->descent = MAX(sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
sd->ascent = MAX(sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
}
sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size));
sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size));
} else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box.
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f);
sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f);
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else {
sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
}
}
sd->width += gl.advance * gl.repeat;
Expand Down Expand Up @@ -760,21 +767,25 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng

if (p_length > 0) {
new_sd->text = sd->text.substr(p_start, p_length);
int sd_size = sd->glyphs.size();
const Glyph *sd_glyphs = sd->glyphs.ptr();

for (int i = 0; i < sd->glyphs.size(); i++) {
if ((sd->glyphs[i].start >= new_sd->start) && (sd->glyphs[i].end <= new_sd->end)) {
Glyph gl = sd->glyphs[i];
for (int i = 0; i < sd_size; i++) {
if ((sd_glyphs[i].start >= new_sd->start) && (sd_glyphs[i].end <= new_sd->end)) {
Glyph gl = sd_glyphs[i];
Variant key;
bool find_embedded = false;
if (gl.count == 1) {
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) {
if (E->get().pos == gl.start) {
find_embedded = true;
key = E->key();
new_sd->objects[key] = E->get();
break;
}
}
}
if (key != Variant()) {
if (find_embedded) {
if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->objects[key].rect.position.x = new_sd->width;
new_sd->width += new_sd->objects[key].rect.size.x;
Expand All @@ -783,8 +794,8 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.y);
} break;
case VALIGN_CENTER: {
new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.y / 2);
new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y / 2);
new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.y / 2));
new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.y / 2));
} break;
case VALIGN_BOTTOM: {
new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y);
Expand All @@ -798,8 +809,8 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.x);
} break;
case VALIGN_CENTER: {
new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.x / 2);
new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x / 2);
new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.x / 2));
new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.x / 2));
} break;
case VALIGN_BOTTOM: {
new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x);
Expand All @@ -813,17 +824,17 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->ascent = MAX(new_sd->ascent, fd->get_ascent(gl.font_size));
new_sd->descent = MAX(new_sd->descent, fd->get_descent(gl.font_size));
} else {
new_sd->ascent = MAX(new_sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
new_sd->descent = MAX(new_sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
new_sd->ascent = MAX(new_sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
new_sd->descent = MAX(new_sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
}
} else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) {
// Glyph not found, replace with hex code box.
if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f);
new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f);
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f));
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else {
new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
}
}
new_sd->width += gl.advance * gl.repeat;
Expand Down Expand Up @@ -943,7 +954,7 @@ float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width,
if (gl.count > 0) {
if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
float old_adv = gl.advance;
gl.advance = MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size);
gl.advance = Math::round(MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size));
sd->width += (gl.advance - old_adv);
}
}
Expand Down Expand Up @@ -978,8 +989,10 @@ float TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<float
delta = -1;
}

Glyph *gl = sd->glyphs.ptrw();

for (int i = start; i != end; i += delta) {
if ((sd->glyphs[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) {
if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) {
float tab_off = 0.f;
while (tab_off <= off) {
tab_off += p_tab_stops[tab_index];
Expand All @@ -988,13 +1001,13 @@ float TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<float
tab_index = 0;
}
}
float old_adv = sd->glyphs.write[i].advance;
sd->glyphs.write[i].advance = (tab_off - off);
sd->width += sd->glyphs.write[i].advance - old_adv;
float old_adv = gl[i].advance;
gl[i].advance = tab_off - off;
sd->width += gl[i].advance - old_adv;
off = 0;
continue;
}
off += sd->glyphs[i].advance * sd->glyphs[i].repeat;
off += gl[i].advance * gl[i].repeat;
}

return 0.f;
Expand All @@ -1012,7 +1025,8 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
return true; // Noting to do.
}

for (int i = 0; i < sd->glyphs.size(); i++) {
int sd_size = sd->glyphs.size();
for (int i = 0; i < sd_size; i++) {
if (sd->glyphs[i].count > 0) {
char32_t c = sd->text[sd->glyphs[i].start];
if (is_whitespace(c) && !is_linebreak(c)) {
Expand Down Expand Up @@ -1086,8 +1100,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y);
} break;
case VALIGN_CENTER: {
sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y / 2);
sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y / 2);
sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
} break;
case VALIGN_BOTTOM: {
sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y);
Expand All @@ -1101,8 +1115,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x);
} break;
case VALIGN_CENTER: {
sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x / 2);
sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x / 2);
sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
} break;
case VALIGN_BOTTOM: {
sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x);
Expand Down Expand Up @@ -1157,14 +1171,14 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
sd->descent = MAX(sd->descent, fd->get_descent(gl.font_size));
} else {
gl.advance = fd->get_advance(gl.index, gl.font_size).y;
gl.x_off = -fd->get_advance(gl.index, gl.font_size).x * 0.5;
gl.x_off = -Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5);
gl.y_off = fd->get_ascent(gl.font_size);
sd->ascent = MAX(sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
sd->descent = MAX(sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5);
sd->ascent = MAX(sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5));
}
}
sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size));
sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size));
sd->upos = MAX(sd->upos, fd->get_underline_position(gl.font_size));
sd->uthk = MAX(sd->uthk, fd->get_underline_thickness(gl.font_size));

// Add kerning to previous glyph.
if (sd->glyphs.size() > 0) {
Expand All @@ -1181,12 +1195,12 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
// Glyph not found, replace with hex code box.
if (sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = get_hex_code_box_size(gl.font_size, gl.index).x;
sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f);
sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f);
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f));
} else {
gl.advance = get_hex_code_box_size(gl.font_size, gl.index).y;
sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f);
sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f));
}
}
sd->width += gl.advance;
Expand Down
1 change: 1 addition & 0 deletions scene/gui/item_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
item.icon_region = Rect2i();
item.icon_modulate = Color(1, 1, 1, 1);
//item.text=p_item;
item.text_buf.instance();
item.selectable = p_selectable;
item.selected = false;
item.disabled = false;
Expand Down
Loading