Finished system font listing and loading on windows
parent
4f3b07168d
commit
54de2b4812
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
35
4ed_font.h
35
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
24
4ed_gui.cpp
24
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;
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ struct Shared_Vars{
|
|||
u32 track_node_size;
|
||||
|
||||
Partition scratch;
|
||||
Partition font_scratch;
|
||||
};
|
||||
global Shared_Vars shared_vars;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
||||
//
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "4ed_render_format.h"
|
||||
#include "4ed_render_target.h"
|
||||
#include "4ed.h"
|
||||
#include "4ed_linked_node_macros.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#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 <GL/gl.h>
|
||||
#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);
|
||||
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue