font work

This commit is contained in:
Allen Webster 2016-06-16 23:31:15 -04:00
parent f8c5738dc1
commit da19d21bac
17 changed files with 686 additions and 473 deletions

View File

@ -103,7 +103,7 @@ typedef struct File_List{
int block_size;
} File_List;
// NOTE(allen|a4.0.7): This is used to identify which buffer
// NOTE(allen|a4.0.8): This is used to identify which buffer
// an operation should work on when you might want to
// identify it by id or by name.
typedef struct Buffer_Identifier{
@ -117,6 +117,8 @@ enum Command_ID{
cmdid_center_view,
cmdid_left_adjust_view,
cmdid_page_up,
cmdid_page_down,
cmdid_word_complete,
@ -125,6 +127,18 @@ enum Command_ID{
cmdid_history_backward,
cmdid_history_forward,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_line_wrap,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_hide_scrollbar,
cmdid_show_scrollbar,
cmdid_interactive_new,
cmdid_interactive_open,
cmdid_reopen,
@ -134,31 +148,15 @@ enum Command_ID{
cmdid_interactive_kill_buffer,
cmdid_kill_buffer,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_line_wrap,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_change_active_panel,
cmdid_page_up,
cmdid_page_down,
cmdid_open_color_tweaker,
cmdid_open_config,
cmdid_open_menu,
cmdid_open_debug,
cmdid_hide_scrollbar,
cmdid_show_scrollbar,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_change_active_panel,
//
cmdid_count

View File

@ -19,7 +19,9 @@
#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
#define BUFFER_SEEK_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags)
#define BUFFER_SET_SETTING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int setting, int value)
#define BUFFER_SAVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len)
#define CREATE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int filename_len, int do_in_background)
#define SAVE_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len)
#define KILL_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id)
#define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app)
#define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view)
#define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index)
@ -34,8 +36,6 @@
#define VIEW_POST_FADE_SIG(n) int n(Application_Links *app, View_Summary *view, int ticks, int start, int end, unsigned int color)
#define VIEW_SET_PASTE_REWRITE__SIG(n) void n(Application_Links *app, View_Summary *view)
#define VIEW_GET_PASTE_REWRITE__SIG(n) int n(Application_Links *app, View_Summary *view)
#define VIEW_OPEN_FILE_SIG(n) int n(Application_Links *app, View_Summary *view, char *filename, int filename_len, int do_in_background)
#define VIEW_KILL_BUFFER_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer)
#define GET_USER_INPUT_SIG(n) User_Input n(Application_Links *app, unsigned int get_type, unsigned int abort_type)
#define GET_COMMAND_INPUT_SIG(n) User_Input n(Application_Links *app)
#define GET_EVENT_MESSAGE_SIG(n) Event_Message n(Application_Links *app)
@ -69,7 +69,9 @@ extern "C"{
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
typedef BUFFER_SEEK_SIG(Buffer_Seek_Function);
typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function);
typedef BUFFER_SAVE_SIG(Buffer_Save_Function);
typedef CREATE_BUFFER_SIG(Create_Buffer_Function);
typedef SAVE_BUFFER_SIG(Save_Buffer_Function);
typedef KILL_BUFFER_SIG(Kill_Buffer_Function);
typedef GET_VIEW_FIRST_SIG(Get_View_First_Function);
typedef GET_VIEW_NEXT_SIG(Get_View_Next_Function);
typedef GET_VIEW_SIG(Get_View_Function);
@ -84,8 +86,6 @@ extern "C"{
typedef VIEW_POST_FADE_SIG(View_Post_Fade_Function);
typedef VIEW_SET_PASTE_REWRITE__SIG(View_Set_Paste_Rewrite__Function);
typedef VIEW_GET_PASTE_REWRITE__SIG(View_Get_Paste_Rewrite__Function);
typedef VIEW_OPEN_FILE_SIG(View_Open_File_Function);
typedef VIEW_KILL_BUFFER_SIG(View_Kill_Buffer_Function);
typedef GET_USER_INPUT_SIG(Get_User_Input_Function);
typedef GET_COMMAND_INPUT_SIG(Get_Command_Input_Function);
typedef GET_EVENT_MESSAGE_SIG(Get_Event_Message_Function);
@ -122,7 +122,9 @@ struct Application_Links{
Buffer_Replace_Range_Function *buffer_replace_range;
Buffer_Seek_Function *buffer_seek;
Buffer_Set_Setting_Function *buffer_set_setting;
Buffer_Save_Function *buffer_save;
Create_Buffer_Function *create_buffer;
Save_Buffer_Function *save_buffer;
Kill_Buffer_Function *kill_buffer;
Get_View_First_Function *get_view_first;
Get_View_Next_Function *get_view_next;
Get_View_Function *get_view;
@ -137,8 +139,6 @@ struct Application_Links{
View_Post_Fade_Function *view_post_fade;
View_Set_Paste_Rewrite__Function *view_set_paste_rewrite_;
View_Get_Paste_Rewrite__Function *view_get_paste_rewrite_;
View_Open_File_Function *view_open_file;
View_Kill_Buffer_Function *view_kill_buffer;
Get_User_Input_Function *get_user_input;
Get_Command_Input_Function *get_command_input;
Get_Event_Message_Function *get_event_message;
@ -177,7 +177,9 @@ app_links->buffer_read_range = external_buffer_read_range;\
app_links->buffer_replace_range = external_buffer_replace_range;\
app_links->buffer_seek = external_buffer_seek;\
app_links->buffer_set_setting = external_buffer_set_setting;\
app_links->buffer_save = external_buffer_save;\
app_links->create_buffer = external_create_buffer;\
app_links->save_buffer = external_save_buffer;\
app_links->kill_buffer = external_kill_buffer;\
app_links->get_view_first = external_get_view_first;\
app_links->get_view_next = external_get_view_next;\
app_links->get_view = external_get_view;\
@ -192,8 +194,6 @@ app_links->view_set_buffer = external_view_set_buffer;\
app_links->view_post_fade = external_view_post_fade;\
app_links->view_set_paste_rewrite_ = external_view_set_paste_rewrite_;\
app_links->view_get_paste_rewrite_ = external_view_get_paste_rewrite_;\
app_links->view_open_file = external_view_open_file;\
app_links->view_kill_buffer = external_view_kill_buffer;\
app_links->get_user_input = external_get_user_input;\
app_links->get_command_input = external_get_command_input;\
app_links->get_event_message = external_get_event_message;\

View File

@ -96,7 +96,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
CUSTOM_COMMAND_SIG(open_my_files){
// TODO(allen|a4.0.8): comment
View_Summary view = app->get_active_view(app);
app->view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), false);
view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), false);
}
CUSTOM_COMMAND_SIG(build_at_launch_location){

View File

@ -784,7 +784,7 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){
append(&file_name, make_string(short_file_name, size));
exec_command(app, cmdid_change_active_panel);
app->view_open_file(app, &view, expand_str(file_name), false);
view_open_file(app, &view, expand_str(file_name), false);
}
}
@ -1065,10 +1065,8 @@ CUSTOM_COMMAND_SIG(close_all_code){
}
}
View_Summary view = app->get_active_view(app);
for (int i = 0; i < buffers_to_close_count; ++i){
app->view_kill_buffer(app, &view, buffer_identifier(buffers_to_close[i]));
app->kill_buffer(app, buffer_identifier(buffers_to_close[i]), true, 0);
}
}

