From 54de2b4812a8d06dc4bee6c48978b381e9d93e6f Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 17 Nov 2017 14:22:12 -0500 Subject: [PATCH] Finished system font listing and loading on windows --- 4ed_app_target.cpp | 2 +- 4ed_file_view.cpp | 58 +- 4ed_font.h | 35 +- 4ed_font_provider_freetype.cpp | 634 +++++++++++------- 4ed_font_provider_freetype.h | 29 +- 4ed_gui.cpp | 24 +- ...inked_list.cpp => 4ed_linked_node_macros.h | 15 +- opengl/4ed_opengl_render.cpp | 4 +- platform_all/4ed_system_shared.cpp | 24 +- platform_all/4ed_system_shared.h | 1 + platform_linux/linux_4ed.cpp | 5 +- platform_mac/mac_4ed.cpp | 5 +- platform_win32/win32_4ed.cpp | 146 +++- string/internal_4coder_string.cpp | 6 +- 14 files changed, 652 insertions(+), 336 deletions(-) rename 4ed_doubly_linked_list.cpp => 4ed_linked_node_macros.h (60%) diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 6e194306..145eaf37 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -41,7 +41,7 @@ #define FCPP_FORBID_MALLOC #include "4cpp/4cpp_lexer.h" -#include "4ed_doubly_linked_list.cpp" +#include "4ed_linked_node_macros.h" #include "4ed_font.cpp" diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 0ea37965..9e86712a 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -4514,16 +4514,8 @@ 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: + case CV_Mode_Global_Font: { Editing_File *file = view->file_data.file; Assert(file != 0); @@ -4535,36 +4527,31 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ view->color_mode = CV_Mode_Library; } - Font_ID font_id = models->global_font_id; - if (view->color_mode == CV_Mode_Font){ - font_id = file->settings.font_id; - } + gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9*view->line_height, show_scrollbar); - Font_ID new_font_id = font_id; - u32 total_count = system->font.get_count(); - for (u32 i = 0; i < total_count; ++i){ - Font_ID this_font_id = i + 1; + Font_ID font_id = file->settings.font_id; + + Font_ID new_font_id = 0; + i32 total_count = system->font.get_loadable_count(); + for (i32 i = 0; i < total_count; ++i){ + Font_Loadable_Description loadable = {0}; + system->font.get_loadable(i, &loadable); - char name_space[256]; - String name = make_fixed_width_string(name_space); - name.size = system->font.get_name_by_id(this_font_id, name.str, name.memory_size); - - 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; + id.id[0] = (u64)i + 1; + if (loadable.valid){ + String name = make_string(loadable.display_name, loadable.display_len); + if (gui_do_button(target, id, name)){ + if (new_font_id == 0){ + new_font_id = font_get_id_by_name(system, name); + if (new_font_id == 0){ + new_font_id = system->font.load_new_font(&loadable.stub); + } + } } } - else{ - char message_space[256]; - message = make_fixed_width_string(message_space); - copy_ss(&message, make_lit_string("currently selected: ")); - append_ss(&message, name); - gui_do_font_button(target, id, this_font_id, message); - } } - if (font_id != new_font_id){ + if (new_font_id != 0 && new_font_id != font_id){ if (view->color_mode == CV_Mode_Font){ file_set_font(system, models, file, new_font_id); } @@ -4572,6 +4559,8 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ global_set_font(system, models, new_font_id); } } + + gui_end_scrollable(target); }break; case CV_Mode_Adjusting: @@ -4588,8 +4577,7 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ view->color_mode = CV_Mode_Library; } - gui_begin_scrollable(target, scroll_context, view->gui_scroll, - 9 * view->line_height, show_scrollbar); + gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9*view->line_height, show_scrollbar); i32 next_color_editing = view->current_color_editing; diff --git a/4ed_font.h b/4ed_font.h index 8864c7e5..78817ac5 100644 --- a/4ed_font.h +++ b/4ed_font.h @@ -14,11 +14,18 @@ // NOTE(allen): A description of an available font. struct Font_Loadable_Stub{ - b32 in_local_folder; + b32 load_from_path; i32 len; char name[256]; }; +struct Font_Loadable_Description{ + b32 valid; + Font_Loadable_Stub stub; + i32 display_len; + char display_name[64]; +}; + // NOTE(allen): Settings that the are specified that determine how a font should be loaded and rendered. struct Font_Settings{ Font_Loadable_Stub stub; @@ -93,11 +100,20 @@ struct Font_Pointers{ typedef u32 Font_ID; // NOTE(allen): Platform layer calls - implemented in a "font provider" -#define Sys_Font_Get_Count_Sig(n) u32 (n)(void) +#define Sys_Font_Get_Loadable_Count_Sig(n) i32 (n)(void) +typedef Sys_Font_Get_Loadable_Count_Sig(Font_Get_Loadable_Count_Function); + +#define Sys_Font_Get_Loadable_Sig(n,i,o) void (n)(i32 i, Font_Loadable_Description *o) +typedef Sys_Font_Get_Loadable_Sig(Font_Get_Loadable_Function, index, out); + +#define Sys_Font_Load_New_Font_Sig(n,s) Font_ID (n)(Font_Loadable_Stub *s) +typedef Sys_Font_Load_New_Font_Sig(Font_Load_New_Font_Function, stub); + +#define Sys_Font_Get_Count_Sig(n) i32 (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_Name_By_ID_Sig(n, out, cap) i32 (n)(Font_ID font_id, char *out, u32 cap) +typedef Sys_Font_Get_Name_By_ID_Sig(Font_Get_Name_By_ID_Function, out, cap); #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); @@ -105,13 +121,16 @@ typedef Sys_Font_Get_Pointers_By_ID_Sig(Font_Get_Pointers_By_ID_Function, font_i #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_Allocate_Sig(n,size) void* (n)(i32 size) +typedef Sys_Font_Allocate_Sig(Font_Allocate_Function,size); -#define Sys_Font_Free_Sig(n) void (n)(void *ptr) -typedef Sys_Font_Free_Sig(Font_Free_Function); +#define Sys_Font_Free_Sig(n,ptr) void (n)(void *ptr) +typedef Sys_Font_Free_Sig(Font_Free_Function,ptr); struct Font_Functions{ + Font_Get_Loadable_Count_Function *get_loadable_count; + Font_Get_Loadable_Function *get_loadable; + Font_Load_New_Font_Function *load_new_font; 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; diff --git a/4ed_font_provider_freetype.cpp b/4ed_font_provider_freetype.cpp index d217951e..c27f7228 100644 --- a/4ed_font_provider_freetype.cpp +++ b/4ed_font_provider_freetype.cpp @@ -32,12 +32,57 @@ font_ft_flags(b32 use_hinting){ return(ft_flags); } -internal void +internal b32 +font_ft_get_face(FT_Library ft, Font_Loadable_Stub *stub, FT_Face *face){ + b32 success = true; + if (stub->load_from_path){ + FT_Error error = FT_New_Face(ft, stub->name, 0, face); + success = (error == 0); + } + else{ + Font_Raw_Data data = system_font_data(stub->name); + if (data.size > 0){ + FT_Error error = FT_New_Memory_Face(ft, data.data, data.size, 0, face); + success = (error == 0); + } + else{ + success = false; + } + end_temp_memory(data.temp); + } + return(success); +} + +internal b32 +font_load_name(Font_Loadable_Stub *stub, char *buffer, i32 capacity){ + b32 success = false; + + // TODO(allen): Stop redoing all this init for each call. + FT_Library ft; + FT_Init_FreeType(&ft); + + FT_Face face; + if (font_ft_get_face(ft, stub, &face)){ + char *name = face->family_name; + i32 name_len = str_size(name); + if (name_len < capacity){ + memcpy(buffer, name, name_len + 1); + success = true; + } + } + + FT_Done_FreeType(ft); + + return(success); +} + +internal b32 font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page *page, u32 page_number){ Assert(page != 0); memset(page, 0, sizeof(*page)); + page->page_number = page_number; + page->has_layout = true; - char *filename = settings->stub.name; u32 pt_size = settings->pt_size; b32 use_hinting = settings->use_hinting; @@ -46,77 +91,83 @@ font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page FT_Init_FreeType(&ft); FT_Face face; - FT_New_Face(ft, filename, 0, &face); + b32 has_a_good_face = font_ft_get_face(ft, &settings->stub, &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); + if (has_a_good_face){ + FT_Size_RequestRec_ size = {}; + size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; + size.height = pt_size << 6; + FT_Request_Size(face, &size); + + // 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; + } + else{ + page->tex_width = 1; + page->tex_height = 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); + + return(has_a_good_face); } internal u32* @@ -125,7 +176,6 @@ font_load_page_pixels(Partition *part, Font_Settings *settings, Glyph_Page *page 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; @@ -134,51 +184,77 @@ font_load_page_pixels(Partition *part, Font_Settings *settings, Glyph_Page *page FT_Init_FreeType(&ft); FT_Face face; - FT_New_Face(ft, filename, 0, &face); + b32 has_a_good_face = font_ft_get_face(ft, &settings->stub, &face); + u32 *pixels = 0; - 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); + if (has_a_good_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; + + pixels = push_array(part, u32, tex_width*tex_height); + + if (pixels != 0){ + memset(pixels, 0, tex_width*tex_height*sizeof(u32)); - // 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]); + // 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 end_x = x + w; + i32 end_y = y + h; + if (src != 0){ + i32 pitch = face->glyph->bitmap.pitch; + 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] = (0x01010101*src[YY*pitch + XX]); + pixels[Y*tex_width + X] = 0x00FFFFFF + (0x01000000*src[YY*pitch + XX]); + } + } + } + else{ + 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] = 0xFFFFFFFF; + } + } + } } } + + *tex_width_out = tex_width; + *tex_height_out = tex_height; + } + else{ + pixels = 0; + *tex_width_out = 1; + *tex_height_out = 1; } } - - *tex_width_out = tex_width; - *tex_height_out = tex_height; + else{ + // TODO(allen): Fill in white boxes here. + pixels = 0; + *tex_width_out = 1; + *tex_height_out = 1; + } FT_Done_FreeType(ft); @@ -187,7 +263,6 @@ font_load_page_pixels(Partition *part, Font_Settings *settings, Glyph_Page *page 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. @@ -195,73 +270,140 @@ font_load(System_Functions *system, Font_Settings *settings, Font_Metrics *metri FT_Init_FreeType(&ft); FT_Face face; - FT_New_Face(ft, filename, 0, &face); + b32 success = font_ft_get_face(ft, &settings->stub, &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); + if (success){ + 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; + if (name != 0){ + i32 name_len = str_size(name); + name_len = clamp_top(name_len, sizeof(metrics->name)-1); + memcpy(metrics->name, name, name_len + 1); + metrics->name_len = name_len; + } + else{ + if (!settings->stub.load_from_path){ + i32 name_len = settings->stub.len; + memcpy(metrics->name, settings->stub.name, name_len + 1); + 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; + if (metrics->height > pt_size*4){ + success = false; + } + else{ + // 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; + } } - 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); + return(success); } //////////////////////////////// +internal +Sys_Font_Get_Loadable_Count_Sig(system_font_get_loadable_count){ + return(fontvars.loadable_count); +} + +internal +Sys_Font_Get_Loadable_Sig(system_font_get_loadable, i, out){ + if (0 <= i && i < fontvars.loadable_count){ + memcpy(out, &fontvars.loadables[i], sizeof(*out)); + } + else{ + memset(out, 0, sizeof(*out)); + } +} + +internal +Sys_Font_Load_New_Font_Sig(system_font_load_new_font, stub){ + Font_ID new_id = 0; + + i32 font_count_max = ArrayCount(fontvars.slots); + if (fontvars.count < font_count_max){ + i32 index = fontvars.count; + Font_Slot *slot = &fontvars.slots[index]; + Font_Settings *settings = &slot->settings; + Font_Metrics *metrics = &slot->metrics; + Font_Page_Storage *pages = &slot->pages; + + Assert(!slot->is_active); + + char *filename = stub->name; + i32 filename_len = 0; + for (;filename[filename_len];++filename_len); + + + // Initialize Font Parameters + Assert(filename_len <= sizeof(settings->stub.name) - 1); + memset(settings, 0, sizeof(*settings)); + memcpy(&settings->stub, stub, sizeof(*stub)); + settings->pt_size = fontvars.pt_size; + settings->use_hinting = fontvars.use_hinting; + + memset(metrics, 0, sizeof(*metrics)); + memset(pages, 0, sizeof(*pages)); + b32 success = font_load(&sysfunc, settings, metrics, pages); + if (success){ + slot->is_active = true; + new_id = (Font_ID)(index + 1); + ++fontvars.count; + } + } + + return(new_id); +} + internal Sys_Font_Get_Count_Sig(system_font_get_count){ return(fontvars.count); @@ -270,7 +412,7 @@ Sys_Font_Get_Count_Sig(system_font_get_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){ + if (0 < font_id && font_id <= (u32)fontvars.count){ u32 index = font_id - 1; Font_Slot *slot = &fontvars.slots[index]; if (slot->is_active){ @@ -285,7 +427,7 @@ Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id, str_out, capacity){ 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){ + if (0 < font_id && font_id <= (u32)fontvars.count){ u32 index = font_id - 1; Font_Slot *slot = &fontvars.slots[index]; if (slot->is_active){ @@ -305,7 +447,7 @@ Sys_Font_Load_Page_Sig(system_font_load_page, settings, metrics, page, page_numb } internal -Sys_Font_Allocate_Sig(system_font_allocate){ +Sys_Font_Allocate_Sig(system_font_allocate, size){ i64 *size_ptr = 0; void *result = system_memory_allocate(size + sizeof(*size_ptr)); size_ptr = (i64*)result; @@ -314,7 +456,7 @@ Sys_Font_Allocate_Sig(system_font_allocate){ } internal -Sys_Font_Free_Sig(system_font_free){ +Sys_Font_Free_Sig(system_font_free, ptr){ if (ptr != 0){ i64 *size_ptr = ((i64*)ptr) - 1; system_memory_free(size_ptr, *size_ptr); @@ -323,10 +465,9 @@ Sys_Font_Free_Sig(system_font_free){ //////////////////////////////// -internal Font_Setup* -system_font_get_stubs(Partition *part){ - Font_Setup *first_setup = 0; - Font_Setup *head_setup = 0; +internal Font_Setup_List +system_font_get_local_stubs(Partition *part){ + Font_Setup_List list = {0}; u32 dir_max = KB(32); u8 *directory = push_array(part, u8, dir_max); @@ -351,96 +492,113 @@ system_font_get_stubs(Partition *part){ 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; - + if (dir_len + len + 1 <= sizeof(list.first->stub.name)){ + Font_Setup *setup = push_struct(part, Font_Setup); partition_align(part, 8); + + sll_push(list.first, list.last, setup); + + setup->stub.load_from_path = true; + memcpy(&setup->stub.name[0], directory, dir_len); + memcpy(&setup->stub.name[dir_len], filename, len + 1); + setup->stub.len = dir_len + len; } - - } system_set_file_list(&file_list, 0, 0, 0, 0); - return(first_setup); + return(list); } internal void -system_font_init(Font_Functions *font, u32 pt_size, b32 use_hinting, Font_Setup *font_setup_head){ +system_font_init(Font_Functions *font_links, u32 pt_size, b32 use_hinting, Font_Setup_List list){ // 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; + font_links->get_loadable_count = system_font_get_loadable_count; + font_links->get_loadable = system_font_get_loadable; + font_links->load_new_font = system_font_load_new_font; + font_links->get_count = system_font_get_count; + font_links->get_name_by_id = system_font_get_name_by_id; + font_links->get_pointers_by_id = system_font_get_pointers_by_id; + font_links->load_page = system_font_load_page; + font_links->allocate = system_font_allocate; + font_links->free = system_font_free; + + fontvars.pt_size = pt_size; + fontvars.use_hinting = use_hinting; + + // Filling loadable font descriptions + for (Font_Setup *ptr = list.first; + ptr != 0; + ptr = ptr->next){ + Font_Loadable_Stub *stub = &ptr->stub; + + if (fontvars.loadable_count < ArrayCount(fontvars.loadables)){ + Font_Loadable_Description *loadable = &fontvars.loadables[fontvars.loadable_count]; + + b32 name_good = false; + i32 capacity = (i32)(sizeof(loadable->display_name)); + + if (stub->load_from_path){ + name_good = font_load_name(stub, loadable->display_name, capacity); + if (name_good){ + loadable->display_len = str_size(loadable->display_name); + } + } + else{ + i32 len = str_size(stub->name); + if (len < capacity){ + name_good = true; + memcpy(loadable->display_name, stub->name, len + 1); + loadable->display_len = len; + } + } + + if (name_good){ + memcpy(&loadable->stub, stub, sizeof(*stub)); + loadable->valid = true; + ++fontvars.loadable_count; + } + } + } // 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; + for (Font_Setup *ptr = list.first; ptr != 0; - ptr = ptr->next_font){ - char *filename = ptr->stub.name; + ptr = ptr->next){ + Font_Loadable_Stub *stub = &ptr->stub; - if (i < font_count_max){ - Font_Slot *slot = &fontvars.slots[i]; + Font_ID new_id = 0; + if (fontvars.count < font_count_max){ + i32 index = fontvars.count; + Font_Slot *slot = &fontvars.slots[index]; Font_Settings *settings = &slot->settings; Font_Metrics *metrics = &slot->metrics; Font_Page_Storage *pages = &slot->pages; Assert(!slot->is_active); + char *filename = stub->name; 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)); + // Initialize Font Parameters + Assert(filename_len <= sizeof(settings->stub.name) - 1); + memset(settings, 0, sizeof(*settings)); + memcpy(&settings->stub, stub, sizeof(*stub)); + settings->pt_size = fontvars.pt_size; + settings->use_hinting = fontvars.use_hinting; + + memset(metrics, 0, sizeof(*metrics)); + memset(pages, 0, sizeof(*pages)); + b32 success = font_load(&sysfunc, settings, metrics, pages); + if (success){ + slot->is_active = true; + new_id = (Font_ID)(index + 1); + ++fontvars.count; } } - 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 diff --git a/4ed_font_provider_freetype.h b/4ed_font_provider_freetype.h index f473ba1a..faf91cfb 100644 --- a/4ed_font_provider_freetype.h +++ b/4ed_font_provider_freetype.h @@ -12,6 +12,7 @@ #if !defined(FCODER_FONT_PROVIDER_FREETYPE_H) #define FCODER_FONT_PROVIDER_FREETYPE_H +// NOTE(allen): Implemented by the freetype font provider. struct Font_Slot{ b32 is_active; Font_Settings settings; @@ -21,16 +22,40 @@ struct Font_Slot{ struct Font_Vars{ Font_Slot slots[32]; - u32 count; + i32 count; + + Font_Loadable_Description loadables[4096]; + i32 loadable_count; + + u32 pt_size; + b32 use_hinting; }; global Font_Vars fontvars = {0}; struct Font_Setup{ - Font_Setup *next_font; + Font_Setup *next; Font_Loadable_Stub stub; }; +struct Font_Setup_List{ + Font_Setup *first; + Font_Setup *last; +}; + +// NOTE(allen): Procedures to be implemented per-OS for the freetype font provider. +struct Font_Raw_Data{ + Temp_Memory temp; + u8 *data; + i32 size; +}; + +#define Sys_Font_Data(name) Font_Raw_Data system_font_data(char *name) +internal Sys_Font_Data(name); + +#define Sys_Font_Data_Not_Used\ +internal Sys_Font_Data(name){Font_Raw_Data data = {0}; InvalidCodePath; return(data);} + #endif // BOTTOM diff --git a/4ed_gui.cpp b/4ed_gui.cpp index 365c6204..1e77096c 100644 --- a/4ed_gui.cpp +++ b/4ed_gui.cpp @@ -451,23 +451,6 @@ gui_do_color_button(GUI_Target *target, GUI_id id, u32 fore, u32 back, String te return(result); } -internal b32 -gui_do_font_button(GUI_Target *target, GUI_id id, Font_ID font_id, String text){ - b32 result = 0; - i32 font_id32 = font_id; - GUI_Interactive *b = gui_push_button_command(target, guicom_font_button, id); - GUI_Header *h = (GUI_Header*)b; - gui_push_item(target, h, &font_id32, sizeof(font_id32)); - gui_push_string(target, h, text); - - if (gui_id_eq(id, target->active)){ - result = 1; - target->animating = 1; - } - - return(result); -} - internal b32 gui_begin_list(GUI_Target *target, GUI_id id, i32 list_i, b32 activate_item, b32 snap_into_view, GUI_Item_Update *update){ @@ -565,6 +548,13 @@ gui_do_button(GUI_Target *target, GUI_id id, String message){ return(result); } +internal b32 +gui_do_button(GUI_Target *target, GUI_id id, char *message){ + String str_message = make_string_slowly(message); + b32 result = gui_do_button(target, id, str_message); + return(result); +} + internal b32 gui_do_fixed_option(GUI_Target *target, GUI_id id, String message, char key){ b32 result = 0; diff --git a/4ed_doubly_linked_list.cpp b/4ed_linked_node_macros.h similarity index 60% rename from 4ed_doubly_linked_list.cpp rename to 4ed_linked_node_macros.h index 4e02a514..5d8f8616 100644 --- a/4ed_doubly_linked_list.cpp +++ b/4ed_linked_node_macros.h @@ -13,21 +13,26 @@ // with a next and prev pointer where the type of the struct // is the same as the type of the next/prev pointers. -#define dll_init_sentinel(s) do{ (s)->next=(s); (s)->prev=(s); }while(0) -#define dll_insert(p,v) do{ (v)->next=(p)->next; (v)->prev=(p); (p)->next=(v); (v)->next->prev=(v); }while(0) -#define dll_back_insert(p,v) do{ (v)->prev=(p)->prev; (v)->next=(p); (p)->prev=(v); (v)->prev->next=(v); }while(0) -#define dll_remove(v) do{ (v)->next->prev = (v)->prev; (v)->prev->next = (v)->next; }while(0) +#define dll_init_sentinel(s) (s)->next=(s),(s)->prev=(s) +#define dll_insert(p,v) (v)->next=(p)->next,(v)->prev=(p),(p)->next=(v),(v)->next->prev=(v) +#define dll_back_insert(p,v) (v)->prev=(p)->prev,(v)->next=(p),(p)->prev=(v),(v)->prev->next=(v) +#define dll_remove(v) (v)->next->prev=(v)->prev,(v)->prev->next=(v)->next +// HACK(allen): I don't like this anymore, get rid of it. // for(dll_items(iterator, sentinel_ptr)){...} #define dll_items(it, st) ((it) = (st)->next); ((it) != (st)); ((it) = (it)->next) -#define sll_push(f,l,n) if((f)==0&&(l)==0){(f)=(l)=(n);}else{(l)->next=(n);(l)=(n);} +// NOTE(allen): These macros work on structs with a next +// pointer to the saem type as the containing struct. + +#define sll_push(f,l,n) if((f)==0&&(l)==0){(f)=(l)=(n);}else{(l)->next=(n);(l)=(n);}(l)->next=0 #define sll_pop(f,l) if((f)!=(l)){(f)=(f)->next;}else{(f)=(l)=0;} #define sll_init_sentinel(s) do{ (s)->next=(s); }while(0) #define sll_insert(p,v) do{ (v)->next=(p)->next; (p)->next = (v); }while(0) #define sll_remove(p,v) do{ Assert((p)->next == (v)); (p)->next = (v)->next; }while(0) +// HACK(allen): I don't like this anymore, get rid of it. // for(sll_items(iterator, sentinel_ptr)){...} #define sll_items(it, st) ((it) = (st)->next); ((it) != (st)); ((it) = (it)->next) diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index 4f60866e..a0559748 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -50,9 +50,6 @@ private_draw_set_color(Render_Target *t, u32 color){ internal void 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; - local_persist b32 first_opengl_call = true; if (first_opengl_call){ first_opengl_call = false; @@ -165,6 +162,7 @@ interpret_render_buffer(Render_Target *t){ } if (!page->has_gpu_setup){ + Partition *part = &target.buffer; Temp_Memory temp = begin_temp_memory(part); i32 tex_width = 0; i32 tex_height = 0; diff --git a/platform_all/4ed_system_shared.cpp b/platform_all/4ed_system_shared.cpp index a07af75b..055a7979 100644 --- a/platform_all/4ed_system_shared.cpp +++ b/platform_all/4ed_system_shared.cpp @@ -28,6 +28,10 @@ init_shared_vars(){ void *scratch_memory = system_memory_allocate(scratch_size); shared_vars.scratch = make_part(scratch_memory, (i32)scratch_size); + umem font_scratch_size = MB(4); + void *font_scratch_memory = system_memory_allocate(font_scratch_size); + shared_vars.font_scratch = make_part(font_scratch_memory, (i32)font_scratch_size); + shared_vars.track_table_size = KB(16); shared_vars.track_table = system_memory_allocate(shared_vars.track_table_size); @@ -150,15 +154,6 @@ sysshared_load_file(char *filename){ return(result); } -internal b32 -usable_ascii(char c){ - b32 result = true; - if ((c < ' ' || c > '~') && c != '\n' && c != '\r' && c != '\t'){ - result = false; - } - return(result); -} - internal void sysshared_filter_real_files(char **files, i32 *file_count){ i32 end = *file_count; @@ -172,6 +167,7 @@ sysshared_filter_real_files(char **files, i32 *file_count){ *file_count = j; } +// HACK(allen): Get rid of this now!? internal Partition sysshared_scratch_partition(i32 size){ void *data = system_memory_allocate((umem)size); @@ -181,9 +177,10 @@ sysshared_scratch_partition(i32 size){ internal void sysshared_partition_grow(Partition *part, i32 new_size){ + Assert(part->pos == 0); + void *data = 0; if (new_size > part->max){ - // TODO(allen): attempt to grow in place by just acquiring next vpages?! data = system_memory_allocate((umem)new_size); memcpy(data, part->base, part->pos); system_memory_free(part->base, part->max); @@ -192,15 +189,10 @@ sysshared_partition_grow(Partition *part, i32 new_size){ } } -internal void -sysshared_partition_double(Partition *part){ - sysshared_partition_grow(part, part->max*2); -} - internal void* sysshared_push_block(Partition *part, i32 size){ void *result = push_block(part, size); - if (!result){ + if (result == 0){ sysshared_partition_grow(part, size + part->max); result = push_block(part, size); } diff --git a/platform_all/4ed_system_shared.h b/platform_all/4ed_system_shared.h index e18a038d..0fd46d96 100644 --- a/platform_all/4ed_system_shared.h +++ b/platform_all/4ed_system_shared.h @@ -34,6 +34,7 @@ struct Shared_Vars{ u32 track_node_size; Partition scratch; + Partition font_scratch; }; global Shared_Vars shared_vars; diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 3a6836fa..39aa5b20 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -42,6 +42,7 @@ #include "4ed_render_format.h" #include "4ed_render_target.h" #include "4ed.h" +#include "4ed_linked_node_macros.h" #include "4ed_file_track.h" #include "4ed_system_shared.h" @@ -1606,8 +1607,8 @@ main(int argc, char **argv){ 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); + Font_Setup_List font_setup = system_font_get_local_stubs(scratch); + system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup); end_temp_memory(temp); // diff --git a/platform_mac/mac_4ed.cpp b/platform_mac/mac_4ed.cpp index cb332aaf..4eabc123 100644 --- a/platform_mac/mac_4ed.cpp +++ b/platform_mac/mac_4ed.cpp @@ -41,6 +41,7 @@ #include "4ed_render_format.h" #include "4ed_render_target.h" #include "4ed.h" +#include "4ed_linked_node_macros.h" #include "4ed_file_track.h" #include "4ed_system_shared.h" @@ -652,8 +653,8 @@ osx_init(){ 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); + Font_Setup_List font_setup = system_font_get_local_stubs(scratch); + system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup); end_temp_memory(temp); // diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index f910776c..335e6347 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -52,6 +52,7 @@ #include "4ed_render_format.h" #include "4ed_render_target.h" #include "4ed.h" +#include "4ed_linked_node_macros.h" #include #include "win32_gl.h" @@ -308,11 +309,20 @@ win32_post_clipboard(char *text, i32 len){ internal Sys_Post_Clipboard_Sig(system_post_clipboard){ + LOG("Beginning clipboard post\n"); Partition *part = &win32vars.clip_post_part; - win32vars.clip_post_len = str.size; + part->pos = 0; u8 *post = (u8*)sysshared_push_block(part, str.size + 1); - memmove(post, str.str, str.size); - post[str.size] = 0; + if (post != 0){ + LOG("Copying post to clipboard buffer\n"); + memcpy(post, str.str, str.size); + post[str.size] = 0; + win32vars.clip_post_len = str.size; + } + else{ + LOGF("Failed to allocate buffer for clipboard post (%d)\n", str.size + 1); + } + LOG("Finished clipboard post\n"); } internal b32 @@ -505,6 +515,131 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ #include "4ed_font_provider_freetype.h" #include "4ed_font_provider_freetype.cpp" + +internal +Sys_Font_Data(name){ + Font_Raw_Data data = {0}; + + HFONT hfont = CreateFontA( + 0, + 0, + 0, + 0, + 0, + FALSE, // Italic + FALSE, // Underline + FALSE, // Strikeout + ANSI_CHARSET, + OUT_DEVICE_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, + name + ); + + if (hfont != 0){ + HDC hdc = CreateCompatibleDC(NULL); + if (hdc != 0){ + SelectObject(hdc, hfont); + DWORD size = GetFontData(hdc, 0, 0, NULL, 0); + if (size > 0){ + Partition *part = &shared_vars.font_scratch; + data.temp = begin_temp_memory(part); + u8 *buffer = push_array(part, u8, size); + if (buffer == 0){ + sysshared_partition_grow(part, l_round_up_i32(size, KB(4))); + buffer = push_array(part, u8, size); + } + + if (buffer != 0){ + push_align(part, 8); + if (GetFontData(hdc, 0, 0, buffer, size) == size){ + data.data = buffer; + data.size = size; + } + } + } + DeleteDC(hdc); + } + } + + return(data); +} + +struct Win32_Font_Enum{ + Partition *part; + Font_Setup_List *list; +}; + +internal int +win32_font_enum_callback( +const LOGFONT *lpelfe, +const TEXTMETRIC *lpntme, +DWORD FontType, +LPARAM lParam +){ + if ((FontType & TRUETYPE_FONTTYPE) != 0){ + ENUMLOGFONTEXDV *log_font = (ENUMLOGFONTEXDV*)lpelfe; + TCHAR *name = ((log_font)->elfEnumLogfontEx).elfLogFont.lfFaceName; + + if ((char)name[0] == '@'){ + return(1); + } + + i32 len = 0; + for (;name[len]!=0;++len); + + if (len >= sizeof(((Font_Loadable_Stub*)0)->name)){ + return(1); + } + + Win32_Font_Enum p = *(Win32_Font_Enum*)lParam; + Temp_Memory reset = begin_temp_memory(p.part); + + Font_Setup *setup = push_array(p.part, Font_Setup, 1); + if (setup != 0){ + memset(setup, 0, sizeof(*setup)); + + b32 good = true; + for (i32 i = 0; i < len; ++i){ + if (name[i] >= 128){ + good = false; + break; + } + setup->stub.name[i] = (char)name[i]; + } + + if (good){ + setup->stub.load_from_path = false; + setup->stub.len = len; + sll_push(p.list->first, p.list->last, setup); + } + else{ + end_temp_memory(reset); + } + } + } + return(1); +} + +internal void +win32_get_loadable_fonts(Partition *part, Font_Setup_List *list){ + HDC hdc= GetDC(0); + + LOGFONT log_font = {0}; + log_font.lfCharSet = ANSI_CHARSET; + log_font.lfFaceName[0] = 0; + + Win32_Font_Enum p = {0}; + p.part = part; + p.list = list; + + int result = EnumFontFamiliesEx(hdc, &log_font, win32_font_enum_callback, (LPARAM)&p,0); + AllowLocal(result); + + ReleaseDC(0, hdc); +} + #include #include "opengl/4ed_opengl_render.cpp" @@ -1118,8 +1253,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS LOG("Initializing fonts\n"); 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); + Font_Setup_List font_setup = system_font_get_local_stubs(scratch); + win32_get_loadable_fonts(scratch, &font_setup); + system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup); end_temp_memory(temp); // diff --git a/string/internal_4coder_string.cpp b/string/internal_4coder_string.cpp index db3bf825..4fec98ad 100644 --- a/string/internal_4coder_string.cpp +++ b/string/internal_4coder_string.cpp @@ -224,7 +224,9 @@ API_EXPORT FSTRING_LINK i32_4tech str_size(char *str) /* DOC(This call returns the number of bytes before a null terminator starting at str.) */{ i32_4tech i = 0; - while (str[i]) ++i; + if (str != 0){ + for (;str[i];++i); + } return(i); } @@ -234,7 +236,7 @@ make_string_slowly(void *str) String result; result.str = (char*)str; result.size = str_size((char*)str); - result.memory_size = result.size+1; + result.memory_size = result.size + 1; return(result); }