font: font_print_rect -> font_clip + scissor test
parent
65b57039a2
commit
3a853d09d7
|
@ -680,7 +680,7 @@ typedef struct font_metrics_t {
|
||||||
vec2 font_xy();
|
vec2 font_xy();
|
||||||
void font_goto(float x, float y);
|
void font_goto(float x, float y);
|
||||||
vec2 font_print(const char *text);
|
vec2 font_print(const char *text);
|
||||||
vec2 font_print_rect(const char *text, vec4 rect);
|
vec2 font_clip(const char *text, vec4 rect);
|
||||||
vec2 font_rect(const char *text);
|
vec2 font_rect(const char *text);
|
||||||
font_metrics_t font_metrics(const char *text);
|
font_metrics_t font_metrics(const char *text);
|
||||||
void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords);
|
void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords);
|
||||||
|
|
|
@ -133,19 +133,37 @@ int main() {
|
||||||
vec2 size=font_rect(txt);
|
vec2 size=font_rect(txt);
|
||||||
font_metrics_t m=font_metrics(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));
|
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));
|
font_clip(txt, vec4(pos.x, pos.y, size.x, size.y+100));
|
||||||
|
ddraw_pop_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
vec2 pos = vec2(1490,240);
|
||||||
|
ddraw_push_2d();
|
||||||
|
char *txt = "This is the first line.\nAnd now the second line.\nYou can do a third great line, too!\nNow this is a very long line aaaaaaaaaa!\n";
|
||||||
|
font_goto(pos.x, pos.y);
|
||||||
|
vec2 size=font_rect(txt);
|
||||||
|
size.y -= 20; // artifically shrink textbox to test clipping
|
||||||
|
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,0));
|
||||||
|
font_clip(txt, vec4(pos.x, pos.y, size.x, size.y));
|
||||||
ddraw_pop_2d();
|
ddraw_pop_2d();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
vec2 pos = vec2(1990,820);
|
vec2 pos = vec2(1990,820);
|
||||||
ddraw_push_2d();
|
ddraw_push_2d();
|
||||||
char *txt = FONT_RIGHT FONT_BOTTOM FONT_WHITE "This is the first line.\n" FONT_LIME "And now the second line.\n" FONT_WHITE "You can do a third" FONT_ORANGE " great" FONT_WHITE " line, too!\n";
|
char *txt = FONT_RIGHT FONT_BOTTOM
|
||||||
|
FONT_WHITE "This is the first line.\n"
|
||||||
|
FONT_LIME "And now the second line.\n"
|
||||||
|
FONT_WHITE "You can do a third"
|
||||||
|
FONT_ORANGE " great"
|
||||||
|
FONT_WHITE " line, too!\n";
|
||||||
font_goto(pos.x, pos.y);
|
font_goto(pos.x, pos.y);
|
||||||
vec2 size=font_rect(txt);
|
vec2 size=font_rect(txt);
|
||||||
font_metrics_t m=font_metrics(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));
|
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));
|
font_clip(txt, vec4(pos.x, pos.y, size.x, size.y+100));
|
||||||
ddraw_pop_2d();
|
ddraw_pop_2d();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16146,10 +16146,9 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
API vec2 font_print_rect(const char *text, vec4 rect);
|
API vec2 font_clip(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
|
||||||
// void font_wrap(vec2 topleft, vec2 bottomright);
|
// void font_wrap(vec2 topleft, vec2 bottomright);
|
||||||
|
|
||||||
// syntax highlighting
|
// syntax highlighting
|
||||||
|
@ -363522,7 +363521,7 @@ void font_face(const char *tag, const char *filename_ttf, float font_size, unsig
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset) {
|
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset, vec4 rect) {
|
||||||
// Backup GL state
|
// Backup GL state
|
||||||
GLint last_program, last_vertex_array;
|
GLint last_program, last_vertex_array;
|
||||||
GLint last_texture0, last_texture1, last_texture2;
|
GLint last_texture0, last_texture1, last_texture2;
|
||||||
|
@ -363546,12 +363545,17 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no depth testing and bind textures
|
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// @fixme: store existing scissor test setup
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
@ -363597,13 +363601,14 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
||||||
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
||||||
|
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. call font_face() if it's the first time it's called.
|
// 1. call font_face() if it's the first time it's called.
|
||||||
// 1. parse the string and update the instance vbo, then upload it
|
// 1. parse the string and update the instance vbo, then upload it
|
||||||
// 1. draw the string
|
// 1. draw the string
|
||||||
static
|
static
|
||||||
vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2)) {
|
vec2 font_draw_ex(const char *text, vec2 offset, vec4 rect, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2,vec4)) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -363643,7 +363648,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
}
|
}
|
||||||
if( ch >= 1 && ch <= 6 ) {
|
if( ch >= 1 && ch <= 6 ) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// reposition offset to align new baseline
|
// reposition offset to align new baseline
|
||||||
|
@ -363664,7 +363669,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
if( ch >= 0x10 && ch <= 0x19 ) {
|
if( ch >= 0x10 && ch <= 0x19 ) {
|
||||||
if( fonts[ ch - 0x10 ].initialized) {
|
if( fonts[ ch - 0x10 ].initialized) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
|
@ -363691,7 +363696,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
X += f->cdata[cp].xadvance*f->scale[S];
|
X += f->cdata[cp].xadvance*f->scale[S];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
|
|
||||||
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
||||||
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
||||||
|
@ -363932,7 +363937,7 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print_rect(const char *text, vec4 rect) {
|
vec2 font_clip(const char *text, vec4 rect) {
|
||||||
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
||||||
|
|
||||||
while ( text[0] == FONT_LEFT[0] ) {
|
while ( text[0] == FONT_LEFT[0] ) {
|
||||||
|
@ -363998,14 +364003,14 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
int gaps = array_count(words) - 1;
|
int gaps = array_count(words) - 1;
|
||||||
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
||||||
for (int k = 0; k < array_count(words); ++k) {
|
for (int k = 0; k < array_count(words); ++k) {
|
||||||
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, NULL, font_draw_cmd);
|
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.x += dims.x + space_offset;
|
gotoxy.x += dims.x + space_offset;
|
||||||
}
|
}
|
||||||
gotoxy.x = rect.x;
|
gotoxy.x = rect.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!j) {
|
if (!j) {
|
||||||
font_draw_ex(line, gotoxy, NULL, font_draw_cmd);
|
font_draw_ex(line, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoxy.y += text_rect.y;
|
gotoxy.y += text_rect.y;
|
||||||
|
@ -364020,7 +364025,7 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
vec2 text_rect = font_rect(text);
|
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;
|
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);
|
vec2 dims = font_draw_ex(text, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -364029,12 +364034,13 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
|
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print(const char *text) {
|
||||||
vec4 dims = {0, 0, window_width(), window_height()};
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
return font_print_rect(text, dims);
|
return font_clip(text, dims);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec4 screen_dim = {0, 0, window_width(), window_height()};
|
||||||
|
vec2 dims = font_draw_ex(text, gotoxy, screen_dim, (const char *)colors, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -364042,7 +364048,8 @@ vec2 font_highlight(const char *text, const void *colors) {
|
||||||
|
|
||||||
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
||||||
vec2 font_rect(const char *str) {
|
vec2 font_rect(const char *str) {
|
||||||
return font_draw_ex(str, gotoxy, NULL, NULL);
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_draw_ex(str, gotoxy, dims, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
font_metrics_t font_metrics(const char *text) {
|
font_metrics_t font_metrics(const char *text) {
|
||||||
|
|
|
@ -1964,7 +1964,7 @@ void font_face(const char *tag, const char *filename_ttf, float font_size, unsig
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset) {
|
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset, vec4 rect) {
|
||||||
// Backup GL state
|
// Backup GL state
|
||||||
GLint last_program, last_vertex_array;
|
GLint last_program, last_vertex_array;
|
||||||
GLint last_texture0, last_texture1, last_texture2;
|
GLint last_texture0, last_texture1, last_texture2;
|
||||||
|
@ -1988,12 +1988,17 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no depth testing and bind textures
|
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// @fixme: store existing scissor test setup
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
@ -2039,13 +2044,14 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
||||||
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
||||||
|
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. call font_face() if it's the first time it's called.
|
// 1. call font_face() if it's the first time it's called.
|
||||||
// 1. parse the string and update the instance vbo, then upload it
|
// 1. parse the string and update the instance vbo, then upload it
|
||||||
// 1. draw the string
|
// 1. draw the string
|
||||||
static
|
static
|
||||||
vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2)) {
|
vec2 font_draw_ex(const char *text, vec2 offset, vec4 rect, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2,vec4)) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -2085,7 +2091,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
}
|
}
|
||||||
if( ch >= 1 && ch <= 6 ) {
|
if( ch >= 1 && ch <= 6 ) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// reposition offset to align new baseline
|
// reposition offset to align new baseline
|
||||||
|
@ -2106,7 +2112,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
if( ch >= 0x10 && ch <= 0x19 ) {
|
if( ch >= 0x10 && ch <= 0x19 ) {
|
||||||
if( fonts[ ch - 0x10 ].initialized) {
|
if( fonts[ ch - 0x10 ].initialized) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
|
@ -2133,7 +2139,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
X += f->cdata[cp].xadvance*f->scale[S];
|
X += f->cdata[cp].xadvance*f->scale[S];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
|
|
||||||
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
||||||
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
||||||
|
@ -2374,7 +2380,7 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print_rect(const char *text, vec4 rect) {
|
vec2 font_clip(const char *text, vec4 rect) {
|
||||||
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
||||||
|
|
||||||
while ( text[0] == FONT_LEFT[0] ) {
|
while ( text[0] == FONT_LEFT[0] ) {
|
||||||
|
@ -2440,14 +2446,14 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
int gaps = array_count(words) - 1;
|
int gaps = array_count(words) - 1;
|
||||||
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
||||||
for (int k = 0; k < array_count(words); ++k) {
|
for (int k = 0; k < array_count(words); ++k) {
|
||||||
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, NULL, font_draw_cmd);
|
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.x += dims.x + space_offset;
|
gotoxy.x += dims.x + space_offset;
|
||||||
}
|
}
|
||||||
gotoxy.x = rect.x;
|
gotoxy.x = rect.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!j) {
|
if (!j) {
|
||||||
font_draw_ex(line, gotoxy, NULL, font_draw_cmd);
|
font_draw_ex(line, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoxy.y += text_rect.y;
|
gotoxy.y += text_rect.y;
|
||||||
|
@ -2462,7 +2468,7 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
vec2 text_rect = font_rect(text);
|
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;
|
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);
|
vec2 dims = font_draw_ex(text, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -2471,12 +2477,13 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
|
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print(const char *text) {
|
||||||
vec4 dims = {0, 0, window_width(), window_height()};
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
return font_print_rect(text, dims);
|
return font_clip(text, dims);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec4 screen_dim = {0, 0, window_width(), window_height()};
|
||||||
|
vec2 dims = font_draw_ex(text, gotoxy, screen_dim, (const char *)colors, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -2484,7 +2491,8 @@ vec2 font_highlight(const char *text, const void *colors) {
|
||||||
|
|
||||||
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
||||||
vec2 font_rect(const char *str) {
|
vec2 font_rect(const char *str) {
|
||||||
return font_draw_ex(str, gotoxy, NULL, NULL);
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_draw_ex(str, gotoxy, dims, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
font_metrics_t font_metrics(const char *text) {
|
font_metrics_t font_metrics(const char *text) {
|
||||||
|
|
|
@ -89,10 +89,9 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
API vec2 font_print_rect(const char *text, vec4 rect);
|
API vec2 font_clip(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
|
||||||
// void font_wrap(vec2 topleft, vec2 bottomright);
|
// void font_wrap(vec2 topleft, vec2 bottomright);
|
||||||
|
|
||||||
// syntax highlighting
|
// syntax highlighting
|
||||||
|
|
34
engine/v4k.c
34
engine/v4k.c
|
@ -10662,7 +10662,7 @@ void font_face(const char *tag, const char *filename_ttf, float font_size, unsig
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset) {
|
void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float factor, vec2 offset, vec4 rect) {
|
||||||
// Backup GL state
|
// Backup GL state
|
||||||
GLint last_program, last_vertex_array;
|
GLint last_program, last_vertex_array;
|
||||||
GLint last_texture0, last_texture1, last_texture2;
|
GLint last_texture0, last_texture1, last_texture2;
|
||||||
|
@ -10686,12 +10686,17 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean last_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no depth testing and bind textures
|
// Setup render state: alpha-blending enabled, no depth testing, enable clipping and bind textures
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// @fixme: store existing scissor test setup
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(rect.x, window_height() - (rect.y+rect.w), rect.z, rect.w);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
@ -10737,13 +10742,14 @@ void font_draw_cmd(font_t *f, const float *glyph_data, int glyph_idx, float fact
|
||||||
|
|
||||||
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
(last_enable_depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
|
||||||
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
(last_enable_blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND));
|
||||||
|
(last_scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. call font_face() if it's the first time it's called.
|
// 1. call font_face() if it's the first time it's called.
|
||||||
// 1. parse the string and update the instance vbo, then upload it
|
// 1. parse the string and update the instance vbo, then upload it
|
||||||
// 1. draw the string
|
// 1. draw the string
|
||||||
static
|
static
|
||||||
vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2)) {
|
vec2 font_draw_ex(const char *text, vec2 offset, vec4 rect, const char *col, void (*draw_cmd)(font_t *,const float *,int,float,vec2,vec4)) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -10783,7 +10789,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
}
|
}
|
||||||
if( ch >= 1 && ch <= 6 ) {
|
if( ch >= 1 && ch <= 6 ) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// reposition offset to align new baseline
|
// reposition offset to align new baseline
|
||||||
|
@ -10804,7 +10810,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
if( ch >= 0x10 && ch <= 0x19 ) {
|
if( ch >= 0x10 && ch <= 0x19 ) {
|
||||||
if( fonts[ ch - 0x10 ].initialized) {
|
if( fonts[ ch - 0x10 ].initialized) {
|
||||||
// flush previous state
|
// flush previous state
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
t = text_glyph_data;
|
t = text_glyph_data;
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
|
@ -10831,7 +10837,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
X += f->cdata[cp].xadvance*f->scale[S];
|
X += f->cdata[cp].xadvance*f->scale[S];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset);
|
if(draw_cmd) draw_cmd(f, text_glyph_data, (t - text_glyph_data)/4, f->scale[S], offset, rect);
|
||||||
|
|
||||||
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
//if(strstr(text, "fps")) printf("(%f,%f) (%f) L:%f LINEDIST:%f\n", X, Y, W, L, f->linedist);
|
||||||
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
return abs2(vec2(W*W > X*X ? W : X, Y*Y > LL*LL ? Y : LL));
|
||||||
|
@ -11072,7 +11078,7 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print_rect(const char *text, vec4 rect) {
|
vec2 font_clip(const char *text, vec4 rect) {
|
||||||
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
int l=0,c=0,r=0,j=0,t=0,b=0,m=0,B=0;
|
||||||
|
|
||||||
while ( text[0] == FONT_LEFT[0] ) {
|
while ( text[0] == FONT_LEFT[0] ) {
|
||||||
|
@ -11138,14 +11144,14 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
int gaps = array_count(words) - 1;
|
int gaps = array_count(words) - 1;
|
||||||
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
float space_offset = gaps > 0 ? extra_space / (float)gaps : 0;
|
||||||
for (int k = 0; k < array_count(words); ++k) {
|
for (int k = 0; k < array_count(words); ++k) {
|
||||||
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, NULL, font_draw_cmd);
|
vec2 dims = font_draw_ex(va("%s%s", tags, words[k]), gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.x += dims.x + space_offset;
|
gotoxy.x += dims.x + space_offset;
|
||||||
}
|
}
|
||||||
gotoxy.x = rect.x;
|
gotoxy.x = rect.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!j) {
|
if (!j) {
|
||||||
font_draw_ex(line, gotoxy, NULL, font_draw_cmd);
|
font_draw_ex(line, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoxy.y += text_rect.y;
|
gotoxy.y += text_rect.y;
|
||||||
|
@ -11160,7 +11166,7 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
vec2 text_rect = font_rect(text);
|
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;
|
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);
|
vec2 dims = font_draw_ex(text, gotoxy, rect, NULL, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? rect.x : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -11169,12 +11175,13 @@ vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
|
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print(const char *text) {
|
||||||
vec4 dims = {0, 0, window_width(), window_height()};
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
return font_print_rect(text, dims);
|
return font_clip(text, dims);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec4 screen_dim = {0, 0, window_width(), window_height()};
|
||||||
|
vec2 dims = font_draw_ex(text, gotoxy, screen_dim, (const char *)colors, font_draw_cmd);
|
||||||
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
gotoxy.y += strchr(text, '\n') ? dims.y : 0;
|
||||||
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
gotoxy.x = strchr(text, '\n') ? 0 : gotoxy.x + dims.x;
|
||||||
return dims;
|
return dims;
|
||||||
|
@ -11182,7 +11189,8 @@ vec2 font_highlight(const char *text, const void *colors) {
|
||||||
|
|
||||||
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
|
||||||
vec2 font_rect(const char *str) {
|
vec2 font_rect(const char *str) {
|
||||||
return font_draw_ex(str, gotoxy, NULL, NULL);
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_draw_ex(str, gotoxy, dims, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
font_metrics_t font_metrics(const char *text) {
|
font_metrics_t font_metrics(const char *text) {
|
||||||
|
|
|
@ -2213,10 +2213,9 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
API vec2 font_print_rect(const char *text, vec4 rect);
|
API vec2 font_clip(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
|
||||||
// void font_wrap(vec2 topleft, vec2 bottomright);
|
// void font_wrap(vec2 topleft, vec2 bottomright);
|
||||||
|
|
||||||
// syntax highlighting
|
// syntax highlighting
|
||||||
|
|
Loading…
Reference in New Issue