Working on font cleanup all day all day all day

master
Allen Webster 2017-11-16 18:03:36 -05:00
parent 5aceb5b910
commit 4f3b07168d
24 changed files with 993 additions and 1135 deletions

View File

@ -1,6 +1,6 @@
#define MAJOR 4
#define MINOR 0
#define PATCH 23
#define PATCH 24
// string
#define VN__(a,b,c) #a "." #b "." #c

View File

@ -15,11 +15,10 @@ global_const char messages[] =
"Welcome to " VERSION "\n"
"If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n"
"\n"
"New in alpha 4.0.22:\n"
"New in alpha 4.0.22 and 4.0.23:\n"
"-The rendering layer is cleaned up and faster\n"
"-4coder can now ship with multiple built in command bindings\n"
" New built in binding \"mac-default\": For the mac version of 4coder - similar to most Mac applications\n"
" New built in binding \"mac-4coder-like\": For the mac version of 4coder - similar to 4coder on other OSes\n"
"-Fullscreen now works on Windows without the '-S' flag\n"
"-Set up a single 4coder project for Windows/Linux/Mac in one command: <alt x> -> \"new project\"\n"
"\n"
@ -1224,7 +1223,7 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
{
if (i < argc){
plat_settings->font_size = str_to_int_c(argv[i]);
plat_settings->font_size = clamp_bottom(8, plat_settings->font_size);
plat_settings->font_size = plat_settings->font_size;
}
action = CLAct_Nothing;
}break;

View File