View File

@ -725,4 +725,25 @@ buffer_identifier(int id){
return(identifier);
}
static int
view_open_file(Application_Links *app, View_Summary *view,
char *filename, int filename_len, int do_in_background){
int result = false;
Buffer_Summary buffer = app->get_buffer_by_name(app, filename, filename_len);
if (buffer.exists){
app->view_set_buffer(app, view, buffer.buffer_id);
result = true;
}
else{
buffer = app->create_buffer(app, filename, filename_len, do_in_background);
if (!do_in_background){
if (buffer.exists){
app->view_set_buffer(app, view, buffer.buffer_id);
result = true;
}
}
}
return(result);
}

View File

@ -31,7 +31,7 @@ i32R(int32_t l, int32_t t, int32_t r, int32_t b){
i32_Rect rect;
rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b;
return rect;
return(rect);
}
inline i32_Rect
@ -41,7 +41,7 @@ i32R(f32_Rect r){
rect.y0 = (int32_t)r.y0;
rect.x1 = (int32_t)r.x1;
rect.y1 = (int32_t)r.y1;
return rect;
return(rect);
}
inline i32_Rect
@ -49,7 +49,7 @@ i32XYWH(int32_t x, int32_t y, int32_t w, int32_t h){
i32_Rect rect;
rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h;
return rect;
return(rect);
}
inline f32_Rect
@ -57,7 +57,7 @@ f32R(float l, float t, float r, float b){
f32_Rect rect;
rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b;
return rect;
return(rect);
}
inline f32_Rect
@ -67,7 +67,7 @@ f32R(i32_Rect r){
rect.y0 = (float)r.y0;
rect.x1 = (float)r.x1;
rect.y1 = (float)r.y1;
return rect;
return(rect);
}
inline f32_Rect
@ -75,7 +75,7 @@ f32XYWH(float x, float y, float w, float h){
f32_Rect rect;
rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h;
return rect;
return(rect);
}
inline int

12
4ed.cpp
View File

