4coder/4ed_font_set.cpp

172 lines
4.3 KiB
C++

/*
* 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){
table_free(&slot->face->advance_map.codepoint_to_index.table);
linalloc_clear(&slot->arena);
}
block_zero_struct(slot);
sll_stack_push(set->free_face_slots, slot);
}
internal void
font_set_init(Font_Set *set){
block_zero_struct(set);
set->arena = make_arena_system();
set->next_id_counter = 1;
set->id_to_slot_table = make_table_u64_u64(set->arena.base_allocator, 40);
set->scale_factor = system_get_screen_scale_factor();
}
internal Face*
font_set_new_face(Font_Set *set, Face_Description *description){
Arena arena = make_arena_system();
Face *face = font_make_face(&arena, description, set->scale_factor);
if (face != 0){
Font_Face_Slot *slot = font_set__alloc_face_slot(set);
slot->arena = arena;
slot->face = face;
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);
}
else{
linalloc_clear(&arena);
}
return(face);
}
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){
i32 version_number = slot->face->version_number;
Arena arena = make_arena_system();
Face *face = font_make_face(&arena, description, set->scale_factor);
if (face != 0){
linalloc_clear(&slot->arena);
slot->arena = arena;
slot->face = face;
face->version_number = version_number + 1;
face->id = id;
result = true;
}
else{
linalloc_clear(&arena);
}
}
return(result);
}
// BOTTOM