2019-02-25 23:42:13 +00:00
|
|
|
/*
|
|
|
|
* Fancy string - immediate mode renderer for colored strings
|
|
|
|
*/
|
|
|
|
|
2019-02-26 00:17:24 +00:00
|
|
|
// TOP
|
|
|
|
|
2019-02-25 23:42:13 +00:00
|
|
|
static Fancy_Color
|
2019-02-26 19:59:57 +00:00
|
|
|
fancy_blend(id_color a, f32 t, id_color b){
|
2019-02-25 23:42:13 +00:00
|
|
|
Fancy_Color result = {};
|
|
|
|
result.index_a = (u16)a;
|
|
|
|
result.index_b = (u16)b;
|
|
|
|
result.table_a = 1;
|
|
|
|
result.table_b = 1;
|
|
|
|
result.c_b = (u8)(clamp(0, 255.0f*t, 255.0f));
|
|
|
|
result.c_a = 255 - result.c_b;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_Color
|
2019-02-26 19:59:57 +00:00
|
|
|
fancy_id(id_color a){
|
2019-02-25 23:42:13 +00:00
|
|
|
Fancy_Color result = {};
|
|
|
|
result.index_a = (u16)a;
|
|
|
|
result.index_b = 0;
|
|
|
|
result.table_a = 1;
|
|
|
|
result.table_b = 0;
|
|
|
|
result.c_a = 255;
|
|
|
|
result.c_b = 0;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_Color
|
2019-02-26 19:59:57 +00:00
|
|
|
fancy_rgba(argb_color color){
|
2019-02-25 23:42:13 +00:00
|
|
|
Fancy_Color result = {};
|
|
|
|
result.rgba = color;
|
|
|
|
result.code = 0;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_Color
|
2019-02-26 19:59:57 +00:00
|
|
|
fancy_rgba(f32 r, f32 g, f32 b, f32 a){
|
|
|
|
Fancy_Color result = fancy_rgba(pack_color4(V4(r, g, b, a)));
|
2019-02-25 23:42:13 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_Color
|
|
|
|
fancy_resolve_to_rgba(Application_Links *app, Fancy_Color source){
|
|
|
|
if (source.code != 0){
|
|
|
|
Vec4 a = unpack_color4(finalize_color(app, source.index_a));
|
|
|
|
Vec4 b = unpack_color4(finalize_color(app, source.index_b));
|
|
|
|
|
|
|
|
f32 ca = (f32)source.c_a/255.0f;
|
|
|
|
f32 cb = (f32)source.c_b/255.0f;
|
|
|
|
|
|
|
|
Vec4 value = ca*a + cb*b;
|
|
|
|
|
|
|
|
source.rgba = pack_color4(value);
|
|
|
|
source.code = 0;
|
|
|
|
}
|
|
|
|
return(source);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_Color
|
2019-04-01 02:41:39 +00:00
|
|
|
fancy_pass_through(void){
|
2019-02-25 23:42:13 +00:00
|
|
|
Fancy_Color result = {};
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int_color
|
|
|
|
int_color_from(Application_Links *app, Fancy_Color source){
|
|
|
|
int_color result = {};
|
|
|
|
if ((source.c_a == 255) && (source.c_b == 0)){
|
|
|
|
result = source.index_a;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
source = fancy_resolve_to_rgba(app, source);
|
|
|
|
result = source.rgba;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static b32
|
2019-02-25 23:42:13 +00:00
|
|
|
is_valid(Fancy_Color source){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 result = !((source.code == 0) && (source.rgba == 0));
|
2019-02-25 23:42:13 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-02-26 19:59:57 +00:00
|
|
|
static void
|
|
|
|
fancy_string_list_push(Fancy_String_List *list, Fancy_String *string){
|
|
|
|
list->last = (list->last ? list->last->next : list->first) = string;
|
|
|
|
}
|
|
|
|
|
2019-02-25 23:42:13 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, Fancy_String_List *list, Fancy_Color fore, Fancy_Color back, String_Const_u8 value){
|
|
|
|
Fancy_String *result = push_array_zero(arena, Fancy_String, 1);
|
2019-07-13 00:43:17 +00:00
|
|
|
result->value = push_string_copy(arena, value);
|
2019-02-25 23:42:13 +00:00
|
|
|
result->fore = fore;
|
2019-02-26 00:17:24 +00:00
|
|
|
result->back = back;
|
2019-02-25 23:42:13 +00:00
|
|
|
if (list != 0){
|
2019-02-26 19:59:57 +00:00
|
|
|
fancy_string_list_push(list, result);
|
2019-02-25 23:42:13 +00:00
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-02-26 19:59:57 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, Fancy_Color fore, Fancy_Color back, String_Const_u8 value){
|
2019-02-26 19:59:57 +00:00
|
|
|
return(push_fancy_string(arena, 0, fore, back, value));
|
|
|
|
}
|
|
|
|
|
2019-02-26 00:17:24 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, Fancy_String_List *list, Fancy_Color fore, String_Const_u8 value){
|
2019-04-01 02:41:39 +00:00
|
|
|
return(push_fancy_string(arena, list, fore, fancy_pass_through(), value));
|
2019-02-26 00:17:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 19:59:57 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, Fancy_Color fore, String_Const_u8 value){
|
2019-04-01 02:41:39 +00:00
|
|
|
return(push_fancy_string(arena, 0, fore, fancy_pass_through(), value));
|
2019-02-26 19:59:57 +00:00
|
|
|
}
|
|
|
|
|
2019-02-25 23:42:13 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, Fancy_String_List *list, String_Const_u8 value){
|
2019-04-01 02:41:39 +00:00
|
|
|
return(push_fancy_string(arena, list, fancy_pass_through(), fancy_pass_through(), value));
|
2019-02-26 00:17:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 19:59:57 +00:00
|
|
|
static Fancy_String *
|
2019-06-01 23:58:28 +00:00
|
|
|
push_fancy_string(Arena *arena, String_Const_u8 value){
|
2019-04-01 02:41:39 +00:00
|
|
|
return(push_fancy_string(arena, 0, fancy_pass_through(), fancy_pass_through(), value));
|
2019-02-26 19:59:57 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 00:17:24 +00:00
|
|
|
static Fancy_String*
|
2019-02-27 21:14:25 +00:00
|
|
|
push_fancy_stringfv(Arena *arena, Fancy_String_List *list, Fancy_Color fore, Fancy_Color back, char *format, va_list args){
|
2019-06-20 23:43:27 +00:00
|
|
|
String_Const_u8 str = push_u8_stringfv(arena, format, args);
|
2019-02-26 00:17:24 +00:00
|
|
|
Fancy_String *result = 0;
|
2019-04-01 06:14:31 +00:00
|
|
|
if (str.size > 0){
|
|
|
|
result = push_fancy_string(arena, list, fore, back, str);
|
2019-02-26 00:17:24 +00:00
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, Fancy_String_List *list, Fancy_Color fore, Fancy_Color back, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
2019-02-27 21:14:25 +00:00
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, list, fore, back, format, args);
|
2019-02-26 00:17:24 +00:00
|
|
|
va_end(args);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, Fancy_String_List *list, Fancy_Color fore, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
2019-04-01 02:41:39 +00:00
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, list, fore, fancy_pass_through(), format, args);
|
2019-02-26 00:17:24 +00:00
|
|
|
va_end(args);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, Fancy_String_List *list, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
2019-04-01 02:41:39 +00:00
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, list, fancy_pass_through(), fancy_pass_through(), format, args);
|
2019-02-27 21:14:25 +00:00
|
|
|
va_end(args);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, Fancy_Color fore, Fancy_Color back, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, 0, fore, back, format, args);
|
|
|
|
va_end(args);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, Fancy_Color fore, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
2019-04-01 02:41:39 +00:00
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, 0, fore, fancy_pass_through(), format, args);
|
2019-02-27 21:14:25 +00:00
|
|
|
va_end(args);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Fancy_String*
|
|
|
|
push_fancy_stringf(Arena *arena, char *format, ...){
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
2019-04-01 02:41:39 +00:00
|
|
|
Fancy_String *result = push_fancy_stringfv(arena, 0, fancy_pass_through(), fancy_pass_through(), format, args);
|
2019-02-26 00:17:24 +00:00
|
|
|
va_end(args);
|
|
|
|
return(result);
|
2019-02-25 23:42:13 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 19:59:57 +00:00
|
|
|
static Fancy_String_List
|
|
|
|
fancy_string_list_single(Fancy_String *fancy_string){
|
|
|
|
Fancy_String_List list = {};
|
|
|
|
list.first = fancy_string;
|
|
|
|
list.last = fancy_string;
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
|
2019-08-24 01:34:42 +00:00
|
|
|
static Vec2_f32
|
|
|
|
draw_fancy_string(Application_Links *app, Face_ID font_id, Fancy_String *string, Vec2 P,
|
|
|
|
int_color fore, int_color back, u32 flags, Vec2 dP){
|
2019-02-25 23:42:13 +00:00
|
|
|
for (;string != 0;
|
|
|
|
string = string->next){
|
|
|
|
Face_ID use_font_id = (string->font_id) ? string->font_id : font_id;
|
|
|
|
int_color use_fore = is_valid(string->fore) ? int_color_from(app, string->fore) : fore;
|
|
|
|
|
|
|
|
f32 adv = get_string_advance(app, use_font_id, string->value);
|
|
|
|
|
|
|
|
// TODO(casey): need to fill the background here, but I don't know the line height,
|
|
|
|
// and I can't actually render filled shapes, so, like, I can't properly do dP :(
|
|
|
|
|
2019-06-20 04:45:58 +00:00
|
|
|
Face_Metrics metrics = get_face_metrics(app, font_id);
|
2019-04-01 00:36:09 +00:00
|
|
|
|
|
|
|
P += (string->pre_margin*metrics.typical_character_width)*dP;
|
2019-10-05 02:48:05 +00:00
|
|
|
draw_string_oriented(app, use_font_id, string->value, P, use_fore, flags, dP);
|
2019-04-01 00:36:09 +00:00
|
|
|
P += (adv + string->post_margin*metrics.typical_character_width)*dP;
|
2019-02-25 23:42:13 +00:00
|
|
|
}
|
|
|
|
return(P);
|
|
|
|
}
|
2019-02-26 00:17:24 +00:00
|
|
|
|
2019-08-24 01:34:42 +00:00
|
|
|
static Vec2_f32
|
|
|
|
draw_fancy_string(Application_Links *app, Face_ID font_id, Fancy_String *string, Vec2 P,
|
|
|
|
int_color fore, int_color back){
|
2019-02-27 05:49:35 +00:00
|
|
|
return(draw_fancy_string(app, font_id, string, P, fore, back, 0, V2(1.f, 0.f)));
|
|
|
|
}
|
|
|
|
|
2019-08-24 01:34:42 +00:00
|
|
|
static f32
|
|
|
|
get_fancy_string_advance(Application_Links *app, Face_ID font_id, Fancy_String *string){
|
|
|
|
f32 advance = 0.f;
|
|
|
|
for (;string != 0;
|
|
|
|
string = string->next){
|
|
|
|
Face_ID use_font_id = (string->font_id) ? string->font_id : font_id;
|
|
|
|
f32 adv = get_string_advance(app, use_font_id, string->value);
|
|
|
|
Face_Metrics metrics = get_face_metrics(app, font_id);
|
|
|
|
advance += (string->pre_margin + string->post_margin)*metrics.typical_character_width + adv;
|
|
|
|
}
|
|
|
|
return(advance);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-10-05 02:48:05 +00:00
|
|
|
draw_rectangle_fancy(Application_Links *app, Rect_f32 rect, Fancy_Color fancy_color){
|
2019-08-24 01:34:42 +00:00
|
|
|
int_color color = int_color_from(app, fancy_color);
|
2019-10-08 17:18:20 +00:00
|
|
|
draw_rectangle(app, rect, 0.f, color);
|
2019-08-24 01:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
2019-09-27 23:56:05 +00:00
|
|
|
// TODO(allen): beta: color palette
|
2019-08-24 01:34:42 +00:00
|
|
|
global Fancy_Color white = fancy_rgba(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
global Fancy_Color light_gray = fancy_rgba(0.7f, 0.7f, 0.7f, 1.0f);
|
|
|
|
global Fancy_Color gray = fancy_rgba(0.5f, 0.5f, 0.5f, 1.0f);
|
|
|
|
global Fancy_Color dark_gray = fancy_rgba(0.3f, 0.3f, 0.3f, 1.0f);
|
|
|
|
global Fancy_Color black = fancy_rgba(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
global Fancy_Color pink = fancy_rgba(1.0f, 0.0f, 1.0f, 1.0f);
|
|
|
|
global Fancy_Color green = fancy_rgba(0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
2019-02-26 00:17:24 +00:00
|
|
|
// BOTTOM
|
|
|
|
|