@ -1793,23 +1793,23 @@ App_Init_Sig(app_init){
Font_Setup font_setup[] = {
{literal("LiberationSans-Regular.ttf"),
literal("liberation sans"),
literal("Liberation Sans"),
font_size},
{literal("liberation-mono.ttf"),
literal("liberation mono"),
literal("Liberation Mono"),
font_size},
{literal("Hack-Regular.ttf"),
literal("hack"),
literal("Hack"),
font_size},
{literal("CutiveMono-Regular.ttf"),
literal("cutive mono"),
literal("Cutive Mono"),
font_size},
{literal("Inconsolata-Regular.ttf"),
literal("inconsolata"),
literal("Inconsolata"),
font_size},
};
i32 font_count = ArrayCount(font_setup);
@ -2650,7 +2650,7 @@ App_Step_Sig(app_step){
"\n"
"New in alpha 4.0.7:\n"
"-Right click sets the mark\n"
"-Clicks are now have key codes so they can have event bound in customizations\n"
"-Clicks now have key codes so they can have events bound in customizations\n"
"-<alt d> opens a debug view, see more in README.txt\n"
"\n"
"New in alpha 4.0.6:\n"

View File

@ -128,16 +128,25 @@ imp_get_file(Command_Data *cmd, Buffer_Summary *buffer){
return(file);
}
internal View*
imp_get_view(Command_Data *cmd, int view_id){
Live_Views *live_set = cmd->live_set;
View *vptr = 0;
view_id = view_id - 1;
if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id;
}
return(vptr);
}
internal View*
imp_get_view(Command_Data *cmd, View_Summary *view){
View *vptr = 0;
Live_Views *live_set = cmd->live_set;
int view_id = view->view_id - 1;
if (view->exists){
if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id;
}
vptr = imp_get_view(cmd, view->view_id);
}
return(vptr);
@ -652,7 +661,7 @@ BUFFER_SET_SETTING_SIG(external_buffer_set_setting){
return(result);
}
BUFFER_SAVE_SIG(external_buffer_save){
SAVE_BUFFER_SIG(external_save_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
@ -670,6 +679,93 @@ BUFFER_SAVE_SIG(external_buffer_save){
return(result);
}
// TODO(allen): REPLACE THIS WITH CREATE_BUFFER!!!
CREATE_BUFFER_SIG(external_create_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
General_Memory *general = &models->mem.general;
Partition *part = &models->mem.part;
Buffer_Summary result = {0};
Temp_Memory temp = begin_temp_memory(part);
if (filename != 0){
String filename_string = make_string(filename, filename_len);
Editing_File *file = working_set_contains(system, working_set, filename_string);
if (file == 0){
File_Loading loading = system->file_load_begin(filename);
if (loading.exists){
b32 in_general_mem = false;
char *buffer = push_array(part, char, loading.size);
if (buffer == 0){
buffer = (char*)general_memory_allocate(general, loading.size);
if (buffer != 0){
in_general_mem = true;
}
}
if (system->file_load_end(loading, buffer)){
file = working_set_alloc_always(working_set, general);
if (file){
file_init_strings(file);
file_set_name(working_set, file, filename_string);
working_set_add(system, working_set, file, general);
init_normal_file(system, models, file,
buffer, loading.size);
fill_buffer_summary(&result, file, cmd);
}
}
if (in_general_mem){
general_memory_free(general, buffer);
}
}
else{
file = working_set_alloc_always(working_set, general);
if (file){
file_init_strings(file);
file_set_name(working_set, file, filename_string);
working_set_add(system, working_set, file, general);
init_normal_file(system, models, file, 0, 0);
fill_buffer_summary(&result, file, cmd);
}
}
}
else{
fill_buffer_summary(&result, file, cmd);
}
}
end_temp_memory(temp);
return(result);
}
KILL_BUFFER_SIG(external_kill_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
View *vptr = imp_get_view(cmd, view_id);
Editing_File *file = get_file_from_identifier(system, working_set, buffer);
int result = false;
if (file){
result = true;
if (always_kill){
kill_file(system, models, file, string_zero());
}
else{
try_kill_file(system, models, file, vptr, string_zero());
}
}
return(result);
}
GET_VIEW_FIRST_SIG(external_get_view_first){
Command_Data *cmd = (Command_Data*)app->cmd_context;
Editing_Layout *layout = &cmd->models->layout;
@ -913,69 +1009,6 @@ VIEW_GET_PASTE_REWRITE__SIG(external_view_get_paste_rewrite_){
return(result);
}
VIEW_OPEN_FILE_SIG(external_view_open_file){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
Live_Views *live_set = cmd->live_set;
int result = false;
// TODO(allen): do in background
// option happens in parallel.
Partition *part = &models->mem.part;
Temp_Memory temp = begin_temp_memory(part);
String string = make_string_terminated(part, filename, filename_len);
if (do_in_background){
result = true;
view_open_file(system, models, 0, string);
}
else if (view){
View *vptr = 0;
int view_id = view->view_id - 1;
if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id;
result = true;
view_open_file(system, models, 0, string);
fill_view_summary(view, vptr, live_set, working_set);
}
}
end_temp_memory(temp);
return(result);
}
VIEW_KILL_BUFFER_SIG(external_view_kill_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
View *vptr = imp_get_view(cmd, view);
Editing_File *file = 0;
int result = false;
if (vptr){
file = get_file_from_identifier(system, working_set, buffer);
if (file){
result = true;
try_kill_file(system, models, file, vptr, string_zero());
fill_view_summary(view, vptr, cmd);
}
}
return(result);
}
GET_USER_INPUT_SIG(external_get_user_input){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;

View File

@ -382,23 +382,22 @@ file_init_strings(Editing_File *file){
file->name.extension = make_fixed_width_string(file->name.extension_);
}
inline void
file_set_name(Working_Set *working_set, Editing_File *file, char *filename){
String f, ext;
internal void
file_set_name(Working_Set *working_set, Editing_File *file, String filename){
String ext;
Assert(file->name.live_name.str != 0);
f = make_string_slowly(filename);
copy_checked(&file->name.source_path, f);
copy_checked(&file->name.source_path, filename);
file->name.live_name.size = 0;
get_front_of_directory(&file->name.live_name, f);
get_front_of_directory(&file->name.live_name, filename);
if (file->name.source_path.size == file->name.live_name.size){
file->name.extension.size = 0;
}
else{
ext = file_extension(f);
ext = file_extension(filename);
copy(&file->name.extension, ext);
}
@ -435,6 +434,12 @@ file_set_name(Working_Set *working_set, Editing_File *file, char *filename){
}
}
inline void
file_set_name(Working_Set *working_set, Editing_File *file, char *filename){
String f = make_string_slowly(filename);
file_set_name(working_set, file, f);
}
inline void
file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){
u64 stamp = system->file_time_stamp(filename);
@ -613,19 +618,6 @@ file_measure_starts_widths(System_Functions *system, General_Memory *general,
buffer->widths_count = state.count;
}
struct Opaque_Font_Advance{
void *data;
int stride;
};
inline Opaque_Font_Advance
get_opaque_font_advance(Render_Font *font){
Opaque_Font_Advance result;
result.data = (char*)font->chardata + OffsetOfPtr(font->chardata, xadvance);
result.stride = sizeof(*font->chardata);
return result;
}
inline i32
view_wrapped_line_span(f32 line_width, f32 max_width){
i32 line_count = CEIL32(line_width / max_width);
@ -700,7 +692,8 @@ view_measure_wraps(General_Memory *general, View *view){
internal void
file_create_from_string(System_Functions *system, Models *models,
Editing_File *file, char *filename, String val, b8 read_only = 0){
Editing_File *file, char *name,
String val, b8 read_only = 0){
Font_Set *font_set = models->font_set;
Working_Set *working_set = &models->working_set;
@ -731,11 +724,12 @@ file_create_from_string(System_Functions *system, Models *models,
}
file_init_strings(file);
file_set_name(working_set, file, (char*)filename);
file_set_name(working_set, file, (char*)name);
file->state.font_id = models->global_font.font_id;
file_synchronize_times(system, file, filename);
file_synchronize_times(system, file, name);
Render_Font *font = get_font_info(font_set, file->state.font_id)->font;
float *advance_data = 0;
@ -5423,7 +5417,14 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
u32 char_color = main_color;
if (item->flags & BRFlag_Special_Character) char_color = special_color;
f32_Rect char_rect = f32R(item->x0, item->y0, item->x1, item->y1);
#if 0
i32_Rect char_rect = i32R(item->x0, item->y0,
item->x1, item->y1);
#else
f32_Rect char_rect = f32R(item->x0, item->y0,
item->x1, item->y1);
#endif
if (view->file_data.show_whitespace && highlight_color == 0 &&
char_is_whitespace((char)item->glyphid)){
highlight_this_color = style->main.highlight_white_color;

View File

@ -119,7 +119,10 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){
font__insert(&set->used_slots, slot);
Render_Font *font = (Render_Font*)(slot + 1);
set->font_load(font, info->filename.str, info->pt_size, 4, 1);
set->font_load(font,
info->filename.str,
info->name.str,
info->pt_size, 4, true);
info->font = font;
slot->font_id = font_id;
}
@ -182,7 +185,10 @@ font_set_add(Partition *partition, Font_Set *set,
info->filename = filename;
info->name = name;
info->pt_size = pt_size;
set->font_load(&dummy_font, info->filename.str, info->pt_size, 4, 0);
set->font_load(&dummy_font,
info->filename.str,
info->name.str,
info->pt_size, 4, false);
info->height = dummy_font.height;
info->advance = dummy_font.advance;

View File

@ -1,11 +1,11 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.17.2014
*
* Rendering layer for project codename "4ed"
*
*/
* Mr. 4th Dimention - Allen Webster
*
* 12.17.2014
*
* Rendering layer for project codename "4ed"
*
*/
// TOP
@ -90,7 +90,7 @@ draw_push_clip(Render_Target *target, i32_Rect clip_box){
fits_inside(clip_box, target->clip_boxes[target->clip_top]));
Assert(target->clip_top+1 < ArrayCount(target->clip_boxes));
target->clip_boxes[++target->clip_top] = clip_box;
draw_push_piece_clip(target, clip_box);
}
@ -114,14 +114,14 @@ inline void
private_draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){
draw_set_color(target, color);
draw_bind_texture(target, 0);
glBegin(GL_QUADS);
glBegin(GL_QUADS);
{
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
glEnd();
}
inline void
@ -152,7 +152,7 @@ private_draw_gradient(Render_Target *target, f32_Rect rect,
Vec4 cr = color_right;
draw_bind_texture(target, 0);
glBegin(GL_QUADS);
glBegin(GL_QUADS);
{
glColor4f(cl.r, cl.g, cl.b, cl.a);
glVertex2f(rect.x0, rect.y0);
@ -162,22 +162,59 @@ private_draw_gradient(Render_Target *target, f32_Rect rect,
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
glEnd();
}
struct Render_Quad{
f32 x0, y0, x1, y1;
f32 s0, t0, s1, t1;
};
inline Render_Quad
get_render_quad(Glyph_Data *b, int pw, int ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos + b->xoff;
q.y0 = ypos + b->yoff;
q.x1 = xpos + b->xoff2;
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline Render_Quad
get_exact_render_quad(Glyph_Data *b, int pw, int ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos;
q.y0 = ypos + b->yoff;
q.x1 = xpos + (b->xoff2 - b->xoff);
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline void
private_draw_glyph(Render_Target *target, Render_Font *font,
u8 character, f32 x, f32 y, u32 color){
f32 x_shift, y_shift;
x_shift = 0;
y_shift = (f32)font->ascent;
x += x_shift;
y += y_shift;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
character, &x, &y, &q, 0);
Render_Quad q = get_render_quad(
font->glyphs + character,
font->tex_width, font->tex_height, x, y
);
draw_set_color(target, color);
draw_bind_texture(target, font->tex);
@ -194,19 +231,18 @@ private_draw_glyph(Render_Target *target, Render_Font *font,
inline void
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
f32 x, f32 y, f32 advance, u32 color){
f32 x_shift, y_shift;
i32 left = font->chardata[character].x0;
i32 right = font->chardata[character].x1;
i32 width = (right - left);
x_shift = (f32)(advance - width) * .5f - font->chardata[character].xoff;
y_shift = (f32)font->ascent;
f32 left = font->glyphs[character].x0;
f32 right = font->glyphs[character].x1;
f32 width = (right - left);
f32 x_shift = (advance - width) * .5f;
x += x_shift;
y += y_shift;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
character, &x, &y, &q, 0);
Render_Quad q = get_exact_render_quad(
font->glyphs + character,
font->tex_width, font->tex_height, x, y
);
draw_set_color(target, color);
draw_bind_texture(target, font->tex);
@ -230,81 +266,98 @@ internal void
launch_rendering(Render_Target *target){
byte *cursor = target->push_buffer;
byte *cursor_end = cursor + target->size;
for (; cursor < cursor_end;){
Render_Piece_Header *header = ExtractStruct(Render_Piece_Header);
i32 type = header->type;
switch (type){
case piece_type_rectangle:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle(target, rectangle->rect, rectangle->color);
}break;
case piece_type_outline:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle_outline(target, rectangle->rect, rectangle->color);
}break;
case piece_type_gradient:
{
Render_Piece_Gradient *gradient =
ExtractStruct(Render_Piece_Gradient);
private_draw_gradient(target, gradient->rect,
unpack_color4(gradient->left_color),
unpack_color4(gradient->right_color));
}break;
case piece_type_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
case piece_type_rectangle:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle(target, rectangle->rect, rectangle->color);
}break;
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
case piece_type_outline:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle_outline(target, rectangle->rect, rectangle->color);
}break;
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph_advance:
{
Render_Piece_Glyph_Advance *glyph =
ExtractStruct(Render_Piece_Glyph_Advance);
case piece_type_gradient:
{
Render_Piece_Gradient *gradient =
ExtractStruct(Render_Piece_Gradient);
private_draw_gradient(target, gradient->rect,
unpack_color4(gradient->left_color),
unpack_color4(gradient->right_color));
}break;
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y,
glyph->advance, glyph->color);
}break;
case piece_type_change_clip:
{
Render_Piece_Change_Clip *clip =
ExtractStruct(Render_Piece_Change_Clip);
draw_set_clip(target, clip->box);
}break;
case piece_type_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph_advance:
{
Render_Piece_Glyph_Advance *glyph =
ExtractStruct(Render_Piece_Glyph_Advance);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y,
glyph->advance, glyph->color);
}break;
case piece_type_change_clip:
{
Render_Piece_Change_Clip *clip =
ExtractStruct(Render_Piece_Change_Clip);
draw_set_clip(target, clip->box);
}break;
}
}
}
#undef ExtractStruct
internal void*
part_alloc(int size, void *context){
Partition *part = (Partition*)context;
void *result = push_block(part, size);
return(result);
}
internal void
part_free(void *ptr, void *context){
}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
// TODO(allen): Put the burden of translation outside
// of this function (and other functions implementing
// the same interface).
@ -324,7 +377,7 @@ draw_font_load(Partition *part,
i32 result = 1;
stbtt_packedchar *chardata = font_out->chardata;
stbtt_packedchar chardata[256];
File_Data file = sysshared_load_file(filename.str);
@ -364,6 +417,7 @@ draw_font_load(Partition *part,
font_out->tex_width = tex_width;
font_out->tex_height = tex_height;
/////////////////////////////////////////////////////////////////
stbtt_pack_context spc;
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
@ -380,6 +434,7 @@ draw_font_load(Partition *part,
else{
result = 0;
}
/////////////////////////////////////////////////////////////////
if (result){
GLuint font_tex;
@ -395,21 +450,37 @@ draw_font_load(Partition *part,
font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' '];
font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width;
f32 *advance_data = font_out->advance_data;
Glyph_Data *glyphs = font_out->glyphs;
for (u8 code_point = 0; code_point < 128; ++code_point){
advance_data[code_point] = (f32)(CEIL32(chardata[code_point].xadvance));
glyphs[code_point].x0 = chardata[code_point].x0;
glyphs[code_point].y0 = chardata[code_point].y0;
glyphs[code_point].x1 = chardata[code_point].x1;
glyphs[code_point].y1 = chardata[code_point].y1;
glyphs[code_point].xoff = chardata[code_point].xoff;
glyphs[code_point].yoff = chardata[code_point].yoff + font_out->ascent;
glyphs[code_point].xoff2 = chardata[code_point].xoff2;
glyphs[code_point].yoff2 = chardata[code_point].yoff2 + font_out->ascent;
}
glyphs['\r'] = glyphs[' '];
advance_data['\r'] = advance_data[' '];
glyphs['\n'] = glyphs[' '];
advance_data['\n'] = advance_data[' '];
glyphs['\t'] = glyphs[' '];
advance_data['\t'] = advance_data[' ']*tab_width;
i32 max_advance = 0;
for (u8 code_point = 0; code_point < 128; ++code_point){
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
font_out->glyphs[code_point].exists = 1;
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
if (max_advance < advance) max_advance = advance;
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
}
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
i32 advance = CEIL32(advance_data[code_point]);
if (max_advance < advance){
max_advance = advance;
}
}
}
font_out->advance = max_advance - 1;

View File

@ -12,25 +12,14 @@
#ifndef FRED_RENDERING_H
#define FRED_RENDERING_H
internal void*
part_alloc(int size, void *context){
Partition *part = (Partition*)context;
void *result = push_block(part, size);
return(result);
}
internal void
part_free(void *ptr, void *context){
}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
struct Glyph_Data{
b32 exists;
f32 x0, x1;
f32 y0, y1;
f32 xoff, yoff;
f32 xoff2, yoff2;
};
struct Render_Font{
@ -38,8 +27,10 @@ struct Render_Font{
String name;
b32 loaded;
// TODO(allen): Have our own type here instead
// of stbtt_packedchar, and have both stb fonts
// and OS fonts go to our type.
Glyph_Data glyphs[256];
stbtt_packedchar chardata[256];
float advance_data[256];
i32 height, ascent, descent, line_skip;
i32 advance;
@ -114,6 +105,7 @@ typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
#define Font_Load_Sig(name) i32 name( \
Render_Font *font_out, \
char *filename, \
char *fontname, \
i32 pt_size, \
i32 tab_width, \
b32 store_texture)

View File

@ -115,11 +115,6 @@ font_predict_size(i32 pt_size){
return pt_size*pt_size*128;
}
internal void
font_set_tabwidth(Render_Font *font, i32 tab_width){
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
}
internal void
font_draw_glyph_mono(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, f32 advance, u32 color){
@ -155,117 +150,95 @@ font_draw_glyph(Render_Target *target, i16 font_id,
font_set_use(target->partition, &target->font_set, font_id);
}
inline f32
font_get_glyph_width(Render_Target *target, i16 font_id, u16 character){
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 result = 0.f;
if (font) result = font->chardata[character].xadvance;
return (result);
}
// TODO(allen): Someday let's not punt on the the unicode rendering
internal f32
font_string_width(Render_Target *target, i16 font_id, char *str){
f32 x = 0;
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i] % 128;
x += advance_data[c];
}
}
return x;
return(x);
}
internal f32
font_string_width(Render_Target *target, i16 font_id, String str){
f32 x = 0;
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i] % 128;
x += advance_data[c];
}
}
return x;
return(x);
}
internal f32
draw_string(Render_Target *target, i16 font_id,
char *str, i32 x_, i32 y, u32 color){
real32 x = (real32)x_;
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c);
f32 x = (f32)x_;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i] % 128;
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += advance_data[c];
}
}
return x;
return(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id,
char *str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
u8 c = str[i] % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return x;
return(x);
}
internal f32
draw_string(Render_Target *target, i16 font_id,
String str, i32 x_, i32 y, u32 color){
f32 x = (f32)x_;
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph(target, font_id, c,
x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c);
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i] % 128;
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += advance_data[c];
}
}
return x;
return(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id,
String str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
u8 c = str.str[i] % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return x;
}
internal f32
font_get_max_width(Font_Set *font_set, i16 font_id, char *characters){
Render_Font *font = get_font_info(font_set, font_id)->font;
f32 cx, x = 0;
if (font){
stbtt_packedchar *chardata = font->chardata;
for (i32 i = 0; characters[i]; ++i){
cx = chardata[characters[i]].xadvance;
if (x < cx) x = cx;
}
}
return x;
}
internal f32
font_get_string_width(Render_Target *target, i16 font_id, String string){
f32 result = 0;
for (i32 i = 0; i < string.size; ++i){
u8 c = string.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_get_glyph_width(target, font_id, c);
}
return result;
return(x);
}
// BOTTOM

