From b79492b709ca05ed24e112b134e5f425dc6d2ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Thu, 8 Feb 2024 13:23:27 +0100 Subject: [PATCH] font: text alignment fixes --- demos/01-font.c | 24 +++++++++++ engine/joint/v4k.h | 96 +++++++++++++++++++++++++---------------- engine/split/v4k_font.c | 95 ++++++++++++++++++++++++---------------- engine/split/v4k_font.h | 1 + engine/v4k.c | 95 ++++++++++++++++++++++++---------------- engine/v4k.h | 1 + 6 files changed, 198 insertions(+), 114 deletions(-) diff --git a/demos/01-font.c b/demos/01-font.c index b6d5dbb..3803cdd 100644 --- a/demos/01-font.c +++ b/demos/01-font.c @@ -124,6 +124,30 @@ int main() { ddraw_pop_2d(); } + { + vec2 pos = vec2(1490,820); + ddraw_push_2d(); + char *txt = FONT_CENTER FONT_MIDDLE "This is the first line.\nAnd now the second line.\nYou can do a third great line, too!\n"; + font_goto(pos.x, pos.y); + vec2 size=font_rect(txt); + font_metrics_t m=font_metrics(txt); + ddraw_aabb(vec3(pos.x,pos.y,0), vec3(pos.x+size.x,pos.y+size.y-m.descent+m.linegap+100,0)); + font_print_rect(txt, vec4(pos.x, pos.y, size.x, size.y+100)); + ddraw_pop_2d(); + } + + { + vec2 pos = vec2(1990,820); + ddraw_push_2d(); + char *txt = FONT_RIGHT FONT_BOTTOM "This is the first line.\nAnd now the second line.\nYou can do a third great line, too!\n"; + font_goto(pos.x, pos.y); + vec2 size=font_rect(txt); + font_metrics_t m=font_metrics(txt); + ddraw_aabb(vec3(pos.x,pos.y,0), vec3(pos.x+size.x,pos.y+size.y-m.descent+m.linegap+100,0)); + font_print_rect(txt, vec4(pos.x, pos.y, size.x, size.y+100)); + ddraw_pop_2d(); + } + { vec2 pos = vec2(830,80); ddraw_push_2d(); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 22c4e6e..9226e8e 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -16090,6 +16090,7 @@ API bool ini_write(const char *filename, const char *section, const char // font align tags #define FONT_LEFT "\\<" #define FONT_CENTER "\\|" +#define FONT_JUSTIFY "\\$" #define FONT_RIGHT "\\>" #define FONT_TOP "\\^" #define FONT_MIDDLE "\\-" @@ -363635,9 +363636,9 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if( X > W ) W = X; X = 0.0; Y -= f->linedist*f->factor*f->scale[S]; - if (i+1==end) { //@hack: ensures we terminate the height at the correct position - Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; - } + // if (i+1==end) { //@hack: ensures we terminate the height at the correct position + // Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; + // } continue; } if( ch >= 1 && ch <= 6 ) { @@ -363677,18 +363678,6 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if (!LL) LL = L; - if (ch == FONT_LEFT[0] && ( - (unicode[i+1]) == FONT_LEFT[1] || - (unicode[i+1]) == FONT_CENTER[1] || - (unicode[i+1]) == FONT_RIGHT[1] || - (unicode[i+1]) == FONT_TOP[1] || - (unicode[i+1]) == FONT_MIDDLE[1] || - (unicode[i+1]) == FONT_BASELINE[1] || - (unicode[i+1]) == FONT_BOTTOM[1] - )) { - continue; - } - // convert to vbo data int cp = ch - f->begin; // f->cp2iter[ch - f->begin]; //if(cp == 0xFFFD) continue; @@ -363944,31 +363933,62 @@ void font_goto(float x, float y) { // Print and linefeed. Text may include markup code vec2 font_print_rect(const char *text, vec4 rect) { - // @fixme: remove this hack - if( text[0] == FONT_LEFT[0] ) { - int l = text[1] == FONT_LEFT[1]; - int c = text[1] == FONT_CENTER[1]; - int r = text[1] == FONT_RIGHT[1]; - if( l || c || r ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; - return font_print_rect(text + 2, rect); - } - int t = text[1] == FONT_TOP[1]; - int b = text[1] == FONT_BOTTOM[1]; - int m = text[1] == FONT_MIDDLE[1]; - int B = text[1] == FONT_BASELINE[1]; - if( t || b || m || B ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; - return font_print_rect(text + 2, rect); - } + int l=0,c=0,r=0,t=0,b=0,m=0,B=0; + + while ( text[0] == FONT_LEFT[0] ) { + int has_set=0; + if (text[1] == FONT_LEFT[1]) l = 1, has_set=1; + if (text[1] == FONT_CENTER[1]) c = 1, has_set=1; + if (text[1] == FONT_RIGHT[1]) r = 1, has_set=1; + if (text[1] == FONT_TOP[1]) t = 1, has_set=1; + if (text[1] == FONT_BOTTOM[1]) b = 1, has_set=1; + if (text[1] == FONT_MIDDLE[1]) m = 1, has_set=1; + if (text[1] == FONT_BASELINE[1]) B = 1, has_set=1; + if (!has_set) break; + else text += 2; + } + + int num_newlines = 0; + for (int i = 0, end = strlen(text); i < end; ++i) { + if (text[i] == '\n') ++num_newlines; } - vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); - gotoxy.y += strchr(text, '\n') ? dims.y : 0; - gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x; - return dims; + if (num_newlines > 1) { + vec2 text_dims = font_rect(text); + array(char *) lines = strsplit(text, "\n"); + if (b) { + gotoxy.y += (rect.w - text_dims.y); + } + if (m) { + gotoxy.y += (rect.w/2. - text_dims.y/2.); + } + if (B) { + gotoxy.y += (rect.w/2. - text_dims.y/1.); + } + for (int i = 0; i < array_count(lines); i++) { + if( l || c || r ) { + vec2 text_rect = font_rect(lines[i]); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + char *line = va("%s\n", lines[i]); + vec2 dims = font_draw_ex(line, gotoxy, NULL, font_draw_cmd); + gotoxy.y += dims.y; + } + return text_dims; + } else { + if( l || c || r ) { + vec2 text_rect = font_rect(text); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + if( t || b || m || B ) { + vec2 text_rect = font_rect(text); + gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; + } + vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); + gotoxy.y += strchr(text, '\n') ? dims.y : 0; + gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x; + return dims; + } } vec2 font_print(const char *text) { diff --git a/engine/split/v4k_font.c b/engine/split/v4k_font.c index a425797..c317645 100644 --- a/engine/split/v4k_font.c +++ b/engine/split/v4k_font.c @@ -2078,9 +2078,9 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if( X > W ) W = X; X = 0.0; Y -= f->linedist*f->factor*f->scale[S]; - if (i+1==end) { //@hack: ensures we terminate the height at the correct position - Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; - } + // if (i+1==end) { //@hack: ensures we terminate the height at the correct position + // Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; + // } continue; } if( ch >= 1 && ch <= 6 ) { @@ -2120,18 +2120,6 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if (!LL) LL = L; - if (ch == FONT_LEFT[0] && ( - (unicode[i+1]) == FONT_LEFT[1] || - (unicode[i+1]) == FONT_CENTER[1] || - (unicode[i+1]) == FONT_RIGHT[1] || - (unicode[i+1]) == FONT_TOP[1] || - (unicode[i+1]) == FONT_MIDDLE[1] || - (unicode[i+1]) == FONT_BASELINE[1] || - (unicode[i+1]) == FONT_BOTTOM[1] - )) { - continue; - } - // convert to vbo data int cp = ch - f->begin; // f->cp2iter[ch - f->begin]; //if(cp == 0xFFFD) continue; @@ -2387,31 +2375,62 @@ void font_goto(float x, float y) { // Print and linefeed. Text may include markup code vec2 font_print_rect(const char *text, vec4 rect) { - // @fixme: remove this hack - if( text[0] == FONT_LEFT[0] ) { - int l = text[1] == FONT_LEFT[1]; - int c = text[1] == FONT_CENTER[1]; - int r = text[1] == FONT_RIGHT[1]; - if( l || c || r ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; - return font_print_rect(text + 2, rect); - } - int t = text[1] == FONT_TOP[1]; - int b = text[1] == FONT_BOTTOM[1]; - int m = text[1] == FONT_MIDDLE[1]; - int B = text[1] == FONT_BASELINE[1]; - if( t || b || m || B ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; - return font_print_rect(text + 2, rect); - } + int l=0,c=0,r=0,t=0,b=0,m=0,B=0; + + while ( text[0] == FONT_LEFT[0] ) { + int has_set=0; + if (text[1] == FONT_LEFT[1]) l = 1, has_set=1; + if (text[1] == FONT_CENTER[1]) c = 1, has_set=1; + if (text[1] == FONT_RIGHT[1]) r = 1, has_set=1; + if (text[1] == FONT_TOP[1]) t = 1, has_set=1; + if (text[1] == FONT_BOTTOM[1]) b = 1, has_set=1; + if (text[1] == FONT_MIDDLE[1]) m = 1, has_set=1; + if (text[1] == FONT_BASELINE[1]) B = 1, has_set=1; + if (!has_set) break; + else text += 2; + } + + int num_newlines = 0; + for (int i = 0, end = strlen(text); i < end; ++i) { + if (text[i] == '\n') ++num_newlines; } - vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); - gotoxy.y += strchr(text, '\n') ? dims.y : 0; - gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x; - return dims; + if (num_newlines > 1) { + vec2 text_dims = font_rect(text); + array(char *) lines = strsplit(text, "\n"); + if (b) { + gotoxy.y += (rect.w - text_dims.y); + } + if (m) { + gotoxy.y += (rect.w/2. - text_dims.y/2.); + } + if (B) { + gotoxy.y += (rect.w/2. - text_dims.y/1.); + } + for (int i = 0; i < array_count(lines); i++) { + if( l || c || r ) { + vec2 text_rect = font_rect(lines[i]); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + char *line = va("%s\n", lines[i]); + vec2 dims = font_draw_ex(line, gotoxy, NULL, font_draw_cmd); + gotoxy.y += dims.y; + } + return text_dims; + } else { + if( l || c || r ) { + vec2 text_rect = font_rect(text); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + if( t || b || m || B ) { + vec2 text_rect = font_rect(text); + gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; + } + vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); + gotoxy.y += strchr(text, '\n') ? dims.y : 0; + gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x; + return dims; + } } vec2 font_print(const char *text) { diff --git a/engine/split/v4k_font.h b/engine/split/v4k_font.h index aafa625..df9a694 100644 --- a/engine/split/v4k_font.h +++ b/engine/split/v4k_font.h @@ -33,6 +33,7 @@ // font align tags #define FONT_LEFT "\\<" #define FONT_CENTER "\\|" +#define FONT_JUSTIFY "\\$" #define FONT_RIGHT "\\>" #define FONT_TOP "\\^" #define FONT_MIDDLE "\\-" diff --git a/engine/v4k.c b/engine/v4k.c index 5b17b0b..023fec4 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -10776,9 +10776,9 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if( X > W ) W = X; X = 0.0; Y -= f->linedist*f->factor*f->scale[S]; - if (i+1==end) { //@hack: ensures we terminate the height at the correct position - Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; - } + // if (i+1==end) { //@hack: ensures we terminate the height at the correct position + // Y -= (f->descent+f->linegap)*f->factor*f->scale[S]; + // } continue; } if( ch >= 1 && ch <= 6 ) { @@ -10818,18 +10818,6 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm if (!LL) LL = L; - if (ch == FONT_LEFT[0] && ( - (unicode[i+1]) == FONT_LEFT[1] || - (unicode[i+1]) == FONT_CENTER[1] || - (unicode[i+1]) == FONT_RIGHT[1] || - (unicode[i+1]) == FONT_TOP[1] || - (unicode[i+1]) == FONT_MIDDLE[1] || - (unicode[i+1]) == FONT_BASELINE[1] || - (unicode[i+1]) == FONT_BOTTOM[1] - )) { - continue; - } - // convert to vbo data int cp = ch - f->begin; // f->cp2iter[ch - f->begin]; //if(cp == 0xFFFD) continue; @@ -11085,31 +11073,62 @@ void font_goto(float x, float y) { // Print and linefeed. Text may include markup code vec2 font_print_rect(const char *text, vec4 rect) { - // @fixme: remove this hack - if( text[0] == FONT_LEFT[0] ) { - int l = text[1] == FONT_LEFT[1]; - int c = text[1] == FONT_CENTER[1]; - int r = text[1] == FONT_RIGHT[1]; - if( l || c || r ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; - return font_print_rect(text + 2, rect); - } - int t = text[1] == FONT_TOP[1]; - int b = text[1] == FONT_BOTTOM[1]; - int m = text[1] == FONT_MIDDLE[1]; - int B = text[1] == FONT_BASELINE[1]; - if( t || b || m || B ) { - vec2 text_rect = font_rect(text + 2); - gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; - return font_print_rect(text + 2, rect); - } + int l=0,c=0,r=0,t=0,b=0,m=0,B=0; + + while ( text[0] == FONT_LEFT[0] ) { + int has_set=0; + if (text[1] == FONT_LEFT[1]) l = 1, has_set=1; + if (text[1] == FONT_CENTER[1]) c = 1, has_set=1; + if (text[1] == FONT_RIGHT[1]) r = 1, has_set=1; + if (text[1] == FONT_TOP[1]) t = 1, has_set=1; + if (text[1] == FONT_BOTTOM[1]) b = 1, has_set=1; + if (text[1] == FONT_MIDDLE[1]) m = 1, has_set=1; + if (text[1] == FONT_BASELINE[1]) B = 1, has_set=1; + if (!has_set) break; + else text += 2; + } + + int num_newlines = 0; + for (int i = 0, end = strlen(text); i < end; ++i) { + if (text[i] == '\n') ++num_newlines; } - vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); - gotoxy.y += strchr(text, '\n') ? dims.y : 0; - gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x; - return dims; + if (num_newlines > 1) { + vec2 text_dims = font_rect(text); + array(char *) lines = strsplit(text, "\n"); + if (b) { + gotoxy.y += (rect.w - text_dims.y); + } + if (m) { + gotoxy.y += (rect.w/2. - text_dims.y/2.); + } + if (B) { + gotoxy.y += (rect.w/2. - text_dims.y/1.); + } + for (int i = 0; i < array_count(lines); i++) { + if( l || c || r ) { + vec2 text_rect = font_rect(lines[i]); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + char *line = va("%s\n", lines[i]); + vec2 dims = font_draw_ex(line, gotoxy, NULL, font_draw_cmd); + gotoxy.y += dims.y; + } + return text_dims; + } else { + if( l || c || r ) { + vec2 text_rect = font_rect(text); + gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.; + } + if( t || b || m || B ) { + vec2 text_rect = font_rect(text); + gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1; + } + vec2 dims = font_draw_ex(text, gotoxy, NULL, font_draw_cmd); + gotoxy.y += strchr(text, '\n') ? dims.y : 0; + gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x; + return dims; + } } vec2 font_print(const char *text) { diff --git a/engine/v4k.h b/engine/v4k.h index b66fc1d..71c8fb8 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -2157,6 +2157,7 @@ API bool ini_write(const char *filename, const char *section, const char // font align tags #define FONT_LEFT "\\<" #define FONT_CENTER "\\|" +#define FONT_JUSTIFY "\\$" #define FONT_RIGHT "\\>" #define FONT_TOP "\\^" #define FONT_MIDDLE "\\-"