began torching the font system
parent
d5ab8eafdc
commit
4a5bfa59b7
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
11
4ed.cpp
11
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){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
231
4ed_font_set.cpp
231
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
|
||||
|
||||
|
|
12
4ed_math.h
12
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 <ft2build.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/*
|
||||
* Insofaras
|
||||
*
|
||||
* ??.??.2016
|
||||
*
|
||||
* For getting the font files on Linux.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#undef internal
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue