diff --git a/4coder_default_framework.h b/4coder_default_framework.h index c840049b..d039ca8e 100644 --- a/4coder_default_framework.h +++ b/4coder_default_framework.h @@ -745,14 +745,7 @@ process_config_file(Application_Links *app){ char str_space[512]; String str = make_fixed_width_string(str_space); if (config_string_var(item, "treat_as_code", 0, &str)){ - if (str.size < sizeof(treat_as_code_exts.extension_space)){ - set_extensions(&treat_as_code_exts, str); - print_message(app, str.str, str.size); - print_message(app, "\n", 1); - } - else{ - print_message(app, literal("STRING TOO LONG!\n")); - } + set_extensions(&treat_as_code_exts, str); } } } diff --git a/4coder_lib/4coder_utf8.h b/4coder_lib/4coder_utf8.h index 51209a9d..d60de499 100644 --- a/4coder_lib/4coder_utf8.h +++ b/4coder_lib/4coder_utf8.h @@ -146,28 +146,28 @@ utf8_to_u32(u8_4tech **buffer_ptr, u8_4tech *end){ } static void -u32_to_utf8_unchecked(u32_4tech code_point, u8_4tech *buffer, u32_4tech *length_out){ - if (code_point <= 0x7F){ - buffer[0] = (u8_4tech)code_point; +u32_to_utf8_unchecked(u32_4tech codepoint, u8_4tech *buffer, u32_4tech *length_out){ + if (codepoint <= 0x7F){ + buffer[0] = (u8_4tech)codepoint; *length_out = 1; } - else if (code_point <= 0x7FF){ - buffer[0] = (u8_4tech)(0xC0 | (code_point >> 6)); - buffer[1] = (u8_4tech)(0x80 | (code_point & 0x3F)); + else if (codepoint <= 0x7FF){ + buffer[0] = (u8_4tech)(0xC0 | (codepoint >> 6)); + buffer[1] = (u8_4tech)(0x80 | (codepoint & 0x3F)); *length_out = 2; } - else if (code_point <= 0xFFFF){ - buffer[0] = (u8_4tech)(0xE0 | (code_point >> 12)); - buffer[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F)); - buffer[2] = (u8_4tech)(0x80 | (code_point & 0x3F)); + else if (codepoint <= 0xFFFF){ + buffer[0] = (u8_4tech)(0xE0 | (codepoint >> 12)); + buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F)); + buffer[2] = (u8_4tech)(0x80 | (codepoint & 0x3F)); *length_out = 3; } else{ - code_point &= 0x001FFFFF; - buffer[0] = (u8_4tech)(0xF0 | (code_point >> 18)); - buffer[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F)); - buffer[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F)); - buffer[3] = (u8_4tech)(0x80 | (code_point & 0x3F)); + codepoint &= 0x001FFFFF; + buffer[0] = (u8_4tech)(0xF0 | (codepoint >> 18)); + buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F)); + buffer[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F)); + buffer[3] = (u8_4tech)(0x80 | (codepoint & 0x3F)); *length_out = 4; } } @@ -186,11 +186,11 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech * *error = false; for(; s < s_end;){ - u32_4tech code_point = 0; + u32_4tech codepoint = 0; u32_4tech utf8_size = 0; if (s[0] <= 0x7F){ - code_point = (u32_4tech)s[0]; + codepoint = (u32_4tech)s[0]; utf8_size = 1; } else if (s[0] <= 0xE0){ @@ -199,8 +199,8 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech * break; } - code_point = ((u32_4tech)((s[0])&0x1F)) << 6; - code_point |= ((u32_4tech)((s[1])&0x3F)); + codepoint = ((u32_4tech)((s[0])&0x1F)) << 6; + codepoint |= ((u32_4tech)((s[1])&0x3F)); utf8_size = 2; } else if (s[0] <= 0xF0){ @@ -209,9 +209,9 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech * break; } - code_point = ((u32_4tech)((s[0])&0x0F)) << 12; - code_point |= ((u32_4tech)((s[1])&0x3F)) << 6; - code_point |= ((u32_4tech)((s[2])&0x3F)); + codepoint = ((u32_4tech)((s[0])&0x0F)) << 12; + codepoint |= ((u32_4tech)((s[1])&0x3F)) << 6; + codepoint |= ((u32_4tech)((s[2])&0x3F)); utf8_size = 3; } else{ @@ -220,26 +220,26 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech * break; } - code_point = ((u32_4tech)((s[0])&0x07)) << 18; - code_point |= ((u32_4tech)((s[1])&0x3F)) << 12; - code_point |= ((u32_4tech)((s[2])&0x3F)) << 6; - code_point |= ((u32_4tech)((s[3])&0x3F)); + codepoint = ((u32_4tech)((s[0])&0x07)) << 18; + codepoint |= ((u32_4tech)((s[1])&0x3F)) << 12; + codepoint |= ((u32_4tech)((s[2])&0x3F)) << 6; + codepoint |= ((u32_4tech)((s[3])&0x3F)); utf8_size = 4; } s += utf8_size; limit -= utf8_size; - if (code_point <= 0xD7FF || (code_point >= 0xE000 && code_point <= 0xFFFF)){ - *d = (u16_4tech)(code_point); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)){ + *d = (u16_4tech)(codepoint); d += advance; needed_max += 1; } - else if (code_point >= 0x10000 && code_point <= 0x10FFFF){ - code_point -= 0x10000; + else if (codepoint >= 0x10000 && codepoint <= 0x10FFFF){ + codepoint -= 0x10000; - u32_4tech high = (code_point >> 10) & 0x03FF; - u32_4tech low = (code_point) & 0x03FF; + u32_4tech high = (codepoint >> 10) & 0x03FF; + u32_4tech low = (codepoint) & 0x03FF; high += 0xD800; low += 0xDC00; @@ -283,11 +283,11 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s *error = false; for (; s < s_end;){ - u32_4tech code_point = 0; + u32_4tech codepoint = 0; u32_4tech utf16_size = 0; if (s[0] <= 0xD7FF || (s[0] >= 0xE000 && s[0] <= 0xFFFF)){ - code_point = s[0]; + codepoint = s[0]; utf16_size = 1; } else{ @@ -299,7 +299,7 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s u32_4tech high = s[0] - 0xD800; u32_4tech low = s[1] - 0xDC00; - code_point = ((high << 10) | (low)) + 0x10000; + codepoint = ((high << 10) | (low)) + 0x10000; utf16_size = 2; } else{ @@ -314,26 +314,26 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s u8_4tech d_fill[4]; u32_4tech d_fill_count = 0; - if (code_point <= 0x7F){ - d_fill[0] = (u8_4tech)code_point; + if (codepoint <= 0x7F){ + d_fill[0] = (u8_4tech)codepoint; d_fill_count = 1; } - else if (code_point <= 0x7FF){ - d_fill[0] = (u8_4tech)(0xC0 | (code_point >> 6)); - d_fill[1] = (u8_4tech)(0x80 | (code_point & 0x3F)); + else if (codepoint <= 0x7FF){ + d_fill[0] = (u8_4tech)(0xC0 | (codepoint >> 6)); + d_fill[1] = (u8_4tech)(0x80 | (codepoint & 0x3F)); d_fill_count = 2; } - else if (code_point <= 0xFFFF){ - d_fill[0] = (u8_4tech)(0xE0 | (code_point >> 12)); - d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F)); - d_fill[2] = (u8_4tech)(0x80 | (code_point & 0x3F)); + else if (codepoint <= 0xFFFF){ + d_fill[0] = (u8_4tech)(0xE0 | (codepoint >> 12)); + d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F)); + d_fill[2] = (u8_4tech)(0x80 | (codepoint & 0x3F)); d_fill_count = 3; } - else if (code_point <= 0x10FFFF){ - d_fill[0] = (u8_4tech)(0xF0 | (code_point >> 18)); - d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F)); - d_fill[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F)); - d_fill[3] = (u8_4tech)(0x80 | (code_point & 0x3F)); + else if (codepoint <= 0x10FFFF){ + d_fill[0] = (u8_4tech)(0xF0 | (codepoint >> 18)); + d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F)); + d_fill[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F)); + d_fill[3] = (u8_4tech)(0x80 | (codepoint & 0x3F)); d_fill_count = 4; } else{ diff --git a/4ed.cpp b/4ed.cpp index 73cf3efb..6c38214c 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1478,13 +1478,13 @@ App_Init_Sig(app_init){ char *custom_font_name = models->settings.custom_font_name; i32 custom_font_size = models->settings.custom_font_size; b32 use_custom_font = true; - if (!custom_font_file){ + if (custom_font_file == 0){ use_custom_font = false; custom_font_file = ""; custom_font_name = ""; } - if (font_size < 8) font_size = 8; + font_size = clamp_bottom(8, font_size); Font_Setup font_setup[] = { {literal("LiberationSans-Regular.ttf"), literal("Liberation Sans"), font_size}, @@ -1531,9 +1531,6 @@ App_Init_Sig(app_init){ // NOTE(allen): style setup app_hardcode_styles(models); - models->palette_size = 40; - models->palette = push_array(partition, u32, models->palette_size); - // NOTE(allen): init first panel Command_Data *cmd = &vars->command_data; @@ -1556,8 +1553,8 @@ App_Init_Sig(app_init){ }; File_Init init_files[] = { - { make_lit_string("*messages*"), &models->message_buffer, 1, }, - { make_lit_string("*scratch*"), &models->scratch_buffer, 0, } + { make_lit_string("*messages*"), &models->message_buffer, true , }, + { make_lit_string("*scratch*"), &models->scratch_buffer, false, } }; for (i32 i = 0; i < ArrayCount(init_files); ++i){ diff --git a/4ed_app_models.h b/4ed_app_models.h index d63fe79f..2c2efe99 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -74,11 +74,8 @@ struct Models{ Input_Filter_Function *input_filter; Scroll_Rule_Function *scroll_rule; - Font_Set *font_set; - Style_Font global_font; Style_Library styles; u32 *palette; - i32 palette_size; Editing_Layout layout; Working_Set working_set; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index e1fbaae0..9f1559d8 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -229,7 +229,6 @@ struct View{ // theme stuff View *hot_file_view; u32 *palette; - i32 palette_size; Color_View_Mode color_mode; Super_Color color; b32 p4c_only; @@ -387,8 +386,12 @@ view_cursor_limits(View *view){ internal Full_Cursor view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){ Editing_File *file = view->file_data.file; + +#if 0 Models *models = view->persistent.models; Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font; +#endif + Render_Font *font = 0; Full_Cursor result = {0}; @@ -1031,7 +1034,11 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, Render_Font *font){ state->i = 0; state->font = font; + +#if 0 state->tab_indent_amount = get_codepoint_advance(font, '\t'); +#endif + state->tab_indent_amount = 2.f; state->tran = null_buffer_translating_state; } @@ -1143,7 +1150,11 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){ u32 n = state->tran.step_current.value; f32 adv = 0; if (state->tran.do_codepoint_advance){ +#if 0 adv = get_codepoint_advance(state->font, n); +#endif + adv = 2.f; + if (n != ' ' && n != '\t'){ skipping_whitespace = false; } @@ -1543,7 +1554,11 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){ word_stage = 1; } else{ +#if 0 f32 adv = get_codepoint_advance(params.font, ch); +#endif + f32 adv = 2.f; + x += adv; self_x += adv; if (self_x > width){ @@ -1670,7 +1685,11 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){ goto doublebreak_stage1; } +#if 0 f32 adv = get_codepoint_advance(params.font, ch); +#endif + f32 adv = 2.f; + x += adv; if (!first_word && x > current_width){ emit_comment_position = 1; @@ -1696,7 +1715,12 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){ goto doublebreak_stage2; } + +#if 0 f32 adv = get_codepoint_advance(params.font, ch); +#endif + f32 adv = 2.f; + x += adv; } still_looping = buffer_stringify_next(&stream); diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp index a4439e71..0f81b0df 100644 --- a/4ed_font_set.cpp +++ b/4ed_font_set.cpp @@ -9,236 +9,5 @@ // TOP -inline u32 -font_hash(String name){ - u32 x = 5381; - char *p = name.str; - for (i32 i = 0; i < name.size; ++i, ++p){ - x = ((x << 5) + x) ^ (*p); - } - return(x); -} - -inline void -font__insert(Font_Slot *pos, Font_Slot *slot){ - Font_Slot *nex; - nex = pos->next; - - slot->next = nex; - slot->prev = pos; - nex->prev = slot; - pos->next = slot; -} - -inline void -font__remove(Font_Slot *slot){ - Font_Slot *n, *p; - n = slot->next; - p = slot->prev; - - p->next = n; - n->prev = p; -} - -inline Font_Slot -font_slot_zero(){ - Font_Slot slot = {0}; - return(slot); -} - -internal void -font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){ - partition_align(partition, 8); - set->info = push_array(partition, Font_Info, max); - partition_align(partition, 8); - set->entries = push_array(partition, Font_Table_Entry, max); - set->count = 0; - set->max = max; - - partition_align(partition, 8); - set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot))); - - set->free_slots = font_slot_zero(); - set->used_slots = font_slot_zero(); - - dll_init_sentinel(&set->free_slots); - dll_init_sentinel(&set->used_slots); - - char *ptr = (char*)set->font_block; - for (i32 i = 0; i < live_max; ++i){ - dll_insert(&set->free_slots, (Font_Slot*)ptr); - ptr += sizeof(Font_Slot) + sizeof(Render_Font); - } - - set->font_used_flags = push_array(partition, b8, max); - set->live_max = live_max; -} - -internal b32 -font_set_can_add(Font_Set *set){ - b32 result = 0; - if (set->count*8 < set->max*7) result = 1; - return(result); -} - -internal void -font_set_add_hash(Font_Set *set, String name, i16 font_id){ - Font_Table_Entry entry; - entry.hash = font_hash(name); - entry.name = name; - entry.font_id = font_id; - - u32 i, j; - i = entry.hash % set->max; - j = i - 1; - if (i <= 1) j += set->max; - - for (; i != j; ++i){ - if (i == set->max) i = 0; - if (set->entries[i].font_id == 0){ - set->entries[i] = entry; - break; - } - } - - Assert(i != j); -} - -inline b32 -font_set_can_load(Font_Set *set){ - b32 result = (set->free_slots.next != &set->free_slots); - return(result); -} - -internal void -font_set_load(Font_Set *set, i16 font_id){ - Font_Info *info = get_font_info(set, font_id); - Font_Slot *slot = set->free_slots.next; - Assert(slot != &set->free_slots); - font__remove(slot); - font__insert(&set->used_slots, slot); - - Render_Font *font = (Render_Font*)(slot + 1); - set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true); - info->font = font; - slot->font_id = font_id; -} - -internal void -font_set_evict_lru(Font_Set *set){ - Font_Slot *slot = set->used_slots.prev; - Assert(slot != &set->used_slots); - - i16 font_id = slot->font_id; - Font_Info *info = get_font_info(set, font_id); - Assert(((Font_Slot*)info->font) - 1 == slot); - - set->release_font(info->font); - - info->font = 0; - slot->font_id = 0; - font__remove(slot); - font__insert(&set->free_slots, slot); -} - -internal void -font_set_use(Font_Set *set, i16 font_id){ - b8 already_used = set->font_used_flags[font_id-1]; - - if (!already_used){ - if (set->used_this_frame < set->live_max){ - ++set->used_this_frame; - set->font_used_flags[font_id-1] = 1; - already_used = 1; - } - } - - if (already_used){ - // TODO(allen): optimize if you don't mind!!!! - Font_Info *info = get_font_info(set, font_id); - Font_Slot *slot; - if (info->font == 0){ - if (!font_set_can_load(set)){ - font_set_evict_lru(set); - } - font_set_load(set, font_id); - } - slot = ((Font_Slot*)info->font) - 1; - - font__remove(slot); - font__insert(&set->used_slots, slot); - } -} - -internal b32 -font_set_add(Font_Set *set, String filename, String name, i32 pt_size){ - b32 result = 0; - if (font_set_can_add(set)){ - Render_Font dummy_font = {0}; - i16 font_id = (i16)(++set->count); - Font_Info *info = get_font_info(set, font_id); - info->filename = filename; - info->name = name; - info->pt_size = pt_size; - set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false); - //info->height = dummy_font.height; - //info->advance = dummy_font.advance; - - font_set_add_hash(set, name, font_id); - - if (font_set_can_load(set)){ - font_set_load(set, font_id); - } - - result = 1; - } - return(result); -} - -internal b32 -font_set_find_pos(Font_Set *set, String name, u32 *position){ - u32 hash = font_hash(name); - u32 i = hash % set->max; - u32 j = i - 1; - if (j <= 1){ - j += set->max; - } - - b32 result = 0; - for (; i != j; ++i){ - if (i == set->max){ - i = 0; - } - - Font_Table_Entry *entry = set->entries + i; - if (entry->hash == hash){ - if (match_ss(name, entry->name)){ - result = 1; - *position = i; - break; - } - } - } - - return(result); -} - -internal b32 -font_set_get_name(Font_Set *set, i16 font_id, String *name){ - Font_Info *info = get_font_info(set, font_id); - b32 result = copy_checked_ss(name, info->name); - return(result); -} - -internal b32 -font_set_extract(Font_Set *set, String name, i16 *font_id){ - u32 position; - b32 result = font_set_find_pos(set, name, &position); - if (result){ - *font_id = set->entries[position].font_id; - } - return(result); -} - // BOTTOM diff --git a/4ed_math.h b/4ed_math.h index 129ae6a7..eedbcafc 100644 --- a/4ed_math.h +++ b/4ed_math.h @@ -475,12 +475,24 @@ clamp_bottom(u32 a, u32 n){ return (n); } +inline u64 +clamp_bottom(u64 a, u64 n){ + if (n < a) n = a; + return (n); +} + inline u32 clamp_top(u32 n, u32 z){ if (n > z) n = z; return (n); } +inline u64 +clamp_top(u64 n, u64 z){ + if (n > z) n = z; + return (n); +} + inline u32 clamp(u32 a, u32 n, u32 z){ if (n < a) n = a; diff --git a/4ed_rendering.h b/4ed_rendering.h index a85a4d6f..73e4cdd5 100644 --- a/4ed_rendering.h +++ b/4ed_rendering.h @@ -12,54 +12,6 @@ #ifndef FRED_RENDERING_H #define FRED_RENDERING_H -// -// Fonts -// - -#include "file/4coder_font_data.h" - -struct Font_Table_Entry{ - u32 hash; - String name; - i16 font_id; -}; - -struct Font_Info{ - Render_Font *font; - String filename; - String name; - i32 pt_size; -}; - -struct Font_Slot{ - Font_Slot *next, *prev; - i16 font_id; - u8 padding[6]; -}; - -#define Font_Load_Sig(name) i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture) -typedef Font_Load_Sig(Font_Load); - -#define Release_Font_Sig(name) void name(Render_Font *font) -typedef Release_Font_Sig(Release_Font); - -struct Font_Set{ - Font_Info *info; - Font_Table_Entry *entries; - u32 count, max; - - void *font_block; - Font_Slot free_slots; - Font_Slot used_slots; - - Font_Load *font_load; - Release_Font *release_font; - - b8 *font_used_flags; - i16 used_this_frame; - i16 live_max; -}; - // // Render Commands // @@ -150,10 +102,6 @@ struct Render_Target{ Draw_Push_Clip *push_clip; Draw_Pop_Clip *pop_clip; Draw_Push_Piece *push_piece; - - // TODO(allen): Does the font set really belong here? Actually, do we still want it at all? - Font_Set font_set; - Partition *partition; }; #define DpiMultiplier(n,dpi) ((n) * (dpi) / 96) @@ -168,12 +116,6 @@ rect_from_target(Render_Target *target){ return(r); } -inline Font_Info* -get_font_info(Font_Set *set, i16 font_id){ - Font_Info *result = set->info + font_id - 1; - return(result); -} - #endif // BOTTOM diff --git a/4ed_rendering_helper.cpp b/4ed_rendering_helper.cpp index 078af7ff..6523982f 100644 --- a/4ed_rendering_helper.cpp +++ b/4ed_rendering_helper.cpp @@ -28,9 +28,6 @@ draw_change_clip(Render_Target *target, i32_Rect clip_box){ internal void begin_render_section(Render_Target *target, System_Functions *system){ - Font_Set *font_set = &target->font_set; - font_set->used_this_frame = 0; - memset(font_set->font_used_flags, 0, font_set->max); target->size = 0; target->clip_top = -1; @@ -117,6 +114,8 @@ font_predict_size(i32 pt_size){ internal void font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 x, f32 y, u32 color){ + +#if 0 Render_Piece_Combined piece; piece.header.type = type; piece.glyph.pos.x = x; @@ -126,6 +125,8 @@ font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 piece.glyph.character = character; target->push_piece(target, piece); font_set_use(&target->font_set, font_id); +#endif + } internal void @@ -135,9 +136,12 @@ font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, internal f32 draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){ + + f32 x = 0; + +#if 0 Font_Info *font_info = get_font_info(&target->font_set, font_id); Render_Font *font = font_info->font; - f32 x = 0; if (font){ f32 y = (f32)y_; @@ -192,6 +196,7 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 } } } +#endif return(x); } diff --git a/4ed_system_shared.cpp b/4ed_system_shared.cpp index 1261feee..4e75350e 100644 --- a/4ed_system_shared.cpp +++ b/4ed_system_shared.cpp @@ -218,7 +218,7 @@ sysshared_to_binary_path(String *out_filename, char *filename){ translate_success = 1; } } - return (translate_success); + return(translate_success); } // @@ -545,77 +545,28 @@ launch_rendering(Render_Target *target){ #undef internal #include #include FT_FREETYPE_H -#include FT_LCD_FILTER_H #define internal static -internal u32 -next_pow_of_2(u32 v){ - --v; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return ++v; -} - -#define NUM_GLYPHS 256 -#define ENABLE_LCD_FILTER 0 - -internal b32 -font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size, i32 tab_width, b32 use_hinting){ - - memset(rf, 0, sizeof(*rf)); - - //TODO(inso): put stuff in linuxvars / init in main - FT_Library ft; - FT_Face face; - b32 use_lcd_filter = 0; - - FT_Init_FreeType(&ft); - - //NOTE(inso): i'm not sure the LCD filter looks better, and it doesn't work perfectly with the coloring stuff - // it will probably need shaders to work properly -#if ENABLE_LCD_FILTER - if(FT_Library_SetLcdFilter(ft, FT_LCD_FILTER_DEFAULT) == 0){ - puts("LCD Filter on"); - use_lcd_filter = 1; - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } -#endif - - FT_New_Face(ft, filename, 0, &face); - - // set size & metrics - FT_Size_RequestRec_ size = {}; - size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - size.height = pt_size << 6; - FT_Request_Size(face, &size); - - rf->loaded = 1; - rf->ascent = ceil32 (face->size->metrics.ascender / 64.0f); - rf->descent = floor32 (face->size->metrics.descender / 64.0f); - rf->advance = ceil32 (face->size->metrics.max_advance / 64.0f); - rf->height = ceil32 (face->size->metrics.height / 64.0f); - rf->line_skip = rf->height - (rf->ascent - rf->descent); - - rf->height -= rf->line_skip; - rf->line_skip = 0; +internal void +font_load_freetype_page_inner(Partition *part, Render_Font *font, FT_Library ft, FT_Face face, b32 use_hinting, Glyph_Page *page, u32 page_number, i32 tab_width){ + Temp_Memory temp = begin_temp_memory(part); + Assert(page != 0); + page->page_number = page_number; + // prepare to read glyphs into a temporary texture buffer i32 max_glyph_w = face->size->metrics.x_ppem; - i32 max_glyph_h = rf->height; + i32 max_glyph_h = font->height; i32 tex_width = 64; i32 tex_height = 0; - // estimate upper bound on texture width do { tex_width *= 2; float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w); - float rows = ceilf(NUM_GLYPHS / glyphs_per_row); + float rows = ceilf(ITEM_PER_FONT_PAGE / glyphs_per_row); tex_height = ceil32(rows * (max_glyph_h + 2)); } while(tex_height > tex_width); - tex_height = next_pow_of_2(tex_height); + tex_height = round_up_pot_u32(tex_height); i32 pen_x = 0; i32 pen_y = 0; @@ -623,60 +574,46 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size u32* pixels = push_array(part, u32, tex_width * tex_height); memset(pixels, 0, tex_width * tex_height * sizeof(u32)); - u32 ft_extra_flags = 0; - if (use_lcd_filter){ - ft_extra_flags = FT_LOAD_TARGET_LCD; + u32 ft_flags = FT_LOAD_RENDER; + if (use_hinting){ + // NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo + // maybe it could be exposed as an option for hinting, instead of just on/off. + ft_flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; } else{ - if (use_hinting){ - // NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo - // maybe it could be exposed as an option for hinting, instead of just on/off. - ft_extra_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; - } - else{ - ft_extra_flags = (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING); - } + ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING); } - for(i32 i = 0; i < NUM_GLYPHS; ++i){ - if(FT_Load_Char(face, i, FT_LOAD_RENDER | ft_extra_flags) != 0) continue; + // fill the texture + u32 base_codepoint = (page_number << 8); + Glyph_Bounds *glyph_ptr = &page->glyphs[0]; + f32 *advance_ptr = &page->advance[0]; + for(u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++glyph_ptr, ++advance_ptr){ + u32 codepoint = i + base_codepoint; - i32 w = face->glyph->bitmap.width; - i32 h = face->glyph->bitmap.rows; - - // lcd filter produces RGB bitmaps, need to account for the extra components - if(use_lcd_filter){ - w /= 3; - } - - // move to next line if necessary - if(pen_x + w >= tex_width){ - pen_x = 0; - pen_y += (max_glyph_h + 2); - } - - // set all this stuff the renderer needs - Glyph_Bounds* c = 0; - f32 *advance_ptr = 0; - get_codepoint_memory(rf, i, &c, &advance_ptr); - if (c != 0 && advance_ptr != 0){ - c->exists = true; + if(FT_Load_Char(face, codepoint, ft_flags) == 0){ + i32 w = face->glyph->bitmap.width; + i32 h = face->glyph->bitmap.rows; - c->x0 = (f32)(pen_x); - c->y0 = (f32)(pen_y); - c->x1 = (f32)(pen_x + w); - c->y1 = (f32)(pen_y + h + 1); + // move to next line if necessary + if(pen_x + w >= tex_width){ + pen_x = 0; + pen_y += (max_glyph_h + 2); + } - c->xoff = (f32)(face->glyph->bitmap_left); - c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top); + // set all this stuff the renderer needs + glyph_ptr->x0 = (f32)(pen_x); + glyph_ptr->y0 = (f32)(pen_y); + glyph_ptr->x1 = (f32)(pen_x + w); + glyph_ptr->y1 = (f32)(pen_y + h + 1); - c->xoff2 = w + c->xoff; - c->yoff2 = h + c->yoff + 1; + glyph_ptr->xoff = (f32)(face->glyph->bitmap_left); + glyph_ptr->yoff = (f32)(font->ascent - face->glyph->bitmap_top); + glyph_ptr->xoff2 = glyph_ptr->xoff + w; + glyph_ptr->yoff2 = glyph_ptr->yoff + h + 1; - // TODO(allen): maybe advance data should be integers for a while... - // I require the actual values to be integers anyway... hmm... - f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f); - *advance_ptr = advance; + // TODO(allen): maybe advance data should be integers? + *advance_ptr = (f32)ceil32(face->glyph->advance.x / 64.0f); // write to texture atlas i32 pitch = face->glyph->bitmap.pitch; @@ -685,67 +622,20 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size i32 x = pen_x + i; i32 y = pen_y + j; - if(use_lcd_filter){ -#if 1 - u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; - u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0]; - u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; - - pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r; - -#else - - u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3]; - u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; - u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; - u8 a = (u8)ROUND32((r + g + b) / 3.0f); - - pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b; -#endif - } else { - pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101; - } + pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x01010101; } } - pen_x = ceil32(c->x1 + 1); + pen_x = ceil32(glyph_ptr->x1 + 1); } } - // NOTE(allen): Setup some basic spacing stuff. - f32 space_adv = get_codepoint_advance(rf, ' '); - f32 backslash_adv = get_codepoint_advance(rf, '\\'); - f32 r_adv = get_codepoint_advance(rf, 'r'); - - set_codepoint_advance(rf, '\n', space_adv); - set_codepoint_advance(rf, '\r', backslash_adv + r_adv); - set_codepoint_advance(rf, '\t', space_adv*tab_width); - - f32 max_hex_advance = 0.f; - for (u32 i = '0'; i <= '9'; ++i){ - f32 adv = get_codepoint_advance(rf, i); - max_hex_advance = Max(max_hex_advance, adv); - } - for (u32 i = 'a'; i <= 'f'; ++i){ - f32 adv = get_codepoint_advance(rf, i); - max_hex_advance = Max(max_hex_advance, adv); - } - for (u32 i = 'A'; i <= 'F'; ++i){ - f32 adv = get_codepoint_advance(rf, i); - max_hex_advance = Max(max_hex_advance, adv); - } - - rf->byte_advance = backslash_adv + max_hex_advance*2; - - FT_Done_FreeType(ft); - - tex_height = next_pow_of_2(pen_y + max_glyph_h + 2); - - u32 page_index = 0; - rf->glyph_pages[page_index].tex_width = tex_width; - rf->glyph_pages[page_index].tex_height = tex_height; - // upload texture + tex_height = round_up_pot_u32(pen_y + max_glyph_h + 2); + + page->tex_width = tex_width; + page->tex_height = tex_height; + u32 tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); @@ -756,28 +646,107 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - if(use_lcd_filter){ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels); - } + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels); glBindTexture(GL_TEXTURE_2D, 0); - rf->glyph_pages[page_index].tex = tex; + page->tex = tex; + page->page_number = page_number; - rf->glyph_pages[page_index].exists = true; + end_temp_memory(temp); + + // whitespace spacing stuff + if (page_number == 0){ + f32 space_adv = get_codepoint_advance(font, ' '); + f32 backslash_adv = get_codepoint_advance(font, '\\'); + f32 r_adv = get_codepoint_advance(font, 'r'); + + set_codepoint_advance(font, '\n', space_adv); + set_codepoint_advance(font, '\r', backslash_adv + r_adv); + set_codepoint_advance(font, '\t', space_adv*tab_width); + } +} + +internal b32 +font_load_freetype_page(Partition *part, Render_Font *font, char *filename, i32 pt_size, b32 use_hinting, u32 page_number, i32 tab_width){ + + // TODO(allen): Stop redoing all this init for each call. + FT_Library ft; + FT_Init_FreeType(&ft); + + FT_Face face; + FT_New_Face(ft, filename, 0, &face); + + Glyph_Page *page = font_get_or_make_page(font, page_number); + font_load_freetype_page_inner(part, font, ft, face, use_hinting, page_number, tab_width); + FT_Done_FreeType(ft); + + return(true); +} + +internal b32 +font_load_freetype(Partition *part, Render_Font *font, char *filename, i32 pt_size, i32 tab_width, b32 use_hinting){ + + memset(font, 0, sizeof(*font)); + + // TODO(allen): Stop redoing all this init for each call. + FT_Library ft; + FT_Init_FreeType(&ft); + + FT_Face face; + FT_New_Face(ft, filename, 0, &face); + + // set size & metrics + FT_Size_RequestRec_ size = {}; + size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; + size.height = pt_size << 6; + FT_Request_Size(face, &size); + + font->loaded = true; + font->ascent = ceil32 (face->size->metrics.ascender / 64.0f); + font->descent = floor32 (face->size->metrics.descender / 64.0f); + font->advance = ceil32 (face->size->metrics.max_advance / 64.0f); + font->height = ceil32 (face->size->metrics.height / 64.0f); + font->line_skip = font->height - (font->ascent - font->descent); + + font->height -= font->line_skip; + font->line_skip = 0; + + // NOTE(allen): set texture and glyph data. + Glyph_Page *page = font_get_or_make_page(font, 0); + font_load_freetype_page_inner(part, font, ft, face, use_hinting, page, 0, tab_width); + + // NOTE(allen): Setup some basic spacing stuff. + f32 backslash_adv = get_codepoint_advance(font, '\\'); + f32 max_hex_advance = 0.f; + for (u32 i = '0'; i <= '9'; ++i){ + f32 adv = get_codepoint_advance(font, i); + max_hex_advance = Max(max_hex_advance, adv); + } + for (u32 i = 'a'; i <= 'f'; ++i){ + f32 adv = get_codepoint_advance(font, i); + max_hex_advance = Max(max_hex_advance, adv); + } + for (u32 i = 'A'; i <= 'F'; ++i){ + f32 adv = get_codepoint_advance(font, i); + max_hex_advance = Max(max_hex_advance, adv); + } + + font->byte_advance = backslash_adv + max_hex_advance*2; + + FT_Done_FreeType(ft); return(true); } internal Release_Font_Sig(draw_release_font){ - for (u32 i = 0; i < ArrayCount(font->glyph_pages); ++i){ - Glyph_Page *page = &font->glyph_pages[i]; - if (page->exists){ + for (u32 i = 0; i < ArrayCount(font->pages); ++i){ + Glyph_Page *page = font->pages[i]; + if (IS_REAL_FONT_PAGE(page)){ glDeleteTextures(1, &page->tex); + FREE(page); } - page->tex = 0; + FREE(font->pages); } } diff --git a/4tech_defines.h b/4tech_defines.h index f916793a..93ae61da 100644 --- a/4tech_defines.h +++ b/4tech_defines.h @@ -60,33 +60,44 @@ typedef double f64; #define Min(a,b) (((a)<(b))?(a):(b)) inline i32 ceil32(f32 v){ - return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) )); - } - - inline i32 floor32(f32 v){ - return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) )); - } - - inline i32 round32(f32 v){ - return(floor32(v + 0.5f)); - } - - inline i32 trun32(f32 v){ - return((i32)(v)); - } - - inline i32 div_ceil(i32 n, i32 d){ - return( ((n) % (d) != 0) + ((n) / (d)) ); - } - - inline i32 l_round_up_i32(i32 x, i32 b){ -return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) ); - } - - inline u32 l_round_up_u32(u32 x, u32 b){ - return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) ); - } - + return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) )); +} + +inline i32 floor32(f32 v){ + return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) )); +} + +inline i32 round32(f32 v){ + return(floor32(v + 0.5f)); +} + +inline i32 trun32(f32 v){ + return((i32)(v)); +} + +inline i32 div_ceil(i32 n, i32 d){ + return( ((n) % (d) != 0) + ((n) / (d)) ); +} + +inline i32 l_round_up_i32(i32 x, i32 b){ + return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) ); +} + +inline u32 l_round_up_u32(u32 x, u32 b){ + return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) ); +} + +inline u32 round_up_pot_u32(u32 x){ + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + ++x; + return(x); +} + #define STR__(s) #s #define STR_(s) STR__(s) diff --git a/file/4coder_buffer.cpp b/file/4coder_buffer.cpp index b2d93e6b..0729980b 100644 --- a/file/4coder_buffer.cpp +++ b/file/4coder_buffer.cpp @@ -13,7 +13,7 @@ // Buffer low level operations // -#include "../file/4coder_font_data.h" +#include "../font/4coder_font_data.h" #include "../4coder_helper/4coder_seek_types.h" typedef struct Cursor_With_Index{ @@ -1093,12 +1093,16 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){ if (!S.skipping_whitespace){ + S.current_adv = 2.f; + +#if 0 if (S.tran.do_codepoint_advance){ S.current_adv = get_codepoint_advance(params.font, S.tran.step_current.value); } else{ S.current_adv = params.font->byte_advance; } +#endif S.did_wrap = false; if (S.i >= S.wrap_unit_end){ @@ -1779,12 +1783,16 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa } else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){ + S.ch_width = 2.f; + +#if 0 if (S.tran.do_codepoint_advance){ S.ch_width = get_codepoint_advance(params.font, S.tran.step_current.value); } else{ S.ch_width = params.font->byte_advance; } +#endif if (S.tran.step_current.i >= S.wrap_unit_end){ S_stop.status = BLStatus_NeedWrapDetermination; @@ -1979,7 +1987,12 @@ typedef struct Render_Item_Write{ inline Render_Item_Write write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){ + +#if 0 f32 ch_width = get_codepoint_advance(write.font, glyphid); +#endif + + f32 ch_width = 2.f; if (write.x <= write.x_max && write.x + ch_width >= write.x_min){ write.item->index = index; @@ -2191,7 +2204,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 case '\t': { + +#if 0 S.ch_width = get_codepoint_advance(params.font, '\t'); +#endif + S.ch_width = 2.f; + f32 new_x = S.write.x + S.ch_width; S.write = write_render_item(S.write, I, ' ', 0); S.write.x = new_x; diff --git a/file/4coder_font_data.h b/file/4coder_font_data.h deleted file mode 100644 index ab0afd5b..00000000 --- a/file/4coder_font_data.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 03.03.2017 - * - * Font data type definitions. - * - */ - -// TOP - -#if !defined(FCODER_FONT_DATA_H) -#define FCODER_FONT_DATA_H - -#define FONT_PAGE_ITEMS 256 - -struct Glyph_Bounds{ - b32 exists; - - f32 x0, x1; - f32 y0, y1; - - f32 xoff, yoff; - f32 xoff2, yoff2; -}; - -struct Glyph_Page{ - Glyph_Bounds glyphs[256]; - u32 tex; - i32 tex_width, tex_height; - b32 exists; -}; - -struct Glyph_Data{ - Glyph_Bounds bounds; - u32 tex; - i32 tex_width, tex_height; -}; - -struct Advance_Page{ - f32 advance[256]; -}; - -struct Render_Font{ - char name_[24]; - String name; - b32 loaded; - - Glyph_Page glyph_pages[1]; - Advance_Page advance_pages[1]; - - f32 byte_advance; - i32 height, ascent, descent, line_skip; - i32 advance; -}; - -internal b32 -get_codepoint_can_render(Render_Font *font, u32 codepoint){ - b32 exists = false; - if (codepoint < FONT_PAGE_ITEMS){ - exists = true; - } - return(exists); -} - -internal u32 -get_codepoint_page_index(Render_Font *font, u32 codepoint, u32 *page_base_codepoint){ - *page_base_codepoint = 0; - return(0); -} - -internal void -get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){ - Glyph_Bounds *bounds = 0; - f32 *advance = 0; - - if (get_codepoint_can_render(font, codepoint)){ - u32 base_codepoint = 0; - u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); - Glyph_Page *bounds_page = &font->glyph_pages[page_index]; - Advance_Page *advance_page = &font->advance_pages[page_index]; - u32 glyph_index = codepoint - base_codepoint; - - bounds = &bounds_page->glyphs[glyph_index]; - advance = &advance_page->advance[glyph_index]; - } - - *bounds_mem_out = bounds; - *advance_mem_out = advance; -} - -internal b32 -get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){ - b32 success = false; - if (get_codepoint_can_render(font, codepoint)){ - u32 base_codepoint = 0; - u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); - Glyph_Page *page = &font->glyph_pages[page_index]; - data_out->bounds = page->glyphs[codepoint - base_codepoint]; - data_out->tex = page->tex; - data_out->tex_width = page->tex_width; - data_out->tex_height = page->tex_height; - success = true; - } - return(success); -} - -internal f32 -get_codepoint_advance(Render_Font *font, u32 codepoint){ - f32 advance = (f32)font->advance; - if (get_codepoint_can_render(font, codepoint)){ - u32 base_codepoint = 0; - u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); - Advance_Page *page = &font->advance_pages[page_index]; - advance = page->advance[codepoint - base_codepoint]; - } - return(advance); -} - -internal b32 -set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){ - b32 success = false; - if (get_codepoint_can_render(font, codepoint)){ - u32 base_codepoint = 0; - u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); - Advance_Page *page = &font->advance_pages[page_index]; - page->advance[codepoint - base_codepoint] = value; - success = true; - } - return(success); -} - -#endif - -// BOTTOM - - diff --git a/font/4coder_font_data.h b/font/4coder_font_data.h new file mode 100644 index 00000000..1884a092 --- /dev/null +++ b/font/4coder_font_data.h @@ -0,0 +1,56 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 03.03.2017 + * + * Font data type definitions. + * + */ + +// TOP + +#if !defined(FCODER_FONT_DATA_H) +#define FCODER_FONT_DATA_H + +#define ITEM_PER_FONT_PAGE 256 + +struct Glyph_Bounds{ + f32 x0, x1; + f32 y0, y1; + f32 xoff, yoff; + f32 xoff2, yoff2; +}; +global_const Glyph_Bounds null_glyph_bounds = {0}; + +struct Glyph_Data{ + Glyph_Bounds bounds; + u32 tex; + i32 tex_width, tex_height; +}; + +struct Glyph_Page{ + u32 page_number; + u32 tex; + i32 tex_width, tex_height; + Glyph_Bounds glyphs[ITEM_PER_FONT_PAGE]; + f32 advance[ITEM_PER_FONT_PAGE]; +}; + +struct Render_Font{ + char name_[24]; + String name; + b32 loaded; + + Glyph_Page **pages; + u32 page_count, page_max; + + f32 byte_advance; + i32 height, ascent, descent, line_skip; + i32 advance; +}; + +#endif + +// BOTTOM + + diff --git a/font/4coder_font_internal.cpp b/font/4coder_font_internal.cpp new file mode 100644 index 00000000..bf23cada --- /dev/null +++ b/font/4coder_font_internal.cpp @@ -0,0 +1,493 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 10.03.2017 + * + * Where I save crappy old font stuff. + * + */ + +// TOP + +#include "font/4coder_font_data.h" + +struct Font_Table_Entry{ + u32 hash; + String name; + i16 font_id; +}; + +struct Font_Info{ + Render_Font *font; + String filename; + String name; + i32 pt_size; +}; + +struct Font_Slot{ + Font_Slot *next, *prev; + i16 font_id; + u8 padding[6]; +}; +global_const Font_Slot null_font_slot = {0}; + +#define Font_Load_Sig(name)\ +i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture) +typedef Font_Load_Sig(Font_Load); + +#define Font_Load_Page_Sig(name)\ +i32 name(Render_Font *font, Glyph_Page *page, char *filename, i32 pt_size, i32 tab_width) +typedef Font_Load_Page_Sig(Font_Load_Page); + +#define Release_Font_Sig(name) void name(Render_Font *font) +typedef Release_Font_Sig(Release_Font); + +struct Font_Set{ + Font_Info *info; + Font_Table_Entry *entries; + u32 count, max; + + void *font_block; + Font_Slot free_slots; + Font_Slot used_slots; + + Font_Load *font_load; + Font_Load_Page *font_load_page; + Release_Font *release_font; + + b8 *font_used_flags; + i16 used_this_frame; + i16 live_max; +}; + +inline Font_Info* +get_font_info(Font_Set *set, i16 font_id){ + Font_Info *result = set->info + font_id - 1; + return(result); +} + +internal void +font_set_begin_render(Font_Set *font_set){ + font_set->used_this_frame = 0; + memset(font_set->font_used_flags, 0, font_set->max); +} + +inline u32 +font_hash(String name){ + u32 x = 5381; + char *p = name.str; + for (i32 i = 0; i < name.size; ++i, ++p){ + x = ((x << 5) + x) ^ (*p); + } + return(x); +} + +inline void +font__insert(Font_Slot *pos, Font_Slot *slot){ + Font_Slot *nex; + nex = pos->next; + + slot->next = nex; + slot->prev = pos; + nex->prev = slot; + pos->next = slot; +} + +inline void +font__remove(Font_Slot *slot){ + Font_Slot *n, *p; + n = slot->next; + p = slot->prev; + + p->next = n; + n->prev = p; +} + +internal void +font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){ + partition_align(partition, 8); + set->info = push_array(partition, Font_Info, max); + partition_align(partition, 8); + set->entries = push_array(partition, Font_Table_Entry, max); + set->count = 0; + set->max = max; + + partition_align(partition, 8); + set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot))); + + set->free_slots = null_font_slot; + set->used_slots = null_font_slot; + + dll_init_sentinel(&set->free_slots); + dll_init_sentinel(&set->used_slots); + + char *ptr = (char*)set->font_block; + for (i32 i = 0; i < live_max; ++i){ + dll_insert(&set->free_slots, (Font_Slot*)ptr); + ptr += sizeof(Font_Slot) + sizeof(Render_Font); + } + + set->font_used_flags = push_array(partition, b8, max); + set->live_max = live_max; +} + +internal b32 +font_set_can_add(Font_Set *set){ + b32 result = 0; + if (set->count*8 < set->max*7) result = 1; + return(result); +} + +internal void +font_set_add_hash(Font_Set *set, String name, i16 font_id){ + Font_Table_Entry entry; + entry.hash = font_hash(name); + entry.name = name; + entry.font_id = font_id; + + u32 i = entry.hash % set->max; + u32 j = i - 1; + if (i <= 1) j += set->max; + + for (; i != j; ++i){ + if (i == set->max) i = 0; + if (set->entries[i].font_id == 0){ + set->entries[i] = entry; + break; + } + } + + Assert(i != j); +} + +inline b32 +font_set_can_load(Font_Set *set){ + b32 result = (set->free_slots.next != &set->free_slots); + return(result); +} + +internal void +font_set_load(Font_Set *set, i16 font_id){ + Font_Info *info = get_font_info(set, font_id); + Font_Slot *slot = set->free_slots.next; + Assert(slot != &set->free_slots); + font__remove(slot); + font__insert(&set->used_slots, slot); + + Render_Font *font = (Render_Font*)(slot + 1); + set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true); + info->font = font; + slot->font_id = font_id; +} + +internal void +font_set_evict_lru(Font_Set *set){ + Font_Slot *slot = set->used_slots.prev; + Assert(slot != &set->used_slots); + + i16 font_id = slot->font_id; + Font_Info *info = get_font_info(set, font_id); + Assert(((Font_Slot*)info->font) - 1 == slot); + + set->release_font(info->font); + + info->font = 0; + slot->font_id = 0; + font__remove(slot); + font__insert(&set->free_slots, slot); +} + +internal void +font_set_use(Font_Set *set, i16 font_id){ + b8 already_used = set->font_used_flags[font_id-1]; + + if (!already_used){ + if (set->used_this_frame < set->live_max){ + ++set->used_this_frame; + set->font_used_flags[font_id-1] = 1; + already_used = 1; + } + } + + if (already_used){ + // TODO(allen): optimize if you don't mind!!!! + Font_Info *info = get_font_info(set, font_id); + Font_Slot *slot; + if (info->font == 0){ + if (!font_set_can_load(set)){ + font_set_evict_lru(set); + } + font_set_load(set, font_id); + } + slot = ((Font_Slot*)info->font) - 1; + + font__remove(slot); + font__insert(&set->used_slots, slot); + } +} + +internal b32 +font_set_add(Font_Set *set, String filename, String name, i32 pt_size){ + b32 result = false; + if (font_set_can_add(set)){ + Render_Font dummy_font = {0}; + i16 font_id = (i16)(++set->count); + Font_Info *info = get_font_info(set, font_id); + info->filename = filename; + info->name = name; + info->pt_size = pt_size; + set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false); + + font_set_add_hash(set, name, font_id); + + if (font_set_can_load(set)){ + font_set_load(set, font_id); + } + + result = true; + } + return(result); +} + +internal b32 +font_set_find_pos(Font_Set *set, String name, u32 *position){ + u32 hash = font_hash(name); + u32 i = hash % set->max; + u32 j = i - 1; + if (j <= 1){ + j += set->max; + } + + b32 result = 0; + for (; i != j; ++i){ + if (i == set->max){ + i = 0; + } + + Font_Table_Entry *entry = set->entries + i; + if (entry->hash == hash){ + if (match_ss(name, entry->name)){ + result = 1; + *position = i; + break; + } + } + } + + return(result); +} + +internal b32 +font_set_get_name(Font_Set *set, i16 font_id, String *name){ + Font_Info *info = get_font_info(set, font_id); + b32 result = copy_checked_ss(name, info->name); + return(result); +} + +internal b32 +font_set_extract(Font_Set *set, String name, i16 *font_id){ + u32 position; + b32 result = font_set_find_pos(set, name, &position); + if (result){ + *font_id = set->entries[position].font_id; + } + return(result); +} + +////////////////////////////////// + +internal b32 +get_codepoint_can_render(Render_Font *font, u32 codepoint){ + b32 exists = false; + if (codepoint < 0x10FFFF){ + exists = true; + } + return(exists); +} + +struct Codepoint_Indexes{ + b32 exists; + u32 page_number; + u32 glyph_index; +}; + +internal Codepoint_Indexes +get_codepoint_page_number(Render_Font *font, u32 codepoint){ + Codepoint_Indexes result = {0}; + u32 page_number = (codepoint >> 8); + if (page_number <= 0x10FF){ + result.exists = true; + result.page_number = page_number; + result.glyph_index = (codepoint & 0x000000FF); + } + return(result); +} + +#define MAX_PAGE_COUNT (u32)(0x1100) +#define GLYPH_PAGE_EMPTY ((Glyph_Page*)(0)) +#define GLYPH_PAGE_DELETED ((Glyph_Page*)(max_u64)) +#define IS_REAL_FONT_PAGE(p) (((p) != GLYPH_PAGE_EMPTY) && ((p) != GLYPH_PAGE_DELETED)) + +internal Glyph_Page** +font_lookup_page(Render_Font *font, u32 page_number, b32 find_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; + } + + if (find_empty_slot){ + for(u32 j = 0; j < range_count; j += 2){ + u32 start = ranges[j]; + u32 stop = ranges[j+1]; + for (u32 i = start; i < stop; ++i){ + Glyph_Page *ptr = font->pages[i]; + if (ptr == GLYPH_PAGE_EMPTY || ptr == GLYPH_PAGE_DELETED){ + result = &font->pages[i]; + goto break2; + } + if (ptr->page_number == page_number){ + goto break2; + } + } + } + } + else{ + for(u32 j = 0; j < range_count; j += 2){ + u32 start = ranges[j]; + u32 stop = ranges[j+1]; + for (u32 i = start; i < stop; ++i){ + Glyph_Page *ptr = font->pages[i]; + if (ptr == GLYPH_PAGE_EMPTY){ + goto break2; + } + if (ptr != GLYPH_PAGE_DELETED){ + if (ptr->page_number == page_number){ + result = &font->pages[i]; + goto break2; + } + } + } + } + } + break2:; + } + return(result); +} + +internal Glyph_Page* +font_get_or_make_page(Render_Font *font, u32 page_number){ + Glyph_Page *page = 0; + if (page_number <= 0x10FF){ + Glyph_Page **page_ptr = font_lookup_page(font, page_number, false); + page = 0; + if (page_ptr != 0){ + page = *page_ptr; + } + + if (page == 0){ + u32 new_count = 1; + if (font->page_max < MAX_PAGE_COUNT && (font->page_count+new_count)*3 < font->page_max*2){ + u32 new_page_max = (font->page_count+new_count)*3; + new_page_max = clamp_top(new_page_max, MAX_PAGE_COUNT); + Glyph_Page **new_pages = (Glyph_Page**)ALLOCATE(new_page_max * sizeof(Glyph_Page*)); + + u32 old_page_max = font->page_max; + Glyph_Page **pages = font->pages; + for (u32 i = 0; i < old_page_max; ++i){ + Glyph_Page *current_page = pages[i]; + if (current_page != GLYPH_PAGE_EMPTY && current_page != GLYPH_PAGE_DELETED){ + Glyph_Page **dest = font_lookup_page(font, current_page->page_number, true); + Assert(dest != 0); + *dest = current_page; + } + } + + FREE(font->pages); + font->pages = new_pages; + font->page_max = new_page_max; + } + + Glyph_Page *new_page = (Glyph_Page*)ALLOCATE(sizeof(Glyph_Page)); + Glyph_Page **dest = font_lookup_page(font, page_number, true); + *dest = new_page; + ++font->page_count; + + //set->font_load_page(font, new_page, ); + } + } + return(page); +} + +internal void +get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){ + Glyph_Bounds *bounds = 0; + f32 *advance = 0; + + if (get_codepoint_can_render(font, codepoint)){ + Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint); + Glyph_Page *page = font_get_or_make_page(font, indexes.page_number); + bounds = &page->glyphs[indexes.glyph_index]; + advance = &page->advance[indexes.glyph_index]; + } + + *bounds_mem_out = bounds; + *advance_mem_out = advance; +} + +internal b32 +get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){ + b32 success = false; + if (get_codepoint_can_render(font, codepoint)){ + Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint); + Glyph_Page *page = font_get_or_make_page(font, indexes.page_number); + data_out->bounds = page->glyphs[indexes.glyph_index]; + data_out->tex = page->tex; + data_out->tex_width = page->tex_width; + data_out->tex_height = page->tex_height; + success = true; + } + return(success); +} + +internal f32 +get_codepoint_advance(Render_Font *font, u32 codepoint){ + f32 advance = (f32)font->advance; + if (get_codepoint_can_render(font, codepoint)){ + Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint); + Glyph_Page *page = font_get_or_make_page(font, indexes.page_number); + advance = page->advance[indexes.glyph_index]; + } + return(advance); +} + +internal b32 +set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){ + b32 success = false; + if (get_codepoint_can_render(font, codepoint)){ + Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint); + Glyph_Page *page = font_get_or_make_page(font, indexes.page_number); + page->advance[indexes.glyph_index] = value; + success = true; + } + return(success); +} + +// BOTTOM + + + + diff --git a/linux_4ed.cpp b/linux_4ed.cpp index 98e59a2c..badee602 100644 --- a/linux_4ed.cpp +++ b/linux_4ed.cpp @@ -103,7 +103,6 @@ #endif #define SUPPORT_DPI 1 -#define LINUX_FONTS 1 #define InterlockedCompareExchange(dest, ex, comp) __sync_val_compare_and_swap((dest), (comp), (ex)) @@ -1359,27 +1358,14 @@ Font_Load_Sig(system_draw_font_load){ linuxvars.font_part = sysshared_scratch_partition(MB(8)); } - i32 oversample = 2; - #if SUPPORT_DPI pt_size = round32(pt_size * size_change(linuxvars.dpi_x, linuxvars.dpi_y)); #endif - for(; attempts < 3; ++attempts){ -#if LINUX_FONTS + b32 success = false; + for (u32 R = 0; R < 3; ++R){ success = linux_font_load(&linuxvars.font_part, font_out, filename, pt_size, tab_width, linuxvars.settings.use_hinting); -#else - success = font_load( - &linuxvars.font_part, - font_out, - filename, - pt_size, - tab_width, - oversample, - store_texture - ); -#endif if(success){ break; @@ -1389,7 +1375,7 @@ Font_Load_Sig(system_draw_font_load){ } } - return success; + return(success); } // diff --git a/linux_font.cpp b/linux_font.cpp index 9f69b4ac..70e1b53d 100644 --- a/linux_font.cpp +++ b/linux_font.cpp @@ -1,3 +1,14 @@ +/* + * Insofaras + * + * ??.??.2016 + * + * For getting the font files on Linux. + * + */ + +// TOP + #undef internal #include #define internal static @@ -8,26 +19,26 @@ static FcConfig* fc; internal char* linux_get_sys_font(char* name, i32 pt_size){ char* result = 0; - + if(!fc){ fc = FcInitLoadConfigAndFonts(); } - + FcPattern* pat = FcPatternBuild( NULL, FC_POSTSCRIPT_NAME, FcTypeString, name, FC_SIZE, FcTypeDouble, (double)pt_size, FC_FONTFORMAT, FcTypeString, "TrueType", NULL - ); - + ); + FcConfigSubstitute(fc, pat, FcMatchPattern); FcDefaultSubstitute(pat); - + FcResult res; FcPattern* font = FcFontMatch(fc, pat, &res); FcChar8* fname = 0; - + if(font){ FcPatternGetString(font, FC_FILE, 0, &fname); if(fname){ @@ -36,9 +47,9 @@ linux_get_sys_font(char* name, i32 pt_size){ } FcPatternDestroy(font); } - + FcPatternDestroy(pat); - + if(!result){ char space[1024]; String str = make_fixed_width_string(space); @@ -48,16 +59,16 @@ linux_get_sys_font(char* name, i32 pt_size){ result = strdup(name); } } - + return result; } internal b32 linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){ b32 result = 0; - + Temp_Memory temp = begin_temp_memory(part); - + #if 0 char* filename = linux_get_sys_font(name, pt_size); #else @@ -67,22 +78,25 @@ linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 t sysshared_to_binary_path(&str, name); } #endif - + if (filename != 0){ struct stat st; if(stat(filename, &st) == -1 || S_ISDIR(st.st_mode)){ char buff[1024]; - + // NOTE(inso): if/when you can load fonts from anywhere, the message should be changed. snprintf(buff, sizeof(buff), "Unable to load font '%s'. Make sure this file is in the same directory as the '4ed' executable.", filename); LinuxFatalErrorMsg(buff); exit(1); } - + result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting); } - + end_temp_memory(temp); - + return(result); } + +// BOTTOM + diff --git a/win32_4ed.cpp b/win32_4ed.cpp index cb266f64..30518aa2 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -67,7 +67,6 @@ #include "4ed_system_shared.h" #define SUPPORT_DPI 1 -#define USE_FT_FONTS 1 #define FPS 60 #define frame_useconds (1000000 / FPS) @@ -1392,9 +1391,7 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){ #include "4ed_system_shared.cpp" -#if USE_FT_FONTS -# include "win32_ft_font.cpp" -#endif +#include "win32_ft_font.cpp" internal f32 size_change(i32 dpi_x, i32 dpi_y){ @@ -1406,60 +1403,29 @@ size_change(i32 dpi_x, i32 dpi_y){ } internal -Font_Load_Sig(system_draw_font_load){ +Font_Load_Sig(font_load){ if (win32vars.font_part.base == 0){ win32vars.font_part = Win32ScratchPartition(MB(8)); } - i32 oversample = 2; - AllowLocal(oversample); - #if SUPPORT_DPI pt_size = round32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y)); #endif - for (b32 success = 0; success == 0;){ -#if USE_WIN32_FONTS + // TODO(allen): Make the growable partition something that can just be passed directly to font load and let it be grown there. + b32 success = false; + for (u32 R = 0; R < 3; ++R){ + success = win32_ft_font_load(&win32vars.font_part, font_out, filename, pt_size, tab_width,win32vars.settings.use_hinting); - success = win32_font_load(&win32vars.font_part, - font_out, - filename, - fontname, - pt_size, - tab_width, - oversample, - store_texture); - -#elif USE_FT_FONTS - - success = win32_ft_font_load(&win32vars.font_part, - font_out, - filename, - pt_size, - tab_width, - win32vars.settings.use_hinting); - -#else - - success = stb_font_load(&win32vars.font_part, - font_out, - filename, - pt_size, - tab_width, - oversample, - store_texture); - -#endif - - // TODO(allen): Make the growable partition something - // that can just be passed directly to font load and - // let it be grown there. - if (!success){ + if (success){ + break; + } + else{ Win32ScratchPartitionDouble(&win32vars.font_part); } } - return(1); + return(success); } // @@ -1541,7 +1507,7 @@ Win32LoadRenderCode(){ win32vars.target.pop_clip = draw_pop_clip; win32vars.target.push_piece = draw_push_piece; - win32vars.target.font_set.font_load = system_draw_font_load; + win32vars.target.font_set.font_load = font_load; win32vars.target.font_set.release_font = draw_release_font; } diff --git a/win32_ft_font.cpp b/win32_ft_font.cpp index 45c49b29..454578bd 100644 --- a/win32_ft_font.cpp +++ b/win32_ft_font.cpp @@ -1,29 +1,29 @@ -// NOTE(allen): Thanks to insofaras. -// This is copy-pasted from some work he -// did to get free type working on linux. -// Once it is working on both sides it might -// be possible to pull some parts out as -// portable FT rendering. +/* + * Mr. 4th Dimention - Allen Webster + * + * ??.??.2016 + * + * For getting the font files on Linux. + * + */ + +// TOP + +// TODO(allen): Get system fonts internal b32 win32_ft_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){ - - b32 result = 0; - Temp_Memory temp = begin_temp_memory(part); - char* filename = push_array(part, char, 256); - + b32 result = false; if (filename != 0){ String str = make_string_cap(filename, 0, 256); sysshared_to_binary_path(&str, name); - result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting); } - end_temp_memory(temp); - return(result); } +// BOTTOM