View File

@ -31,7 +31,9 @@ int Buffer_Replace_Range(Application_Links *app, Buffer_Summary *buffer, int sta
int Buffer_Seek(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags);
int Buffer_Set_Setting(Application_Links *app, Buffer_Summary *buffer, int setting, int value);
int Buffer_Save(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len);
Buffer_Summary Create_Buffer(Application_Links *app, char *filename, int filename_len, int do_in_background);
int Save_Buffer(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len);
int Kill_Buffer(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id);
// View manipulation
View_Summary Get_View_First(Application_Links *app);
@ -57,10 +59,6 @@ int View_Post_Fade(Application_Links *app, View_Summary *view, int ticks, int st
void View_Set_Paste_Rewrite_(Application_Links *app, View_Summary *view);
int View_Get_Paste_Rewrite_(Application_Links *app, View_Summary *view);
// TODO(allen): Make sure this is just right.
int View_Open_File(Application_Links *app, View_Summary *view, char *filename, int filename_len, int do_in_background);
int View_Kill_Buffer(Application_Links *app, View_Summary *view, Buffer_Identifier buffer);
// Directly get user input
User_Input Get_User_Input(Application_Links *app, unsigned int get_type, unsigned int abort_type);
User_Input Get_Command_Input(Application_Links *app);

View File

@ -520,7 +520,8 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf
#endif
// NOTE(allen): This opens the file and puts it in &view
app->view_open_file(app, &view, expand_str(FileName), false);
// This returns false if the open fails.
view_open_file(app, &view, expand_str(FileName), false);
Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size);
@ -655,7 +656,7 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking)
exec_command(app, cmdid_save);
#endif
app->buffer_save(app, &buffer, buffer.file_name, buffer.file_name_len);
app->save_buffer(app, &buffer, buffer.file_name, buffer.file_name_len);
}
#if 0
@ -1153,7 +1154,7 @@ OpenProject(Application_Links *app, char *ProjectFileName)
exec_command(app, cmdid_interactive_open);
#endif
app->view_open_file(app, 0, dir.str, dir.size, true);
view_open_file(app, 0, dir.str, dir.size, true);
++TotalOpenAttempts;
}
}