@ -1029,7 +1029,7 @@ DOC_SEE(Buffer_Setting_ID)
new_value = 48;
}
if (new_value != file->settings.display_width){
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
file->settings.display_width = new_value;
file_measure_wraps_and_fix_cursor(system, models, file, font);
}
@ -1042,7 +1042,7 @@ DOC_SEE(Buffer_Setting_ID)
new_value = 0;
}
if (new_value != file->settings.minimum_base_display_width){
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
file->settings.minimum_base_display_width = new_value;
file_measure_wraps_and_fix_cursor(system, models, file, font);
}
@ -1125,7 +1125,7 @@ DOC_SEE(Buffer_Setting_ID)
}
if (full_remeasure){
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
file_allocate_character_starts_as_needed(&models->mem.general, file);
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
@ -2259,11 +2259,13 @@ DOC(This call changes 4coder's default font to one of the built in fonts.)
String font_name = make_string(name, len);
Font_ID font_id = font_get_id_by_name(system, font_name);
if (apply_to_all_files){
global_set_font(system, models, font_id);
}
else{
models->global_font_id = font_id;
if (font_id != 0){
if (apply_to_all_files){
global_set_font(system, models, font_id);
}
else{
models->global_font_id = font_id;
}
}
}
@ -2284,7 +2286,9 @@ DOC(This call sets the display font of a particular buffer.)
if (file != 0){
String font_name = make_string(name, len);
Font_ID font_id = font_get_id_by_name(system, font_name);
file_set_font(system, models, file, font_id);
if (font_id != 0){
file_set_font(system, models, file, font_id);
}
}
}

View File

@ -17,6 +17,7 @@
#include "4coder_API/custom.h"
#include "4ed_math.h"
#include "4ed_font.h"
#include "4ed_system.h"
#define PREFERRED_ALIGNMENT 8
@ -42,6 +43,8 @@
#include "4ed_doubly_linked_list.cpp"
#include "4ed_font.cpp"
#include "4ed_translation.cpp"
#include "4ed_render_target.cpp"
@ -69,7 +72,5 @@
#include "4ed_file_view.cpp"
#include "4ed.cpp"
#include "4ed_font_static_functions.cpp"
// BOTTOM

View File

@ -13,7 +13,6 @@
// Buffer low level operations
//
#include "4ed_font_data.h"
#include "4coder_helper/4coder_seek_types.h"
struct Cursor_With_Index{
@ -668,7 +667,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Gap_Buffer *buffer){
}
internal void
buffer_measure_character_starts(System_Functions *system, Render_Font *font, Gap_Buffer *buffer, i32 *character_starts, i32 mode, i32 virtual_white){
buffer_measure_character_starts(System_Functions *system, Font_Pointers font, Gap_Buffer *buffer, i32 *character_starts, i32 mode, i32 virtual_white){
PRFL_FUNC_GROUP();
Assert(mode == 0);
@ -749,7 +748,7 @@ struct Buffer_Measure_Wrap_Params{
Gap_Buffer *buffer;
i32 *wrap_line_index;
System_Functions *system;
Render_Font *font;
Font_Pointers font;
b32 virtual_white;
};
@ -853,10 +852,10 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){
if (!S.skipping_whitespace){
if (S.behavior.do_codepoint_advance){
S.current_adv = font_get_glyph_advance(params.system, params.font, S.step.value);
S.current_adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, S.step.value);
}
else{
S.current_adv = font_get_byte_advance(params.font);
S.current_adv = params.font.metrics->byte_advance;
}
S.did_wrap = false;
@ -986,7 +985,7 @@ buffer_remeasure_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 li
}
internal void
buffer_remeasure_character_starts(System_Functions *system, Render_Font *font, Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){
buffer_remeasure_character_starts(System_Functions *system, Font_Pointers font, Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){
Assert(mode == 0);
i32 new_line_count = buffer->line_count;
@ -1299,7 +1298,7 @@ struct Buffer_Cursor_Seek_Params{
Gap_Buffer *buffer;
Buffer_Seek seek;
System_Functions *system;
Render_Font *font;
Font_Pointers font;
i32 *wrap_line_index;
i32 *character_starts;
b32 virtual_white;
@ -1351,7 +1350,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
DrCase(4);
}
S.font_height = font_get_height(params.font);
S.font_height = params.font.metrics->height;
S.xy_seek = (params.seek.type == buffer_seek_wrapped_xy || params.seek.type == buffer_seek_unwrapped_xy);
S.size = buffer_size(params.buffer);
@ -1539,10 +1538,10 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){
if (S.behavior.do_codepoint_advance){
S.ch_width = font_get_glyph_advance(params.system, params.font, S.step.value);
S.ch_width = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, S.step.value);
}
else{
S.ch_width = font_get_byte_advance(params.font);
S.ch_width = params.font.metrics->byte_advance;
}
if (S.step.i >= S.wrap_unit_end){
@ -1732,7 +1731,7 @@ struct Render_Item_Write{
Buffer_Render_Item *item;
f32 x, y;
System_Functions *system;
Render_Font *font;
Font_Pointers font;
i32 font_height;
f32 x_min;
f32 x_max;
@ -1741,7 +1740,7 @@ struct Render_Item_Write{
inline Render_Item_Write
write_render_item(Render_Item_Write write, i32 index, u32 codepoint, u32 flags){
f32 ch_width = font_get_glyph_advance(write.system, write.font, codepoint);
f32 ch_width = font_get_glyph_advance(write.system, write.font.settings, write.font.metrics, write.font.pages, codepoint);
if (write.x <= write.x_max && write.x + ch_width >= write.x_min){
write.item->index = index;
@ -1775,7 +1774,7 @@ struct Buffer_Render_Params{
Full_Cursor start_cursor;
i32 wrapped;
System_Functions *system;
Render_Font *font;
Font_Pointers font;
b32 virtual_white;
i32 wrap_slashes;
};
@ -1854,11 +1853,11 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
S.write.y = S.shift_y;
S.write.system = params.system;
S.write.font = params.font;
S.write.font_height = font_get_height(params.font);
S.write.font_height = params.font.metrics->height;
S.write.x_min = params.port_x;
S.write.x_max = params.port_x + params.clip_w;
S.byte_advance = font_get_byte_advance(params.font);
S.byte_advance = params.font.metrics->byte_advance;
if (params.virtual_white){
S.skipping_whitespace = 1;
@ -1963,7 +1962,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
case '\t':
{
S.ch_width = font_get_glyph_advance(params.system, params.font, '\t');
S.ch_width = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, '\t');
f32 new_x = S.write.x + S.ch_width;
S.write = write_render_item(S.write, I, ' ', 0);

View File

@ -143,8 +143,8 @@ internal Full_Cursor
view_compute_cursor(System_Functions *system, View *view, Buffer_Seek seek, b32 return_hint){
Editing_File *file = view->file_data.file;
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Assert(font != 0);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
Assert(font.valid);
Full_Cursor result = {0};
@ -708,7 +708,7 @@ file_allocate_character_starts_as_needed(General_Memory *general, Editing_File *
internal void
file_measure_character_starts(System_Functions *system, Models *models, Editing_File *file){
file_allocate_character_starts_as_needed(&models->mem.general, file);
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
file_update_cursor_positions(system, models, file);
}
@ -760,7 +760,7 @@ struct Code_Wrap_State{
i32 size;
i32 i;
Render_Font *font;
Font_Pointers font;
f32 tab_indent_amount;
f32 byte_advance;
@ -772,7 +772,7 @@ struct Code_Wrap_State{
};
internal void
wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File *file, Render_Font *font){
wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File *file, Font_Pointers font){
state->token_array = file->state.token_array;
state->token_ptr = state->token_array.tokens;
state->end_token = state->token_ptr + state->token_array.count;
@ -789,8 +789,8 @@ wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File *
state->font = font;
state->tab_indent_amount = font_get_glyph_advance(system, font, '\t');
state->byte_advance = font_get_byte_advance(font);
state->tab_indent_amount = font_get_glyph_advance(system, font.settings, font.metrics, font.pages, '\t');
state->byte_advance = font.metrics->byte_advance;
state->tran = null_buffer_translating_state;
}
@ -823,7 +823,7 @@ struct Code_Wrap_Step{
};
internal Code_Wrap_Step
wrap_state_consume_token(System_Functions *system, Render_Font *font, Code_Wrap_State *state, i32 fixed_end_point){
wrap_state_consume_token(System_Functions *system, Font_Pointers font, Code_Wrap_State *state, i32 fixed_end_point){
Code_Wrap_Step result = {0};
i32 i = state->i;
@ -913,7 +913,7 @@ wrap_state_consume_token(System_Functions *system, Render_Font *font, Code_Wrap_
u32 n = state->step.value;
f32 adv = 0;
if (state->behavior.do_codepoint_advance){
adv = font_get_glyph_advance(system, state->font, n);
adv = font_get_glyph_advance(system, state->font.settings, state->font.metrics, state->font.pages, n);
if (n != ' ' && n != '\t'){
skipping_whitespace = false;
@ -1231,7 +1231,7 @@ get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start){
}
internal void
file_measure_wraps(System_Functions *system, Models *models, Editing_File *file, Render_Font *font){
file_measure_wraps(System_Functions *system, Models *models, Editing_File *file, Font_Pointers font){
PRFL_FUNC_GROUP();
General_Memory *general = &models->mem.general;
@ -1339,7 +1339,7 @@ file_measure_wraps(System_Functions *system, Models *models, Editing_File *file,
word_stage = 1;
}
else{
f32 adv = font_get_glyph_advance(params.system, params.font, codepoint);
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, codepoint);
x += adv;
self_x += adv;
@ -1484,7 +1484,7 @@ file_measure_wraps(System_Functions *system, Models *models, Editing_File *file,
goto doublebreak_stage1;
}
f32 adv = font_get_glyph_advance(params.system, params.font, buffer_step.value);
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, buffer_step.value);
x += adv;
if (!first_word && x > current_width){
@ -1520,7 +1520,7 @@ file_measure_wraps(System_Functions *system, Models *models, Editing_File *file,
goto doublebreak_stage2;
}
f32 adv = font_get_glyph_advance(params.system, params.font, buffer_step.value);
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, buffer_step.value);
x += adv;
}
}
@ -1737,7 +1737,7 @@ file_measure_wraps(System_Functions *system, Models *models, Editing_File *file,
}
internal void
file_measure_wraps_and_fix_cursor(System_Functions *system, Models *models, Editing_File *file, Render_Font *font){
file_measure_wraps_and_fix_cursor(System_Functions *system, Models *models, Editing_File *file, Font_Pointers font){
if (file->state.hacks.suppression_mode){
file->state.hacks.needs_wraps_and_fix_cursor = true;
}
@ -1785,7 +1785,8 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
Font_ID font_id = models->global_font_id;
file->settings.font_id = font_id;
Render_Font *font = system->font.get_render_data_by_id(font_id);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
Assert(font.valid);
{
file_measure_starts(general, &file->state.buffer);
@ -2657,8 +2658,9 @@ file_view_nullify_file(View *view){
internal void
update_view_line_height(System_Functions *system, Models *models, View *view, Font_ID font_id){
Render_Font *font = system->font.get_render_data_by_id(font_id);
view->line_height = font_get_height(font);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
Assert(font.valid);
view->line_height = font.metrics->height;
}
inline void
@ -3142,7 +3144,9 @@ file_do_single_edit(System_Functions *system, Models *models, Editing_File *file
i32 new_line_count = buffer_count_newlines(&file->state.buffer, start, start+str_len);
i32 line_shift = new_line_count - replaced_line_count;
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
Assert(font.valid);
file_grow_starts_as_needed(general, buffer, line_shift);
buffer_remeasure_starts(buffer, line_start, line_end, line_shift, shift_amount);
@ -3262,7 +3266,8 @@ file_do_batch_edit(System_Functions *system, Models *models, Editing_File *file,
// NOTE(allen): meta data
file_measure_starts(general, &file->state.buffer);
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
Assert(font.valid);
// TODO(allen): write the remeasurement version
file_allocate_character_starts_as_needed(general, file);
@ -3543,7 +3548,7 @@ style_get_color(Style *style, Cpp_Token token){
internal void
file_set_font(System_Functions *system, Models *models, Editing_File *file, Font_ID font_id){
file->settings.font_id = font_id;
Render_Font *font = system->font.get_render_data_by_id(font_id);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
file_measure_wraps_and_fix_cursor(system, models, file, font);
Editing_Layout *layout = &models->layout;
@ -4509,6 +4514,14 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ
}
break;
#if 0
case CV_Mode_Font_Loading:
{
}break;
#endif
case CV_Mode_Global_Font:
case CV_Mode_Font:
{
@ -4527,20 +4540,16 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ
font_id = file->settings.font_id;
}
// TODO(allen): paginate the display
Font_ID new_font_id = font_id;
u32 total_count = system->font.get_count();
u32 count = Min(total_count, 10);
for (u32 font_index = 0; font_index < count; ++font_index){
Font_ID this_font_id = 0;
system->font.get_ids_by_index(font_index, 1, &this_font_id);
for (u32 i = 0; i < total_count; ++i){
Font_ID this_font_id = i + 1;
char name_space[256];
String name = make_fixed_width_string(name_space);
name.size = system->font.get_name_by_index(font_index, name.str, name.memory_size);
name.size = system->font.get_name_by_id(this_font_id, name.str, name.memory_size);
id.id[0] = (u64)font_index + 1;
id.id[0] = (u64)this_font_id + 1;
if (this_font_id != font_id){
if (gui_do_font_button(target, id, this_font_id, name)){
new_font_id = this_font_id;
@ -5683,7 +5692,7 @@ draw_file_loaded(System_Functions *system, View *view, Models *models, i32_Rect
Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max);
Font_ID font_id = file->settings.font_id;
Render_Font *font = system->font.get_render_data_by_id(font_id);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
f32 scroll_x = view->edit_pos->scroll.scroll_x;
f32 scroll_y = view->edit_pos->scroll.scroll_y;
@ -5922,7 +5931,7 @@ draw_text_with_cursor(System_Functions *system, Render_Target *target, View *vie
draw_rectangle(target, rect, back_color);
if (pos >= 0 && pos < s.size){
Render_Font *font = system->font.get_render_data_by_id(font_id);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
String part1 = substr(s, 0, pos);
String part2 = substr(s, pos, 1);
@ -5930,7 +5939,7 @@ draw_text_with_cursor(System_Functions *system, Render_Target *target, View *vie
x = draw_string(system, target, font_id, part1, floor32(x), y, text_color);
f32 adv = font_get_glyph_advance(system, font, s.str[pos]);
f32 adv = font_get_glyph_advance(system, font.settings, font.metrics, font.pages, s.str[pos]);
i32_Rect cursor_rect;
cursor_rect.x0 = floor32(x);
cursor_rect.x1 = floor32(x) + ceil32(adv);
@ -6137,7 +6146,7 @@ draw_style_preview(System_Functions *system, GUI_Target *gui_target, Render_Targ
char font_name_space[256];
String font_name = make_fixed_width_string(font_name_space);
font_name.size = system->font.get_name_by_id(font_id, font_name.str, font_name.memory_size);
Render_Font *font = system->font.get_render_data_by_id(font_id);
Font_Pointers font = system->font.get_pointers_by_id(font_id);
i32_Rect inner = get_inner_rect(rect, 3);
@ -6159,7 +6168,7 @@ draw_style_preview(System_Functions *system, GUI_Target *gui_target, Render_Targ
draw_string(system, target, font_id, font_name, font_x, y, text_color);
}
i32 height = font_get_height(font);
i32 height = font.metrics->height;
x = inner.x0;
y += height;
x = ceil32(draw_string(system, target, font_id, "if", x, y, keyword_color));

225
4ed_font.cpp Normal file
View File

@ -0,0 +1,225 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 11.03.2017
*
* Implements some basic getters for fonts set up to make the font type opaque.
*
*/
// TOP
internal Font_ID
font_get_id_by_name(System_Functions *system, String name){
Font_ID id = 0;
u32 count = system->font.get_count();
for (Font_ID id_it = 1; id_it <= count; ++id_it){
char str[256];
i32 str_len = system->font.get_name_by_id(id_it, str, sizeof(str));
if (str_len > 0){
String font_name = make_string(str, str_len);
if (match_ss(font_name, name)){
id = id_it;
break;
}
}
}
return(id);
}
internal Glyph_Page**
font_page_lookup(Font_Page_Storage *page_storage, u32 page_number, b32 get_empty_slot){
Glyph_Page **result = 0;
if (page_storage->page_max > 0){
u32 first_index = page_number % page_storage->page_max;
u32 range_count = 0;
u32 ranges[4];
if (first_index == 0){
ranges[0] = 0;
ranges[1] = page_storage->page_max;
range_count = 2;
}
else{
ranges[0] = first_index;
ranges[1] = page_storage->page_max;
ranges[2] = 0;
ranges[3] = first_index;
range_count = 4;
}
Glyph_Page **pages = page_storage->pages;
if (get_empty_slot){
for (u32 j = 0; j < range_count; j += 2){
u32 stop = ranges[j+1];
for (u32 i = ranges[j]; i < stop; ++i){
if (pages[i] == FONT_PAGE_EMPTY || pages[i] == FONT_PAGE_DELETED){
result = &pages[i];
goto break2;
}
if (pages[i]->page_number == page_number){
goto break2;
}
}
}
}
else{
for (u32 j = 0; j < range_count; j += 2){
u32 stop = ranges[j+1];
for (u32 i = ranges[j]; i < stop; ++i){
if (pages[i] == FONT_PAGE_EMPTY){
goto break2;
}
if (pages[i] != FONT_PAGE_DELETED && pages[i]->page_number == page_number){
result = &pages[i];
goto break2;
}
}
}
}
break2:;
}
return(result);
}
internal Glyph_Page*
font_get_page(Font_Page_Storage *pages, u32 page_number){
Glyph_Page *result = 0;
if (page_number <= 0x10FF){
Glyph_Page **page_get_result = font_page_lookup(pages, page_number, false);
if (page_get_result != 0){
result = *page_get_result;
}
}
return(result);
}
internal Glyph_Page*
font_allocate_and_hash_new_page(System_Functions *system, Font_Page_Storage *storage, u32 page_number){
Glyph_Page *new_page = 0;
if (page_number <= 0x10FF){
b32 has_space = true;
// Grow and rehash the table if we need to now.
u32 new_page_count = 1;
u32 new_max = (storage->page_count + new_page_count)*3;
if (storage->page_max < FONT_PAGE_MAX && new_max > storage->page_max*2){
Glyph_Page **pages = (Glyph_Page**)system->font.allocate(sizeof(Glyph_Page*)*new_max);
if (pages != 0){
u32 old_max = storage->page_max;
Glyph_Page **old_pages = storage->pages;
storage->pages = pages;
storage->page_max = new_max;
memset(pages, 0, sizeof(*pages)*new_max);
if (old_pages != 0){
for (u32 i = 0; i < old_max; ++i){
Glyph_Page *this_page = old_pages[i];
if (this_page != FONT_PAGE_EMPTY && this_page != FONT_PAGE_DELETED){
u32 this_page_number = this_page->page_number;
Glyph_Page **dest = font_page_lookup(storage, this_page_number, true);
Assert(dest != 0);
*dest = this_page;
}
}
system->font.free(old_pages);
}
}
else{
has_space = false;
}
}
// Allocate and hash a new page if there is room in the table.
if (has_space){
new_page = (Glyph_Page*)system->font.allocate(sizeof(Glyph_Page));
if (new_page != 0){
Glyph_Page **dest = font_page_lookup(storage, page_number, true);
Assert(dest != 0);
*dest = new_page;
storage->page_count += new_page_count;
}
}
}
return(new_page);
}
internal Glyph_Page*
font_make_page(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 page_number){
Glyph_Page *new_page = font_allocate_and_hash_new_page(system, pages, page_number);
if (new_page != 0){
system->font.load_page(settings, metrics, new_page, page_number);
}
return(new_page);
}
internal b32
font_can_render(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 codepoint){
b32 result = (codepoint <= 0x10FFFF);
return(result);
}
///////
// HACK(allen): Hack optimizations
struct Font_Cached_Lookup_Result{
Glyph_Page *page;
u32 index;
};
internal Font_Cached_Lookup_Result
font_cached_lookup(Font_Page_Storage *pages, u32 page_number){
Font_Cached_Lookup_Result result = {0};
result.index = page_number % ArrayCount(pages->cache);
if (pages->cache[result.index].page_number == page_number){
result.page = pages->cache[result.index].page;
}
if (result.page == 0){
result.page = font_get_page(pages, page_number);
}
return(result);
}
internal Glyph_Page*
font_cached_get_page(Font_Page_Storage *pages, u32 page_number){
Font_Cached_Lookup_Result result = font_cached_lookup(pages, page_number);
if (result.page != 0){
pages->cache[result.index].page = result.page;
pages->cache[result.index].page_number = page_number;
}
return(result.page);
}
internal Glyph_Page*
font_cached_get_or_make_page(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 page_number){
Font_Cached_Lookup_Result result = font_cached_lookup(pages, page_number);
if (result.page == 0){
result.page = font_make_page(system, settings, metrics, pages, page_number);
}
if (result.page != 0){
pages->cache[result.index].page = result.page;
pages->cache[result.index].page_number = page_number;
}
return(result.page);
}
///////
internal f32
font_get_glyph_advance(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 codepoint){
f32 result = 0.f;
u32 page_number = (codepoint >> 8);
Glyph_Page *page = font_cached_get_or_make_page(system, settings, metrics, pages, page_number);
u32 glyph_index = codepoint & 0xFF;
if (page != 0 && page->advance[glyph_index] > 0.f){
result = page->advance[glyph_index];
}
return(result);
}
// BOTTOM

127
4ed_font.h Normal file
View File

@ -0,0 +1,127 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 11.03.2017
*
* Font system interface.
*
*/
// TOP
#if !defined(FCODER_FONT_H)
#define FCODER_FONT_H
// NOTE(allen): A description of an available font.
struct Font_Loadable_Stub{
b32 in_local_folder;
i32 len;
char name[256];
};
// NOTE(allen): Settings that the are specified that determine how a font should be loaded and rendered.
struct Font_Settings{
Font_Loadable_Stub stub;
i32 pt_size;
b32 use_hinting;
};
// NOTE(allen): Results about the font true for the entire font as a whole.
struct Font_Metrics{
i32 name_len;
char name[256];
i32 height;
i32 ascent;
i32 descent;
i32 line_skip;
i32 advance;
f32 byte_advance;
f32 sub_advances[3];
};
// NOTE(allen): The pages of glyph data.
#define GLYPHS_PER_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_Page{
u32 page_number;
b32 has_layout;
f32 advance[GLYPHS_PER_PAGE];
Glyph_Bounds glyphs[GLYPHS_PER_PAGE];
i32 tex_width, tex_height;
b32 has_gpu_setup;
u32 gpu_tex;
};
#define FONT_PAGE_EMPTY ((Glyph_Page*)0)
#define FONT_PAGE_DELETED ((Glyph_Page*)(1))
#define FONT_PAGE_MAX 0x1100
struct Font_Page_Storage{
Glyph_Page **pages;
u32 page_count;
u32 page_max;
// Hack optimizations
struct Page_Cache{
u32 page_number;
Glyph_Page *page;
};
Page_Cache cache[16];
};
// NOTE(allen): Types of refernces fonts.
struct Font_Pointers{
b32 valid;
Font_Settings *settings;
Font_Metrics *metrics;
Font_Page_Storage *pages;
};
typedef u32 Font_ID;
// NOTE(allen): Platform layer calls - implemented in a "font provider"
#define Sys_Font_Get_Count_Sig(n) u32 (n)(void)
typedef Sys_Font_Get_Count_Sig(Font_Get_Count_Function);
#define Sys_Font_Get_Name_By_ID_Sig(n, str_out, capacity) i32 (n)(Font_ID font_id, char *str_out, u32 capacity)
typedef Sys_Font_Get_Name_By_ID_Sig(Font_Get_Name_By_ID_Function, str_out, capacity);
#define Sys_Font_Get_Pointers_By_ID_Sig(n,font_id) Font_Pointers (n)(Font_ID font_id)
typedef Sys_Font_Get_Pointers_By_ID_Sig(Font_Get_Pointers_By_ID_Function, font_id);
#define Sys_Font_Load_Page_Sig(n,s,m,p,pn) void (n)(Font_Settings *s, Font_Metrics *m, Glyph_Page *p, u32 pn)
typedef Sys_Font_Load_Page_Sig(Font_Load_Page_Function, settings, metrics, page, page_number);
#define Sys_Font_Allocate_Sig(n) void* (n)(i32 size)
typedef Sys_Font_Allocate_Sig(Font_Allocate_Function);
#define Sys_Font_Free_Sig(n) void (n)(void *ptr)
typedef Sys_Font_Free_Sig(Font_Free_Function);
struct Font_Functions{
Font_Get_Count_Function *get_count;
Font_Get_Name_By_ID_Function *get_name_by_id;
Font_Get_Pointers_By_ID_Function *get_pointers_by_id;
Font_Load_Page_Function *load_page;
Font_Allocate_Function *allocate;
Font_Free_Function *free;
};
#endif
// BOTTOM

View File

@ -1,74 +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 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_Page{
u32 page_number;
b32 has_layout;
f32 advance[ITEM_PER_FONT_PAGE];
Glyph_Bounds glyphs[ITEM_PER_FONT_PAGE];
i32 tex_width, tex_height;
b32 has_gpu_setup;
u32 gpu_tex;
};
#define FONT_PAGE_EMPTY ((Glyph_Page*)0)
#define FONT_PAGE_DELETED ((Glyph_Page*)(1))
#define FONT_PAGE_MAX 0x1100
struct Render_Font{
Glyph_Page **pages;
u32 page_count, page_max;
f32 byte_advance;
f32 byte_sub_advances[3];
i32 height, ascent, descent, line_skip, advance;
i32 pt_size;
b32 use_hinting;
u32 filename_len;
u32 name_len;
char filename[256];
char name[256];
// Hack optimizations
struct Page_Cache{
u32 page_number;
Glyph_Page *page;
};
Page_Cache cache[16];
};
struct Glyph_Data{
Glyph_Bounds bounds;
b32 has_gpu_setup;
u32 tex;
i32 tex_width, tex_height;
};
#endif
// BOTTOM

View File

@ -1,78 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 11.03.2017
*
* Font system interface.
*
*/
// TOP
#if !defined(FCODER_FONT_INTERFACE_H)
#define FCODER_FONT_INTERFACE_H
typedef u32 Font_ID;
struct Render_Font;
struct Glyph_Page;
#define Sys_Font_Get_Count_Sig(name_) u32 (name_)(void)
typedef Sys_Font_Get_Count_Sig(Font_Get_Count_Function);
#define Sys_Font_Get_IDs_By_Index_Sig(name_) b32 (name_)(Font_ID first_index, u32 index_count, u32 *id_out)
typedef Sys_Font_Get_IDs_By_Index_Sig(Font_Get_IDs_By_Index_Function);
#define Sys_Font_Get_Name_By_Index_Sig(name_) u32 (name_)(u32 font_index, char *str_out, u32 str_out_cap)
typedef Sys_Font_Get_Name_By_Index_Sig(Font_Get_Name_By_Index_Function);
#define Sys_Font_Get_Name_By_ID_Sig(name_) u32 (name_)(Font_ID font_id, char *str_out, u32 str_out_cap)
typedef Sys_Font_Get_Name_By_ID_Sig(Font_Get_Name_By_ID_Function);
#define Sys_Font_Get_Render_Data_By_ID_Sig(name_) Render_Font* (name_)(Font_ID font_id)
typedef Sys_Font_Get_Render_Data_By_ID_Sig(Font_Get_Render_Data_By_ID_Function);
#define Sys_Font_Load_Page_Sig(name_) void (name_)(Render_Font *font, Glyph_Page *page, u32 page_number)
typedef Sys_Font_Load_Page_Sig(Font_Load_Page_Function);
#define Sys_Font_Allocate_Sig(name_) void* (name_)(i32 size)
typedef Sys_Font_Allocate_Sig(Font_Allocate_Function);
#define Sys_Font_Free_Sig(name_) void (name_)(void *ptr)
typedef Sys_Font_Free_Sig(Font_Free_Function);
struct Font_Functions{
Font_Get_Count_Function *get_count;
Font_Get_IDs_By_Index_Function *get_ids_by_index;
Font_Get_Name_By_Index_Function *get_name_by_index;
Font_Get_Name_By_ID_Function *get_name_by_id;
Font_Get_Render_Data_By_ID_Function *get_render_data_by_id;
Font_Load_Page_Function *load_page;
Font_Allocate_Function *allocate;
Font_Free_Function *free;
};
internal u32 font_get_id_by_name(struct System_Functions *system, String name);
internal f32 font_get_byte_advance(Render_Font *font);
internal f32*font_get_byte_sub_advances(Render_Font *font);
internal i32 font_get_height(Render_Font *font);
internal i32 font_get_ascent(Render_Font *font);
internal i32 font_get_descent(Render_Font *font);
internal i32 font_get_line_skip(Render_Font *font);
internal i32 font_get_advance(Render_Font *font);
internal b32 font_can_render(struct System_Functions *system, Render_Font *font, u32 codepoint);
internal f32 font_get_glyph_advance(struct System_Functions *system, Render_Font *font, u32 codepoint);
struct Glyph_Data;
internal Glyph_Data font_get_glyph(System_Functions *system, Render_Font *font, u32 codepoint);
internal Glyph_Page *font_get_or_make_page(struct System_Functions *system, Render_Font *font, u32 page_number);
#endif
// BOTTOM

View File

@ -1,24 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 13.03.2017
*
* Font system interface to the OS layer.
*
*/
// TOP
#if !defined(FCODER_FONT_INTERFACE_TO_OS_H)
#define FCODER_FONT_INTERFACE_TO_OS_H
#define Sys_Font_Init_Sig(name_) void (name_)(Font_Functions *font, void *memory, umem memory_size, u32 font_size, b32 use_hinting)
internal Sys_Font_Init_Sig(system_font_init);
#endif
// BOTTOM

View File

@ -0,0 +1,447 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 18.07.2017
*
* Freetype implementation of the font provider interface.
*
*/
// TOP
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
#undef internal
#include <ft2build.h>
#include FT_FREETYPE_H
#define internal static
internal u32
font_ft_flags(b32 use_hinting){
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{
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
return(ft_flags);
}
internal void
font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page *page, u32 page_number){
Assert(page != 0);
memset(page, 0, sizeof(*page));
char *filename = settings->stub.name;
u32 pt_size = settings->pt_size;
b32 use_hinting = settings->use_hinting;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
page->page_number = page_number;
// NOTE(allen): Determine glyph layout dimensions
i32 max_glyph_w = face->size->metrics.x_ppem;
i32 max_glyph_h = metrics->height;
i32 pen_y_descent = max_glyph_h + 2;
i32 tex_width = 64;
i32 tex_height = 0;
do {
tex_width *= 2;
f32 glyphs_per_row = ceilf(tex_width/(f32)max_glyph_w);
f32 rows = ceilf(GLYPHS_PER_PAGE/glyphs_per_row);
tex_height = ceil32(rows*pen_y_descent);
} while(tex_height > tex_width);
tex_height = round_up_pot_u32(tex_height);
i32 pen_x = 0;
i32 pen_y = 0;
// NOTE(allen): Fill the glyph bounds array
u32 ft_flags = font_ft_flags(use_hinting);
u32 codepoint = (page_number << 8);
Glyph_Bounds *glyph_out = &page->glyphs[0];
f32 *advance_out = &page->advance[0];
for (u32 i = 0; i < GLYPHS_PER_PAGE; ++i, ++codepoint, ++glyph_out, ++advance_out){
if (FT_Load_Char(face, codepoint, ft_flags) == 0){
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
i32 ascent = metrics->ascent;
// NOTE(allen): Move to next line if necessary
if (pen_x + w >= tex_width){
pen_x = 0;
pen_y += pen_y_descent;
}
// NOTE(allen): Set all this stuff the renderer needs
glyph_out->x0 = (f32)(pen_x);
glyph_out->y0 = (f32)(pen_y);
glyph_out->x1 = (f32)(pen_x + w);
glyph_out->y1 = (f32)(pen_y + h + 1);
glyph_out->xoff = (f32)(face->glyph->bitmap_left);
glyph_out->yoff = (f32)(ascent - face->glyph->bitmap_top);
glyph_out->xoff2 = glyph_out->xoff + w;
glyph_out->yoff2 = glyph_out->yoff + h + 1;
// TODO(allen): maybe advance data should be integers?
*advance_out = (f32)ceil32(face->glyph->advance.x / 64.0f);
pen_x = ceil32(glyph_out->x1 + 1);
}
}
// TODO(allen): Not sure setting tex_height here is right... double check.
tex_height = round_up_pot_u32(pen_y + pen_y_descent);
page->tex_width = tex_width;
page->tex_height = tex_height;
page->has_layout = true;
FT_Done_FreeType(ft);
}
internal u32*
font_load_page_pixels(Partition *part, Font_Settings *settings, Glyph_Page *page, u32 page_number, i32 *tex_width_out, i32 *tex_height_out){
Assert(page != 0);
Assert(page->has_layout);
Assert(page->page_number == page_number);
char *filename = settings->stub.name;
i32 pt_size = settings->pt_size;
b32 use_hinting = settings->use_hinting;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
page->page_number = page_number;
// NOTE(allen): Prepare a pixel buffer.
i32 tex_width = page->tex_width;
i32 tex_height = page->tex_height;
u32* pixels = push_array(part, u32, tex_width*tex_height);
memset(pixels, 0, tex_width*tex_height*sizeof(u32));
// NOTE(allen): Fill the texture
u32 ft_flags = font_ft_flags(use_hinting);
u32 codepoint = (page_number << 8);
Glyph_Bounds *glyph_ptr = &page->glyphs[0];
for (i32 i = 0; i < GLYPHS_PER_PAGE; ++i, ++codepoint, ++glyph_ptr){
if (FT_Load_Char(face, codepoint, ft_flags) == 0){
// NOTE(allen): Extract this glyph's dimensions.
i32 x = (i32)glyph_ptr->x0;
i32 y = (i32)glyph_ptr->y0;
i32 w = (i32)(glyph_ptr->x1 - glyph_ptr->x0);
i32 h = (i32)(glyph_ptr->y1 - glyph_ptr->y0 - 1);
// NOTE(allen): Write to the pixels.
u8 *src = face->glyph->bitmap.buffer;
i32 pitch = face->glyph->bitmap.pitch;
i32 end_x = x + w;
i32 end_y = y + h;
for (i32 Y = y, YY = 0; Y < end_y; ++Y, ++YY){
for (i32 X = x, XX = 0; X < end_x; ++X, ++XX){
pixels[Y*tex_width + X] = 0x00FFFFFF + (0x01000000*src[YY*pitch + XX]);
//pixels[Y*tex_width + X] = (0x01010101*src[YY*pitch + XX]);
}
}
}
}
*tex_width_out = tex_width;
*tex_height_out = tex_height;
FT_Done_FreeType(ft);
return(pixels);
}
internal b32
font_load(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages){
char *filename = settings->stub.name;
i32 pt_size = settings->pt_size;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = (pt_size << 6);
FT_Request_Size(face, &size);
// NOTE(allen): Set size and metrics
char *name = face->family_name;
u32 name_len = 0;
for (;name[name_len];++name_len);
name_len = clamp_top(name_len, sizeof(metrics->name)-1);
memcpy(metrics->name, name, name_len);
metrics->name[name_len] = 0;
metrics->name_len = name_len;
metrics->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
metrics->descent = floor32 (face->size->metrics.descender / 64.0f);
metrics->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
metrics->height = ceil32 (face->size->metrics.height / 64.0f);
metrics->line_skip = metrics->height - (metrics->ascent - metrics->descent);
metrics->height -= metrics->line_skip;
metrics->line_skip = 0;
// NOTE(allen): Set texture and glyph data.
Assert(font_get_page(pages, 0) == 0);
Glyph_Page *page = font_allocate_and_hash_new_page(system, pages, 0);
font_load_page_layout(settings, metrics, page, 0);
// NOTE(allen): Whitespace spacing stuff
i32 tab_width = 4;
f32 space_adv = page->advance[' '];
f32 backslash_adv = page->advance['\\'];
f32 r_adv = page->advance['r'];
page->advance['\n'] = space_adv;
page->advance['\r'] = backslash_adv + r_adv;
page->advance['\t'] = space_adv*tab_width;
// NOTE(allen): The rest of the metrics.
f32 max_hex_advance = 0.f;
for (u32 i = '0'; i <= '9'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'a'; i <= 'f'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
metrics->byte_advance = backslash_adv + max_hex_advance*2;
metrics->sub_advances[0] = backslash_adv;
metrics->sub_advances[1] = max_hex_advance;
metrics->sub_advances[2] = max_hex_advance;
FT_Done_FreeType(ft);
return(true);
}
////////////////////////////////
internal
Sys_Font_Get_Count_Sig(system_font_get_count){
return(fontvars.count);
}
internal
Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id, str_out, capacity){
i32 length = 0;
if (0 < font_id && font_id <= fontvars.count){
u32 index = font_id - 1;
Font_Slot *slot = &fontvars.slots[index];
if (slot->is_active){
Font_Metrics *metrics = &slot->metrics;
length = metrics->name_len;
copy_partial_cs(str_out, capacity, make_string(metrics->name, length));
}
}
return(length);
}
internal
Sys_Font_Get_Pointers_By_ID_Sig(system_font_get_pointers_by_id, font_id){
Font_Pointers font = {0};
if (0 < font_id && font_id <= fontvars.count){
u32 index = font_id - 1;
Font_Slot *slot = &fontvars.slots[index];
if (slot->is_active){
font.valid = true;
font.settings = &slot->settings;
font.metrics = &slot->metrics;
font.pages = &slot->pages;
}
}
return(font);
}
internal
Sys_Font_Load_Page_Sig(system_font_load_page, settings, metrics, page, page_number){
Assert(page_number != 0);
font_load_page_layout(settings, metrics, page, page_number);
}
internal
Sys_Font_Allocate_Sig(system_font_allocate){
i64 *size_ptr = 0;
void *result = system_memory_allocate(size + sizeof(*size_ptr));
size_ptr = (i64*)result;
*size_ptr = size + 4;
return(size_ptr + 1);
}
internal
Sys_Font_Free_Sig(system_font_free){
if (ptr != 0){
i64 *size_ptr = ((i64*)ptr) - 1;
system_memory_free(size_ptr, *size_ptr);
}
}
////////////////////////////////
internal Font_Setup*
system_font_get_stubs(Partition *part){
Font_Setup *first_setup = 0;
Font_Setup *head_setup = 0;
u32 dir_max = KB(32);
u8 *directory = push_array(part, u8, dir_max);
String dir_str = make_string_cap(directory, 0, dir_max);
u32 dir_len = dir_str.size = system_get_4ed_path(dir_str.str, dir_str.memory_size);
Assert(dir_len < dir_max);
set_last_folder_sc(&dir_str, "fonts", SLASH);
terminate_with_null(&dir_str);
dir_len = dir_str.size;
partition_reduce(part, dir_max - dir_len - 1);
partition_align(part, 8);
File_List file_list = {0};
system_set_file_list(&file_list, (char*)directory, 0, 0, 0);
for (u32 i = 0; i < file_list.count; ++i){
File_Info *info = &file_list.infos[i];
char *filename = info->filename;
u32 len = 0;
for (;filename[len];++len);
if (dir_len + len + 1 <= sizeof(head_setup->stub.name)){
if (first_setup == 0){
first_setup = push_struct(part, Font_Setup);
head_setup = first_setup;
}
else{
head_setup->next_font = push_struct(part, Font_Setup);
head_setup = head_setup->next_font;
}
head_setup->next_font = 0;
head_setup->stub.in_local_folder = true;
memcpy(&head_setup->stub.name[0], directory, dir_len);
memcpy(&head_setup->stub.name[dir_len], filename, len + 1);
head_setup->stub.len = dir_len + len;
partition_align(part, 8);
}
}
system_set_file_list(&file_list, 0, 0, 0, 0);
return(first_setup);
}
internal void
system_font_init(Font_Functions *font, u32 pt_size, b32 use_hinting, Font_Setup *font_setup_head){
// Linking
font->get_count = system_font_get_count;
font->get_name_by_id = system_font_get_name_by_id;
font->get_pointers_by_id = system_font_get_pointers_by_id;
font->load_page = system_font_load_page;
font->allocate = system_font_allocate;
font->free = system_font_free;
// Filling initial fonts
//i32 font_count_max = ArrayCount(fontvars.slots);
i32 font_count_max = 1;
i32 font_count = 0;
i32 i = 0;
for (Font_Setup *ptr = font_setup_head;
ptr != 0;
ptr = ptr->next_font){
char *filename = ptr->stub.name;
if (i < font_count_max){
Font_Slot *slot = &fontvars.slots[i];
Font_Settings *settings = &slot->settings;
Font_Metrics *metrics = &slot->metrics;
Font_Page_Storage *pages = &slot->pages;
Assert(!slot->is_active);
i32 filename_len = 0;
for (;filename[filename_len];++filename_len);
if (filename_len <= sizeof(settings->stub.name) - 1){
memset(settings, 0, sizeof(*settings));
memset(metrics, 0, sizeof(*metrics));
memset(pages, 0, sizeof(*pages));
// Initialize Font Parameters
memcpy(&settings->stub, &ptr->stub, sizeof(ptr->stub));
settings->pt_size = pt_size;
settings->use_hinting = use_hinting;
b32 success = font_load(&sysfunc, settings, metrics, pages);
if (!success){
memset(font, 0, sizeof(*font));
LOGF("font \"%.*s\" failed to load, unknown error\n", filename_len, filename);
}
else{
slot->is_active = true;
++i;
}
}
else{
LOGF("font \"%.*s\" name is too long to load in current build (max %d)\n", filename_len, filename, (i32)(sizeof(settings->stub.name) - 1));
}
}
else{
LOGF("Exceeded maximum font slots (%d) skipping %s\n", font_count_max, filename);
}
++font_count;
}
fontvars.count = clamp_top(font_count, font_count_max);
}
// BOTTOM

View File

@ -0,0 +1,37 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 16.11.2017
*
* Data types for the freetype font provider.
*
*/
// TOP
#if !defined(FCODER_FONT_PROVIDER_FREETYPE_H)
#define FCODER_FONT_PROVIDER_FREETYPE_H
struct Font_Slot{
b32 is_active;
Font_Settings settings;
Font_Metrics metrics;
Font_Page_Storage pages;
};
struct Font_Vars{
Font_Slot slots[32];
u32 count;
};
global Font_Vars fontvars = {0};
struct Font_Setup{
Font_Setup *next_font;
Font_Loadable_Stub stub;
};
#endif
// BOTTOM

View File

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

View File

@ -1,305 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 14.11.2017
*
* FreeType font loader implementation
*
*/
// TOP
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
#undef internal
#include <ft2build.h>
#include FT_FREETYPE_H
#define internal static
internal u32
font_ft_flags(b32 use_hinting){
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{
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
return(ft_flags);
}
internal void
font_load_page_layout(Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
Assert(page != 0);
memset(page, 0, sizeof(*page));
char *filename = font->filename;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
page->page_number = page_number;
i32 tab_width = 4;
// NOTE(allen): Determine glyph layout dimensions
i32 max_glyph_w = face->size->metrics.x_ppem;
i32 max_glyph_h = font_get_height(font);
i32 pen_y_descent = max_glyph_h + 2;
i32 tex_width = 64;
i32 tex_height = 0;
do {
tex_width *= 2;
f32 glyphs_per_row = ceilf(tex_width/(f32)max_glyph_w);
f32 rows = ceilf(ITEM_PER_FONT_PAGE/glyphs_per_row);
tex_height = ceil32(rows*pen_y_descent);
} while(tex_height > tex_width);
tex_height = round_up_pot_u32(tex_height);
i32 pen_x = 0;
i32 pen_y = 0;
// NOTE(allen): Fill the glyph bounds array
u32 ft_flags = font_ft_flags(use_hinting);
u32 codepoint = (page_number << 8);
Glyph_Bounds *glyph_out = &page->glyphs[0];
f32 *advance_out = &page->advance[0];
for (u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++codepoint, ++glyph_out, ++advance_out){
if (FT_Load_Char(face, codepoint, ft_flags) == 0){
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
i32 ascent = font_get_ascent(font);
// NOTE(allen): Move to next line if necessary
if (pen_x + w >= tex_width){
pen_x = 0;
pen_y += pen_y_descent;
}
// NOTE(allen): Set all this stuff the renderer needs
glyph_out->x0 = (f32)(pen_x);
glyph_out->y0 = (f32)(pen_y);
glyph_out->x1 = (f32)(pen_x + w);
glyph_out->y1 = (f32)(pen_y + h + 1);
glyph_out->xoff = (f32)(face->glyph->bitmap_left);
glyph_out->yoff = (f32)(ascent - face->glyph->bitmap_top);
glyph_out->xoff2 = glyph_out->xoff + w;
glyph_out->yoff2 = glyph_out->yoff + h + 1;
// TODO(allen): maybe advance data should be integers?
*advance_out = (f32)ceil32(face->glyph->advance.x / 64.0f);
pen_x = ceil32(glyph_out->x1 + 1);
}
}
// TODO(allen): Not sure setting tex_height here is right... double check.
tex_height = round_up_pot_u32(pen_y + pen_y_descent);
page->tex_width = tex_width;
page->tex_height = tex_height;
page->has_layout = true;
// HACK(allen): Put this somewhere else!
// NOTE(allen): whitespace spacing stuff
if (page_number == 0){
f32 space_adv = page->advance[' '];
f32 backslash_adv = page->advance['\\'];
f32 r_adv = page->advance['r'];
page->advance['\n'] = space_adv;
page->advance['\r'] = backslash_adv + r_adv;
page->advance['\t'] = space_adv*tab_width;
}
FT_Done_FreeType(ft);
}
internal u32*
font_load_page_pixels(Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, i32 *tex_width_out, i32 *tex_height_out){
Assert(page != 0);
Assert(page->has_layout);
Assert(page->page_number == page_number);
char *filename = font->filename;
i32 pt_size = font->pt_size;
b32 use_hinting = font->use_hinting;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
page->page_number = page_number;
// NOTE(allen): Prepare a pixel buffer.
i32 tex_width = page->tex_width;
i32 tex_height = page->tex_height;
u32* pixels = push_array(part, u32, tex_width*tex_height);
memset(pixels, 0, tex_width*tex_height*sizeof(u32));
// NOTE(allen): Fill the texture
u32 ft_flags = font_ft_flags(use_hinting);
u32 codepoint = (page_number << 8);
Glyph_Bounds *glyph_ptr = &page->glyphs[0];
for (u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++codepoint, ++glyph_ptr){
if (FT_Load_Char(face, codepoint, ft_flags) == 0){
// NOTE(allen): Extract this glyph's dimensions.
i32 x = (i32)glyph_ptr->x0;
i32 y = (i32)glyph_ptr->y0;
i32 w = (i32)(glyph_ptr->x1 - glyph_ptr->x0);
i32 h = (i32)(glyph_ptr->y1 - glyph_ptr->y0 - 1);
// NOTE(allen): Write to the pixels.
u8 *src = face->glyph->bitmap.buffer;
i32 pitch = face->glyph->bitmap.pitch;
i32 end_x = x + w;
i32 end_y = y + h;
for (i32 Y = y, YY = 0; Y < end_y; ++Y, ++YY){
for (i32 X = x, XX = 0; X < end_x; ++X, ++XX){
pixels[Y*tex_width + X] = 0x00FFFFFF + (0x01000000*src[YY*pitch + XX]);
}
}
}
}
*tex_width_out = tex_width;
*tex_height_out = tex_height;
FT_Done_FreeType(ft);
return(pixels);
}
internal b32
font_load(System_Functions *system, Partition *part, Render_Font *font, i32 pt_size, b32 use_hinting){
char *filename = font->filename;
// 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);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
// NOTE(allen): Set size and metrics
char *name = face->family_name;
u32 name_len = 0;
for (;name[name_len];++name_len);
name_len = clamp_top(name_len, sizeof(font->name)-1);
memcpy(font->name, name, name_len);
font->name[name_len] = 0;
font->name_len = name_len;
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;
font->pt_size = pt_size;
font->use_hinting = use_hinting;
// NOTE(allen): Set texture and glyph data.
Glyph_Page *page = font_get_or_make_page(system, font, 0);
// NOTE(allen): Setup some basic spacing stuff.
f32 backslash_adv = page->advance['\\'];
f32 max_hex_advance = 0.f;
for (u32 i = '0'; i <= '9'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'a'; i <= 'f'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
font->byte_advance = backslash_adv + max_hex_advance*2;
font->byte_sub_advances[0] = backslash_adv;
font->byte_sub_advances[1] = max_hex_advance;
font->byte_sub_advances[2] = max_hex_advance;
FT_Done_FreeType(ft);
return(true);
}
// TODO(allen): Remove Partition
internal void
system_set_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
Assert(pt_size >= 8);
font_load_page_layout(font, page, page_number, pt_size, use_hinting);
}
internal void
system_set_font(System_Functions *system, Partition *part, Render_Font *font, char *filename, u32 pt_size, b32 use_hinting){
memset(font, 0, sizeof(*font));
u32 filename_len = 0;
for (;filename[filename_len];++filename_len);
if (filename_len <= sizeof(font->filename) - 1){
memcpy(font->filename, filename, filename_len);
font->filename[filename_len] = 0;
font->filename_len = filename_len;
if (part->base == 0){
*part = sysshared_scratch_partition(MB(8));
}
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = font_load(system, part, font, pt_size, use_hinting);
if (success){
break;
}
else{
sysshared_partition_double(part);
}
}
}
else{
LOGF("font \"%.*s\" name is too long to load in current build (max %u)\n", filename_len, filename, (u32)(sizeof(font->filename) - 1));
}
}
// BOTTOM

View File

@ -106,13 +106,13 @@ internal f32
draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_id, String str_, i32 x_, i32 y_, u32 color){
f32 x = 0;
Render_Font *font = system->font.get_render_data_by_id(font_id);
if (font != 0){
Font_Pointers font = system->font.get_pointers_by_id(font_id);
if (font.valid != 0){
f32 y = (f32)y_;
x = (f32)x_;
f32 byte_advance = font_get_byte_advance(font);
f32 *sub_advances = font_get_byte_sub_advances(font);
f32 byte_advance = font.metrics->byte_advance;
f32 *sub_advances = font.metrics->sub_advances;
u8 *str = (u8*)str_.str;
u8 *str_end = str + str_.size;
@ -131,7 +131,7 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i
if (color != 0){
draw_font_glyph(target, font_id, codepoint, x, y, color);
}
x += font_get_glyph_advance(system, font, codepoint);
x += font_get_glyph_advance(system, font.settings, font.metrics, font.pages, codepoint);
}
else if (behavior.do_number_advance){
u8 n = (u8)(step.value);

View File

@ -12,8 +12,6 @@
#if !defined(FCODER_SYSTEM_INTERFACE_H)
#define FCODER_SYSTEM_INTERFACE_H
#include "4ed_font_interface.h"
// types
struct Plat_Handle{
u32 d[4];

View File

@ -133,7 +133,7 @@ translating_select_emit_rule_ASCII(Translation_State *tran, Translation_Byte_Des
}
internal void
translating_select_emit_rule_with_font(System_Functions *system, Render_Font *font, Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
translating_select_emit_rule_with_font(System_Functions *system, Font_Pointers font, Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
type_out->byte_class = desc.byte_class;
type_out->last_byte_handler = desc.last_byte_handler;
type_out->emit_type = desc.prelim_emit_type;
@ -148,7 +148,7 @@ translating_select_emit_rule_with_font(System_Functions *system, Render_Font *fo
}
else{
type_out->codepoint = cp;
if (!font_can_render(system, font, cp)){
if (!font_can_render(system, font.settings, font.metrics, font.pages, cp)){
type_out->emit_type = BufferModelUnit_Numbers;
}
}
@ -213,7 +213,7 @@ translating_generate_emits(Translation_State *tran, Translation_Emit_Rule emit_r
}
internal void
translating_fully_process_byte(System_Functions *system, Render_Font *font, Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Emits *emits_out){
translating_fully_process_byte(System_Functions *system, Font_Pointers font, Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Emits *emits_out){
Translation_Byte_Description description = {0};
translating_consume_byte(tran, ch, i, size, &description);
Translation_Emit_Rule emit_rule = {0};

View File

@ -49,7 +49,7 @@ private_draw_set_color(Render_Target *t, u32 color){
}
internal void
interpret_render_buffer(System_Functions *system, Render_Target *t){
interpret_render_buffer(Render_Target *t){
// HACK(allen): Probably should use a different partition that can be resized, but whatevs for now scro.
Partition *part = &t->buffer;
@ -152,57 +152,59 @@ interpret_render_buffer(System_Functions *system, Render_Target *t){
case RenCom_Glyph:
{
Render_Command_Glyph *glyph = (Render_Command_Glyph*)header;
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
if (font == 0){
Font_Pointers font = system_font_get_pointers_by_id(glyph->font_id);
if (!font.valid){
break;
}
// HACK(allen): Super stupid... gotta fucking cleanup the font loading fiasco system.
Glyph_Data g = font_get_glyph(system, font, glyph->codepoint);
if (g.tex == 0){
if (g.has_gpu_setup){
break;
}
else{
u32 page_number = (glyph->codepoint/ITEM_PER_FONT_PAGE);
Glyph_Page *page = font_get_or_make_page(system, font, page_number);
Temp_Memory temp = begin_temp_memory(part);
i32 tex_width = 0;
i32 tex_height = 0;
u32 *pixels = font_load_page_pixels(part, font, page, page_number, &tex_width, &tex_height);
page->has_gpu_setup = true;
page->gpu_tex = private_texture_initialize(tex_width, tex_height, pixels);
end_temp_memory(temp);
g = font_get_glyph(system, font, glyph->codepoint);
if (g.tex == 0){
break;
}
}
u32 codepoint = glyph->codepoint;
u32 page_number = codepoint/GLYPHS_PER_PAGE;
Glyph_Page *page = font_cached_get_page(font.pages, page_number);
if (page == 0){
break;
}
if (!page->has_gpu_setup){
Temp_Memory temp = begin_temp_memory(part);
i32 tex_width = 0;
i32 tex_height = 0;
u32 *pixels = font_load_page_pixels(part, font.settings, page, page_number, &tex_width, &tex_height);
page->has_gpu_setup = true;
page->gpu_tex = private_texture_initialize(tex_width, tex_height, pixels);
end_temp_memory(temp);
}
if (page->gpu_tex == 0){
break;
}
u32 glyph_index = codepoint%GLYPHS_PER_PAGE;
Glyph_Bounds bounds = page->glyphs[glyph_index];
GLuint tex = page->gpu_tex;
i32 tex_width = page->tex_width;
i32 tex_height = page->tex_height;
f32 x = glyph->pos.x;
f32 y = glyph->pos.y;
f32_Rect xy = {0};
xy.x0 = x + g.bounds.xoff;
xy.y0 = y + g.bounds.yoff;
xy.x1 = x + g.bounds.xoff2;
xy.y1 = y + g.bounds.yoff2;
xy.x0 = x + bounds.xoff;
xy.y0 = y + bounds.yoff;
xy.x1 = x + bounds.xoff2;
xy.y1 = y + bounds.yoff2;
// TODO(allen): Why aren't these baked in???
f32 unit_u = 1.f/g.tex_width;
f32 unit_v = 1.f/g.tex_height;
f32 unit_u = 1.f/tex_width;
f32 unit_v = 1.f/tex_height;
f32_Rect uv = {0};
uv.x0 = g.bounds.x0*unit_u;
uv.y0 = g.bounds.y0*unit_v;
uv.x1 = g.bounds.x1*unit_u;
uv.y1 = g.bounds.y1*unit_v;
uv.x0 = bounds.x0*unit_u;
uv.y0 = bounds.y0*unit_v;
uv.x1 = bounds.x1*unit_u;
uv.y1 = bounds.y1*unit_v;
private_draw_set_color(t, glyph->color);
private_draw_bind_texture(t, g.tex);
private_draw_bind_texture(t, tex);
glBegin(GL_QUADS);
{
glTexCoord2f(uv.x0, uv.y1); glVertex2f(xy.x0, xy.y1);

View File

@ -1,168 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 18.07.2017
*
* Shared font functions
*
*/
// TOP
struct Font_Vars{
Partition part;
Render_Font fonts[32];
u32 font_count;
};
global Font_Vars fontvars = {0};
internal
Sys_Font_Get_Count_Sig(system_font_get_count){
return(fontvars.font_count);
}
internal
Sys_Font_Get_IDs_By_Index_Sig(system_font_get_ids_by_index){
b32 result = false;
u32 stop_index = first_index + index_count;
if (stop_index <= fontvars.font_count){
result = true;
for (u32 i = first_index; i < stop_index; ++i){
id_out[i-first_index] = i;
}
}
return(result);
}
internal
Sys_Font_Get_Name_By_Index_Sig(system_font_get_name_by_index){
u32 length = 0;
if (font_index < fontvars.font_count){
Render_Font *font = &fontvars.fonts[font_index];
char *name = font->name;
length = font->name_len;
copy_partial_cs(str_out, str_out_cap, make_string(name, length));
}
return(length);
}
internal
Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id){
u32 font_index = font_id;
u32 result = system_font_get_name_by_index(font_index, str_out, str_out_cap);
return(result);
}
internal
Sys_Font_Get_Render_Data_By_ID_Sig(system_font_get_render_data_by_id){
Render_Font *result = 0;
u32 font_index = font_id;
if (font_index < fontvars.font_count){
result = &fontvars.fonts[font_index];
}
return(result);
}
internal
Sys_Font_Load_Page_Sig(system_font_load_page){
system_set_page(&sysfunc, &fontvars.part, font, page, page_number, plat_settings.font_size, plat_settings.use_hinting);
}
internal
Sys_Font_Allocate_Sig(system_font_allocate){
void *result = system_memory_allocate(size);
return(result);
}
// HACK(allen): Have to pass the size somehow or the free doesn't actually happen on linux.
internal
Sys_Font_Free_Sig(system_font_free){
system_memory_free(ptr, 0);
}
internal
Sys_Font_Init_Sig(system_font_init){
Assert(font_size >= 8);
Partition *scratch = &shared_vars.scratch;
Temp_Memory temp = begin_temp_memory(scratch);
font->get_count = system_font_get_count;
font->get_ids_by_index = system_font_get_ids_by_index;
font->get_name_by_index = system_font_get_name_by_index;
font->get_name_by_id = system_font_get_name_by_id;
font->get_render_data_by_id = system_font_get_render_data_by_id;
font->load_page = system_font_load_page;
font->allocate = system_font_allocate;
font->free = system_font_free;
struct Font_Setup{
Font_Setup *next_font;
char *c_filename;
};
Font_Setup *first_setup = 0;
Font_Setup *head_setup = 0;
u32 dir_max = KB(32);
u8 *directory = push_array(scratch, u8, dir_max);
String dir_str = make_string_cap(directory, 0, dir_max);
u32 dir_len = dir_str.size = system_get_4ed_path(dir_str.str, dir_str.memory_size);
Assert(dir_len < dir_max);
set_last_folder_sc(&dir_str, "fonts", SLASH);
terminate_with_null(&dir_str);
dir_len = dir_str.size;
partition_reduce(scratch, dir_max - dir_len - 1);
partition_align(scratch, 8);
File_List file_list = {0};
system_set_file_list(&file_list, (char*)directory, 0, 0, 0);
for (u32 i = 0; i < file_list.count; ++i){
File_Info *info = &file_list.infos[i];
if (first_setup == 0){
first_setup = push_struct(scratch, Font_Setup);
head_setup = first_setup;
}
else{
head_setup->next_font = push_struct(scratch, Font_Setup);
head_setup = head_setup->next_font;
}
head_setup->next_font = 0;
char *filename = info->filename;
u32 len = 0;
for (;filename[len];++len);
head_setup->c_filename = push_array(scratch, char, dir_len+len+1);
memcpy(head_setup->c_filename, directory, dir_len);
memcpy(head_setup->c_filename + dir_len, filename, len+1);
partition_align(scratch, 8);
}
system_set_file_list(&file_list, 0, 0, 0, 0);
u32 font_count_max = ArrayCount(fontvars.fonts);
u32 font_count = 0;
u32 i = 0;
for (Font_Setup *ptr = first_setup; ptr != 0; ptr = ptr->next_font, ++i){
if (i < font_count_max){
Render_Font *render_font = &fontvars.fonts[i];
system_set_font(&sysfunc, &fontvars.part, render_font, ptr->c_filename, font_size, use_hinting);
}
++font_count;
}
fontvars.font_count = clamp_top(font_count, font_count_max);
end_temp_memory(temp);
}
// BOTTOM

View File

@ -36,6 +36,7 @@
#include "4ed_math.h"
#include "4ed_font.h"
#include "4ed_system.h"
#include "4ed_log.h"
#include "4ed_render_format.h"
@ -43,7 +44,6 @@
#include "4ed.h"
#include "4ed_file_track.h"
#include "4ed_font_interface_to_os.h"
#include "4ed_system_shared.h"
#include "unix_4ed_headers.h"
@ -120,9 +120,10 @@ internal void LinuxStringDup(String*, void*, size_t);
global System_Functions sysfunc;
#include "4ed_shared_library_constants.h"
#include "unix_library_wrapper.h"
#include "4ed_standard_libraries.cpp"
#include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
#include "4ed_font.cpp"
////////////////////////////////
@ -332,7 +333,6 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
#include "4ed_coroutine_functions.cpp"
#include "4ed_font_data.h"
#include "4ed_system_shared.cpp"
//
@ -456,8 +456,8 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
return(close_me);
}
#include "4ed_font_system_functions.cpp"
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#include <GL/gl.h>
#include "opengl/4ed_opengl_render.cpp"
@ -1604,7 +1604,11 @@ main(int argc, char **argv){
// Font System Init
//
system_font_init(&sysfunc.font, 0, 0, plat_settings.font_size, plat_settings.use_hinting);
Partition *scratch = &shared_vars.scratch;
Temp_Memory temp = begin_temp_memory(scratch);
Font_Setup *font_setup_head = system_font_get_stubs(scratch);
system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup_head);
end_temp_memory(temp);
//
// Epoll init
@ -1771,7 +1775,7 @@ main(int argc, char **argv){
}
// NOTE(allen): Render
interpret_render_buffer(&sysfunc, &target);
interpret_render_buffer(&target);
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
// NOTE(allen): Toggle Full Screen
@ -1809,9 +1813,7 @@ main(int argc, char **argv){
return(0);
}
#include "4ed_shared_fonts.cpp"
#include "linux_4ed_file_track.cpp"
#include "4ed_font_static_functions.cpp"
// BOTTOM
// vim: expandtab:ts=4:sts=4:sw=4

View File

@ -1,104 +0,0 @@
/*
* Insofaras
*
* ??.??.2016
*
* For getting the font files on Linux.
*
*/
// TOP
#if 0
#undef internal
#include <fontconfig/fontconfig.h>
#define internal static
//TODO(inso): put in linuxvars
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){
result = strdup((char*)fname);
fprintf(stderr, "Got system font from FontConfig: %s\n", result);
}
FcPatternDestroy(font);
}
FcPatternDestroy(pat);
if (!result){
char space[1024];
String str = make_fixed_width_string(space);
if (sysshared_to_binary_path(&str, name)){
result = strdup(space);
}
else{
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
char* filename = push_array(part, char, 256);
if (filename != 0){
String str = make_string_cap(filename, 0, 256);
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);
system_error_box(buff);
}
result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting);
}
end_temp_memory(temp);
return(result);
}
#endif
// BOTTOM

View File

@ -35,6 +35,7 @@
#include "4ed_math.h"
#include "4ed_font.h"
#include "4ed_system.h"
#include "4ed_log.h"
#include "4ed_render_format.h"
@ -42,7 +43,6 @@
#include "4ed.h"
#include "4ed_file_track.h"
#include "4ed_font_interface_to_os.h"
#include "4ed_system_shared.h"
#include "unix_4ed_headers.h"
@ -75,9 +75,10 @@ __sync_val_compare_and_swap((dest), (comp), (ex))
global System_Functions sysfunc;
#include "4ed_shared_library_constants.h"
#include "unix_library_wrapper.h"
#include "4ed_standard_libraries.cpp"
#include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
#include "4ed_font.cpp"
////////////////////////////////
@ -192,7 +193,6 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
#include "4ed_coroutine_functions.cpp"
#include "4ed_font_data.h"
#include "4ed_system_shared.cpp"
//
@ -331,8 +331,8 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
return(close_me);
}
#include "4ed_font_system_functions.cpp"
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include "opengl/4ed_opengl_render.cpp"
@ -562,7 +562,7 @@ osx_step(void){
// NOTE(allen): Render
osx_begin_render();
interpret_render_buffer(&sysfunc, &target);
interpret_render_buffer(&target);
osx_end_render();
// NOTE(allen): Toggle Full Screen
@ -649,7 +649,12 @@ osx_init(){
//
DBG_POINT();
system_font_init(&sysfunc.font, 0, 0, plat_settings.font_size, plat_settings.use_hinting);
Partition *scratch = &shared_vars.scratch;
Temp_Memory temp = begin_temp_memory(scratch);
Font_Setup *font_setup_head = system_font_get_stubs(scratch);
system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup_head);
end_temp_memory(temp);
//
// App Init
@ -680,9 +685,7 @@ osx_init(){
DBG_POINT();
}
#include "4ed_shared_fonts.cpp"
#include "mac_4ed_file_track.cpp"
#include "4ed_font_static_functions.cpp"
// BOTTOM

View File

@ -46,6 +46,7 @@
#include "4ed_math.h"
#include "4ed_font.h"
#include "4ed_system.h"
#include "4ed_log.h"
#include "4ed_render_format.h"
@ -62,7 +63,6 @@
#include "win32_utf8.h"
#include "4ed_file_track.h"
#include "4ed_font_interface_to_os.h"
#include "4ed_system_shared.h"
#include "4ed_shared_thread_constants.h"
@ -113,9 +113,10 @@ struct Win32_Input_Chunk{
global System_Functions sysfunc;
#include "4ed_shared_library_constants.h"
#include "win32_library_wrapper.h"
#include "4ed_standard_libraries.cpp"
#include "4ed_standard_libraries.cpp"
#include "4ed_coroutine.cpp"
#include "4ed_font.cpp"
////////////////////////////////
@ -281,7 +282,6 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
#include "4ed_coroutine_functions.cpp"
#include "4ed_font_data.h"
#include "4ed_system_shared.cpp"
//
@ -503,7 +503,8 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
return(close_me);
}
#include "4ed_font_system_functions.cpp"
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#include <GL/gl.h>
#include "opengl/4ed_opengl_render.cpp"
@ -1115,7 +1116,11 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
//
LOG("Initializing fonts\n");
system_font_init(&sysfunc.font, 0, 0, plat_settings.font_size, plat_settings.use_hinting);
Partition *scratch = &shared_vars.scratch;
Temp_Memory temp = begin_temp_memory(scratch);
Font_Setup *font_setup_head = system_font_get_stubs(scratch);
system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup_head);
end_temp_memory(temp);
//
// Misc System Initializations
@ -1425,7 +1430,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// NOTE(allen): Render
HDC hdc = GetDC(win32vars.window_handle);
interpret_render_buffer(&sysfunc, &target);
interpret_render_buffer(&target);
SwapBuffers(hdc);
ReleaseDC(win32vars.window_handle, hdc);
@ -1462,9 +1467,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
return(0);
}
#include "4ed_shared_fonts.cpp"
#include "win32_4ed_file_track.cpp"
#include "4ed_font_static_functions.cpp"
#include "win32_utf8.cpp"
#if 0