rejigged font system, and rewrote code dealing with fonts

This commit is contained in:
Allen Webster 2017-03-03 18:57:11 -05:00
parent 16b11c593a
commit d5ab8eafdc
11 changed files with 407 additions and 424 deletions

View File

@ -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)

View File

@ -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{

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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){

View File

@ -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

View File

@ -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];

137
file/4coder_font_data.h Normal file
View File

@ -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