rejigged font system, and rewrote code dealing with fonts
This commit is contained in:
parent
16b11c593a
commit
d5ab8eafdc
|
@ -1,6 +1,6 @@
|
|||
#define MAJOR 4
|
||||
#define MINOR 0
|
||||
#define PATCH 17
|
||||
#define PATCH 18
|
||||
|
||||
#define VN__(a,b,c) #a"."#b"."#c
|
||||
#define VN_(a,b,c) VN__(a,b,c)
|
||||
|
|
|
@ -487,10 +487,12 @@ CUSTOM_COMMAND_SIG(execute_arbitrary_command){
|
|||
else if (match_ss(bar.string, make_lit_string("open menu"))){
|
||||
exec_command(app, cmdid_open_menu);
|
||||
}
|
||||
else if (match_ss(bar.string, make_lit_string("dos lines"))){
|
||||
else if (match_ss(bar.string, make_lit_string("dos lines")) ||
|
||||
match_ss(bar.string, make_lit_string("dosify"))){
|
||||
exec_command(app, eol_dosify);
|
||||
}
|
||||
else if (match_ss(bar.string, make_lit_string("nix lines"))){
|
||||
else if (match_ss(bar.string, make_lit_string("nix lines")) ||
|
||||
match_ss(bar.string, make_lit_string("nixify"))){
|
||||
exec_command(app, eol_nixify);
|
||||
}
|
||||
else{
|
||||
|
|
2
4ed.cpp
2
4ed.cpp
|
@ -1507,7 +1507,7 @@ App_Init_Sig(app_init){
|
|||
String file_name = make_string(font_setup[i].c_file_name, font_setup[i].file_name_len);
|
||||
String name = make_string(font_setup[i].c_name, font_setup[i].name_len);
|
||||
i32 pt_size = font_setup[i].pt_size;
|
||||
font_set_add(partition, models->font_set, file_name, name, pt_size);
|
||||
font_set_add(models->font_set, file_name, name, pt_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -878,8 +878,9 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
}
|
||||
if (new_value != file->settings.display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
file_set_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
Font_Info *font_info = get_font_info(models->font_set, font_id);
|
||||
Render_Font *font = font_info->font;
|
||||
file_set_width(models, file, new_value, font);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -892,7 +893,7 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
if (new_value != file->settings.minimum_base_display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
file_set_min_base_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_set_min_base_width(models, file, new_value, font);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -981,7 +982,7 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
|
||||
file_allocate_character_starts_as_needed(&models->mem.general, file);
|
||||
buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_measure_wraps(models, file, font);
|
||||
file_update_cursor_positions(models, file);
|
||||
}
|
||||
}break;
|
||||
|
|
|
@ -395,9 +395,7 @@ view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){
|
|||
Buffer_Cursor_Seek_Params params;
|
||||
params.buffer = &file->state.buffer;
|
||||
params.seek = seek;
|
||||
params.font_height = (f32)font->height;
|
||||
params.cp_adv = font->codepoint_advance_data;
|
||||
params.byte_adv = font->byte_advance;
|
||||
params.font = font;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.character_starts = file->state.character_starts;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
|
@ -1011,15 +1009,14 @@ struct Code_Wrap_State{
|
|||
i32 size;
|
||||
i32 i;
|
||||
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
Render_Font *font;
|
||||
f32 tab_indent_amount;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
};
|
||||
|
||||
internal void
|
||||
wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byte_adv){
|
||||
wrap_state_init(Code_Wrap_State *state, Editing_File *file, Render_Font *font){
|
||||
state->token_array = file->state.token_array;
|
||||
state->token_ptr = state->token_array.tokens;
|
||||
state->end_token = state->token_ptr + state->token_array.count;
|
||||
|
@ -1033,9 +1030,8 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byt
|
|||
state->size = size;
|
||||
state->i = 0;
|
||||
|
||||
state->cp_adv = cp_adv;
|
||||
state->byte_adv = byte_adv;
|
||||
state->tab_indent_amount = cp_adv['\t'];
|
||||
state->font = font;
|
||||
state->tab_indent_amount = get_codepoint_advance(font, '\t');
|
||||
|
||||
state->tran = null_buffer_translating_state;
|
||||
}
|
||||
|
@ -1147,13 +1143,13 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){
|
|||
u32 n = state->tran.step_current.value;
|
||||
f32 adv = 0;
|
||||
if (state->tran.do_codepoint_advance){
|
||||
adv = state->cp_adv[n];
|
||||
adv = get_codepoint_advance(state->font, n);
|
||||
if (n != ' ' && n != '\t'){
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
adv = state->byte_adv;
|
||||
adv = state->font->byte_advance;
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
|
||||
|
@ -1450,7 +1446,7 @@ get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start, b32 *adjust_
|
|||
}
|
||||
|
||||
internal void
|
||||
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){
|
||||
General_Memory *general = &models->mem.general;
|
||||
Partition *part = &models->mem.part;
|
||||
|
||||
|
@ -1463,8 +1459,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
Buffer_Measure_Wrap_Params params;
|
||||
params.buffer = &file->state.buffer;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.cp_adv = cp_adv;
|
||||
params.byte_adv = byte_adv;
|
||||
params.font = font;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
|
||||
f32 width = (f32)file->settings.display_width;
|
||||
|
@ -1496,7 +1491,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
i32 max_wrap_indent_mark = 0;
|
||||
|
||||
if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){
|
||||
wrap_state_init(&wrap_state, file, cp_adv, byte_adv);
|
||||
wrap_state_init(&wrap_state, file, font);
|
||||
use_tokens = 1;
|
||||
|
||||
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width));
|
||||
|
@ -1548,7 +1543,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
word_stage = 1;
|
||||
}
|
||||
else{
|
||||
f32 adv = params.cp_adv[ch];
|
||||
f32 adv = get_codepoint_advance(params.font, ch);
|
||||
x += adv;
|
||||
self_x += adv;
|
||||
if (self_x > width){
|
||||
|
@ -1675,7 +1670,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
goto doublebreak_stage1;
|
||||
}
|
||||
|
||||
f32 adv = params.cp_adv[ch];
|
||||
f32 adv = get_codepoint_advance(params.font, ch);
|
||||
x += adv;
|
||||
if (!first_word && x > current_width){
|
||||
emit_comment_position = 1;
|
||||
|
@ -1701,7 +1696,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
goto doublebreak_stage2;
|
||||
}
|
||||
|
||||
f32 adv = params.cp_adv[ch];
|
||||
f32 adv = get_codepoint_advance(params.font, ch);
|
||||
x += adv;
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
|
@ -1908,21 +1903,21 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_
|
|||
}
|
||||
|
||||
internal void
|
||||
file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file_measure_wraps(models, file, font_height, cp_adv, byte_adv);
|
||||
file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, Render_Font *font){
|
||||
file_measure_wraps(models, file, font);
|
||||
file_update_cursor_positions(models, file);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_set_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file_set_width(Models *models, Editing_File *file, i32 display_width, Render_Font *font){
|
||||
file->settings.display_width = display_width;
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
|
||||
file_measure_wraps_and_fix_cursor(models, file, font);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_set_min_base_width(Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file_set_min_base_width(Models *models, Editing_File *file, i32 minimum_base_display_width, Render_Font *font){
|
||||
file->settings.minimum_base_display_width = minimum_base_display_width;
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
|
||||
file_measure_wraps_and_fix_cursor(models, file, font);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1971,7 +1966,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
file->settings.font_id = font_id;
|
||||
Render_Font *font = get_font_info(font_set, font_id)->font;
|
||||
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_measure_wraps(models, file, font);
|
||||
|
||||
file->settings.read_only = read_only;
|
||||
if (!read_only){
|
||||
|
@ -3269,12 +3264,10 @@ file_do_single_edit(System_Functions *system, Models *models, Editing_File *file
|
|||
// TODO(allen): Redo this as some sort of dialogical API
|
||||
#if 0
|
||||
file_allocate_wraps_as_needed(general, file);
|
||||
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift,
|
||||
file->state.wraps, (f32)font->height, font->advance_data,
|
||||
(f32)file->settings.display_width);
|
||||
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift, file->state.wraps, (f32)font->height, font->advance_data, (f32)file->settings.display_width);
|
||||
#endif
|
||||
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_measure_wraps(models, file, font);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
Cursor_Fix_Descriptor desc = {0};
|
||||
|
@ -3388,7 +3381,7 @@ file_do_batch_edit(System_Functions *system, Models *models, Editing_File *file,
|
|||
buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
|
||||
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_measure_wraps(models, file, font);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
Cursor_Fix_Descriptor desc = {0};
|
||||
|
@ -3667,8 +3660,9 @@ style_get_color(Style *style, Cpp_Token token){
|
|||
internal void
|
||||
file_set_font(Models *models, Editing_File *file, i16 font_id){
|
||||
file->settings.font_id = font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
|
||||
file_measure_wraps_and_fix_cursor(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
Font_Info *font_info = get_font_info(models->font_set, file->settings.font_id);
|
||||
Render_Font *font = font_info->font;
|
||||
file_measure_wraps_and_fix_cursor(models, file, font);
|
||||
|
||||
Editing_Layout *layout = &models->layout;
|
||||
for (View_Iter iter = file_view_iter_init(layout, file, 0);
|
||||
|
@ -5959,9 +5953,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
|
|||
params.height = (f32)max_y;
|
||||
params.start_cursor = render_cursor;
|
||||
params.wrapped = wrapped;
|
||||
params.font_height = (f32)line_height;
|
||||
params.cp_adv = font->codepoint_advance_data;
|
||||
params.byte_adv = font->byte_advance;
|
||||
params.font = font;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
params.wrap_slashes = file->settings.wrap_indicator;
|
||||
|
||||
|
@ -6173,12 +6165,10 @@ draw_text_with_cursor(Render_Target *target, View *view, i16 font_id, i32_Rect r
|
|||
part2 = substr(s, pos, 1);
|
||||
part3 = substr(s, pos+1, s.size-pos-1);
|
||||
|
||||
|
||||
x = draw_string(target, font_id, part1, floor32(x), y, text_color);
|
||||
|
||||
// TODO(allen): WHAT TO DO NOW?
|
||||
cursor_rect.x0 = floor32(x);
|
||||
cursor_rect.x1 = floor32(x) + ceil32(font->codepoint_advance_data[s.str[pos]]);
|
||||
cursor_rect.x1 = floor32(x) + ceil32(get_codepoint_advance(font, s.str[pos]));
|
||||
cursor_rect.y0 = y;
|
||||
cursor_rect.y1 = y + view->line_height;
|
||||
draw_rectangle(target, cursor_rect, cursor_color);
|
||||
|
@ -6385,8 +6375,7 @@ draw_button(GUI_Target *gui_target, Render_Target *target, View *view, i16 font_
|
|||
}
|
||||
|
||||
internal void
|
||||
draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view,
|
||||
i16 font_id, i32_Rect rect, GUI_id id, Style *style){
|
||||
draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view, i16 font_id, i32_Rect rect, GUI_id id, Style *style){
|
||||
Models *models = view->persistent.models;
|
||||
|
||||
i32 active_level = gui_active_level(gui_target, id);
|
||||
|
@ -6412,8 +6401,9 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view,
|
|||
draw_string(target, font_id, info->name.str, font_x, y, text_color);
|
||||
}
|
||||
|
||||
i32 height = info->font->height;
|
||||
x = inner.x0;
|
||||
y += info->height;
|
||||
y += height;
|
||||
x = ceil32(draw_string(target, font_id, "if", x, y, keyword_color));
|
||||
x = ceil32(draw_string(target, font_id, "(x < ", x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, "0", x, y, int_constant_color));
|
||||
|
@ -6423,7 +6413,7 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view,
|
|||
x = ceil32(draw_string(target, font_id, "// comment", x, y, comment_color));
|
||||
|
||||
x = inner.x0;
|
||||
y += info->height;
|
||||
y += height;
|
||||
draw_string(target, font_id, "[] () {}; * -> +-/ <>= ! && || % ^", x, y, text_color);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ font_set_can_load(Font_Set *set){
|
|||
}
|
||||
|
||||
internal void
|
||||
font_set_load(Partition *partition, Font_Set *set, i16 font_id){
|
||||
font_set_load(Font_Set *set, i16 font_id){
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Font_Slot *slot = set->free_slots.next;
|
||||
Assert(slot != &set->free_slots);
|
||||
|
@ -119,10 +119,7 @@ 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->name.str,
|
||||
info->pt_size, 4, true);
|
||||
set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true);
|
||||
info->font = font;
|
||||
slot->font_id = font_id;
|
||||
}
|
||||
|
@ -145,7 +142,7 @@ font_set_evict_lru(Font_Set *set){
|
|||
}
|
||||
|
||||
internal void
|
||||
font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
||||
font_set_use(Font_Set *set, i16 font_id){
|
||||
b8 already_used = set->font_used_flags[font_id-1];
|
||||
|
||||
if (!already_used){
|
||||
|
@ -164,7 +161,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
|||
if (!font_set_can_load(set)){
|
||||
font_set_evict_lru(set);
|
||||
}
|
||||
font_set_load(partition, set, font_id);
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
slot = ((Font_Slot*)info->font) - 1;
|
||||
|
||||
|
@ -174,7 +171,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
|||
}
|
||||
|
||||
internal b32
|
||||
font_set_add(Partition *partition, Font_Set *set, String filename, String name, i32 pt_size){
|
||||
font_set_add(Font_Set *set, String filename, String name, i32 pt_size){
|
||||
b32 result = 0;
|
||||
if (font_set_can_add(set)){
|
||||
Render_Font dummy_font = {0};
|
||||
|
@ -184,13 +181,13 @@ font_set_add(Partition *partition, Font_Set *set, String filename, String name,
|
|||
info->name = name;
|
||||
info->pt_size = pt_size;
|
||||
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;
|
||||
//info->height = dummy_font.height;
|
||||
//info->advance = dummy_font.advance;
|
||||
|
||||
font_set_add_hash(set, name, font_id);
|
||||
|
||||
if (font_set_can_load(set)){
|
||||
font_set_load(partition, set, font_id);
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
|
||||
result = 1;
|
||||
|
|
120
4ed_rendering.h
120
4ed_rendering.h
|
@ -12,30 +12,58 @@
|
|||
#ifndef FRED_RENDERING_H
|
||||
#define FRED_RENDERING_H
|
||||
|
||||
struct Glyph_Data{
|
||||
b32 exists;
|
||||
|
||||
f32 x0, x1;
|
||||
f32 y0, y1;
|
||||
|
||||
f32 xoff, yoff;
|
||||
f32 xoff2, yoff2;
|
||||
//
|
||||
// Fonts
|
||||
//
|
||||
|
||||
#include "file/4coder_font_data.h"
|
||||
|
||||
struct Font_Table_Entry{
|
||||
u32 hash;
|
||||
String name;
|
||||
i16 font_id;
|
||||
};
|
||||
|
||||
struct Render_Font{
|
||||
char name_[24];
|
||||
struct Font_Info{
|
||||
Render_Font *font;
|
||||
String filename;
|
||||
String name;
|
||||
b32 loaded;
|
||||
|
||||
Glyph_Data glyphs[256];
|
||||
f32 byte_advance;
|
||||
f32 codepoint_advance_data[256];
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
i32 pt_size;
|
||||
};
|
||||
|
||||
struct Font_Slot{
|
||||
Font_Slot *next, *prev;
|
||||
i16 font_id;
|
||||
u8 padding[6];
|
||||
};
|
||||
|
||||
#define Font_Load_Sig(name) i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||
typedef Release_Font_Sig(Release_Font);
|
||||
|
||||
struct Font_Set{
|
||||
Font_Info *info;
|
||||
Font_Table_Entry *entries;
|
||||
u32 count, max;
|
||||
|
||||
void *font_block;
|
||||
Font_Slot free_slots;
|
||||
Font_Slot used_slots;
|
||||
|
||||
Font_Load *font_load;
|
||||
Release_Font *release_font;
|
||||
|
||||
b8 *font_used_flags;
|
||||
i16 used_this_frame;
|
||||
i16 live_max;
|
||||
};
|
||||
|
||||
//
|
||||
// Render Commands
|
||||
//
|
||||
|
||||
enum Render_Piece_Type{
|
||||
piece_type_rectangle,
|
||||
piece_type_outline,
|
||||
|
@ -101,49 +129,9 @@ typedef Draw_Pop_Clip_Sig(Draw_Pop_Clip);
|
|||
#define Draw_Push_Piece_Sig(name) void name(Render_Target *target, Render_Piece_Combined piece)
|
||||
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)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||
typedef Release_Font_Sig(Release_Font);
|
||||
|
||||
struct Font_Table_Entry{
|
||||
u32 hash;
|
||||
String name;
|
||||
i16 font_id;
|
||||
};
|
||||
|
||||
struct Font_Info{
|
||||
Render_Font *font;
|
||||
String filename;
|
||||
String name;
|
||||
i32 height, advance;
|
||||
i32 pt_size;
|
||||
};
|
||||
|
||||
struct Font_Slot{
|
||||
Font_Slot *next, *prev;
|
||||
i16 font_id;
|
||||
u8 padding[14];
|
||||
};
|
||||
|
||||
struct Font_Set{
|
||||
Font_Info *info;
|
||||
Font_Table_Entry *entries;
|
||||
u32 count, max;
|
||||
|
||||
void *font_block;
|
||||
Font_Slot free_slots;
|
||||
Font_Slot used_slots;
|
||||
|
||||
//Font_Info_Load *font_info_load;
|
||||
Font_Load *font_load;
|
||||
Release_Font *release_font;
|
||||
|
||||
b8 *font_used_flags;
|
||||
i16 used_this_frame;
|
||||
i16 live_max;
|
||||
};
|
||||
//
|
||||
// Render target stuff
|
||||
//
|
||||
|
||||
struct Render_Target{
|
||||
void *handle;
|
||||
|
@ -159,13 +147,13 @@ struct Render_Target{
|
|||
char *push_buffer;
|
||||
i32 size, max;
|
||||
|
||||
// TODO(allen): rename this to font_partition
|
||||
Font_Set font_set;
|
||||
Partition *partition;
|
||||
|
||||
Draw_Push_Clip *push_clip;
|
||||
Draw_Pop_Clip *pop_clip;
|
||||
Draw_Push_Piece *push_piece;
|
||||
|
||||
// TODO(allen): Does the font set really belong here? Actually, do we still want it at all?
|
||||
Font_Set font_set;
|
||||
Partition *partition;
|
||||
};
|
||||
|
||||
#define DpiMultiplier(n,dpi) ((n) * (dpi) / 96)
|
||||
|
|
|
@ -125,7 +125,7 @@ font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32
|
|||
piece.glyph.font_id = font_id;
|
||||
piece.glyph.character = character;
|
||||
target->push_piece(target, piece);
|
||||
font_set_use(target->partition, &target->font_set, font_id);
|
||||
font_set_use(&target->font_set, font_id);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -135,7 +135,8 @@ font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y,
|
|||
|
||||
internal f32
|
||||
draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
Font_Info *font_info = get_font_info(&target->font_set, font_id);
|
||||
Render_Font *font = font_info->font;
|
||||
f32 x = 0;
|
||||
|
||||
if (font){
|
||||
|
@ -143,7 +144,6 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
|
|||
x = (f32)x_;
|
||||
|
||||
f32 byte_advance = font->byte_advance;
|
||||
f32 *codepoint_advance_data = font->codepoint_advance_data;
|
||||
|
||||
u8 *str = (u8*)str_.str;
|
||||
u8 *str_end = str + str_.size;
|
||||
|
@ -170,7 +170,7 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
|
|||
if (color != 0){
|
||||
font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color);
|
||||
}
|
||||
x += codepoint_advance_data[codepoint];
|
||||
x += get_codepoint_advance(font, codepoint);
|
||||
}
|
||||
else if (do_numbers){
|
||||
for (;byte < str; ++byte){
|
||||
|
|
|
@ -225,13 +225,9 @@ sysshared_to_binary_path(String *out_filename, char *filename){
|
|||
// Rendering
|
||||
//
|
||||
|
||||
|
||||
inline void
|
||||
draw_set_clip(Render_Target *target, i32_Rect clip_box){
|
||||
glScissor(clip_box.x0,
|
||||
target->height - clip_box.y1,
|
||||
clip_box.x1 - clip_box.x0,
|
||||
clip_box.y1 - clip_box.y0);
|
||||
glScissor(clip_box.x0, target->height - clip_box.y1, clip_box.x1 - clip_box.x0, clip_box.y1 - clip_box.y0);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -267,23 +263,25 @@ draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
|
|||
PutStruct(Render_Piece_Header, piece.header);
|
||||
|
||||
switch (piece.header.type){
|
||||
case piece_type_rectangle:
|
||||
case piece_type_outline:
|
||||
PutStruct(Render_Piece_Rectangle, piece.rectangle);
|
||||
break;
|
||||
case piece_type_rectangle: case piece_type_outline:
|
||||
{
|
||||
PutStruct(Render_Piece_Rectangle, piece.rectangle);
|
||||
}break;
|
||||
|
||||
case piece_type_gradient:
|
||||
PutStruct(Render_Piece_Gradient, piece.gradient);
|
||||
break;
|
||||
{
|
||||
PutStruct(Render_Piece_Gradient, piece.gradient);
|
||||
}break;
|
||||
|
||||
case piece_type_glyph:
|
||||
case piece_type_mono_glyph:
|
||||
PutStruct(Render_Piece_Glyph, piece.glyph);
|
||||
break;
|
||||
case piece_type_glyph: case piece_type_mono_glyph:
|
||||
{
|
||||
PutStruct(Render_Piece_Glyph, piece.glyph);
|
||||
}break;
|
||||
|
||||
case piece_type_mono_glyph_advance:
|
||||
PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance);
|
||||
break;
|
||||
{
|
||||
PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance);
|
||||
}break;
|
||||
}
|
||||
|
||||
Assert(target->size <= target->max);
|
||||
|
@ -385,7 +383,7 @@ struct Render_Quad{
|
|||
};
|
||||
|
||||
inline Render_Quad
|
||||
get_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){
|
||||
get_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
|
||||
Render_Quad q;
|
||||
|
||||
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||
|
@ -404,7 +402,7 @@ get_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){
|
|||
}
|
||||
|
||||
inline Render_Quad
|
||||
get_exact_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){
|
||||
get_exact_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
|
||||
Render_Quad q;
|
||||
|
||||
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||
|
@ -423,47 +421,48 @@ get_exact_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, u32 color){
|
||||
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);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
|
||||
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
|
||||
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
|
||||
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
|
||||
private_draw_glyph(Render_Target *target, Render_Font *font, u32 character, f32 x, f32 y, u32 color){
|
||||
Glyph_Data glyph = {0};
|
||||
if (get_codepoint_glyph_data(font, character, &glyph)){
|
||||
Render_Quad q = get_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
|
||||
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, glyph.tex);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
|
||||
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
|
||||
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
|
||||
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
||||
f32 x, f32 y, f32 advance, u32 color){
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
|
||||
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
|
||||
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
|
||||
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, f32 advance, u32 color){
|
||||
Glyph_Data glyph = {0};
|
||||
if (get_codepoint_glyph_data(font, character, &glyph)){
|
||||
f32 left = glyph.bounds.x0;
|
||||
f32 right = glyph.bounds.x1;
|
||||
f32 width = (right - left);
|
||||
f32 x_shift = (advance - width) * .5f;
|
||||
|
||||
x += x_shift;
|
||||
|
||||
Render_Quad q = get_exact_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
|
||||
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, glyph.tex);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
|
||||
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
|
||||
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
|
||||
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -541,149 +540,6 @@ launch_rendering(Render_Target *target){
|
|||
|
||||
#undef ExtractStruct
|
||||
|
||||
#if 0
|
||||
internal void*
|
||||
part_alloc(i32 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"
|
||||
|
||||
internal b32
|
||||
stb_font_load(Partition *part, Render_Font *font_out, char *filename_untranslated, i32 pt_size, i32 tab_width, i32 oversample, b32 store_texture){
|
||||
|
||||
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;
|
||||
|
||||
b32 result = true;
|
||||
|
||||
stbtt_packedchar chardata[256];
|
||||
|
||||
File_Data file = sysshared_load_file(filename.str);
|
||||
|
||||
if (!file.data){
|
||||
result = false;
|
||||
}
|
||||
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
|
||||
result = false;
|
||||
}
|
||||
else{
|
||||
memset(font_out, 0, sizeof(*font_out));
|
||||
|
||||
i32 ascent, descent, line_gap;
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
|
||||
f32 scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
f32 scaled_ascent = scale*ascent;
|
||||
f32 scaled_descent = scale*descent;
|
||||
f32 scaled_line_gap = scale*line_gap;
|
||||
|
||||
font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
||||
font_out->ascent = (i32)(scaled_ascent);
|
||||
font_out->descent = (i32)(scaled_descent);
|
||||
font_out->line_skip = (i32)(scaled_line_gap);
|
||||
|
||||
if (store_texture){
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
i32 tex_width = pt_size*16*oversample;
|
||||
i32 tex_height = pt_size*16*oversample;
|
||||
void *block = sysshared_push_block(part, tex_width * tex_height);
|
||||
|
||||
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, tex_width, 1, part)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (!stbtt_PackFontRange(&spc, (u8*)file.data, 0, STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
||||
result = false;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = false;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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(advance_data[code_point]);
|
||||
if (max_advance < advance){
|
||||
max_advance = advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
}
|
||||
system_free_memory(file.data);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
|
||||
|
||||
#undef internal
|
||||
|
@ -800,88 +656,99 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
}
|
||||
|
||||
// set all this stuff the renderer needs
|
||||
Glyph_Data* c = rf->glyphs + i;
|
||||
|
||||
c->x0 = (f32)(pen_x);
|
||||
c->y0 = (f32)(pen_y);
|
||||
c->x1 = (f32)(pen_x + w);
|
||||
c->y1 = (f32)(pen_y + h + 1);
|
||||
|
||||
c->xoff = (f32)(face->glyph->bitmap_left);
|
||||
c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top);
|
||||
|
||||
c->xoff2 = w + c->xoff;
|
||||
c->yoff2 = h + c->yoff + 1;
|
||||
|
||||
// TODO(allen): maybe advance data should be integers for a while...
|
||||
// I require the actual values to be integers anyway... hmm...
|
||||
f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
rf->codepoint_advance_data[i] = advance;
|
||||
|
||||
rf->glyphs[i].exists = 1;
|
||||
|
||||
i32 pitch = face->glyph->bitmap.pitch;
|
||||
|
||||
// write to texture atlas
|
||||
for(i32 j = 0; j < h; ++j){
|
||||
for(i32 i = 0; i < w; ++i){
|
||||
i32 x = pen_x + i;
|
||||
i32 y = pen_y + j;
|
||||
|
||||
if(use_lcd_filter){
|
||||
Glyph_Bounds* c = 0;
|
||||
f32 *advance_ptr = 0;
|
||||
get_codepoint_memory(rf, i, &c, &advance_ptr);
|
||||
if (c != 0 && advance_ptr != 0){
|
||||
c->exists = true;
|
||||
|
||||
c->x0 = (f32)(pen_x);
|
||||
c->y0 = (f32)(pen_y);
|
||||
c->x1 = (f32)(pen_x + w);
|
||||
c->y1 = (f32)(pen_y + h + 1);
|
||||
|
||||
c->xoff = (f32)(face->glyph->bitmap_left);
|
||||
c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top);
|
||||
|
||||
c->xoff2 = w + c->xoff;
|
||||
c->yoff2 = h + c->yoff + 1;
|
||||
|
||||
// TODO(allen): maybe advance data should be integers for a while...
|
||||
// I require the actual values to be integers anyway... hmm...
|
||||
f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
*advance_ptr = advance;
|
||||
|
||||
// write to texture atlas
|
||||
i32 pitch = face->glyph->bitmap.pitch;
|
||||
for(i32 j = 0; j < h; ++j){
|
||||
for(i32 i = 0; i < w; ++i){
|
||||
i32 x = pen_x + i;
|
||||
i32 y = pen_y + j;
|
||||
|
||||
if(use_lcd_filter){
|
||||
#if 1
|
||||
u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r;
|
||||
|
||||
u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r;
|
||||
|
||||
#else
|
||||
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3];
|
||||
u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
u8 a = (u8)ROUND32((r + g + b) / 3.0f);
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3];
|
||||
u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
u8 a = (u8)ROUND32((r + g + b) / 3.0f);
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
#endif
|
||||
} else {
|
||||
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101;
|
||||
} else {
|
||||
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pen_x = ceil32(c->x1 + 1);
|
||||
}
|
||||
|
||||
pen_x = ceil32(c->x1 + 1);
|
||||
}
|
||||
|
||||
f32 *cp_adv = rf->codepoint_advance_data;
|
||||
cp_adv['\n'] = cp_adv[' '];
|
||||
cp_adv['\r'] = cp_adv['\\'] + cp_adv['r'];
|
||||
cp_adv['\t'] = cp_adv[' ']*tab_width;
|
||||
// NOTE(allen): Setup some basic spacing stuff.
|
||||
f32 space_adv = get_codepoint_advance(rf, ' ');
|
||||
f32 backslash_adv = get_codepoint_advance(rf, '\\');
|
||||
f32 r_adv = get_codepoint_advance(rf, 'r');
|
||||
|
||||
f32 max_hex_advance = cp_adv['0'];
|
||||
for (u32 i = '1'; i <= '9'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
set_codepoint_advance(rf, '\n', space_adv);
|
||||
set_codepoint_advance(rf, '\r', backslash_adv + r_adv);
|
||||
set_codepoint_advance(rf, '\t', space_adv*tab_width);
|
||||
|
||||
f32 max_hex_advance = 0.f;
|
||||
for (u32 i = '0'; i <= '9'; ++i){
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'a'; i <= 'f'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'A'; i <= 'F'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
|
||||
rf->byte_advance = cp_adv['\\'] + max_hex_advance*2;
|
||||
rf->byte_advance = backslash_adv + max_hex_advance*2;
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
tex_height = next_pow_of_2(pen_y + max_glyph_h + 2);
|
||||
|
||||
rf->tex_width = tex_width;
|
||||
rf->tex_height = tex_height;
|
||||
u32 page_index = 0;
|
||||
rf->glyph_pages[page_index].tex_width = tex_width;
|
||||
rf->glyph_pages[page_index].tex_height = tex_height;
|
||||
|
||||
// upload texture
|
||||
glGenTextures(1, &rf->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, rf->tex);
|
||||
u32 tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
@ -896,14 +763,22 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
rf->glyph_pages[page_index].tex = tex;
|
||||
|
||||
return 1;
|
||||
rf->glyph_pages[page_index].exists = true;
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
internal
|
||||
Release_Font_Sig(draw_release_font){
|
||||
glDeleteTextures(1, &font->tex);
|
||||
font->tex = 0;
|
||||
for (u32 i = 0; i < ArrayCount(font->glyph_pages); ++i){
|
||||
Glyph_Page *page = &font->glyph_pages[i];
|
||||
if (page->exists){
|
||||
glDeleteTextures(1, &page->tex);
|
||||
}
|
||||
page->tex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// Buffer low level operations
|
||||
//
|
||||
|
||||
#include "../file/4coder_font_data.h"
|
||||
#include "../4coder_helper/4coder_seek_types.h"
|
||||
|
||||
typedef struct Cursor_With_Index{
|
||||
|
@ -992,8 +993,7 @@ struct Buffer_Layout_Stop{
|
|||
struct Buffer_Measure_Wrap_Params{
|
||||
Gap_Buffer *buffer;
|
||||
i32 *wrap_line_index;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
Render_Font *font;
|
||||
b32 virtual_white;
|
||||
};
|
||||
|
||||
|
@ -1094,10 +1094,10 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
if (!S.skipping_whitespace){
|
||||
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.current_adv = params.cp_adv[S.tran.step_current.value];
|
||||
S.current_adv = get_codepoint_advance(params.font, S.tran.step_current.value);
|
||||
}
|
||||
else{
|
||||
S.current_adv = params.byte_adv;
|
||||
S.current_adv = params.font->byte_advance;
|
||||
}
|
||||
|
||||
S.did_wrap = false;
|
||||
|
@ -1461,7 +1461,7 @@ buffer_get_line_index_from_character_pos(i32 *character_starts, i32 pos, i32 l_b
|
|||
}
|
||||
|
||||
inline i32
|
||||
buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, f32 line_height, i32 l_bound, i32 u_bound){
|
||||
buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, i32 line_height, i32 l_bound, i32 u_bound){
|
||||
i32 wrap_index = floor32(y/line_height);
|
||||
i32 i = binary_search(wrap_line_index, wrap_index, l_bound, u_bound);
|
||||
return(i);
|
||||
|
@ -1539,9 +1539,7 @@ buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){
|
|||
struct Buffer_Cursor_Seek_Params{
|
||||
Gap_Buffer *buffer;
|
||||
Buffer_Seek seek;
|
||||
f32 font_height;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
Render_Font *font;
|
||||
i32 *wrap_line_index;
|
||||
i32 *character_starts;
|
||||
b32 virtual_white;
|
||||
|
@ -1628,7 +1626,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
|
||||
case buffer_seek_unwrapped_xy:
|
||||
{
|
||||
line_index = (i32)(params.seek.y / params.font_height);
|
||||
line_index = (i32)(params.seek.y / params.font->height);
|
||||
if (line_index >= params.buffer->line_count){
|
||||
line_index = params.buffer->line_count - 1;
|
||||
}
|
||||
|
@ -1639,8 +1637,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
|
||||
case buffer_seek_wrapped_xy:
|
||||
{
|
||||
line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, params.font_height,
|
||||
0, params.buffer->line_count);
|
||||
line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, params.font->height, 0, params.buffer->line_count);
|
||||
}break;
|
||||
|
||||
default: InvalidCodePath;
|
||||
|
@ -1652,9 +1649,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.next_cursor.line = line_index + 1;
|
||||
S.next_cursor.character = 1;
|
||||
S.next_cursor.wrap_line = params.wrap_line_index[line_index] + 1;
|
||||
S.next_cursor.unwrapped_y = (f32)(line_index * params.font_height);
|
||||
S.next_cursor.unwrapped_y = (f32)(line_index * params.font->height);
|
||||
S.next_cursor.unwrapped_x = 0;
|
||||
S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[line_index] * params.font_height);
|
||||
S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[line_index] * params.font->height);
|
||||
S.next_cursor.wrapped_x = 0;
|
||||
}
|
||||
|
||||
|
@ -1765,8 +1762,8 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
++S.next_cursor.character_pos;
|
||||
++S.next_cursor.line;
|
||||
++S.next_cursor.wrap_line;
|
||||
S.next_cursor.unwrapped_y += params.font_height;
|
||||
S.next_cursor.wrapped_y += params.font_height;
|
||||
S.next_cursor.unwrapped_y += params.font->height;
|
||||
S.next_cursor.wrapped_y += params.font->height;
|
||||
S.next_cursor.character = 1;
|
||||
S.next_cursor.unwrapped_x = 0;
|
||||
|
||||
|
@ -1783,10 +1780,10 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
|
||||
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.ch_width = params.cp_adv[S.tran.step_current.value];
|
||||
S.ch_width = get_codepoint_advance(params.font, S.tran.step_current.value);
|
||||
}
|
||||
else{
|
||||
S.ch_width = params.byte_adv;
|
||||
S.ch_width = params.font->byte_advance;
|
||||
}
|
||||
|
||||
if (S.tran.step_current.i >= S.wrap_unit_end){
|
||||
|
@ -1800,7 +1797,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.wrap_unit_end = wrap_unit_end;
|
||||
|
||||
if (do_wrap && !S.first_of_the_line){
|
||||
S.next_cursor.wrapped_y += params.font_height;
|
||||
S.next_cursor.wrapped_y += params.font->height;
|
||||
|
||||
++S.next_cursor.wrap_line;
|
||||
if (params.virtual_white){
|
||||
|
@ -1869,7 +1866,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
goto buffer_cursor_seek_end;
|
||||
}
|
||||
|
||||
if (y > params.seek.y - params.font_height && x >= params.seek.x){
|
||||
if (y > params.seek.y - params.font->height && x >= params.seek.x){
|
||||
if (!params.seek.round_down){
|
||||
if (py >= y && S.ch != '\n' && (params.seek.x - px) < (x - params.seek.x)){
|
||||
S.this_cursor = S.prev_cursor;
|
||||
|
@ -1975,15 +1972,14 @@ typedef struct Buffer_Render_Item{
|
|||
typedef struct Render_Item_Write{
|
||||
Buffer_Render_Item *item;
|
||||
f32 x, y;
|
||||
f32 *adv;
|
||||
f32 font_height;
|
||||
Render_Font *font;
|
||||
f32 x_min;
|
||||
f32 x_max;
|
||||
} Render_Item_Write;
|
||||
|
||||
inline Render_Item_Write
|
||||
write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
|
||||
f32 ch_width = write.adv[(u8)glyphid];
|
||||
f32 ch_width = get_codepoint_advance(write.font, glyphid);
|
||||
|
||||
if (write.x <= write.x_max && write.x + ch_width >= write.x_min){
|
||||
write.item->index = index;
|
||||
|
@ -1992,7 +1988,7 @@ write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
|
|||
write.item->x0 = write.x;
|
||||
write.item->y0 = write.y;
|
||||
write.item->x1 = write.x + ch_width;
|
||||
write.item->y1 = write.y + write.font_height;
|
||||
write.item->y1 = write.y + write.font->height;
|
||||
|
||||
++write.item;
|
||||
}
|
||||
|
@ -2017,9 +2013,7 @@ struct Buffer_Render_Params{
|
|||
f32 height;
|
||||
Full_Cursor start_cursor;
|
||||
i32 wrapped;
|
||||
f32 font_height;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
Render_Font *font;
|
||||
b32 virtual_white;
|
||||
i32 wrap_slashes;
|
||||
};
|
||||
|
@ -2092,8 +2086,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
S.write.item = params.items;
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y = S.shift_y;
|
||||
S.write.adv = params.cp_adv;
|
||||
S.write.font_height = params.font_height;
|
||||
S.write.font = params.font;
|
||||
S.write.x_min = params.port_x;
|
||||
S.write.x_max = params.port_x + params.clip_w;
|
||||
|
||||
|
@ -2149,7 +2142,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
}
|
||||
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font_height;
|
||||
S.write.y += params.font->height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2175,7 +2168,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
++S.wrap_line;
|
||||
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font_height;
|
||||
S.write.y += params.font->height;
|
||||
|
||||
S.first_of_the_line = true;
|
||||
}
|
||||
|
@ -2198,7 +2191,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
|
||||
case '\t':
|
||||
{
|
||||
S.ch_width = params.cp_adv['\t'];
|
||||
S.ch_width = get_codepoint_advance(params.font, '\t');
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
S.write = write_render_item(S.write, I, ' ', 0);
|
||||
S.write.x = new_x;
|
||||
|
@ -2216,7 +2209,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
u32 I = S.tran.step_current.i;
|
||||
S.skipping_whitespace = false;
|
||||
|
||||
S.ch_width = params.byte_adv;
|
||||
S.ch_width = params.font->byte_advance;
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
|
||||
u8 cs[3];
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 03.03.2017
|
||||
*
|
||||
* Font data type definitions.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_FONT_DATA_H)
|
||||
#define FCODER_FONT_DATA_H
|
||||
|
||||
#define FONT_PAGE_ITEMS 256
|
||||
|
||||
struct Glyph_Bounds{
|
||||
b32 exists;
|
||||
|
||||
f32 x0, x1;
|
||||
f32 y0, y1;
|
||||
|
||||
f32 xoff, yoff;
|
||||
f32 xoff2, yoff2;
|
||||
};
|
||||
|
||||
struct Glyph_Page{
|
||||
Glyph_Bounds glyphs[256];
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
b32 exists;
|
||||
};
|
||||
|
||||
struct Glyph_Data{
|
||||
Glyph_Bounds bounds;
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
};
|
||||
|
||||
struct Advance_Page{
|
||||
f32 advance[256];
|
||||
};
|
||||
|
||||
struct Render_Font{
|
||||
char name_[24];
|
||||
String name;
|
||||
b32 loaded;
|
||||
|
||||
Glyph_Page glyph_pages[1];
|
||||
Advance_Page advance_pages[1];
|
||||
|
||||
f32 byte_advance;
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
};
|
||||
|
||||
internal b32
|
||||
get_codepoint_can_render(Render_Font *font, u32 codepoint){
|
||||
b32 exists = false;
|
||||
if (codepoint < FONT_PAGE_ITEMS){
|
||||
exists = true;
|
||||
}
|
||||
return(exists);
|
||||
}
|
||||
|
||||
internal u32
|
||||
get_codepoint_page_index(Render_Font *font, u32 codepoint, u32 *page_base_codepoint){
|
||||
*page_base_codepoint = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
internal void
|
||||
get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){
|
||||
Glyph_Bounds *bounds = 0;
|
||||
f32 *advance = 0;
|
||||
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Glyph_Page *bounds_page = &font->glyph_pages[page_index];
|
||||
Advance_Page *advance_page = &font->advance_pages[page_index];
|
||||
u32 glyph_index = codepoint - base_codepoint;
|
||||
|
||||
bounds = &bounds_page->glyphs[glyph_index];
|
||||
advance = &advance_page->advance[glyph_index];
|
||||
}
|
||||
|
||||
*bounds_mem_out = bounds;
|
||||
*advance_mem_out = advance;
|
||||
}
|
||||
|
||||
internal b32
|
||||
get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Glyph_Page *page = &font->glyph_pages[page_index];
|
||||
data_out->bounds = page->glyphs[codepoint - base_codepoint];
|
||||
data_out->tex = page->tex;
|
||||
data_out->tex_width = page->tex_width;
|
||||
data_out->tex_height = page->tex_height;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal f32
|
||||
get_codepoint_advance(Render_Font *font, u32 codepoint){
|
||||
f32 advance = (f32)font->advance;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Advance_Page *page = &font->advance_pages[page_index];
|
||||
advance = page->advance[codepoint - base_codepoint];
|
||||
}
|
||||
return(advance);
|
||||
}
|
||||
|
||||
internal b32
|
||||
set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Advance_Page *page = &font->advance_pages[page_index];
|
||||
page->advance[codepoint - base_codepoint] = value;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
Loading…
Reference in New Issue