#include <alias/ui.h>
struct alias_ui_dstack_child {
uint32_t hole;
float weight;
};
struct alias_ui_named_scope {
uint64_t hash;
uint32_t query_capacity;
float *query_rects;
uint32_t slot_capacity;
uint32_t *slot;
};
struct alias_ui_tree_scope {
uint32_t named_scope_index;
uint32_t font_index;
float font_size;
uint32_t font_color;
float weight;
bool handle_alignment;
float align_x;
float align_y;
union {
struct {
uint32_t hole;
uint32_t num_children;
} stack;
struct {
bool vertical;
uint32_t hole;
uint32_t child_pmark;
uint32_t child_mmark;
float total_weight;
uint32_t children_capacity;
uint32_t children_length;
struct alias_ui_dstack_child *children;
} dstack;
};
void (*begin_child)(struct alias_ui *, struct alias_ui_tree_scope *);
void (*end_child)(struct alias_ui *, struct alias_ui_tree_scope *);
void (*end_scope)(struct alias_ui *, struct alias_ui_tree_scope *);
void *user_data;
};
struct alias_ui {
alias_MemoryCB *mcb;
alias_ui_Input input;
alias_ui_Output *output;
uint32_t font_capacity;
uint32_t font_length;
struct alias_ui_Font *font;
uint32_t named_scope_capacity;
uint32_t named_scope_length;
struct alias_ui_named_scope *named_scope;
uint32_t tree_scope_capacity;
uint32_t tree_scope_length;
struct alias_ui_tree_scope *tree_scope;
uint32_t program_capacity;
uint32_t program_length;
uint32_t *program;
uint32_t *ip;
uint32_t memory_capacity;
uint32_t memory_length;
uint32_t *memory;
uint32_t *mp;
uint32_t groups_capacity;
uint32_t groups_length;
struct alias_ui_group *groups;
uint32_t texture_id;
#ifdef UNICAT_UI_ENABLE_FREETYPE
uint32_t (*freetype_texture_callback)(uint32_t length, void ** ptr);
#endif
struct {
uint32_t texture_id;
uint32_t num_vertexes;
uint32_t num_indexes;
uint32_t num_groups;
} stats;
};
enum {
P_TERMINATE,
P_EMPTY_FILL,
P_COLOR_FILL,
P_IMAGE,
P_TEXT,
P_BACKGROUND_COLOR,
P_BORDER,
P_STACK,
P_HORIZONTAL_STACK,
P_VERTICAL_STACK,
P_SIZE,
P_WIDTH,
P_HEIGHT,
P_ALIGN,
P_ALIGN_X,
P_ALIGN_Y,
P_PADDING,
P_QUERY,
};
static inline bool alias_ui__grow(void **ptr, uint32_t element_size, uint32_t length, uint32_t *capacity) {
uint32_t old_capacity = *capacity;
if(length > old_capacity) {
*capacity = length + 1;
*capacity += *capacity >> 1;
void * new_ptr = alias_realloc(NULL, *ptr, element_size * old_capacity, element_size * *capacity, 4);
if(new_ptr == NULL) {
return false;
}
*ptr = new_ptr;
}
return true;
}
static inline void alias_ui__tree__space_for(struct alias_ui *ui, uint32_t count) {
alias_ui__grow((void **)&ui->tree_scope, sizeof(*ui->tree_scope), ui->tree_scope_length + count,
&ui->tree_scope_capacity);
}
static inline struct alias_ui_tree_scope *alias_ui__tree__top_scope(struct alias_ui *ui) {
assert(ui->tree_scope_length > 0);
return &ui->tree_scope[ui->tree_scope_length - 1];
}
static inline void alias_ui__tree__begin_child(struct alias_ui *ui) {
if(ui->tree_scope_length > 0) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
if(scope->begin_child) {
scope->begin_child(ui, scope);
}
}
}
static inline void alias_ui__tree__end_child(struct alias_ui *ui) {
if(ui->tree_scope_length > 0) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
if(scope->end_child) {
scope->end_child(ui, scope);
}
}
}
static inline void alias_ui__tree__end_scope(struct alias_ui *ui) {
if(ui->tree_scope_length > 0) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
ui->tree_scope_length -= 1;
if(scope->end_scope) {
scope->end_scope(ui, scope);
}
}
}
static inline void alias_ui__tree__begin_scope(struct alias_ui *ui,
void (*begin_child)(struct alias_ui *, struct alias_ui_tree_scope *),
void (*end_child)(struct alias_ui *, struct alias_ui_tree_scope *),
void (*end_scope)(struct alias_ui *, struct alias_ui_tree_scope *)) {
alias_ui__tree__space_for(ui, 1);
struct alias_ui_tree_scope *parent_scope = ui->tree_scope_length > 0 ? alias_ui__tree__top_scope(ui) : NULL;
ui->tree_scope_length += 1;
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
if(parent_scope != NULL) {
scope->named_scope_index = parent_scope->named_scope_index;
scope->font_index = parent_scope->font_index;
scope->font_size = parent_scope->font_size;
scope->font_color = parent_scope->font_color;
if(parent_scope->handle_alignment) {
scope->handle_alignment = true;
scope->align_x = parent_scope->align_x;
scope->align_y = parent_scope->align_y;
}
} else {
scope->named_scope_index = -1;
scope->font_index = 0;
scope->font_size = 16;
scope->font_color = 0xFFFFFFFF;
}
scope->begin_child = begin_child;
scope->end_child = end_child;
scope->end_scope = end_scope;
}
static inline void alias_ui__program__space_for(struct alias_ui *ui, uint32_t count) {
alias_ui__grow((void **)&ui->program, sizeof(*ui->program), ui->program_length + count, &ui->program_capacity);
}
static inline void alias_ui__program__initialize(struct alias_ui *ui) {
ui->program_length = 0;
}
static inline uint32_t alias_ui__program__mark(struct alias_ui *ui) {
return ui->program_length;
}
static inline uint32_t alias_ui__program__mark_size(struct alias_ui *ui, uint32_t mark) {
return ui->program_length - mark;
}
static inline void alias_ui__program__reserve(struct alias_ui *ui, uint32_t space) {
alias_ui__program__space_for(ui, space);
ui->program_length += space;
}
static inline uint32_t alias_ui__program__dig(struct alias_ui *ui, uint32_t space) {
uint32_t result = alias_ui__program__mark(ui);
alias_ui__program__reserve(ui, space);
return result;
}
static inline void alias_ui__program__emit_u32(struct alias_ui *ui, uint32_t value) {
alias_ui__program__space_for(ui, 1);
ui->program[ui->program_length++] = value;
}
static inline void alias_ui__program__emit_f32(struct alias_ui *ui, float value) {
union {
uint32_t u;
float f;
} flip = {.f = value};
alias_ui__program__emit_u32(ui, flip.u);
}
static inline void alias_ui__program__fill_u32(struct alias_ui *ui, uint32_t hole, uint32_t value) {
ui->program[hole] = value;
}
static inline void alias_ui__program__fill_f32(struct alias_ui *ui, uint32_t hole, float value) {
union {
uint32_t u;
float f;
} flip = {.f = value};
alias_ui__program__fill_u32(ui, hole, flip.u);
}
static inline void alias_ui__ip__initialize(struct alias_ui *ui) {
ui->ip = ui->program;
}
static inline void alias_ui__ip__advance(struct alias_ui *ui, uint32_t count) {
ui->ip += count;
}
static inline uint32_t alias_ui__ip__read_u32(struct alias_ui *ui) {
return *ui->ip++;
}
static inline float alias_ui__ip__read_f32(struct alias_ui *ui) {
union {
uint32_t u;
float f;
} flip = {.u = alias_ui__ip__read_u32(ui)};
return flip.f;
}
static inline void alias_ui__memory__space_for(struct alias_ui *ui, uint32_t count) {
alias_ui__grow((void **)&ui->memory, sizeof(*ui->memory), ui->memory_length + count, &ui->memory_capacity);
}
static inline void alias_ui__memory__initialize(struct alias_ui *ui) {
ui->memory_length = 0;
}
static inline uint32_t alias_ui__memory__mark(struct alias_ui *ui) {
return ui->memory_length;
}
static inline uint32_t alias_ui__memory__mark_size(struct alias_ui *ui, uint32_t mark) {
return ui->memory_length - mark;
}
static inline void alias_ui__memory__reserve(struct alias_ui *ui, uint32_t space) {
alias_ui__memory__space_for(ui, space);
ui->memory_length += space;
}
static inline uint32_t alias_ui__memory__dig(struct alias_ui *ui, uint32_t space) {
uint32_t result = alias_ui__memory__mark(ui);
alias_ui__memory__reserve(ui, space);
return result;
}
static inline void alias_ui__memory__fill_u32(struct alias_ui *ui, uint32_t hole, uint32_t value) {
assert(hole < ui->memory_length);
ui->memory[hole] = value;
}
static inline void alias_ui__memory__fill_f32(struct alias_ui *ui, uint32_t hole, float value) {
union {
uint32_t u;
float f;
} flip = {.f = value};
alias_ui__memory__fill_u32(ui, hole, flip.u);
}
static inline float alias_ui__float__min(float a, float b) {
return a < b ? a : b;
}
static inline float alias_ui__float__max(float a, float b) {
return a > b ? a : b;
}
static inline float alias_ui__float__clamp(float x, float min, float max) {
return alias_ui__float__min(alias_ui__float__max(x, min), max);
}
static inline uint8_t alias_ui__float__to_color_channel(float x) {
return (uint8_t)alias_ui__float__clamp(x * 255.0f, 0.0f, 255.0f);
}
static inline uint32_t alias_ui__color__pack(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
return ((uint32_t)r << 24) | ((uint32_t)g << 16) | ((uint32_t)b << 8) | a;
}
static inline void alias_ui__color__unpack(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a) {
*r = (color >> 24) & 0xFF;
*g = (color >> 16) & 0xFF;
*b = (color >> 8) & 0xFF;
*a = (color >> 0) & 0xFF;
}
static inline void alias_ui__mp__initialize(struct alias_ui *ui) {
ui->mp = ui->memory;
}
static inline void alias_ui__mp__advance(struct alias_ui *ui, uint32_t count) {
ui->mp += count;
}
static inline uint32_t alias_ui__mp__read_u32(struct alias_ui *ui) {
return *ui->mp++;
}
static inline float alias_ui__mp__read_f32(struct alias_ui *ui) {
union {
uint32_t u;
float f;
} flip = {.u = alias_ui__mp__read_u32(ui)};
return flip.f;
}
static inline void alias_ui__vertex__initialize(struct alias_ui *ui) {
ui->output->num_vertexes = 0;
}
static inline uint32_t alias_ui__vertex__emit(struct alias_ui *ui, float x, float y, float s, float t, uint8_t r,
uint8_t g, uint8_t b, uint8_t a) {
float xy[] = {x, y};
float rgba[] = {r, g, b, a};
float st[] = {s, t};
alias_memory_SubBuffer_write(&ui->output->xy_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Float32, 0, xy);
alias_memory_SubBuffer_write(&ui->output->rgba_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Unorm8, 0, rgba);
alias_memory_SubBuffer_write(&ui->output->st_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Float32, 0, st);
return ui->output->num_vertexes++;
}
static inline void alias_ui__index__initialize(struct alias_ui *ui) {
ui->output->num_indexes = 0;
}
static inline uint32_t alias_ui__index__emit(struct alias_ui *ui, uint32_t vertex_index) {
alias_memory_SubBuffer_write(&ui->output->index_sub_buffer, ui->output->num_indexes, 1, alias_memory_Format_Sint32, 0, &vertex_index);
return ui->output->num_indexes++;
}
static inline void alias_ui__group__initialize(struct alias_ui *ui) {
ui->output->num_groups = 0;
}
static inline struct alias_ui_OutputGroup *alias_ui__group__top(struct alias_ui *ui) {
return &ui->output->groups[ui->groups_length - 1];
}
static inline void alias_ui__group__prepare(struct alias_ui *ui) {
struct alias_ui_OutputGroup *group = alias_ui__group__top(ui);
group->texture_id = ui->texture_id;
group->index = ui->output->num_indexes;
group->length = 0;
}
static inline void alias_ui__group__finalize(struct alias_ui *ui) {
struct alias_ui_OutputGroup *group = alias_ui__group__top(ui);
group->length = ui->output->num_indexes - group->index;
}
static inline void alias_ui__group__advance(struct alias_ui *ui) {
if(ui->groups_length > 0) {
alias_ui__group__finalize(ui);
}
ui->groups_length++;
alias_ui__group__prepare(ui);
}
void alias_ui_set_texture(struct alias_ui *ui, uint32_t texture_id) {
if(ui->texture_id != texture_id) {
ui->texture_id = texture_id;
alias_ui__group__advance(ui);
}
}
void alias_ui_draw_rectangle(struct alias_ui *ui, float x, float y, float width, float height,
float s0, float t0, float s1, float t1, uint8_t r, uint8_t g,
uint8_t b, uint8_t a) {
float x0 = x;
float y0 = y;
float x1 = x + width;
float y1 = y + height;
uint32_t A = alias_ui__vertex__emit(ui, x0, y0, s0, t0, r, g, b, a);
uint32_t B = alias_ui__vertex__emit(ui, x0, y1, s0, t1, r, g, b, a);
uint32_t C = alias_ui__vertex__emit(ui, x1, y1, s1, t1, r, g, b, a);
uint32_t D = alias_ui__vertex__emit(ui, x1, y0, s1, t0, r, g, b, a);
alias_ui__index__emit(ui, A);
alias_ui__index__emit(ui, B);
alias_ui__index__emit(ui, C);
alias_ui__index__emit(ui, A);
alias_ui__index__emit(ui, C);
alias_ui__index__emit(ui, D);
}
static inline void alias_ui__stats__initialize(alias_ui *ui) {
memset(&ui->stats, 0, sizeof(ui->stats));
ui->stats.texture_id = -1;
}
static inline void alias_ui__stats__set_texture(alias_ui *ui, uint32_t texture_id) {
if(ui->stats.texture_id != texture_id) {
ui->stats.texture_id = texture_id;
ui->stats.num_groups += 1;
}
}
static inline void alias_ui__stats__draw_rectangle(struct alias_ui *ui) {
ui->stats.num_vertexes += 4;
ui->stats.num_indexes += 6;
}
static inline void alias_ui__layout(struct alias_ui *, float, float, float, float, float *, float *);
static inline void alias_ui__render(struct alias_ui *, float, float, float, float);
static void alias_ui__empty_fill__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
*out_width = max_width;
*out_height = max_height;
}
static void alias_ui__empty_fill__render(struct alias_ui *ui, float x, float y, float width, float height) {}
void alias_ui_empty_fill(struct alias_ui *ui) {
alias_ui__tree__begin_child(ui);
alias_ui__program__emit_u32(ui, P_EMPTY_FILL);
alias_ui__tree__end_child(ui);
}
static void alias_ui__color_fill__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
alias_ui__ip__advance(ui, 4);
*out_width = max_width;
*out_height = max_height;
}
static void alias_ui__color_fill__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t color = alias_ui__ip__read_u32(ui);
uint8_t r, g, b, a;
alias_ui__color__unpack(color, &r, &g, &b, &a);
alias_ui_set_texture(ui, 0);
alias_ui_draw_rectangle(ui, x, y, width, height, 0, 0, 1, 1, r, g, b, a);
}
void alias_ui_color_fill(struct alias_ui *ui, float _r, float _g, float _b, float _a) {
alias_ui__tree__begin_child(ui);
alias_ui__program__emit_u32(ui, P_COLOR_FILL);
uint32_t r = alias_ui__float__to_color_channel(_r);
uint32_t g = alias_ui__float__to_color_channel(_g);
uint32_t b = alias_ui__float__to_color_channel(_b);
uint32_t a = alias_ui__float__to_color_channel(_a);
alias_ui__program__emit_u32(ui, alias_ui__color__pack(r, g, b, a));
alias_ui__tree__end_child(ui);
alias_ui__stats__set_texture(ui, 0);
alias_ui__stats__draw_rectangle(ui);
}
static void alias_ui__image__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
(void)alias_ui__ip__read_u32(ui);
float width = alias_ui__ip__read_f32(ui);
float height = alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
*out_width = alias_ui__float__clamp(width, min_width, max_width);
*out_height = alias_ui__float__clamp(height, min_height, max_height);
}
static void alias_ui__image__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t texture_id = alias_ui__ip__read_u32(ui);
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
float s0 = alias_ui__ip__read_f32(ui);
float t0 = alias_ui__ip__read_f32(ui);
float s1 = alias_ui__ip__read_f32(ui);
float t1 = alias_ui__ip__read_f32(ui);
alias_ui_set_texture(ui, texture_id);
alias_ui_draw_rectangle(ui, x, y, width, height, s0, t0, s1, t1, 255, 255, 255, 255);
}
void alias_ui_image(struct alias_ui *ui, float width, float height, float s0, float t0,
float s1, float t1, uint32_t texture_id) {
alias_ui__tree__begin_child(ui);
alias_ui__program__emit_u32(ui, P_IMAGE);
alias_ui__program__emit_u32(ui, texture_id);
alias_ui__program__emit_f32(ui, width);
alias_ui__program__emit_f32(ui, height);
alias_ui__program__emit_f32(ui, s0);
alias_ui__program__emit_f32(ui, t0);
alias_ui__program__emit_f32(ui, s1);
alias_ui__program__emit_f32(ui, t1);
alias_ui__tree__end_child(ui);
alias_ui__stats__set_texture(ui, texture_id);
alias_ui__stats__draw_rectangle(ui);
}
void alias_ui_font_index(struct alias_ui *ui, uint32_t index) {
assert(index < ui->font_length);
assert(ui->tree_scope_length > 0);
alias_ui__tree__top_scope(ui)->font_index = index;
}
void alias_ui_font_size(struct alias_ui *ui, float size) {
assert(ui->tree_scope_length > 0);
alias_ui__tree__top_scope(ui)->font_size = size;
}
void alias_ui_font_color(struct alias_ui *ui, alias_Color _color) {
assert(ui->tree_scope_length > 0);
uint8_t r = alias_ui__float__to_color_channel(_color.r);
uint8_t g = alias_ui__float__to_color_channel(_color.g);
uint8_t b = alias_ui__float__to_color_channel(_color.b);
uint8_t a = alias_ui__float__to_color_channel(_color.a);
uint32_t color = alias_ui__color__pack(r, g, b, a);
alias_ui__tree__top_scope(ui)->font_color = color;
}
static void alias_ui__text__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
uint32_t font_index = alias_ui__ip__read_u32(ui);
float font_size = alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_u32(ui);
uint32_t len = alias_ui__ip__read_u32(ui);
const char *string = (const char *)ui->ip;
alias_ui__ip__advance(ui, (len + 3) >> 2);
struct alias_ui_Font *font = &ui->font[font_index];
uint32_t glyph = 0;
float x = 0;
float y = 0;
float width = 0;
float height = 0;
for(; *string; ) {
uint32_t string_advance;
struct alias_ui_Font_GlyphInfo glyph_info;
struct alias_ui_Font *glyph_font = font;
while(glyph_font != NULL && !glyph_font->decode(glyph_font, string, &glyph, &string_advance, &glyph_info)) {
glyph_font = glyph_font->fallback;
}
string += string_advance;
float glyph_width = (glyph_info.x + glyph_info.width) * font_size;
float glyph_height = (glyph_info.y + glyph_info.height) * font_size;
width = alias_ui__float__max(width, x + glyph_width);
height = alias_ui__float__max(height, y + glyph_height);
x += glyph_info.advance_x * font_size;
if(glyph_info.newline) {
x = 0;
y += font_size;
}
}
*out_width = alias_ui__float__clamp(width, min_width, max_width);
*out_height = alias_ui__float__clamp(height, min_height, max_height);
}
static void alias_ui__text__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t font_index = alias_ui__ip__read_u32(ui);
float font_size = alias_ui__ip__read_f32(ui);
uint32_t font_color = alias_ui__ip__read_u32(ui);
uint32_t len = alias_ui__ip__read_u32(ui);
const char *string = (const char *)ui->ip;
alias_ui__ip__advance(ui, (len + 3) >> 2);
struct alias_ui_Font *font = &ui->font[font_index];
uint32_t glyph = 0;
float offset_x = 0;
float offset_y = 0;
uint8_t r = (font_color >> 24) & 0xFF;
uint8_t g = (font_color >> 16) & 0xFF;
uint8_t b = (font_color >> 8) & 0xFF;
uint8_t a = (font_color >> 0) & 0xFF;
for(; *string; ) {
uint32_t string_advance;
struct alias_ui_Font_GlyphInfo glyph_info;
struct alias_ui_Font *glyph_font = font;
while(glyph_font != NULL && !glyph_font->decode(glyph_font, string, &glyph, &string_advance, &glyph_info)) {
glyph_font = glyph_font->fallback;
}
string += string_advance;
alias_ui_set_texture(ui, glyph_font->texture_id);
alias_ui_draw_rectangle(ui, x + offset_x + glyph_info.x, y + offset_y + glyph_info.y, glyph_info.width * font_size,
glyph_info.height * font_size, glyph_info.s0, glyph_info.t0, glyph_info.s1, glyph_info.t1, r,
g, b, a);
offset_x += glyph_info.advance_x * font_size;
if(glyph_info.newline) {
offset_x = 0;
offset_y += font_size;
}
}
}
void alias_ui_textv(struct alias_ui *ui, const char *format, va_list ap) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
scope->handle_alignment = true;
alias_ui__tree__begin_child(ui);
alias_ui__program__emit_u32(ui, P_TEXT);
alias_ui__program__emit_u32(ui, scope->font_index);
alias_ui__program__emit_f32(ui, scope->font_size);
alias_ui__program__emit_u32(ui, scope->font_color);
va_list ap1, ap2;
va_copy(ap1, ap);
va_copy(ap2, ap);
int size = vcprintf(format, ap1);
va_end(ap1);
alias_ui__program__emit_u32(ui, size);
alias_ui__program__space_for(ui, (size + 3) >> 2);
char *mut_string = (char *)(ui->program + ui->program_length);
vsprintf(mut_string, size + 1, format, ap2);
va_end(ap2);
ui->program_length += (size + 3) >> 2;
alias_ui__tree__end_child(ui);
uint32_t string_advance;
uint32_t font_index = scope->font_index;
const char * string = mut_string;
struct alias_ui_Font *font = &ui->font[font_index];
uint32_t glyph = 0;
for(; *string; ) {
struct alias_ui_Font_GlyphInfo glyph_info;
struct alias_ui_Font *glyph_font = font;
while(glyph_font != NULL && !glyph_font->decode(glyph_font, string, &glyph, &string_advance, &glyph_info)) {
glyph_font = glyph_font->fallback;
}
string += string_advance;
alias_ui__stats__set_texture(ui, glyph_font->texture_id);
alias_ui__stats__draw_rectangle(ui);
}
}
static inline void alias_ui__background_color__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
}
static inline void alias_ui__background_color__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__background_color__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__background_color__layout(struct alias_ui *ui, float min_width, float max_width,
float min_height, float max_height, float *out_width,
float *out_height) {
(void)alias_ui__ip__read_u32(ui);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, out_width, out_height);
}
static inline void alias_ui__background_color__render(struct alias_ui *ui, float x, float y, float width,
float height) {
uint32_t color = alias_ui__ip__read_u32(ui);
uint8_t r, g, b, a;
alias_ui__color__unpack(color, &r, &g, &b, &a);
alias_ui_set_texture(ui, 0);
alias_ui_draw_rectangle(ui, x, y, width, height, 0, 0, 0, 0, r, g, b, a);
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_background_color(struct alias_ui *ui, float r, float g, float b, float a) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__background_color__begin_child, alias_ui__background_color__end_child,
alias_ui__background_color__end_scope);
uint32_t color =
alias_ui__color__pack(alias_ui__float__to_color_channel(r), alias_ui__float__to_color_channel(g),
alias_ui__float__to_color_channel(b), alias_ui__float__to_color_channel(a));
alias_ui__program__emit_u32(ui, P_BACKGROUND_COLOR);
alias_ui__program__emit_u32(ui, color);
}
static inline void alias_ui__border__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__border__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__border__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__border__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float size = alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_u32(ui);
float child_width;
float child_height;
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &child_width, &child_height);
child_width += size * 2;
child_height += size * 2;
*out_width = alias_ui__float__clamp(child_width, min_width, max_width);
*out_height = alias_ui__float__clamp(child_height, min_height, max_height);
}
static inline void alias_ui__border__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t color = alias_ui__ip__read_u32(ui);
uint8_t r, g, b, a;
alias_ui__color__unpack(color, &r, &g, &b, &a);
alias_ui_set_texture(ui, 0);
alias_ui_draw_rectangle(ui, x, y, width, height, 0, 0, 0, 0, r, g, b, a);
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_border(struct alias_ui *ui, float size, float r, float g, float b, float a) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__background_color__begin_child, alias_ui__background_color__end_child,
alias_ui__background_color__end_scope);
uint32_t color =
alias_ui__color__pack(alias_ui__float__to_color_channel(r), alias_ui__float__to_color_channel(g),
alias_ui__float__to_color_channel(b), alias_ui__float__to_color_channel(a));
alias_ui__program__emit_u32(ui, P_BORDER);
alias_ui__program__emit_f32(ui, size);
alias_ui__program__emit_u32(ui, color);
}
static inline void alias_ui__stack__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
scope->stack.num_children += 1;
}
static inline void alias_ui__stack__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__stack__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__program__fill_u32(ui, scope->stack.hole, scope->stack.num_children);
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__stack__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float max_child_width = min_width;
float max_child_height = min_height;
uint32_t len = alias_ui__ip__read_u32(ui);
for(uint32_t i = 0; i < len; i++) {
uint32_t hole = alias_ui__memory__dig(ui, 2);
float child_width;
float child_height;
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &child_width, &child_height);
alias_ui__memory__fill_f32(ui, hole + 0, child_width);
alias_ui__memory__fill_f32(ui, hole + 1, child_height);
max_child_width = alias_ui__float__max(max_child_width, child_width);
max_child_height = alias_ui__float__max(max_child_height, child_height);
}
*out_width = alias_ui__float__min(max_child_width, max_width);
*out_height = alias_ui__float__min(max_child_height, max_height);
}
static inline void alias_ui__stack__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t len = alias_ui__ip__read_u32(ui);
for(uint32_t i = 0; i < len; i++) {
float child_width = alias_ui__mp__read_f32(ui);
float child_height = alias_ui__mp__read_f32(ui);
alias_ui__render(ui, x, y, child_width, child_height);
}
}
void alias_ui_begin_stack(struct alias_ui *ui) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__stack__begin_child, alias_ui__stack__end_child,
alias_ui__stack__end_scope);
alias_ui__program__emit_u32(ui, P_STACK);
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
scope->stack.hole = alias_ui__program__dig(ui, 1);
}
static inline void alias_ui__dstack__space_for(struct alias_ui *ui, uint32_t count) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
alias_ui__grow((void **)&scope->dstack.children, sizeof(*scope->dstack.children),
scope->dstack.children_length + count, &scope->dstack.children_capacity);
}
static inline void alias_ui__dstack__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
scope->dstack.child_pmark = alias_ui__program__mark(ui);
scope->dstack.child_mmark = alias_ui__memory__mark(ui);
alias_ui__dstack__space_for(ui, 1);
scope->dstack.children_length += 1;
struct alias_ui_dstack_child *child = &scope->dstack.children[scope->dstack.children_length - 1];
child->hole = alias_ui__program__dig(ui, 3);
child->weight = alias_ui__float__max(scope->weight, 0);
scope->dstack.total_weight += child->weight;
alias_ui__program__emit_f32(ui, scope->dstack.vertical ? scope->align_x : scope->align_y);
alias_ui__memory__reserve(ui, 2);
scope->weight = 0;
scope->align_x = 0.5;
scope->align_y = 0.5;
}
static inline void alias_ui__dstack__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
uint32_t psize = alias_ui__program__mark_size(ui, scope->dstack.child_pmark);
uint32_t msize = alias_ui__memory__mark_size(ui, scope->dstack.child_mmark);
struct alias_ui_dstack_child *child = &scope->dstack.children[scope->dstack.children_length - 1];
alias_ui__program__fill_u32(ui, child->hole + 0, psize);
alias_ui__program__fill_u32(ui, child->hole + 1, msize);
}
static inline void alias_ui__dstack__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__program__fill_u32(ui, scope->dstack.hole, scope->dstack.children_length);
for(uint32_t i = 0; i < scope->dstack.children_length; i++) {
struct alias_ui_dstack_child *child = &scope->dstack.children[i];
alias_ui__program__fill_f32(ui, child->hole + 2, child->weight / scope->dstack.total_weight);
}
alias_free(ui->mcb, scope->dstack.children, sizeof(*scope->dstack.children) * scope->dstack.children_capacity, 4);
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__dstack__create(struct alias_ui *ui, bool vertical) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__dstack__begin_child, alias_ui__dstack__end_child,
alias_ui__dstack__end_scope);
alias_ui__program__emit_u32(ui, vertical ? P_VERTICAL_STACK : P_HORIZONTAL_STACK);
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
scope->handle_alignment = true;
scope->align_x = 0.5;
scope->align_y = 0.5;
scope->dstack.vertical = vertical;
scope->dstack.hole = alias_ui__program__dig(ui, 1);
scope->dstack.total_weight = 0;
scope->dstack.children_capacity = 0;
scope->dstack.children_length = 0;
scope->dstack.children = NULL;
}
static inline void alias_ui__dstack__layout(struct alias_ui *ui, bool vertical, float min_width, float max_width,
float min_height, float max_height, float *out_width, float *out_height) {
uint32_t len = alias_ui__ip__read_u32(ui);
uint32_t *prepass_ip = ui->ip;
float max_child_width = min_width;
float max_child_height = min_height;
for(uint32_t pass = 0; pass < 2; pass++) {
ui->ip = prepass_ip;
for(uint32_t i = 0; i < len; i++) {
uint32_t psize = alias_ui__ip__read_u32(ui);
uint32_t msize = alias_ui__ip__read_u32(ui);
float weight = alias_ui__ip__read_f32(ui);
if(pass != (weight > 0 ? 1 : 0)) {
alias_ui__ip__advance(ui, psize - 3);
alias_ui__mp__advance(ui, msize);
continue;
}
(void)alias_ui__ip__read_f32(ui);
float child_width;
float child_height;
uint32_t mhole = alias_ui__memory__dig(ui, 2);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &child_width, &child_height);
if(pass == 1) {
if(!vertical) {
child_width = weight * max_width;
} else {
child_height = weight * max_height;
}
}
alias_ui__memory__fill_f32(ui, mhole + 0, child_width);
alias_ui__memory__fill_f32(ui, mhole + 1, child_height);
max_child_width = alias_ui__float__max(max_child_width, child_width);
max_child_height = alias_ui__float__max(max_child_height, child_height);
if(pass == 0) {
if(vertical) {
min_height = alias_ui__float__max(min_height - child_height, 0);
max_height = alias_ui__float__max(max_height - child_height, 0);
} else {
min_width = alias_ui__float__max(min_width - child_width, 0);
max_width = alias_ui__float__max(max_width - child_width, 0);
}
}
}
}
*out_width = alias_ui__float__min(max_width, max_child_width);
*out_height = alias_ui__float__min(max_height, max_child_height);
}
static inline void alias_ui__dstack__render(struct alias_ui *ui, bool vertical, float x, float y, float width,
float height) {
uint32_t len = alias_ui__ip__read_u32(ui);
for(uint32_t i = 0; i < len; i++) {
(void)alias_ui__ip__read_u32(ui);
(void)alias_ui__ip__read_u32(ui);
(void)alias_ui__ip__read_f32(ui);
float align = alias_ui__ip__read_f32(ui);
float child_width = alias_ui__mp__read_f32(ui);
float child_height = alias_ui__mp__read_f32(ui);
alias_ui__render(ui, vertical ? x + alias_ui__float__max(width - child_width, 0) * align : x,
vertical ? y : y + alias_ui__float__max(height - child_height, 0) * align, child_width,
child_height);
if(!vertical) {
x += child_width;
} else {
y += child_height;
}
}
}
void alias_ui_begin_horizontal_stack(struct alias_ui *ui) {
alias_ui__dstack__create(ui, false);
}
void alias_ui_begin_vertical_stack(struct alias_ui *ui) {
alias_ui__dstack__create(ui, true);
}
void alias_ui_stack_weight(struct alias_ui *ui, float weight) {
alias_ui__tree__top_scope(ui)->weight = weight;
}
void alias_ui_end_stack(struct alias_ui *ui) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__named_scope__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__named_scope__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__named_scope__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
void alias_ui_named_scope(struct alias_ui *ui, const char *format, ...) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__named_scope__begin_child, alias_ui__named_scope__end_child,
alias_ui__named_scope__end_scope);
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
va_list ap;
va_start(ap, format);
int size = vcprintf(format, ap);
va_end(ap);
char *buffer = alloca(size + 1);
va_start(ap, format);
vsprintf(buffer, size + 1, format, ap);
va_end(ap);
uint64_t hash =
0xCBF29CE484222325ul ^
(scope->named_scope_index < ui->named_scope_length ? ui->named_scope[scope->named_scope_index].hash : 0);
while(*buffer) {
hash ^= *buffer++;
hash *= 0x00000100000001B3ul;
}
for(uint32_t i = 0; i < ui->named_scope_length; i++) {
if(ui->named_scope[i].hash == hash) {
scope->named_scope_index = i;
return;
}
}
alias_ui__grow((void **)&ui->named_scope, sizeof(*ui->named_scope), ui->named_scope_length + 1,
&ui->named_scope_capacity);
ui->named_scope[ui->named_scope_length].hash = hash;
ui->named_scope[ui->named_scope_length].query_capacity = 0;
ui->named_scope[ui->named_scope_length].query_rects = NULL;
ui->named_scope[ui->named_scope_length].slot_capacity = 0;
ui->named_scope[ui->named_scope_length].slot = NULL;
scope->named_scope_index = ui->named_scope_length++;
}
void alias_ui_set_uint32(struct alias_ui *ui, uint32_t slot_index, uint32_t value) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
struct alias_ui_named_scope *named_scope = &ui->named_scope[scope->named_scope_index];
alias_ui__grow((void **)&named_scope->slot, sizeof(*named_scope->slot), slot_index, &named_scope->slot_capacity);
named_scope->slot[slot_index] = value;
}
void alias_ui_set_float(struct alias_ui *ui, uint32_t slot_index, float value) {
union {
uint32_t u;
float f;
} flip = {.f = value};
alias_ui_set_uint32(ui, slot_index, flip.u);
}
uint32_t alias_ui_get_uint32(struct alias_ui *ui, uint32_t slot_index) {
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
struct alias_ui_named_scope *named_scope = &ui->named_scope[scope->named_scope_index];
if(slot_index < named_scope->slot_capacity) {
return named_scope->slot[slot_index];
} else {
return 0;
}
}
float alias_ui_get_float(struct alias_ui *ui, uint32_t slot_index) {
union {
uint32_t u;
float f;
} flip = {.u = alias_ui_get_uint32(ui, slot_index)};
return flip.f;
}
static inline void alias_ui__size__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__size__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__size__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__size__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float width = alias_ui__ip__read_f32(ui);
float height = alias_ui__ip__read_f32(ui);
float unused_width;
float unused_height;
alias_ui__layout(ui, width, width, height, height, &unused_width, &unused_height);
*out_width = alias_ui__float__clamp(width, min_width, max_width);
*out_height = alias_ui__float__clamp(height, min_height, max_height);
}
static inline void alias_ui__size__render(struct alias_ui *ui, float x, float y, float width, float height) {
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_size(struct alias_ui *ui, float width, float height) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__size__begin_child, alias_ui__size__end_child,
alias_ui__size__end_scope);
alias_ui__program__emit_u32(ui, P_SIZE);
alias_ui__program__emit_f32(ui, width);
alias_ui__program__emit_f32(ui, height);
}
static inline void alias_ui__width__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__width__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__width__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__width__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float width = alias_ui__ip__read_f32(ui);
float unused_width;
float height;
alias_ui__layout(ui, width, width, min_height, max_height, &unused_width, &height);
*out_width = alias_ui__float__clamp(width, min_width, max_width);
*out_height = alias_ui__float__clamp(height, min_height, max_height);
}
static inline void alias_ui__width__render(struct alias_ui *ui, float x, float y, float width, float height) {
(void)alias_ui__ip__read_f32(ui);
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_width(struct alias_ui *ui, float width) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__width__begin_child, alias_ui__width__end_child,
alias_ui__width__end_scope);
alias_ui__program__emit_u32(ui, P_WIDTH);
alias_ui__program__emit_f32(ui, width);
}
static inline void alias_ui__height__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__height__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__height__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__height__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float height = alias_ui__ip__read_f32(ui);
float width;
float unused_height;
alias_ui__layout(ui, min_width, max_width, height, height, &width, &unused_height);
*out_width = alias_ui__float__clamp(width, min_width, max_width);
*out_height = alias_ui__float__clamp(height, min_height, max_height);
}
static inline void alias_ui__height__render(struct alias_ui *ui, float x, float y, float width, float height) {
(void)alias_ui__ip__read_f32(ui);
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_height(struct alias_ui *ui, float height) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__height__begin_child, alias_ui__height__end_child,
alias_ui__height__end_scope);
alias_ui__program__emit_u32(ui, P_HEIGHT);
alias_ui__program__emit_f32(ui, height);
}
static inline void alias_ui__align__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__memory__reserve(ui, 2);
}
static inline void alias_ui__align__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__align__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__align__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
(void)alias_ui__ip__read_f32(ui);
(void)alias_ui__ip__read_f32(ui);
float width;
float height;
uint32_t mhole = alias_ui__memory__dig(ui, 2);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &width, &height);
alias_ui__memory__fill_f32(ui, mhole + 0, width);
alias_ui__memory__fill_f32(ui, mhole + 1, height);
*out_width = max_width;
*out_height = max_height;
}
static inline void alias_ui__align__render(struct alias_ui *ui, float x, float y, float width, float height) {
float align_x = alias_ui__ip__read_f32(ui);
float align_y = alias_ui__ip__read_f32(ui);
float child_width = alias_ui__mp__read_f32(ui);
float child_height = alias_ui__mp__read_f32(ui);
alias_ui__render(ui, x + (width - child_width) * align_x, y + (height - child_height) * align_y, child_width,
child_height);
}
void alias_ui_align(struct alias_ui *ui, float x, float y) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__align__begin_child, alias_ui__align__end_child,
alias_ui__align__end_scope);
alias_ui__program__emit_u32(ui, P_ALIGN);
alias_ui__program__emit_f32(ui, x);
alias_ui__program__emit_f32(ui, y);
}
static inline void alias_ui__alignx__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__memory__reserve(ui, 1);
}
static inline void alias_ui__alignx__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__alignx__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__alignx__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
(void)alias_ui__ip__read_f32(ui);
float width;
float height;
uint32_t mhole = alias_ui__memory__dig(ui, 1);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &width, &height);
alias_ui__memory__fill_f32(ui, mhole, width);
*out_width = max_width;
*out_height = alias_ui__float__clamp(height, min_height, min_height);
}
static inline void alias_ui__alignx__render(struct alias_ui *ui, float x, float y, float width, float height) {
float align_x = alias_ui__ip__read_f32(ui);
float child_width = alias_ui__mp__read_f32(ui);
alias_ui__render(ui, x + (width - child_width) * align_x, y, child_width, height);
}
void alias_ui_align_x(struct alias_ui *ui, float x) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__alignx__begin_child, alias_ui__alignx__end_child,
alias_ui__alignx__end_scope);
alias_ui__program__emit_u32(ui, P_ALIGN_X);
alias_ui__program__emit_f32(ui, x);
}
static inline void alias_ui__aligny__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__memory__reserve(ui, 1);
}
static inline void alias_ui__aligny__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__aligny__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__aligny__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
(void)alias_ui__ip__read_f32(ui);
float width;
float height;
uint32_t mhole = alias_ui__memory__dig(ui, 1);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, &width, &height);
alias_ui__memory__fill_f32(ui, mhole, height);
*out_width = alias_ui__float__clamp(width, min_width, min_width);
*out_height = max_height;
}
static inline void alias_ui__aligny__render(struct alias_ui *ui, float x, float y, float width, float height) {
float align_y = alias_ui__ip__read_f32(ui);
float child_height = alias_ui__mp__read_f32(ui);
alias_ui__render(ui, x, y + (height - child_height) * align_y, width, child_height);
}
void alias_ui_align_y(struct alias_ui *ui, float y) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__aligny__begin_child, alias_ui__aligny__end_child,
alias_ui__aligny__end_scope);
alias_ui__program__emit_u32(ui, P_ALIGN_Y);
alias_ui__program__emit_f32(ui, y);
}
static inline void alias_ui__padding__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
}
static inline void alias_ui__padding__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__padding__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__padding__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
float left = alias_ui__ip__read_f32(ui);
float top = alias_ui__ip__read_f32(ui);
float right = alias_ui__ip__read_f32(ui);
float bottom = alias_ui__ip__read_f32(ui);
float padding_width = left + right;
float padding_height = top + bottom;
float child_width;
float child_height;
float child_min_width = alias_ui__float__max(min_width - padding_width, 0);
float child_max_width = alias_ui__float__max(max_width - padding_width, 0);
float child_min_height = alias_ui__float__max(min_height - padding_height, 0);
float child_max_height = alias_ui__float__max(max_height - padding_height, 0);
alias_ui__layout(ui, child_min_width, child_max_width, child_min_height, child_max_height, &child_width, &child_height);
*out_width = alias_ui__float__clamp(child_width + padding_width, min_width, max_width);
*out_height = alias_ui__float__clamp(child_height + padding_height, min_height, max_height);
}
static inline void alias_ui__padding__render(struct alias_ui *ui, float x, float y, float width, float height) {
float left = alias_ui__ip__read_f32(ui);
float top = alias_ui__ip__read_f32(ui);
float right = alias_ui__ip__read_f32(ui);
float bottom = alias_ui__ip__read_f32(ui);
float padding_width = left + right;
float padding_height = top + bottom;
alias_ui__render(ui, x + left, y + top, width - padding_width, height - padding_height);
}
void alias_ui_padding(struct alias_ui *ui, float left, float top, float right, float bottom) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__padding__begin_child, alias_ui__padding__end_child,
alias_ui__padding__end_scope);
alias_ui__program__emit_u32(ui, P_PADDING);
alias_ui__program__emit_f32(ui, left);
alias_ui__program__emit_f32(ui, top);
alias_ui__program__emit_f32(ui, right);
alias_ui__program__emit_f32(ui, bottom);
}
static inline void alias_ui__query__begin_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {}
static inline void alias_ui__query__end_child(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_scope(ui);
}
static inline void alias_ui__query__end_scope(struct alias_ui *ui, struct alias_ui_tree_scope *scope) {
alias_ui__tree__end_child(ui);
}
static inline void alias_ui__query__layout(struct alias_ui *ui, float min_width, float max_width, float min_height,
float max_height, float *out_width, float *out_height) {
(void)alias_ui__ip__read_u32(ui);
(void)alias_ui__ip__read_u32(ui);
alias_ui__layout(ui, min_width, max_width, min_height, max_height, out_width, out_height);
}
static inline void alias_ui__query__render(struct alias_ui *ui, float x, float y, float width, float height) {
uint32_t named_scope_index = alias_ui__ip__read_u32(ui);
uint32_t query_index = alias_ui__ip__read_u32(ui);
struct alias_ui_named_scope *named_scope = &ui->named_scope[named_scope_index];
named_scope->query_rects[query_index * 4 + 0] = x;
named_scope->query_rects[query_index * 4 + 1] = y;
named_scope->query_rects[query_index * 4 + 2] = width;
named_scope->query_rects[query_index * 4 + 3] = height;
alias_ui__render(ui, x, y, width, height);
}
void alias_ui_query(struct alias_ui *ui, uint32_t query_index, float *out_rect) {
alias_ui__tree__begin_child(ui);
alias_ui__tree__begin_scope(ui, alias_ui__query__begin_child, alias_ui__query__end_child,
alias_ui__query__end_scope);
struct alias_ui_tree_scope *scope = alias_ui__tree__top_scope(ui);
alias_ui__program__emit_u32(ui, P_QUERY);
alias_ui__program__emit_u32(ui, scope->named_scope_index);
alias_ui__program__emit_u32(ui, query_index);
struct alias_ui_named_scope *named_scope = &ui->named_scope[scope->named_scope_index];
alias_ui__grow((void **)&named_scope->query_rects, sizeof(*named_scope->query_rects) * 4, query_index + 1,
&named_scope->query_capacity);
out_rect[0] = named_scope->query_rects[query_index * 4 + 0];
out_rect[1] = named_scope->query_rects[query_index * 4 + 1];
out_rect[2] = named_scope->query_rects[query_index * 4 + 2];
out_rect[3] = named_scope->query_rects[query_index * 4 + 3];
}
static inline void alias_ui__layout__initialize(struct alias_ui *ui) {
alias_ui__ip__initialize(ui);
alias_ui__memory__initialize(ui);
}
static inline void alias_ui__layout(struct alias_ui *ui, float aw, float bw, float ah, float bh, float *oh,
float *ow) {
uint32_t code = alias_ui__ip__read_u32(ui);
switch(code) {
case P_TERMINATE:
break;
case P_EMPTY_FILL:
alias_ui__empty_fill__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_COLOR_FILL:
alias_ui__color_fill__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_TEXT:
alias_ui__text__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_IMAGE:
alias_ui__image__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_BACKGROUND_COLOR:
alias_ui__background_color__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_BORDER:
alias_ui__border__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_STACK:
alias_ui__stack__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_HORIZONTAL_STACK:
alias_ui__dstack__layout(ui, false, aw, bw, ah, bh, oh, ow);
break;
case P_VERTICAL_STACK:
alias_ui__dstack__layout(ui, true, aw, bw, ah, bh, oh, ow);
break;
case P_SIZE:
alias_ui__size__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_WIDTH:
alias_ui__width__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_HEIGHT:
alias_ui__height__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_ALIGN:
alias_ui__align__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_ALIGN_X:
alias_ui__alignx__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_ALIGN_Y:
alias_ui__aligny__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_PADDING:
alias_ui__padding__layout(ui, aw, bw, ah, bh, oh, ow);
break;
case P_QUERY:
alias_ui__query__layout(ui, aw, bw, ah, bh, oh, ow);
break;
}
}
static inline void alias_ui__render__initialize(struct alias_ui *ui) {
alias_ui__ip__initialize(ui);
alias_ui__mp__initialize(ui);
alias_ui__vertex__initialize(ui);
alias_ui__index__initialize(ui);
alias_ui__group__initialize(ui);
ui->texture_id = 0;
alias_ui__group__advance(ui);
}
static inline void alias_ui__render(struct alias_ui *ui, float x, float y, float w, float h) {
uint32_t code = alias_ui__ip__read_u32(ui);
switch(code) {
case P_TERMINATE:
break;
case P_EMPTY_FILL:
alias_ui__empty_fill__render(ui, x, y, w, h);
break;
case P_COLOR_FILL:
alias_ui__color_fill__render(ui, x, y, w, h);
break;
case P_TEXT:
alias_ui__text__render(ui, x, y, w, h);
break;
case P_IMAGE:
alias_ui__image__render(ui, x, y, w, h);
break;
case P_BACKGROUND_COLOR:
alias_ui__background_color__render(ui, x, y, w, h);
break;
case P_BORDER:
alias_ui__border__render(ui, x, y, w, h);
break;
case P_STACK:
alias_ui__stack__render(ui, x, y, w, h);
break;
case P_HORIZONTAL_STACK:
alias_ui__dstack__render(ui, false, x, y, w, h);
break;
case P_VERTICAL_STACK:
alias_ui__dstack__render(ui, true, x, y, w, h);
break;
case P_SIZE:
alias_ui__size__render(ui, x, y, w, h);
break;
case P_WIDTH:
alias_ui__width__render(ui, x, y, w, h);
break;
case P_HEIGHT:
alias_ui__height__render(ui, x, y, w, h);
break;
case P_ALIGN:
alias_ui__align__render(ui, x, y, w, h);
break;
case P_ALIGN_X:
alias_ui__alignx__render(ui, x, y, w, h);
break;
case P_ALIGN_Y:
alias_ui__aligny__render(ui, x, y, w, h);
break;
case P_PADDING:
alias_ui__padding__render(ui, x, y, w, h);
break;
case P_QUERY:
alias_ui__query__render(ui, x, y, w, h);
break;
}
}
static inline bool alias_ui__dev_font__decode(struct alias_ui_Font *font, const char *string, uint32_t *inout_glyph,
uint32_t *out_num_bytes, struct alias_ui_Font_GlyphInfo *out_info) {
uint32_t glyph = *string;
*inout_glyph = glyph;
*out_num_bytes = 1;
uint32_t row = glyph >> 4;
uint32_t col = glyph & 15;
out_info->newline = glyph == '\n';
out_info->advance_x = 0.5f;
out_info->x = 0.0f;
out_info->y = 0.0f;
out_info->width = 1.33f;
out_info->height = 1.33f;
if(row < 2 || glyph == ' ') {
out_info->width = 0;
out_info->height = 0;
} else {
row -= 2;
}
out_info->s0 = (float)(col + 0) / 16.0f;
out_info->t0 = (float)(row + 0) / 16.0f;
out_info->s1 = (float)(col + 1) / 16.0f;
out_info->t1 = (float)(row + 1) / 16.0f;
return true;
}
static struct alias_ui_Font alias_ui__dev_font = {
.texture_id = 0,
.decode = alias_ui__dev_font__decode,
};
#ifdef UNICAT_UI_ENABLE_FREETYPE
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#define MULTILINE_STRING(...) #__VA_ARGS__
const char * alias_ui_freetype_opengl_fragment_shader(uint32_t major, uint32_t minor) {
return
MULTILINE_STRING(
vec2 alias_ui_freetype_snorm16_decode2(uvec2 x) {
return vec2(x) / 65535.0 - 0.5;
}
float alias_ui_freetype_draw_curve(vec2 p0, vec2 p1, vec2 p2, float inverse_pixel_width) {
vec2 a = p0 - 2.0*p1 + p2;
vec2 b = p0 - p1;
vec2 c = p0;
vec2 t;
float si = b.y*b.y - a.y*c.y;
float s = sqrt(max(si, 0.0));
t = vec2(b.y - s, b.y + s) / a.y;
vec2 x = (a.x*t - 2.0*b.x)*t + c.x;
vec2 weight = clamp(x * inverse_pixel_width + 0.5, 0.0, 1.0) * step(0.0, t) * step(-1.0, -t);
return dot(weight, vec2(1, -1)) * step(0.0, si);
}
float alias_ui_freetype_draw_layer(vec2 uv, vec2 inverse_pixel_width, uint curve_start, uint curve_length, bool super_sampling) {
float alpha = 0.0;
uint row = curve_start;
uint end = row + curve_length;
while(row < end) {
uvec4 contour = alias_ui_freetype_user_font(row++);
uint count = contour.x;
vec2 a = alias_ui_freetype_snorm16_decode2(contour.zw) * scale - uv;
for(uint i = 0u; i < count; i++) {
uvec4 curve = alias_ui_freetype_user_font(row++);
vec2 b = alias_ui_freetype_snorm16_decode2(curve.xy) * scale - uv;
vec2 c = alias_ui_freetype_snorm16_decode2(curve.zw) * scale - uv;
vec3 x = vec3(a.x, b.x, c.x);
vec3 y = vec3(a.y, b.y, c.y);
if(!all(lessThan(y, vec3(0))) && !all(greaterThan(y, vec3(0)))) {
alpha += alias_ui_freetype_draw_curve(a, b, c, inverse_pixel_width.x);
}
if(super_sampling && !all(lessThan(x, vec3(0))) && !all(greaterThan(x, vec3(0)))) {
alpha += alias_ui_freetype_draw_curve(vec2(a.y, -a.x), vec2(b.y, -b.x), vec2(c.y, -c.x), inverse_pixel_width.y);
}
a = c;
}
}
return alpha * (float(!super_sampling)*0.5+0.5);
}
vec4 alias_ui_freetype_draw_glyph(vec4 default_color, vec2 uv, uint glyph_index, bool super_sampling) {
vec2 inverse_pixel_width = 1.0 / fwidth(uv);
uvec4 glyph = alias_ui_freetype_user_font(glyph_index);
if(glyph.y == 1u) {
float alpha = alias_ui_freetype_draw_layer(uv, inverse_pixel_width, glyph.z, glyph.w, super_sampling);
return vec4(default_color.rgb, default_color.a * alpha);
} else {
vec4 color = vec4(0);
for(uint i = 0u; i < glyph.y; i++) {
uvec4 layer = alias_ui_freetype_user_font(glyph.x + i);
float alpha = alias_ui_freetype_draw_layer(uv, inverse_pixel_width, glyph.z, glyph.w, super_sampling);
}
return color;
}
}
);
}
#undef MULTILINE_STRING
void alias_ui_freetype_texture_callback(struct alias_ui *ui, uint32_t (*f)(uint32_t length, void ** ptr)) {
ui->freetype_texture_callback = f;
}
struct alias_ui_freetype__Counter {
uint32_t num_points;
uint32_t num_contours;
};
static int alias_ui_freetype__counter_move(const FT_Vector * to, void * user) {
struct alias_ui_freetype__Counter *c = (struct alias_ui_freetype__Counter *)user;
c->num_points += 1;
c->num_contours += 1;
return 0;
}
static int alias_ui_freetype__counter_line(const FT_Vector * to, void * user) {
struct alias_ui_freetype__Counter *c = (struct alias_ui_freetype__Counter *)user;
c->num_points += 2;
return 0;
}
static int alias_ui_freetype__counter_conic(const FT_Vector * control, const FT_Vector * to, void * user) {
struct alias_ui_freetype__Counter *c = (struct alias_ui_freetype__Counter *)user;
c->num_points += 2;
return 0;
}
static int alias_ui_freetype__counter_cubic(const FT_Vector * control1, const FT_Vector * control2, const FT_Vector * to, void * user) {
struct alias_ui_freetype__Counter *c = (struct alias_ui_freetype__Counter *)user;
c->num_points += 4;
return 0;
}
struct alias_ui_freetype__Emitter {
float scale;
uint16_t * data;
uint32_t contour_data_index_start;
uint32_t data_index;
float ax;
float ay;
};
static void alias_ui_freetype__Emitter_flush(struct alias_ui_freetype__Emitter *e) {
if(e->contour_data_index_start > 0) {
e->data[e->contour_data_index_start * 4 + 0] = e->data_index - e->data[e->contour_data_index_start * 4 + 0];
}
e->contour_data_index_start = 0;
}
static void alias_ui_freetype__Emitter_contour(struct alias_ui_freetype__Emitter *e, float ax, float ay) {
alias_ui_freetype__Emitter_flush(e);
e->contour_data_index_start = e->data_index;
e->data[e->data_index * 4 + 0] = 0;
e->data[e->data_index * 4 + 1] = 0;
e->data[e->data_index * 4 + 2] = (uint16_t)((int32_t)e->ax + 32768);
e->data[e->data_index * 4 + 3] = (uint16_t)((int32_t)e->ay + 32768);
e->data_index++;
e->ax = ax;
e->ay = ay;
}
static void alias_ui_freetype__Emitter_curve(struct alias_ui_freetype__Emitter *e, float bx, float by, float cx, float cy) {
float x = e->ax - 2.0f*bx + cx;
float y = e->ay - 2.0f*by + cy;
if(fabs(x) < 0.00001f || fabs(y) < 0.00001f) {
bx += (e->ax - cx) * 0.1f;
by += (e->ay - cy) * 0.1f;
}
e->data[e->data_index * 4 + 0] = (uint16_t)((int32_t)bx + 32768);
e->data[e->data_index * 4 + 1] = (uint16_t)((int32_t)by + 32768);
e->data[e->data_index * 4 + 2] = (uint16_t)((int32_t)cx + 32768);
e->data[e->data_index * 4 + 3] = (uint16_t)((int32_t)cy + 32768);
e->data_index++;
e->ax = cx;
e->ay = cy;
}
static int alias_ui_freetype__emitter_move(const FT_Vector * to, void * user) {
struct alias_ui_freetype__Emitter *e = (struct alias_ui_freetype__Emitter *)user;
alias_ui_freetype__Emitter_contour(e, (float)to->x * e->scale, (float)to->y * e->scale);
return 0;
}
static int alias_ui_freetype__emitter_line(const FT_Vector * to, void * user) {
struct alias_ui_freetype__Emitter *e = (struct alias_ui_freetype__Emitter *)user;
float cx = (float)to->x * e->scale;
float cy = (float)to->y * e->scale;
float bx = (e->ax + cx) * 0.5f;
float by = (e->ay + cy) * 0.5f;
alias_ui_freetype__Emitter_curve(e, bx, by, cx, cy);
return 0;
}
static int alias_ui_freetype__emitter_conic(const FT_Vector * control, const FT_Vector * to, void * user) {
struct alias_ui_freetype__Emitter *e = (struct alias_ui_freetype__Emitter *)user;
float bx = (float)control->x * e->scale;
float by = (float)control->y * e->scale;
float cx = (float)to->x * e->scale;
float cy = (float)to->y * e->scale;
alias_ui_freetype__Emitter_curve(e, bx, by, cx, cy);
return 0;
}
static int alias_ui_freetype__emitter_cubic(const FT_Vector * control1, const FT_Vector * control2, const FT_Vector * to, void * user) {
struct alias_ui_freetype__Emitter *e = (struct alias_ui_freetype__Emitter *)user;
float control1x = (float)control1->x * e->scale;
float control1y = (float)control1->y * e->scale;
float control2x = (float)control2->x * e->scale;
float control2y = (float)control2->y * e->scale;
float ex = (float)to->x * e->scale;
float ey = (float)to->y * e->scale;
float bx = e->ax + (control1x - e->ax) * 0.75;
float by = e->ax + (control1y - e->ay) * 0.75;
float dx = ex + (control2x - ex) * 0.75;
float dy = ey + (control2y - ey) * 0.75;
float cx = (bx + dx) * 0.5;
float cy = (by + dy) * 0.5;
alias_ui_freetype__Emitter_curve(e, bx, by, cx, cy);
alias_ui_freetype__Emitter_curve(e, dx, dy, ex, ey);
return 0;
}
struct alias_ui_freetype_font_character {
uint32_t charcode;
uint32_t have_bold : 1;
uint32_t have_italic : 1;
uint32_t have_bold_italic : 1;
uint32_t glyph_index : 29;
};
struct alias_ui_freetype_font_glyph {
float advance_x;
float x;
float y;
float width;
float height;
};
struct alias_ui_freetype_font {
struct alias_ui_font root;
struct alias_ui_freetype_font_character * character_map;
uint32_t num_characters;
struct alias_ui_freetype_font_glyph * glyph_map;
uint32_t num_glyphs;
};
static int alias_ui_freetype_character_map_compare(const void * a, const void * b) {
uint32_t charcode = *(const uint32_t *)a;
const struct alias_ui_freetype_font_character * character = (const struct alias_ui_freetype_font_character *)b;
return (int)((int64_t)character->charcode - (int64_t)a);
}
static bool alias_ui_freetype_font_decode(struct alias_ui_font *_font, const char *string, uint32_t *inout_glyph, uint32_t *out_num_bytes, struct alias_ui_font_glyph_info *out_info) {
struct alias_ui_freetype_font * font = (struct alias_ui_freetype_font *)_font->user_data;
uint32_t charcode = *string;
struct alias_ui_freetype_font_character * character = bsearch(&charcode, font->character_map, font->num_characters, sizeof(*font->character_map), alias_ui_freetype_character_map_compare);
*out_num_bytes = 1;
if(character != NULL) {
*inout_glyph = character - font->character_map;
} else {
return false;
}
out_info->newline == *string == '\n';
out_info->advance_x = font->glyph_map[*inout_glyph].advance_x;
out_info->x = font->glyph_map[*inout_glyph].x;
out_info->y = font->glyph_map[*inout_glyph].y;
out_info->width = font->glyph_map[*inout_glyph].width;
out_info->height = font->glyph_map[*inout_glyph].height;
out_info->s0 = 0.0f + *inout_glyph;
out_info->t0 = 0.0f;
out_info->s1 = 1.0f + *inout_glyph;
out_info->t1 = 1.0f;
return true;
}
struct alias_ui_font * alias_ui_freetype_create_font(struct alias_ui *ui, const char ** filenames, uint32_t num_filenames) {
FT_Library library;
FT_Init_FreeType(&library);
struct alias_ui_freetype_font * font = malloc(sizeof(*font));
uint32_t num_faces = num_filenames;
FT_Face * faces = malloc(sizeof(FT_Face) * num_faces);
for(uint32_t i = 0; i < num_filenames; i++) {
FT_New_Face(library, filenames[i], 0, &faces[i]);
}
struct {
struct {
uint32_t face;
uint32_t glyph;
} style[4];
} *building_character_map = NULL;
font->num_glyphs = 0;
for(uint32_t charcode = ' '; charcode < 0x1FFFFF; charcode++) {
uint32_t face_index = 0;
FT_UInt glyph_index = 0;
struct {
uint32_t face;
uint32_t glyph;
} style[4] = {{-1,-1},{-1,-1},{-1,-1},{-1,-1}};
for(; face_index < num_faces; face_index++) {
glyph_index = FT_Get_Char_Index(faces[face_index], charcode);
if(glyph_index != 0) {
if(style[faces[face_index]->style_flags].face == -1) {
style[faces[face_index]->style_flags].face = face_index;
style[faces[face_index]->style_flags].glyph = glyph_index;
}
}
}
if(style[0].face == -1) {
continue;
}
font->character_map = realloc(font->character_map, sizeof(*font->character_map) * (font->num_characters + 1));
building_character_map = realloc(building_character_map, sizeof(*building_character_map) * (font->num_characters + 1));
font->character_map[font->num_characters].charcode = charcode;
font->character_map[font->num_characters].glyph_index = font->num_glyphs;
font->character_map[font->num_characters].have_bold = style[1].face != -1;
font->character_map[font->num_characters].have_italic = style[2].face != -1;
font->character_map[font->num_characters].have_bold_italic = style[3].face != -1;
building_character_map[font->num_characters].style[0].face = style[0].face;
building_character_map[font->num_characters].style[0].glyph = style[0].glyph;
building_character_map[font->num_characters].style[1].face = style[1].face;
building_character_map[font->num_characters].style[1].glyph = style[1].glyph;
building_character_map[font->num_characters].style[2].face = style[2].face;
building_character_map[font->num_characters].style[2].glyph = style[2].glyph;
building_character_map[font->num_characters].style[3].face = style[3].face;
building_character_map[font->num_characters].style[3].glyph = style[3].glyph;
font->num_glyphs += 1 +
font->character_map[font->num_characters].have_bold +
font->character_map[font->num_characters].have_italic +
font->character_map[font->num_characters].have_bold_italic;
font->num_characters++;
}
struct alias_ui_freetype__Counter counter;
memset(&counter, 0, sizeof(counter));
FT_Outline_Funcs counter_funcs;
memset(&counter_funcs, 0, sizeof(counter_funcs));
counter_funcs.move_to = alias_ui_freetype__counter_move;
counter_funcs.line_to = alias_ui_freetype__counter_line;
counter_funcs.conic_to = alias_ui_freetype__counter_conic;
counter_funcs.cubic_to = alias_ui_freetype__counter_cubic;
for(uint32_t character_index = 0; character_index < font->num_characters; character_index++) {
for(uint32_t style_index = 0; style_index < 4; style_index) {
if(building_character_map[character_index].style[style_index].face != -1) {
FT_Face face = faces[building_character_map[character_index].style[style_index].face];
FT_Load_Glyph(
face,
building_character_map[character_index].style[style_index].glyph,
FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE | FT_LOAD_LINEAR_DESIGN
);
FT_Outline_Decompose(&face->glyph->outline, &counter_funcs, &counter);
}
}
}
FT_Outline_Funcs emitter_funcs;
memset(&emitter_funcs, 0, sizeof(emitter_funcs));
emitter_funcs.move_to = alias_ui_freetype__emitter_move;
emitter_funcs.line_to = alias_ui_freetype__emitter_line;
emitter_funcs.conic_to = alias_ui_freetype__emitter_conic;
emitter_funcs.cubic_to = alias_ui_freetype__emitter_cubic;
uint32_t length = font->num_glyphs + counter.num_contours + (counter.num_points - counter.num_contours) * 2;
struct alias_ui_freetype__Emitter emitter;
memset(&emitter, 0, sizeof(emitter));
ui->freetype_texture_callback(length, (void **)&emitter.data);
emitter.data_index = font->num_characters;
font->glyph_map = malloc(sizeof(*font->glyph_map) * font->num_glyphs);
uint32_t glyph_index = 0;
for(uint32_t character_index = 0; character_index < font->num_characters; character_index++) {
for(uint32_t style_index = 0; style_index < 4; style_index) {
if(building_character_map[character_index].style[style_index].face != -1) {
FT_Face face = faces[building_character_map[character_index].style[style_index].face];
FT_Load_Glyph(
face,
building_character_map[character_index].style[style_index].glyph,
FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE
);
emitter.scale = 65535.0f / (float)face->units_per_EM;
FT_Outline_Decompose(&face->glyph->outline, &emitter_funcs, &emitter);
alias_ui_freetype__Emitter_flush(&emitter);
font->glyph_map[glyph_index].advance_x = (float)face->glyph->metrics.horiAdvance * emitter.scale;
font->glyph_map[glyph_index].x = (float)face->glyph->metrics.horiBearingX * emitter.scale;
font->glyph_map[glyph_index].y = (float)face->glyph->metrics.horiBearingY * emitter.scale;
font->glyph_map[glyph_index].width = (float)face->glyph->metrics.width * emitter.scale;
font->glyph_map[glyph_index].height = (float)face->glyph->metrics.height * emitter.scale;
}
}
}
for(uint32_t i = 0; i < num_faces; i++) {
FT_Done_Face(faces[i]);
}
free(faces);
free(building_character_map);
font->root.texture_id = ui->freetype_texture_callback(length, (void **)&emitter.data);
font->root.decode = alias_ui_freetype_font_decode;
font->root.user_data = font;
return &font->root;
}
void alias_ui_freetype_free_font(struct alias_ui_font * font) {
}
#endif
alias_ui_Result alias_ui_initialize(alias_MemoryCB *mcb, alias_ui **ui_ptr) {
struct alias_ui * ui = alias_malloc(mcb, sizeof(struct alias_ui), alignof(struct alias_ui));
*ui_ptr = ui;
if(ui == NULL) {
return alias_ui_ErrorOutOfMemory;
}
memset(ui, 0, sizeof(*ui));
ui->mcb = mcb;
return alias_ui_add_font(ui, &alias_ui__dev_font, NULL);
}
void alias_ui_free(alias_ui *ui, alias_MemoryCB *mcb) {
}
alias_ui_Result alias_ui_add_font(alias_ui *ui, struct alias_ui_Font *font, uint32_t *out_result) {
if(!alias_ui__grow((void **)&ui->font, sizeof(*ui->font), ui->font_length + 1, &ui->font_capacity)) {
return alias_ui_ErrorOutOfMemory;
}
uint32_t index = ui->font_length;
ui->font[index] = *font;
ui->font_length += 1;
if(out_result != NULL) {
*out_result = index;
}
return alias_ui_Success;
}
alias_ui_Result alias_ui_begin_frame(alias_ui *ui, alias_MemoryCB *mcb, const alias_ui_Input *input) {
alias_ui__program__initialize(ui);
alias_ui__memory__initialize(ui);
alias_ui__stats__initialize(ui);
ui->input = *input;
return alias_ui_Success;
}
void alias_ui_stats(alias_ui *ui, uint32_t *num_vertexes, uint32_t *num_indexes, uint32_t *num_groups) {
*num_vertexes = ui->stats.num_vertexes;
*num_indexes = ui->stats.num_indexes;
*num_groups = ui->stats.num_groups;
}
alias_ui_Result alias_ui_end_frame(alias_ui *ui, alias_MemoryCB *mcb, alias_ui_Output *output) {
ui->output = output;
float width = ui->input.screen_size.width;
float height = ui->input.screen_size.height;
alias_ui__layout__initialize(ui);
alias_ui__layout(ui, 0, width, 0, height, &width, &height);
alias_ui__render__initialize(ui);
alias_ui__render(ui, 0, 0, width, height);
alias_ui__group__finalize(ui);
return alias_ui_Success;
}