2019-07-24 07:41:40 +00:00
|
|
|
/*
|
|
|
|
* Mr. 4th Dimention - Allen Webster
|
|
|
|
*
|
|
|
|
* 23.07.2019
|
|
|
|
*
|
|
|
|
* Type for organizating the set of all loaded font faces.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
|
|
|
internal Face_ID
|
|
|
|
font_set__alloc_face_id(Font_Set *set){
|
|
|
|
Face_ID result = 0;
|
|
|
|
if (set->free_ids != 0){
|
|
|
|
Font_Face_ID_Node *node = set->free_ids;
|
|
|
|
result = node->id;
|
|
|
|
sll_stack_pop(set->free_ids);
|
|
|
|
sll_stack_push(set->free_id_nodes, node);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
result = set->next_id_counter;
|
|
|
|
set->next_id_counter += 1;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
font_set__free_face_id(Font_Set *set, Face_ID id){
|
|
|
|
if (id + 1 == set->next_id_counter){
|
|
|
|
set->next_id_counter -= 1;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
Font_Face_ID_Node *node = 0;
|
|
|
|
if (set->free_id_nodes == 0){
|
|
|
|
node = push_array(&set->arena, Font_Face_ID_Node, 1);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
node = set->free_id_nodes;
|
|
|
|
sll_stack_pop(set->free_id_nodes);
|
|
|
|
}
|
|
|
|
sll_stack_push(set->free_ids, node);
|
|
|
|
node->id = id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Font_Face_Slot*
|
|
|
|
font_set__alloc_face_slot(Font_Set *set){
|
|
|
|
Font_Face_Slot *result = 0;
|
|
|
|
if (set->free_face_slots == 0){
|
|
|
|
result = push_array(&set->arena, Font_Face_Slot, 1);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
result = set->free_face_slots;
|
|
|
|
sll_stack_pop(set->free_face_slots);
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
font_set__free_face_slot(Font_Set *set, Font_Face_Slot *slot){
|
|
|
|
if (slot->arena.base_allocator != 0){
|
2019-11-22 05:37:11 +00:00
|
|
|
table_free(&slot->face->advance_map.codepoint_to_index.table);
|
2019-07-24 07:41:40 +00:00
|
|
|
linalloc_clear(&slot->arena);
|
|
|
|
}
|
|
|
|
block_zero_struct(slot);
|
|
|
|
sll_stack_push(set->free_face_slots, slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2019-10-03 17:57:44 +00:00
|
|
|
font_set_init(Font_Set *set){
|
2019-07-24 07:41:40 +00:00
|
|
|
block_zero_struct(set);
|
2019-10-03 17:57:44 +00:00
|
|
|
set->arena = make_arena_system();
|
2019-07-24 07:41:40 +00:00
|
|
|
set->next_id_counter = 1;
|
|
|
|
set->id_to_slot_table = make_table_u64_u64(set->arena.base_allocator, 40);
|
2019-10-03 17:57:44 +00:00
|
|
|
set->scale_factor = system_get_screen_scale_factor();
|
2019-07-24 07:41:40 +00:00
|
|
|
}
|
|
|
|
|
2019-09-02 21:32:52 +00:00
|
|
|
internal Face*
|
2019-07-24 07:41:40 +00:00
|
|
|
font_set_new_face(Font_Set *set, Face_Description *description){
|
2019-10-03 17:57:44 +00:00
|
|
|
Arena arena = make_arena_system();
|
|
|
|
Face *face = font_make_face(&arena, description, set->scale_factor);
|
2019-07-24 07:41:40 +00:00
|
|
|
if (face != 0){
|
|
|
|
Font_Face_Slot *slot = font_set__alloc_face_slot(set);
|
|
|
|
slot->arena = arena;
|
|
|
|
slot->face = face;
|
2019-09-02 21:32:52 +00:00
|
|
|
Face_ID new_id = font_set__alloc_face_id(set);
|
|
|
|
face->id = new_id;
|
|
|
|
table_insert(&set->id_to_slot_table, new_id, (u64)slot);
|
2019-07-24 07:41:40 +00:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
linalloc_clear(&arena);
|
|
|
|
}
|
2019-09-02 21:32:52 +00:00
|
|
|
return(face);
|
2019-07-24 07:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal Font_Face_Slot*
|
|
|
|
font_set__get_face_slot(Font_Set *set, Face_ID id){
|
|
|
|
Font_Face_Slot *result = 0;
|
|
|
|
u64 slot_ptr_u64 = 0;
|
|
|
|
if (table_read(&set->id_to_slot_table, id, &slot_ptr_u64)){
|
|
|
|
result = (Font_Face_Slot*)slot_ptr_u64;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal b32
|
|
|
|
font_set_release_face(Font_Set *set, Face_ID id){
|
|
|
|
b32 result = false;
|
|
|
|
Font_Face_Slot *slot = font_set__get_face_slot(set, id);
|
|
|
|
if (slot != 0){
|
|
|
|
table_erase(&set->id_to_slot_table, id);
|
|
|
|
font_set__free_face_slot(set, slot);
|
|
|
|
font_set__free_face_id(set, id);
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Face*
|
|
|
|
font_set_face_from_id(Font_Set *set, Face_ID id){
|
|
|
|
Face *result = 0;
|
|
|
|
Font_Face_Slot *slot = font_set__get_face_slot(set, id);
|
|
|
|
if (slot != 0){
|
|
|
|
result = slot->face;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Face_ID
|
|
|
|
font_set_get_fallback_face(Font_Set *set){
|
|
|
|
Face_ID result = 0;
|
|
|
|
for (Face_ID i = 1; i < set->next_id_counter; i += 1){
|
|
|
|
if (font_set__get_face_slot(set, i) != 0){
|
|
|
|
result = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal Face_ID
|
|
|
|
font_set_get_largest_id(Font_Set *set){
|
|
|
|
return(set->next_id_counter - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal b32
|
|
|
|
font_set_modify_face(Font_Set *set, Face_ID id, Face_Description *description){
|
|
|
|
b32 result = false;
|
|
|
|
Font_Face_Slot *slot = font_set__get_face_slot(set, id);
|
|
|
|
if (slot != 0){
|
2019-09-02 18:59:36 +00:00
|
|
|
i32 version_number = slot->face->version_number;
|
2019-10-03 17:57:44 +00:00
|
|
|
Arena arena = make_arena_system();
|
|
|
|
Face *face = font_make_face(&arena, description, set->scale_factor);
|
2019-07-24 07:41:40 +00:00
|
|
|
if (face != 0){
|
|
|
|
linalloc_clear(&slot->arena);
|
|
|
|
slot->arena = arena;
|
|
|
|
slot->face = face;
|
2019-09-02 18:59:36 +00:00
|
|
|
face->version_number = version_number + 1;
|
2019-07-27 01:40:31 +00:00
|
|
|
face->id = id;
|
2019-07-24 07:41:40 +00:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
linalloc_clear(&arena);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
// BOTTOM
|
|
|
|
|