4coder/custom/4coder_fancy.cpp

845 lines
29 KiB
C++

/*
* Fancy string - immediate mode renderer for colored strings
*/
// TOP
function FColor
fcolor_argb(ARGB_Color color){
FColor result = {};
result.argb = color;
if (result.a_byte == 0){
result.argb = 0;
}
return(result);
}
function FColor
fcolor_argb(Vec4_f32 color){
return(fcolor_argb(pack_color(color)));
}
function FColor
fcolor_argb(f32 r, f32 g, f32 b, f32 a){
return(fcolor_argb(pack_color(V4f32(r, g, b, a))));
}
function FColor
fcolor_id(Managed_ID id){
FColor result = {};
result.id = (ID_Color)id;
return(result);
}
function FColor
fcolor_id(Managed_ID id, u32 sub_index){
FColor result = {};
result.id = (ID_Color)id;
result.sub_index = (u8)sub_index;
return(result);
}
function ARGB_Color
argb_color_blend(ARGB_Color a, f32 at, ARGB_Color b, f32 bt){
Vec4_f32 av = unpack_color(a);
Vec4_f32 bv = unpack_color(b);
Vec4_f32 value = at*av + bt*bv;
return(pack_color(value));
}
function ARGB_Color
argb_color_blend(ARGB_Color a, f32 t, ARGB_Color b){
return(argb_color_blend(a, 1.f - t, b, t));
}
function ARGB_Color
fcolor_resolve(FColor color){
ARGB_Color result = 0;
if (color.a_byte == 0){
if (color.id != 0){
result = finalize_color(color.id, color.sub_index);
}
}
else{
result = color.argb;
}
return(result);
}
function FColor
fcolor_change_alpha(FColor color, f32 alpha){
Vec4_f32 v = unpack_color(fcolor_resolve(color));
v.a = alpha;
return(fcolor_argb(pack_color(v)));
}
function FColor
fcolor_blend(FColor a, f32 at, FColor b, f32 bt){
ARGB_Color a_argb = fcolor_resolve(a);
ARGB_Color b_argb = fcolor_resolve(b);
return(fcolor_argb(argb_color_blend(a_argb, at, b_argb, bt)));
}
function FColor
fcolor_blend(FColor a, f32 t, FColor b){
return(fcolor_blend(a, 1.f - t, b, t));
}
function FColor
fcolor_zero(void){
FColor result = {};
return(result);
}
function b32
fcolor_is_valid(FColor color){
return(color.argb != 0);
}
////////////////////////////////
function void
push_fancy_string(Fancy_Line *line, Fancy_String *string){
sll_queue_push(line->first, line->last, string);
}
function void
push_fancy_line(Fancy_Block *block, Fancy_Line *line){
sll_queue_push(block->first, block->last, line);
block->line_count += 1;
}
////////////////////////////////
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
f32 pre_margin, f32 post_margin, String_Const_u8 value){
Fancy_String *result = push_array_zero(arena, Fancy_String, 1);
result->value = value;
result->face = face;
result->fore = fore;
result->pre_margin = pre_margin;
result->post_margin = post_margin;
if (line != 0){
push_fancy_string(line, result);
}
return(result);
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
String_Const_u8 value){
return(push_fancy_string(arena, line, face, fore, 0, 0, value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, Face_ID face,
f32 pre_margin, f32 post_margin, String_Const_u8 value){
return(push_fancy_string(arena, line, face, fcolor_zero(),
pre_margin, post_margin, value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, FColor fore,
f32 pre_margin, f32 post_margin, String_Const_u8 value){
return(push_fancy_string(arena, line, 0, fore, pre_margin, post_margin, value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, Face_ID face, String_Const_u8 value){
return(push_fancy_string(arena, line, face, fcolor_zero(), 0, 0, value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, FColor color, String_Const_u8 value){
return(push_fancy_string(arena, line, 0, color, 0, 0, value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, f32 pre_margin, f32 post_margin,
String_Const_u8 value){
return(push_fancy_string(arena, line, 0, fcolor_zero(), pre_margin, post_margin,
value));
}
function Fancy_String*
push_fancy_string(Arena *arena, Fancy_Line *line, String_Const_u8 value){
return(push_fancy_string(arena, line, 0, fcolor_zero(), 0, 0, value));
}
////////////////////////////////
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
f32 pre_margin, f32 post_margin,
char *format, va_list args){
return(push_fancy_string(arena, line, face, fore, pre_margin, post_margin,
push_u8_stringfv(arena, format, args)));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, face, fore, 0, 0, format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, Face_ID face,
f32 pre_margin, f32 post_margin,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, face, fcolor_zero(),
pre_margin, post_margin, format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, FColor fore,
f32 pre_margin, f32 post_margin,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, 0, fore, pre_margin, post_margin,
format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, Face_ID face,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, face, fcolor_zero(), 0, 0,
format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, FColor color,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, 0, color, 0, 0, format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line, f32 pre_margin, f32 post_margin,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, 0, fcolor_zero(), pre_margin, post_margin,
format, args));
}
function Fancy_String*
push_fancy_stringfv(Arena *arena, Fancy_Line *line,
char *format, va_list args){
return(push_fancy_stringfv(arena, line, 0, fcolor_zero(), 0, 0, format, args));
}
#define StringFBegin() va_list args; va_start(args, format)
#define StringFPass(N) Fancy_String *result = N
#define StringFEnd() va_end(args); return(result)
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
f32 pre_margin, f32 post_margin,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_string(arena, line, face, fore, pre_margin, post_margin,
push_u8_stringfv(arena, format, args)));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, face, fore, 0, 0, format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, Face_ID face,
f32 pre_margin, f32 post_margin,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, face, fcolor_zero(),
pre_margin, post_margin, format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, FColor fore,
f32 pre_margin, f32 post_margin,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, 0, fore, pre_margin, post_margin,
format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, Face_ID face,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, face, fcolor_zero(), 0, 0,
format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, FColor color,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, 0, color, 0, 0, format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line, f32 pre_margin, f32 post_margin,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, 0, fcolor_zero(),
pre_margin, post_margin, format, args));
StringFEnd();
}
function Fancy_String*
push_fancy_stringf(Arena *arena, Fancy_Line *line,
char *format, ...){
StringFBegin();
StringFPass(push_fancy_stringfv(arena, line, 0, fcolor_zero(), 0, 0, format, args));
StringFEnd();
}
////////////////////////////////
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
f32 pre_margin, f32 post_margin,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fore, pre_margin, post_margin,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fore, pre_margin, post_margin,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fore, 0.f, 0.f,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fore, 0.f, 0.f,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, Face_ID face,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fcolor_zero(),
pre_margin, post_margin,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fcolor_zero(),
pre_margin, post_margin,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, FColor fore,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, 0, fore, pre_margin, post_margin,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, 0, fore, pre_margin, post_margin,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, Face_ID face,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fcolor_zero(), 0.f, 0.f,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fcolor_zero(), 0.f, 0.f,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, FColor fore,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fore, 0.f, 0.f,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fore, 0.f, 0.f,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(),
pre_margin, post_margin,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(),
pre_margin, post_margin,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_fixed(Arena *arena, Fancy_Line *line, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(), 0.f, 0.f,
"%-*.*s", max, string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(), 0.f, 0.f,
"%-*.*s...", max - 3, string_expand(value)));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
f32 pre_margin, f32 post_margin,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fore, pre_margin, post_margin,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fore, pre_margin, post_margin,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, Face_ID face, FColor fore,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fore, 0.f, 0.f,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fore, 0.f, 0.f,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, Face_ID face,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fcolor_zero(),
pre_margin, post_margin,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fcolor_zero(),
pre_margin, post_margin,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, FColor fore,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, 0, fore, pre_margin, post_margin,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, 0, fore, pre_margin, post_margin,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, Face_ID face,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, face, fcolor_zero(), 0.f, 0.f,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, face, fcolor_zero(), 0.f, 0.f,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, FColor fore,
String_Const_u8 value, i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fore, 0.f, 0.f,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fore, 0.f, 0.f,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line,
f32 pre_margin, f32 post_margin, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(),
pre_margin, post_margin,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(),
pre_margin, post_margin,
"%.*s...", max - 3, value.str));
}
}
function Fancy_String*
push_fancy_string_trunc(Arena *arena, Fancy_Line *line, String_Const_u8 value,
i32 max){
if (value.size <= max){
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(), 0.f, 0.f,
"%.*s", string_expand(value)));
}
else{
return(push_fancy_stringf(arena, line, (Face_ID)0, fcolor_zero(), 0.f, 0.f,
"%.*s...", max - 3, value.str));
}
}
////////////////////////////////
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, Face_ID face, FColor fore,
String_Const_u8 text){
Fancy_Line *line = push_array_zero(arena, Fancy_Line, 1);
line->face = face;
line->fore = fore;
if (text.size != 0){
push_fancy_string(arena, line, text);
}
if (block != 0){
push_fancy_line(block, line);
}
return(line);
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, Face_ID face, FColor fcolor){
return(push_fancy_line(arena, block, face, fcolor, SCu8()));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, Face_ID face, String_Const_u8 val){
return(push_fancy_line(arena, block, face, fcolor_zero(), val));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, FColor color, String_Const_u8 val){
return(push_fancy_line(arena, block, 0, color, val));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, Face_ID face){
return(push_fancy_line(arena, block, face, fcolor_zero(), SCu8()));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, FColor color){
return(push_fancy_line(arena, block, 0, color, SCu8()));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block, String_Const_u8 val){
return(push_fancy_line(arena, block, 0, fcolor_zero(), val));
}
function Fancy_Line*
push_fancy_line(Arena *arena, Fancy_Block *block){
return(push_fancy_line(arena, block, 0, fcolor_zero(), SCu8()));
}
////////////////////////////////
function f32
get_fancy_string_width__inner(Application_Links *app, Face_ID face,
Fancy_String *string){
f32 result = 0.f;
for (;string != 0;
string = string->next){
Face_ID use_face = face;
if (string->face != 0){
use_face = string->face;
}
if (use_face != 0){
result += get_string_advance(app, use_face, string->value);
Face_Metrics metrics = get_face_metrics(app, use_face);
f32 normal_advance = metrics.normal_advance;
result += (string->pre_margin + string->post_margin)*normal_advance;
}
}
return(result);
}
function f32
get_fancy_string_height__inner(Application_Links *app, Face_ID face, Fancy_String *string){
f32 result = 0.f;
if (face != 0){
Face_Metrics metrics = get_face_metrics(app, face);
result = metrics.line_height;
}
for (;string != 0;
string = string->next){
if (string->face != 0){
Face_ID use_face = string->face;
Face_Metrics metrics = get_face_metrics(app, use_face);
result = Max(result, metrics.line_height);
}
}
return(result);
}
function f32
get_fancy_string_text_height__inner(Application_Links *app, Face_ID face, Fancy_String *string){
f32 result = 0.f;
if (face != 0){
Face_Metrics metrics = get_face_metrics(app, face);
result = metrics.text_height;
}
for (;string != 0;
string = string->next){
if (string->face != 0){
Face_ID use_face = string->face;
Face_Metrics metrics = get_face_metrics(app, use_face);
result = Max(result, metrics.text_height);
}
}
return(result);
}
function Vec2_f32
draw_fancy_string__inner(Application_Links *app, Face_ID face, FColor fore, Fancy_String *first_string, Vec2_f32 p, u32 flags, Vec2_f32 delta){
f32 base_line = 0.f;
for (Fancy_String *string = first_string;
string != 0;
string = string->next){
Face_ID use_face = face;
if (string->face != 0){
use_face = string->face;
}
if (use_face != 0){
Face_Metrics metrics = get_face_metrics(app, use_face);
base_line = Max(base_line, metrics.ascent);
}
}
Vec2_f32 down_delta = V2f32(-delta.y, delta.x);
for (Fancy_String *string = first_string;
string != 0;
string = string->next){
Face_ID use_face = face;
if (string->face != 0){
use_face = string->face;
}
FColor use_fore = fore;
if (fcolor_is_valid(string->fore)){
use_fore = string->fore;
}
if (use_face != 0){
ARGB_Color use_argb = fcolor_resolve(use_fore);
Face_Metrics metrics = get_face_metrics(app, use_face);
f32 down_shift = (base_line - metrics.ascent);
down_shift = clamp_bot(0.f, down_shift);
Vec2_f32 p_shift = down_shift*down_delta;
Vec2_f32 p_shifted = p + p_shift;
if (fcolor_is_valid(use_fore)){
Vec2_f32 margin_delta = delta*metrics.normal_advance;
p_shifted += margin_delta*string->pre_margin;
p_shifted = draw_string_oriented(app, use_face, use_argb, string->value, p_shifted, flags, delta);
p_shifted += margin_delta*string->post_margin;
}
else{
f32 adv =
(string->pre_margin + string->post_margin)*metrics.normal_advance;
adv += get_string_advance(app, use_face, string->value);
p_shifted += adv*delta;
}
p = p_shifted - p_shift;
}
}
return(p);
}
function f32
get_fancy_string_width(Application_Links *app, Face_ID face,
Fancy_String *string){
Fancy_String *next = string->next;
string->next = 0;
f32 result = get_fancy_string_width__inner(app, face, string);
string->next = next;
return(result);
}
function f32
get_fancy_string_height(Application_Links *app, Face_ID face,
Fancy_String *string){
Fancy_String *next = string->next;
string->next = 0;
f32 result = get_fancy_string_height__inner(app, face, string);
string->next = next;
return(result);
}
function f32
get_fancy_string_text_height(Application_Links *app, Face_ID face,
Fancy_String *string){
Fancy_String *next = string->next;
string->next = 0;
f32 result = get_fancy_string_text_height__inner(app, face, string);
string->next = next;
return(result);
}
function Vec2_f32
get_fancy_string_dim(Application_Links *app, Face_ID face, Fancy_String *string){
Fancy_String *next = string->next;
string->next = 0;
Vec2_f32 result = V2f32(get_fancy_string_width__inner(app, face, string),
get_fancy_string_height__inner(app, face, string));
string->next = next;
return(result);
}
function Vec2_f32
draw_fancy_string(Application_Links *app, Face_ID face, FColor fore,
Fancy_String *string, Vec2_f32 p, u32 flags, Vec2_f32 delta){
Fancy_String *next = string->next;
string->next = 0;
Vec2_f32 result = draw_fancy_string__inner(app, face, fore, string, p, flags, delta);
string->next = next;
return(result);
}
function f32
get_fancy_line_width(Application_Links *app, Face_ID face, Fancy_Line *line){
f32 result = 0.f;
if (line != 0){
if (line->face != 0){
face = line->face;
}
result = get_fancy_string_width__inner(app, face, line->first);
}
return(result);
}
function f32
get_fancy_line_height(Application_Links *app, Face_ID face, Fancy_Line *line){
f32 result = 0.f;
if (line != 0){
if (line->face != 0){
face = line->face;
}
result = get_fancy_string_height__inner(app, face, line->first);
}
return(result);
}
function f32
get_fancy_line_text_height(Application_Links *app, Face_ID face, Fancy_Line *line){
f32 result = 0.f;
if (line != 0){
if (line->face != 0){
face = line->face;
}
result = get_fancy_string_text_height__inner(app, face, line->first);
}
return(result);
}
function Vec2_f32
get_fancy_line_dim(Application_Links *app, Face_ID face, Fancy_Line *line){
Vec2_f32 result = {};
if (line != 0){
if (line->face != 0){
face = line->face;
}
result = V2f32(get_fancy_string_width__inner(app, face, line->first), get_fancy_string_height__inner(app, face, line->first));
}
return(result);
}
function Vec2_f32
draw_fancy_line(Application_Links *app, Face_ID face, FColor fore,
Fancy_Line *line, Vec2_f32 p, u32 flags, Vec2_f32 delta){
Vec2_f32 result = {};
if (line != 0){
if (line->face != 0){
face = line->face;
}
if (fcolor_is_valid(line->fore)){
fore = line->fore;
}
result = draw_fancy_string__inner(app, face, fore, line->first, p, flags, delta);
}
return(result);
}
function f32
get_fancy_block_width(Application_Links *app, Face_ID face, Fancy_Block *block){
f32 width = 0.f;
for (Fancy_Line *node = block->first;
node != 0;
node = node->next){
f32 w = get_fancy_line_width(app, face, node);
width = Max(width, w);
}
return(width);
}
function f32
get_fancy_block_height(Application_Links *app, Face_ID face, Fancy_Block *block){
f32 height = 0.f;
for (Fancy_Line *node = block->first;
node != 0;
node = node->next){
height += get_fancy_line_height(app, face, node);
}
return(height);
}
function Vec2_f32
get_fancy_block_dim(Application_Links *app, Face_ID face, Fancy_Block *block){
Vec2_f32 result = {};
result.x = get_fancy_block_width(app, face, block);
result.y = get_fancy_block_height(app, face, block);
return(result);
}
function void
draw_fancy_block(Application_Links *app, Face_ID face, FColor fore,
Fancy_Block *block, Vec2_f32 p, u32 flags, Vec2_f32 delta){
for (Fancy_Line *node = block->first;
node != 0;
node = node->next){
draw_fancy_line(app, face, fore, node, p, flags, delta);
p.y += get_fancy_line_height(app, face, node);
}
}
function Vec2_f32
draw_fancy_string(Application_Links *app, Face_ID face, FColor fore,
Fancy_String *string, Vec2_f32 p){
return(draw_fancy_string(app, face, fore, string, p, 0, V2f32(1.f, 0.f)));
}
function Vec2_f32
draw_fancy_string(Application_Links *app, Fancy_String *string, Vec2_f32 p){
return(draw_fancy_string(app, 0, fcolor_zero(), string, p, 0, V2f32(1.f, 0.f)));
}
function Vec2_f32
draw_fancy_line(Application_Links *app, Face_ID face, FColor fore,
Fancy_Line *line, Vec2_f32 p){
return(draw_fancy_line(app, face, fore, line, p, 0, V2f32(1.f, 0.f)));
}
function void
draw_fancy_block(Application_Links *app, Face_ID face, FColor fore,
Fancy_Block *block, Vec2_f32 p){
draw_fancy_block(app, face, fore, block, p, 0, V2f32(1.f, 0.f));
}
////////////////////////////////
// TODO(allen): beta: color palette
global FColor f_white = fcolor_argb(1.0f, 1.0f, 1.0f, 1.0f);
global FColor f_light_gray = fcolor_argb(0.7f, 0.7f, 0.7f, 1.0f);
global FColor f_gray = fcolor_argb(0.5f, 0.5f, 0.5f, 1.0f);
global FColor f_dark_gray = fcolor_argb(0.3f, 0.3f, 0.3f, 1.0f);
global FColor f_black = fcolor_argb(0.0f, 0.0f, 0.0f, 1.0f);
global FColor f_red = fcolor_argb(1.0f, 0.0f, 0.0f, 1.0f);
global FColor f_green = fcolor_argb(0.0f, 1.0f, 0.0f, 1.0f);
global FColor f_blue = fcolor_argb(0.0f, 0.0f, 1.0f, 1.0f);
global FColor f_yellow = fcolor_argb(1.0f, 1.0f, 0.0f, 1.0f);
global FColor f_pink = fcolor_argb(1.0f, 0.0f, 1.0f, 1.0f);
global FColor f_cyan = fcolor_argb(0.0f, 1.0f, 1.0f, 1.0f);
// BOTTOM