/* * Mr. 4th Dimention - Allen Webster * * 11.03.2017 * * Implements some basic getters for fonts set up to make the font type opaque. * */ // TOP #include "4ed_font_data.h" internal u32 font_get_id_by_name(System_Functions *system, String name){ u32 id = 0; u32 count = system->font.get_count(); for (u32 index = 0; index < count; ++index){ char str[256]; u32 str_len = system->font.get_name_by_index(index, str, sizeof(str)); String font_name = make_string(str, str_len); if (match_ss(font_name, name)){ system->font.get_ids_by_index(index, 1, &id); break; } } return(id); } internal f32 font_get_byte_advance(Render_Font *font){ return(font->byte_advance); } internal f32* font_get_byte_sub_advances(Render_Font *font){ return(font->byte_sub_advances); } internal i32 font_get_height(Render_Font *font){ return(font->height); } internal i32 font_get_ascent(Render_Font *font){ return(font->ascent); } internal i32 font_get_descent(Render_Font *font){ return(font->descent); } internal i32 font_get_line_skip(Render_Font *font){ return(font->line_skip); } internal i32 font_get_advance(Render_Font *font){ return(font->advance); } internal b32 font_can_render(System_Functions *system, Render_Font *font, u32 codepoint){ b32 result = false; u32 page_number = (codepoint >> 8); u32 glyph_index = codepoint & 0xFF; Glyph_Page *page = font_get_or_make_page(system, font, page_number); if (page != 0 && page->advance[glyph_index] > 0.f){ result = true; } return(result); } internal f32 font_get_glyph_advance(System_Functions *system, Render_Font *font, u32 codepoint){ f32 result = 0.f; u32 page_number = (codepoint >> 8); u32 glyph_index = codepoint & 0xFF; Glyph_Page *page = 0; // Hack optimizations u32 cache_index = page_number % ArrayCount(font->cache); if (font->cache[cache_index].page_number == page_number){ page = font->cache[cache_index].page; } if (page == 0){ page = font_get_or_make_page(system, font, page_number); font->cache[cache_index].page = page; font->cache[cache_index].page_number = page_number; } if (page != 0 && page->advance[glyph_index] > 0.f){ result = page->advance[glyph_index]; } return(result); } internal Glyph_Data font_get_glyph(System_Functions *system, Render_Font *font, u32 codepoint){ Glyph_Data result = {0}; u32 page_number = (codepoint >> 8); u32 glyph_index = codepoint & 0xFF; Glyph_Page *page = 0; // Hack optimizations u32 cache_index = page_number % ArrayCount(font->cache); if (font->cache[cache_index].page_number == page_number){ page = font->cache[cache_index].page; } if (page == 0){ page = font_get_or_make_page(system, font, page_number); font->cache[cache_index].page = page; font->cache[cache_index].page_number = page_number; } if (page != 0 && page->advance[glyph_index] > 0.f){ result.bounds = page->glyphs[glyph_index]; result.tex = page->tex; result.tex_width = page->tex_width; result.tex_height = page->tex_height; } return(result); } internal Glyph_Page** font_page_lookup(Render_Font *font, u32 page_number, b32 get_empty_slot){ Glyph_Page **result = 0; if (font->page_max > 0){ u32 first_index = page_number % font->page_max; u32 range_count = 0; u32 ranges[4]; if (first_index == 0){ ranges[0] = 0; ranges[1] = font->page_max; range_count = 2; } else{ ranges[0] = first_index; ranges[1] = font->page_max; ranges[2] = 0; ranges[3] = first_index; range_count = 4; } Glyph_Page **pages = font->pages; if (get_empty_slot){ for (u32 j = 0; j < range_count; j += 2){ u32 stop = ranges[j+1]; for (u32 i = ranges[j]; i < stop; ++i){ if (pages[i] == FONT_PAGE_EMPTY || pages[i] == FONT_PAGE_DELETED){ result = &pages[i]; goto break2; } if (pages[i]->page_number == page_number){ goto break2; } } } } else{ for (u32 j = 0; j < range_count; j += 2){ u32 stop = ranges[j+1]; for (u32 i = ranges[j]; i < stop; ++i){ if (pages[i] == FONT_PAGE_EMPTY){ goto break2; } if (pages[i] != FONT_PAGE_DELETED && pages[i]->page_number == page_number){ result = &pages[i]; goto break2; } } } } break2:; } return(result); } internal Glyph_Page* font_get_or_make_page(System_Functions *system, Render_Font *font, u32 page_number){ Glyph_Page *result = 0; if (page_number <= 0x10FF){ Glyph_Page **page_get_result = font_page_lookup(font, page_number, false); if (page_get_result == 0){ b32 has_space = true; u32 new_page_count = 1; u32 new_max = (font->page_count+new_page_count)*3; if (font->page_max < FONT_PAGE_MAX && new_max > font->page_max*2){ Glyph_Page **pages = (Glyph_Page**)system->font.allocate(sizeof(Glyph_Page*)*new_max); has_space = false; if (pages != 0){ memset(pages, 0, sizeof(*pages)*new_max); u32 old_max = font->page_max; Glyph_Page **old_pages = font->pages; font->pages = pages; font->page_max = new_max; for (u32 i = 0; i < old_max; ++i){ Glyph_Page *this_page = old_pages[i]; if (this_page != FONT_PAGE_EMPTY && this_page != FONT_PAGE_DELETED){ u32 this_page_number = this_page->page_number; Glyph_Page **dest = font_page_lookup(font, this_page_number, true); Assert(dest != 0); *dest = this_page; } } system->font.free(old_pages); has_space = true; } } if (has_space){ Glyph_Page *new_page = (Glyph_Page*)system->font.allocate(sizeof(Glyph_Page)); if (new_page != 0){ Glyph_Page **dest = font_page_lookup(font, page_number, true); Assert(dest != 0); *dest = new_page; font->page_count += new_page_count; result = new_page; system->font.load_page(font, new_page, page_number); } } } else{ result = *page_get_result; } } return(result); } // BOTTOM