View File

@ -1177,6 +1177,7 @@ Font_Load_Sig(system_draw_font_load){
success = win32_draw_font_load(&win32vars.font_part,
font_out,
filename,
fontname,
pt_size,
tab_width,
oversample,

View File

@ -9,25 +9,36 @@
// TOP
struct Glyph_Bitmap{
HBITMAP bitmap_handle;
char *pixels;
struct GMetrics{
f32 advance;
f32 xoff;
f32 xoff2;
};
void
win32_get_box(HDC dc, TCHAR character, int *x0, int *y0, int *x1, int *y1){
SIZE size;
GetTextExtentPoint32A(dc, &character, 1, &size);
*x0 = 0;
*y0 = 0;
*x1 = size.cx;
*y1 = size.cy;
internal b32
win32_glyph_metrics(HDC dc, int code, GMetrics *gmetrics){
b32 result = false;
ABCFLOAT abc = {0};
INT width;
if (GetCharWidth32W(dc, code, code, &width)){
gmetrics->advance = (f32)width;
if (GetCharABCWidthsFloat(dc, code, code, &abc)){
gmetrics->xoff = abc.abcfA;
gmetrics->xoff2 = (abc.abcfA + abc.abcfB);
result = true;
}
}
return(result);
}
internal i32
win32_draw_font_load(Partition *part,
Render_Font *font_out,
char *filename_untranslated,
char *fontname,
i32 pt_size,
i32 tab_width,
i32 oversample,
@ -36,77 +47,127 @@ win32_draw_font_load(Partition *part,
char space_[1024];
String filename = make_fixed_width_string(space_);
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
if (!translate_success) return 0;
i32 result = 0;
AddFontResourceEx(filename.str, FR_PRIVATE, 0);
HFONT font_handle =
CreateFontA(pt_size, 0, 0, 0,
FW_NORMAL, // WEIGHT
FALSE, // ITALICS
FALSE, // UNDERLINE
FALSE, // STRIKE-OUT
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
filename.str);
if (font_handle){
HDC dc = CreateCompatibleDC(0);
if (translate_success){
HDC dc = GetDC(win32vars.window_handle);
if (dc){
TEXTMETRIC metrics;
GetTextMetrics(dc, &metrics);
font_out->height = metrics.tmHeight + metrics.tmExternalLeading;
font_out->ascent = metrics.tmAscent;
font_out->descent = -metrics.tmDescent;
font_out->line_skip = metrics.tmExternalLeading;
font_out->advance = metrics.tmMaxCharWidth;
AddFontResourceEx(filename.str, FR_PRIVATE, 0);
HFONT font_handle = CreateFont(
pt_size,
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_DONTCARE | DEFAULT_PITCH,
fontname
);
HBITMAP bmp_handle = CreateBitmap(
pt_size*2, pt_size*2,
4, 32,
0
);
if (font_handle != 0 && bmp_handle != 0){
SelectObject(dc, font_handle);
SelectObject(dc, bmp_handle);
result = 1;
if (store_texture){
Temp_Memory temp = begin_temp_memory(part);
memset(font_out, 0, sizeof(*font_out));
TEXTMETRIC metric;
if (GetTextMetrics(dc, &metric)){
i32 tex_width = pt_size*16*oversample;
i32 tex_height = pt_size*16*oversample;
font_out->height = (i32)(metric.tmHeight + metric.tmExternalLeading);
font_out->ascent = (i32)(metric.tmAscent);
font_out->descent = (i32)(metric.tmDescent);
font_out->line_skip = (i32)(metric.tmExternalLeading);
Glyph_Bitmap glyph_bitmap;
glyph_bitmap.bitmap_handle = CreateCompatibleBitmap(dc, tex_width, tex_height);
glyph_bitmap.pixels = push_array(part, char, tex_width*tex_height);
SelectObject(dc, glyph_bitmap.bitmap_handle);
SelectObject(dc, font_handle);
SetBkColor(dc, RGB(0, 0, 0));
stbtt_pack_context context = {0};
stbtt_PackBegin(&context, (unsigned char*)glyph_bitmap.pixels, tex_width, tex_height, 0, 1, part);
{
stbtt_pack_context *spc = &context;
int first_unicode_char_in_range = 0;
int num_chars_in_range = 128;
stbtt_packedchar *chardata_for_range = font_out->chardata;
if (!store_texture){
result = 1;
}
else{
Temp_Memory temp = begin_temp_memory(part);
i32 tex_width = pt_size*16;
i32 tex_height = pt_size*16;
void *block = sysshared_push_block(part, tex_width * tex_height);
font_out->tex_width = tex_width;
font_out->tex_height = tex_height;
result = 1;
/////////////////////////////////////////////////////////////////
stbtt_pack_context spc_;
int pack_result;
{
stbtt_pack_range range;
range.first_unicode_char_in_range = first_unicode_char_in_range;
range.num_chars_in_range = num_chars_in_range;
range.chardata_for_range = chardata_for_range;
stbtt_pack_context *spc = &spc_;
unsigned char *pixels = (u8*)block;
int pw = tex_width;
int ph = tex_height;
int stride_in_bytes = tex_width;
int padding = 1;
void *alloc_context = part;
{
stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
int num_nodes = pw - padding;
stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
if (context == NULL || nodes == NULL) {
if (context != NULL) STBTT_free(context, alloc_context);
if (nodes != NULL) STBTT_free(nodes , alloc_context);
pack_result = 0;
goto packbegin_end;
}
spc->user_allocator_context = alloc_context;
spc->width = pw;
spc->height = ph;
spc->pixels = pixels;
spc->pack_info = context;
spc->nodes = nodes;
spc->padding = padding;
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
spc->h_oversample = 1;
spc->v_oversample = 1;
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
pack_result = 1;
goto packbegin_end;
}
}
packbegin_end:;
if (pack_result){
int pack_font_range_result;
{
stbtt_pack_range range;
range.first_unicode_char_in_range = 0;
range.num_chars_in_range = 128;
range.chardata_for_range = font_out->chardata;
range.font_size = STBTT_POINT_SIZE((f32)pt_size);
stbtt_pack_context *spc = &spc_;
stbtt_pack_range *ranges = &range;
int num_ranges = 1;
{
float recip_h = 1.0f / spc->h_oversample;
float recip_v = 1.0f / spc->v_oversample;
float sub_x = stbtt__oversample_shift(spc->h_oversample);
float sub_y = stbtt__oversample_shift(spc->v_oversample);
int i,j,k,n, return_value = 1;
stbrp_context *context = (stbrp_context *) spc->pack_info;
stbrp_rect *rects;
@ -124,19 +185,32 @@ win32_draw_font_load(Partition *part,
n += ranges[i].num_chars_in_range;
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL)
return 0;
if (rects == NULL){
pack_font_range_result = 0;
goto pack_font_range_end;
}
//info.userdata = spc->user_allocator_context;
//stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
k=0;
for (i=0; i < num_ranges; ++i) {
//float fh = ranges[i].font_size;
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
int x0,y0,x1,y1;
int w,h;
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j);
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
GMetrics gmetrics;
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
if (!win32_glyph_metrics(dc, ranges[i].first_unicode_char_in_range + j, &gmetrics)){
result = 0;
break;
}
w = CEIL32(gmetrics.xoff2 - gmetrics.xoff);
h = font_out->ascent + font_out->descent;
rects[k].w = (stbrp_coord) (w + spc->padding);
rects[k].h = (stbrp_coord) (h + spc->padding);
++k;
}
}
@ -145,47 +219,65 @@ win32_draw_font_load(Partition *part,
k = 0;
for (i=0; i < num_ranges; ++i) {
//float fh = ranges[i].font_size;
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
stbrp_rect *r = &rects[k];
if (r->was_packed) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, x0,y0,x1,y1;
int glyph = ranges[i].first_unicode_char_in_range + j;
//int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
int code = ranges[i].first_unicode_char_in_range + j;
stbrp_coord pad = (stbrp_coord) spc->padding;
GetCharWidth32W(dc, glyph, glyph, &advance);
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j);
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
// pad on left and top
r->x += pad;
r->y += pad;
r->w -= pad;
r->h -= pad;
SetTextColor(dc, RGB(255, 255, 255));
TextOutA(dc, r->x, r->y, &character, 1);
#if 0
int advance, lsb, x0,y0,x1,y1;
if (spc->h_oversample > 1)
stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w, r->h, spc->stride_in_bytes,
spc->h_oversample);
stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
stbtt_GetGlyphBitmapBox(&info, glyph,
scale * spc->h_oversample,
scale * spc->v_oversample,
&x0,&y0,&x1,&y1);
stbtt_MakeGlyphBitmapSubpixel(&info,
spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w - spc->h_oversample+1,
r->h - spc->v_oversample+1,
spc->stride_in_bytes,
scale * spc->h_oversample,
scale * spc->v_oversample,
0,0,
glyph);
#else
float advance, x0, y0, x1, y1;
if (spc->v_oversample > 1)
stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w, r->h, spc->stride_in_bytes,
spc->v_oversample);
GMetrics gmetrics;
if (!win32_glyph_metrics(dc, code, &gmetrics)){
result = false;
break;
}
advance = gmetrics.advance;
x0 = gmetrics.xoff;
y0 = -font_out->ascent;
x1 = gmetrics.xoff2;
y1 = font_out->descent;
#endif
bc->x0 = (stbtt_int16) r->x;
bc->y0 = (stbtt_int16) r->y;
bc->x1 = (stbtt_int16) (r->x + r->w);
bc->y1 = (stbtt_int16) (r->y + r->h);
bc->xadvance = (float) advance;
bc->xoff = (float) x0 * recip_h + sub_x;
bc->yoff = (float) y0 * recip_v + sub_y;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
bc->xadvance = (float) advance;
bc->xoff = (float) x0;
bc->yoff = (float) y0;
bc->xoff2 = (float) (x0 + r->w);
bc->yoff2 = (float) (y0 + r->h);
} else {
return_value = 0; // if any fail, report failure
}
@ -195,40 +287,68 @@ win32_draw_font_load(Partition *part,
}
STBTT_free(rects, spc->user_allocator_context);
result = return_value;
if (return_value){
GLuint font_tex;
glGenTextures(1, &font_tex);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph_bitmap.pixels);
font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' '];
font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width;
}
pack_font_range_result = return_value;
goto pack_font_range_end;
}
}
pack_font_range_end:;
if (!pack_font_range_result){
result = 0;
}
{
stbtt_pack_context *spc = &spc_;
{
STBTT_free(spc->nodes , spc->user_allocator_context);
STBTT_free(spc->pack_info, spc->user_allocator_context);
}
}
}
else{
result = 0;
}
/////////////////////////////////////////////////////////////////
if (result){
GLuint font_tex;
glGenTextures(1, &font_tex);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
memset(block, 0xFF, tex_width*tex_height);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' '];
font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width;
for (u8 code_point = 0; code_point < 128; ++code_point){
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
}
i32 max_advance = metric.tmMaxCharWidth;
font_out->advance = max_advance - 1;
}
end_temp_memory(temp);
}
stbtt_PackEnd(&context);
end_temp_memory(temp);
}
DeleteObject(font_handle);
DeleteObject(bmp_handle);
}
DeleteObject(font_handle);
ReleaseDC(win32vars.window_handle, dc);
}
return(result);