Working on font cleanup all day all day all day
This commit is contained in:
parent
5aceb5b910
commit
4f3b07168d
|
@ -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
|
||||
|
|
5
4ed.cpp
5
4ed.cpp
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue