began torching the font system

master
Allen Webster 2017-03-10 15:44:42 -05:00
parent d5ab8eafdc
commit 4a5bfa59b7
19 changed files with 903 additions and 788 deletions

View File

@ -745,14 +745,7 @@ process_config_file(Application_Links *app){
char str_space[512];
String str = make_fixed_width_string(str_space);
if (config_string_var(item, "treat_as_code", 0, &str)){
if (str.size < sizeof(treat_as_code_exts.extension_space)){
set_extensions(&treat_as_code_exts, str);
print_message(app, str.str, str.size);
print_message(app, "\n", 1);
}
else{
print_message(app, literal("STRING TOO LONG!\n"));
}
set_extensions(&treat_as_code_exts, str);
}
}
}

View File

@ -146,28 +146,28 @@ utf8_to_u32(u8_4tech **buffer_ptr, u8_4tech *end){
}
static void
u32_to_utf8_unchecked(u32_4tech code_point, u8_4tech *buffer, u32_4tech *length_out){
if (code_point <= 0x7F){
buffer[0] = (u8_4tech)code_point;
u32_to_utf8_unchecked(u32_4tech codepoint, u8_4tech *buffer, u32_4tech *length_out){
if (codepoint <= 0x7F){
buffer[0] = (u8_4tech)codepoint;
*length_out = 1;
}
else if (code_point <= 0x7FF){
buffer[0] = (u8_4tech)(0xC0 | (code_point >> 6));
buffer[1] = (u8_4tech)(0x80 | (code_point & 0x3F));
else if (codepoint <= 0x7FF){
buffer[0] = (u8_4tech)(0xC0 | (codepoint >> 6));
buffer[1] = (u8_4tech)(0x80 | (codepoint & 0x3F));
*length_out = 2;
}
else if (code_point <= 0xFFFF){
buffer[0] = (u8_4tech)(0xE0 | (code_point >> 12));
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
buffer[2] = (u8_4tech)(0x80 | (code_point & 0x3F));
else if (codepoint <= 0xFFFF){
buffer[0] = (u8_4tech)(0xE0 | (codepoint >> 12));
buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
buffer[2] = (u8_4tech)(0x80 | (codepoint & 0x3F));
*length_out = 3;
}
else{
code_point &= 0x001FFFFF;
buffer[0] = (u8_4tech)(0xF0 | (code_point >> 18));
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F));
buffer[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
buffer[3] = (u8_4tech)(0x80 | (code_point & 0x3F));
codepoint &= 0x001FFFFF;
buffer[0] = (u8_4tech)(0xF0 | (codepoint >> 18));
buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F));
buffer[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
buffer[3] = (u8_4tech)(0x80 | (codepoint & 0x3F));
*length_out = 4;
}
}
@ -186,11 +186,11 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
*error = false;
for(; s < s_end;){
u32_4tech code_point = 0;
u32_4tech codepoint = 0;
u32_4tech utf8_size = 0;
if (s[0] <= 0x7F){
code_point = (u32_4tech)s[0];
codepoint = (u32_4tech)s[0];
utf8_size = 1;
}
else if (s[0] <= 0xE0){
@ -199,8 +199,8 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
break;
}
code_point = ((u32_4tech)((s[0])&0x1F)) << 6;
code_point |= ((u32_4tech)((s[1])&0x3F));
codepoint = ((u32_4tech)((s[0])&0x1F)) << 6;
codepoint |= ((u32_4tech)((s[1])&0x3F));
utf8_size = 2;
}
else if (s[0] <= 0xF0){
@ -209,9 +209,9 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
break;
}
code_point = ((u32_4tech)((s[0])&0x0F)) << 12;
code_point |= ((u32_4tech)((s[1])&0x3F)) << 6;
code_point |= ((u32_4tech)((s[2])&0x3F));
codepoint = ((u32_4tech)((s[0])&0x0F)) << 12;
codepoint |= ((u32_4tech)((s[1])&0x3F)) << 6;
codepoint |= ((u32_4tech)((s[2])&0x3F));
utf8_size = 3;
}
else{
@ -220,26 +220,26 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
break;
}
code_point = ((u32_4tech)((s[0])&0x07)) << 18;
code_point |= ((u32_4tech)((s[1])&0x3F)) << 12;
code_point |= ((u32_4tech)((s[2])&0x3F)) << 6;
code_point |= ((u32_4tech)((s[3])&0x3F));
codepoint = ((u32_4tech)((s[0])&0x07)) << 18;
codepoint |= ((u32_4tech)((s[1])&0x3F)) << 12;
codepoint |= ((u32_4tech)((s[2])&0x3F)) << 6;
codepoint |= ((u32_4tech)((s[3])&0x3F));
utf8_size = 4;
}
s += utf8_size;
limit -= utf8_size;
if (code_point <= 0xD7FF || (code_point >= 0xE000 && code_point <= 0xFFFF)){
*d = (u16_4tech)(code_point);
if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)){
*d = (u16_4tech)(codepoint);
d += advance;
needed_max += 1;
}
else if (code_point >= 0x10000 && code_point <= 0x10FFFF){
code_point -= 0x10000;
else if (codepoint >= 0x10000 && codepoint <= 0x10FFFF){
codepoint -= 0x10000;
u32_4tech high = (code_point >> 10) & 0x03FF;
u32_4tech low = (code_point) & 0x03FF;
u32_4tech high = (codepoint >> 10) & 0x03FF;
u32_4tech low = (codepoint) & 0x03FF;
high += 0xD800;
low += 0xDC00;
@ -283,11 +283,11 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
*error = false;
for (; s < s_end;){
u32_4tech code_point = 0;
u32_4tech codepoint = 0;
u32_4tech utf16_size = 0;
if (s[0] <= 0xD7FF || (s[0] >= 0xE000 && s[0] <= 0xFFFF)){
code_point = s[0];
codepoint = s[0];
utf16_size = 1;
}
else{
@ -299,7 +299,7 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
u32_4tech high = s[0] - 0xD800;
u32_4tech low = s[1] - 0xDC00;
code_point = ((high << 10) | (low)) + 0x10000;
codepoint = ((high << 10) | (low)) + 0x10000;
utf16_size = 2;
}
else{
@ -314,26 +314,26 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
u8_4tech d_fill[4];
u32_4tech d_fill_count = 0;
if (code_point <= 0x7F){
d_fill[0] = (u8_4tech)code_point;
if (codepoint <= 0x7F){
d_fill[0] = (u8_4tech)codepoint;
d_fill_count = 1;
}
else if (code_point <= 0x7FF){
d_fill[0] = (u8_4tech)(0xC0 | (code_point >> 6));
d_fill[1] = (u8_4tech)(0x80 | (code_point & 0x3F));
else if (codepoint <= 0x7FF){
d_fill[0] = (u8_4tech)(0xC0 | (codepoint >> 6));
d_fill[1] = (u8_4tech)(0x80 | (codepoint & 0x3F));
d_fill_count = 2;
}
else if (code_point <= 0xFFFF){
d_fill[0] = (u8_4tech)(0xE0 | (code_point >> 12));
d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
d_fill[2] = (u8_4tech)(0x80 | (code_point & 0x3F));
else if (codepoint <= 0xFFFF){
d_fill[0] = (u8_4tech)(0xE0 | (codepoint >> 12));
d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
d_fill[2] = (u8_4tech)(0x80 | (codepoint & 0x3F));
d_fill_count = 3;
}
else if (code_point <= 0x10FFFF){
d_fill[0] = (u8_4tech)(0xF0 | (code_point >> 18));
d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F));
d_fill[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
d_fill[3] = (u8_4tech)(0x80 | (code_point & 0x3F));
else if (codepoint <= 0x10FFFF){
d_fill[0] = (u8_4tech)(0xF0 | (codepoint >> 18));
d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F));
d_fill[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
d_fill[3] = (u8_4tech)(0x80 | (codepoint & 0x3F));
d_fill_count = 4;
}
else{

11
4ed.cpp
View File

@ -1478,13 +1478,13 @@ App_Init_Sig(app_init){
char *custom_font_name = models->settings.custom_font_name;
i32 custom_font_size = models->settings.custom_font_size;
b32 use_custom_font = true;
if (!custom_font_file){
if (custom_font_file == 0){
use_custom_font = false;
custom_font_file = "";
custom_font_name = "";
}
if (font_size < 8) font_size = 8;
font_size = clamp_bottom(8, font_size);
Font_Setup font_setup[] = {
{literal("LiberationSans-Regular.ttf"), literal("Liberation Sans"), font_size},
@ -1531,9 +1531,6 @@ App_Init_Sig(app_init){
// NOTE(allen): style setup
app_hardcode_styles(models);
models->palette_size = 40;
models->palette = push_array(partition, u32, models->palette_size);
// NOTE(allen): init first panel
Command_Data *cmd = &vars->command_data;
@ -1556,8 +1553,8 @@ App_Init_Sig(app_init){
};
File_Init init_files[] = {
{ make_lit_string("*messages*"), &models->message_buffer, 1, },
{ make_lit_string("*scratch*"), &models->scratch_buffer, 0, }
{ make_lit_string("*messages*"), &models->message_buffer, true , },
{ make_lit_string("*scratch*"), &models->scratch_buffer, false, }
};
for (i32 i = 0; i < ArrayCount(init_files); ++i){

View File

@ -74,11 +74,8 @@ struct Models{
Input_Filter_Function *input_filter;
Scroll_Rule_Function *scroll_rule;
Font_Set *font_set;
Style_Font global_font;
Style_Library styles;
u32 *palette;
i32 palette_size;
Editing_Layout layout;
Working_Set working_set;

View File

@ -229,7 +229,6 @@ struct View{
// theme stuff
View *hot_file_view;
u32 *palette;
i32 palette_size;
Color_View_Mode color_mode;
Super_Color color;
b32 p4c_only;
@ -387,8 +386,12 @@ view_cursor_limits(View *view){
internal Full_Cursor
view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){
Editing_File *file = view->file_data.file;
#if 0
Models *models = view->persistent.models;
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
#endif
Render_Font *font = 0;
Full_Cursor result = {0};
@ -1031,7 +1034,11 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, Render_Font *font){
state->i = 0;
state->font = font;
#if 0
state->tab_indent_amount = get_codepoint_advance(font, '\t');
#endif
state->tab_indent_amount = 2.f;
state->tran = null_buffer_translating_state;
}
@ -1143,7 +1150,11 @@ 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){
#if 0
adv = get_codepoint_advance(state->font, n);
#endif
adv = 2.f;
if (n != ' ' && n != '\t'){
skipping_whitespace = false;
}
@ -1543,7 +1554,11 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){
word_stage = 1;
}
else{
#if 0
f32 adv = get_codepoint_advance(params.font, ch);
#endif
f32 adv = 2.f;
x += adv;
self_x += adv;
if (self_x > width){
@ -1670,7 +1685,11 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){
goto doublebreak_stage1;
}
#if 0
f32 adv = get_codepoint_advance(params.font, ch);
#endif
f32 adv = 2.f;
x += adv;
if (!first_word && x > current_width){
emit_comment_position = 1;
@ -1696,7 +1715,12 @@ file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){
goto doublebreak_stage2;
}
#if 0
f32 adv = get_codepoint_advance(params.font, ch);
#endif
f32 adv = 2.f;
x += adv;
}
still_looping = buffer_stringify_next(&stream);

View File

@ -9,236 +9,5 @@
// TOP
inline u32
font_hash(String name){
u32 x = 5381;
char *p = name.str;
for (i32 i = 0; i < name.size; ++i, ++p){
x = ((x << 5) + x) ^ (*p);
}
return(x);
}
inline void
font__insert(Font_Slot *pos, Font_Slot *slot){
Font_Slot *nex;
nex = pos->next;
slot->next = nex;
slot->prev = pos;
nex->prev = slot;
pos->next = slot;
}
inline void
font__remove(Font_Slot *slot){
Font_Slot *n, *p;
n = slot->next;
p = slot->prev;
p->next = n;
n->prev = p;
}
inline Font_Slot
font_slot_zero(){
Font_Slot slot = {0};
return(slot);
}
internal void
font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
partition_align(partition, 8);
set->info = push_array(partition, Font_Info, max);
partition_align(partition, 8);
set->entries = push_array(partition, Font_Table_Entry, max);
set->count = 0;
set->max = max;
partition_align(partition, 8);
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
set->free_slots = font_slot_zero();
set->used_slots = font_slot_zero();
dll_init_sentinel(&set->free_slots);
dll_init_sentinel(&set->used_slots);
char *ptr = (char*)set->font_block;
for (i32 i = 0; i < live_max; ++i){
dll_insert(&set->free_slots, (Font_Slot*)ptr);
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
}
set->font_used_flags = push_array(partition, b8, max);
set->live_max = live_max;
}
internal b32
font_set_can_add(Font_Set *set){
b32 result = 0;
if (set->count*8 < set->max*7) result = 1;
return(result);
}
internal void
font_set_add_hash(Font_Set *set, String name, i16 font_id){
Font_Table_Entry entry;
entry.hash = font_hash(name);
entry.name = name;
entry.font_id = font_id;
u32 i, j;
i = entry.hash % set->max;
j = i - 1;
if (i <= 1) j += set->max;
for (; i != j; ++i){
if (i == set->max) i = 0;
if (set->entries[i].font_id == 0){
set->entries[i] = entry;
break;
}
}
Assert(i != j);
}
inline b32
font_set_can_load(Font_Set *set){
b32 result = (set->free_slots.next != &set->free_slots);
return(result);
}
internal void
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);
font__remove(slot);
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);
info->font = font;
slot->font_id = font_id;
}
internal void
font_set_evict_lru(Font_Set *set){
Font_Slot *slot = set->used_slots.prev;
Assert(slot != &set->used_slots);
i16 font_id = slot->font_id;
Font_Info *info = get_font_info(set, font_id);
Assert(((Font_Slot*)info->font) - 1 == slot);
set->release_font(info->font);
info->font = 0;
slot->font_id = 0;
font__remove(slot);
font__insert(&set->free_slots, slot);
}
internal void
font_set_use(Font_Set *set, i16 font_id){
b8 already_used = set->font_used_flags[font_id-1];
if (!already_used){
if (set->used_this_frame < set->live_max){
++set->used_this_frame;
set->font_used_flags[font_id-1] = 1;
already_used = 1;
}
}
if (already_used){
// TODO(allen): optimize if you don't mind!!!!
Font_Info *info = get_font_info(set, font_id);
Font_Slot *slot;
if (info->font == 0){
if (!font_set_can_load(set)){
font_set_evict_lru(set);
}
font_set_load(set, font_id);
}
slot = ((Font_Slot*)info->font) - 1;
font__remove(slot);
font__insert(&set->used_slots, slot);
}
}
internal b32
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};
i16 font_id = (i16)(++set->count);
Font_Info *info = get_font_info(set, font_id);
info->filename = filename;
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;
font_set_add_hash(set, name, font_id);
if (font_set_can_load(set)){
font_set_load(set, font_id);
}
result = 1;
}
return(result);
}
internal b32
font_set_find_pos(Font_Set *set, String name, u32 *position){
u32 hash = font_hash(name);
u32 i = hash % set->max;
u32 j = i - 1;
if (j <= 1){
j += set->max;
}
b32 result = 0;
for (; i != j; ++i){
if (i == set->max){
i = 0;
}
Font_Table_Entry *entry = set->entries + i;
if (entry->hash == hash){
if (match_ss(name, entry->name)){
result = 1;
*position = i;
break;
}
}
}
return(result);
}
internal b32
font_set_get_name(Font_Set *set, i16 font_id, String *name){
Font_Info *info = get_font_info(set, font_id);
b32 result = copy_checked_ss(name, info->name);
return(result);
}
internal b32
font_set_extract(Font_Set *set, String name, i16 *font_id){
u32 position;
b32 result = font_set_find_pos(set, name, &position);
if (result){
*font_id = set->entries[position].font_id;
}
return(result);
}
// BOTTOM

View File

@ -475,12 +475,24 @@ clamp_bottom(u32 a, u32 n){
return (n);
}
inline u64
clamp_bottom(u64 a, u64 n){
if (n < a) n = a;
return (n);
}
inline u32
clamp_top(u32 n, u32 z){
if (n > z) n = z;
return (n);
}
inline u64
clamp_top(u64 n, u64 z){
if (n > z) n = z;
return (n);
}
inline u32
clamp(u32 a, u32 n, u32 z){
if (n < a) n = a;

View File

@ -12,54 +12,6 @@
#ifndef FRED_RENDERING_H
#define FRED_RENDERING_H
//
// Fonts
//
#include "file/4coder_font_data.h"
struct Font_Table_Entry{
u32 hash;
String name;
i16 font_id;
};
struct Font_Info{
Render_Font *font;
String filename;
String name;
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
//
@ -150,10 +102,6 @@ struct Render_Target{
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)
@ -168,12 +116,6 @@ rect_from_target(Render_Target *target){
return(r);
}
inline Font_Info*
get_font_info(Font_Set *set, i16 font_id){
Font_Info *result = set->info + font_id - 1;
return(result);
}
#endif
// BOTTOM

View File

@ -28,9 +28,6 @@ draw_change_clip(Render_Target *target, i32_Rect clip_box){
internal void
begin_render_section(Render_Target *target, System_Functions *system){
Font_Set *font_set = &target->font_set;
font_set->used_this_frame = 0;
memset(font_set->font_used_flags, 0, font_set->max);
target->size = 0;
target->clip_top = -1;
@ -117,6 +114,8 @@ font_predict_size(i32 pt_size){
internal void
font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 x, f32 y, u32 color){
#if 0
Render_Piece_Combined piece;
piece.header.type = type;
piece.glyph.pos.x = x;
@ -126,6 +125,8 @@ font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32
piece.glyph.character = character;
target->push_piece(target, piece);
font_set_use(&target->font_set, font_id);
#endif
}
internal void
@ -135,9 +136,12 @@ 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){
f32 x = 0;
#if 0
Font_Info *font_info = get_font_info(&target->font_set, font_id);
Render_Font *font = font_info->font;
f32 x = 0;
if (font){
f32 y = (f32)y_;
@ -192,6 +196,7 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
}
}
}
#endif
return(x);
}

View File

@ -218,7 +218,7 @@ sysshared_to_binary_path(String *out_filename, char *filename){
translate_success = 1;
}
}
return (translate_success);
return(translate_success);
}
//
@ -545,77 +545,28 @@ launch_rendering(Render_Target *target){
#undef internal
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_LCD_FILTER_H
#define internal static
internal u32
next_pow_of_2(u32 v){
--v;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return ++v;
}
#define NUM_GLYPHS 256
#define ENABLE_LCD_FILTER 0
internal b32
font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size, i32 tab_width, b32 use_hinting){
memset(rf, 0, sizeof(*rf));
//TODO(inso): put stuff in linuxvars / init in main
FT_Library ft;
FT_Face face;
b32 use_lcd_filter = 0;
FT_Init_FreeType(&ft);
//NOTE(inso): i'm not sure the LCD filter looks better, and it doesn't work perfectly with the coloring stuff
// it will probably need shaders to work properly
#if ENABLE_LCD_FILTER
if(FT_Library_SetLcdFilter(ft, FT_LCD_FILTER_DEFAULT) == 0){
puts("LCD Filter on");
use_lcd_filter = 1;
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
#endif
FT_New_Face(ft, filename, 0, &face);
// set size & metrics
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
rf->loaded = 1;
rf->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
rf->descent = floor32 (face->size->metrics.descender / 64.0f);
rf->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
rf->height = ceil32 (face->size->metrics.height / 64.0f);
rf->line_skip = rf->height - (rf->ascent - rf->descent);
rf->height -= rf->line_skip;
rf->line_skip = 0;
internal void
font_load_freetype_page_inner(Partition *part, Render_Font *font, FT_Library ft, FT_Face face, b32 use_hinting, Glyph_Page *page, u32 page_number, i32 tab_width){
Temp_Memory temp = begin_temp_memory(part);
Assert(page != 0);
page->page_number = page_number;
// prepare to read glyphs into a temporary texture buffer
i32 max_glyph_w = face->size->metrics.x_ppem;
i32 max_glyph_h = rf->height;
i32 max_glyph_h = font->height;
i32 tex_width = 64;
i32 tex_height = 0;
// estimate upper bound on texture width
do {
tex_width *= 2;
float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w);
float rows = ceilf(NUM_GLYPHS / glyphs_per_row);
float rows = ceilf(ITEM_PER_FONT_PAGE / glyphs_per_row);
tex_height = ceil32(rows * (max_glyph_h + 2));
} while(tex_height > tex_width);
tex_height = next_pow_of_2(tex_height);
tex_height = round_up_pot_u32(tex_height);
i32 pen_x = 0;
i32 pen_y = 0;
@ -623,60 +574,46 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
u32* pixels = push_array(part, u32, tex_width * tex_height);
memset(pixels, 0, tex_width * tex_height * sizeof(u32));
u32 ft_extra_flags = 0;
if (use_lcd_filter){
ft_extra_flags = FT_LOAD_TARGET_LCD;
u32 ft_flags = FT_LOAD_RENDER;
if (use_hinting){
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
// maybe it could be exposed as an option for hinting, instead of just on/off.
ft_flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
}
else{
if (use_hinting){
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
// maybe it could be exposed as an option for hinting, instead of just on/off.
ft_extra_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
}
else{
ft_extra_flags = (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
for(i32 i = 0; i < NUM_GLYPHS; ++i){
if(FT_Load_Char(face, i, FT_LOAD_RENDER | ft_extra_flags) != 0) continue;
// fill the texture
u32 base_codepoint = (page_number << 8);
Glyph_Bounds *glyph_ptr = &page->glyphs[0];
f32 *advance_ptr = &page->advance[0];
for(u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++glyph_ptr, ++advance_ptr){
u32 codepoint = i + base_codepoint;
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
// lcd filter produces RGB bitmaps, need to account for the extra components
if(use_lcd_filter){
w /= 3;
}
// move to next line if necessary
if(pen_x + w >= tex_width){
pen_x = 0;
pen_y += (max_glyph_h + 2);
}
// set all this stuff the renderer needs
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;
if(FT_Load_Char(face, codepoint, ft_flags) == 0){
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
c->x0 = (f32)(pen_x);
c->y0 = (f32)(pen_y);
c->x1 = (f32)(pen_x + w);
c->y1 = (f32)(pen_y + h + 1);
// move to next line if necessary
if(pen_x + w >= tex_width){
pen_x = 0;
pen_y += (max_glyph_h + 2);
}
c->xoff = (f32)(face->glyph->bitmap_left);
c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top);
// set all this stuff the renderer needs
glyph_ptr->x0 = (f32)(pen_x);
glyph_ptr->y0 = (f32)(pen_y);
glyph_ptr->x1 = (f32)(pen_x + w);
glyph_ptr->y1 = (f32)(pen_y + h + 1);
c->xoff2 = w + c->xoff;
c->yoff2 = h + c->yoff + 1;
glyph_ptr->xoff = (f32)(face->glyph->bitmap_left);
glyph_ptr->yoff = (f32)(font->ascent - face->glyph->bitmap_top);
glyph_ptr->xoff2 = glyph_ptr->xoff + w;
glyph_ptr->yoff2 = glyph_ptr->yoff + h + 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;
// TODO(allen): maybe advance data should be integers?
*advance_ptr = (f32)ceil32(face->glyph->advance.x / 64.0f);
// write to texture atlas
i32 pitch = face->glyph->bitmap.pitch;
@ -685,67 +622,20 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
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;
#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;
#endif
} else {
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101;
}
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x01010101;
}
}
pen_x = ceil32(c->x1 + 1);
pen_x = ceil32(glyph_ptr->x1 + 1);
}
}
// 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');
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){
f32 adv = get_codepoint_advance(rf, i);
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = get_codepoint_advance(rf, i);
max_hex_advance = Max(max_hex_advance, adv);
}
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);
u32 page_index = 0;
rf->glyph_pages[page_index].tex_width = tex_width;
rf->glyph_pages[page_index].tex_height = tex_height;
// upload texture
tex_height = round_up_pot_u32(pen_y + max_glyph_h + 2);
page->tex_width = tex_width;
page->tex_height = tex_height;
u32 tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
@ -756,28 +646,107 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if(use_lcd_filter){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
rf->glyph_pages[page_index].tex = tex;
page->tex = tex;
page->page_number = page_number;
rf->glyph_pages[page_index].exists = true;
end_temp_memory(temp);
// whitespace spacing stuff
if (page_number == 0){
f32 space_adv = get_codepoint_advance(font, ' ');
f32 backslash_adv = get_codepoint_advance(font, '\\');
f32 r_adv = get_codepoint_advance(font, 'r');
set_codepoint_advance(font, '\n', space_adv);
set_codepoint_advance(font, '\r', backslash_adv + r_adv);
set_codepoint_advance(font, '\t', space_adv*tab_width);
}
}
internal b32
font_load_freetype_page(Partition *part, Render_Font *font, char *filename, i32 pt_size, b32 use_hinting, u32 page_number, i32 tab_width){
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
Glyph_Page *page = font_get_or_make_page(font, page_number);
font_load_freetype_page_inner(part, font, ft, face, use_hinting, page_number, tab_width);
FT_Done_FreeType(ft);
return(true);
}
internal b32
font_load_freetype(Partition *part, Render_Font *font, char *filename, i32 pt_size, i32 tab_width, b32 use_hinting){
memset(font, 0, sizeof(*font));
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
// set size & metrics
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
font->loaded = true;
font->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
font->descent = floor32 (face->size->metrics.descender / 64.0f);
font->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
font->height = ceil32 (face->size->metrics.height / 64.0f);
font->line_skip = font->height - (font->ascent - font->descent);
font->height -= font->line_skip;
font->line_skip = 0;
// NOTE(allen): set texture and glyph data.
Glyph_Page *page = font_get_or_make_page(font, 0);
font_load_freetype_page_inner(part, font, ft, face, use_hinting, page, 0, tab_width);
// NOTE(allen): Setup some basic spacing stuff.
f32 backslash_adv = get_codepoint_advance(font, '\\');
f32 max_hex_advance = 0.f;
for (u32 i = '0'; i <= '9'; ++i){
f32 adv = get_codepoint_advance(font, i);
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'a'; i <= 'f'; ++i){
f32 adv = get_codepoint_advance(font, i);
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = get_codepoint_advance(font, i);
max_hex_advance = Max(max_hex_advance, adv);
}
font->byte_advance = backslash_adv + max_hex_advance*2;
FT_Done_FreeType(ft);
return(true);
}
internal
Release_Font_Sig(draw_release_font){
for (u32 i = 0; i < ArrayCount(font->glyph_pages); ++i){
Glyph_Page *page = &font->glyph_pages[i];
if (page->exists){
for (u32 i = 0; i < ArrayCount(font->pages); ++i){
Glyph_Page *page = font->pages[i];
if (IS_REAL_FONT_PAGE(page)){
glDeleteTextures(1, &page->tex);
FREE(page);
}
page->tex = 0;
FREE(font->pages);
}
}

View File

@ -60,33 +60,44 @@ typedef double f64;
#define Min(a,b) (((a)<(b))?(a):(b))
inline i32 ceil32(f32 v){
return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ));
}
inline i32 floor32(f32 v){
return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ));
}
inline i32 round32(f32 v){
return(floor32(v + 0.5f));
}
inline i32 trun32(f32 v){
return((i32)(v));
}
inline i32 div_ceil(i32 n, i32 d){
return( ((n) % (d) != 0) + ((n) / (d)) );
}
inline i32 l_round_up_i32(i32 x, i32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
inline u32 l_round_up_u32(u32 x, u32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ));
}
inline i32 floor32(f32 v){
return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ));
}
inline i32 round32(f32 v){
return(floor32(v + 0.5f));
}
inline i32 trun32(f32 v){
return((i32)(v));
}
inline i32 div_ceil(i32 n, i32 d){
return( ((n) % (d) != 0) + ((n) / (d)) );
}
inline i32 l_round_up_i32(i32 x, i32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
inline u32 l_round_up_u32(u32 x, u32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
inline u32 round_up_pot_u32(u32 x){
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
++x;
return(x);
}
#define STR__(s) #s
#define STR_(s) STR__(s)

View File

@ -13,7 +13,7 @@
// Buffer low level operations
//
#include "../file/4coder_font_data.h"
#include "../font/4coder_font_data.h"
#include "../4coder_helper/4coder_seek_types.h"
typedef struct Cursor_With_Index{
@ -1093,12 +1093,16 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
if (!S.skipping_whitespace){
S.current_adv = 2.f;
#if 0
if (S.tran.do_codepoint_advance){
S.current_adv = get_codepoint_advance(params.font, S.tran.step_current.value);
}
else{
S.current_adv = params.font->byte_advance;
}
#endif
S.did_wrap = false;
if (S.i >= S.wrap_unit_end){
@ -1779,12 +1783,16 @@ 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){
S.ch_width = 2.f;
#if 0
if (S.tran.do_codepoint_advance){
S.ch_width = get_codepoint_advance(params.font, S.tran.step_current.value);
}
else{
S.ch_width = params.font->byte_advance;
}
#endif
if (S.tran.step_current.i >= S.wrap_unit_end){
S_stop.status = BLStatus_NeedWrapDetermination;
@ -1979,7 +1987,12 @@ typedef struct Render_Item_Write{
inline Render_Item_Write
write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
#if 0
f32 ch_width = get_codepoint_advance(write.font, glyphid);
#endif
f32 ch_width = 2.f;
if (write.x <= write.x_max && write.x + ch_width >= write.x_min){
write.item->index = index;
@ -2191,7 +2204,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
case '\t':
{
#if 0
S.ch_width = get_codepoint_advance(params.font, '\t');
#endif
S.ch_width = 2.f;
f32 new_x = S.write.x + S.ch_width;
S.write = write_render_item(S.write, I, ' ', 0);
S.write.x = new_x;

View File

@ -1,137 +0,0 @@
/*
* 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

56
font/4coder_font_data.h Normal file
View File

@ -0,0 +1,56 @@
/*
* 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 ITEM_PER_FONT_PAGE 256
struct Glyph_Bounds{
f32 x0, x1;
f32 y0, y1;
f32 xoff, yoff;
f32 xoff2, yoff2;
};
global_const Glyph_Bounds null_glyph_bounds = {0};
struct Glyph_Data{
Glyph_Bounds bounds;
u32 tex;
i32 tex_width, tex_height;
};
struct Glyph_Page{
u32 page_number;
u32 tex;
i32 tex_width, tex_height;
Glyph_Bounds glyphs[ITEM_PER_FONT_PAGE];
f32 advance[ITEM_PER_FONT_PAGE];
};
struct Render_Font{
char name_[24];
String name;
b32 loaded;
Glyph_Page **pages;
u32 page_count, page_max;
f32 byte_advance;
i32 height, ascent, descent, line_skip;
i32 advance;
};
#endif
// BOTTOM

View File

@ -0,0 +1,493 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 10.03.2017
*
* Where I save crappy old font stuff.
*
*/
// TOP
#include "font/4coder_font_data.h"
struct Font_Table_Entry{
u32 hash;
String name;
i16 font_id;
};
struct Font_Info{
Render_Font *font;
String filename;
String name;
i32 pt_size;
};
struct Font_Slot{
Font_Slot *next, *prev;
i16 font_id;
u8 padding[6];
};
global_const Font_Slot null_font_slot = {0};
#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 Font_Load_Page_Sig(name)\
i32 name(Render_Font *font, Glyph_Page *page, char *filename, i32 pt_size, i32 tab_width)
typedef Font_Load_Page_Sig(Font_Load_Page);
#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;
Font_Load_Page *font_load_page;
Release_Font *release_font;
b8 *font_used_flags;
i16 used_this_frame;
i16 live_max;
};
inline Font_Info*
get_font_info(Font_Set *set, i16 font_id){
Font_Info *result = set->info + font_id - 1;
return(result);
}
internal void
font_set_begin_render(Font_Set *font_set){
font_set->used_this_frame = 0;
memset(font_set->font_used_flags, 0, font_set->max);
}
inline u32
font_hash(String name){
u32 x = 5381;
char *p = name.str;
for (i32 i = 0; i < name.size; ++i, ++p){
x = ((x << 5) + x) ^ (*p);
}
return(x);
}
inline void
font__insert(Font_Slot *pos, Font_Slot *slot){
Font_Slot *nex;
nex = pos->next;
slot->next = nex;
slot->prev = pos;
nex->prev = slot;
pos->next = slot;
}
inline void
font__remove(Font_Slot *slot){
Font_Slot *n, *p;
n = slot->next;
p = slot->prev;
p->next = n;
n->prev = p;
}
internal void
font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
partition_align(partition, 8);
set->info = push_array(partition, Font_Info, max);
partition_align(partition, 8);
set->entries = push_array(partition, Font_Table_Entry, max);
set->count = 0;
set->max = max;
partition_align(partition, 8);
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
set->free_slots = null_font_slot;
set->used_slots = null_font_slot;
dll_init_sentinel(&set->free_slots);
dll_init_sentinel(&set->used_slots);
char *ptr = (char*)set->font_block;
for (i32 i = 0; i < live_max; ++i){
dll_insert(&set->free_slots, (Font_Slot*)ptr);
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
}
set->font_used_flags = push_array(partition, b8, max);
set->live_max = live_max;
}
internal b32
font_set_can_add(Font_Set *set){
b32 result = 0;
if (set->count*8 < set->max*7) result = 1;
return(result);
}
internal void
font_set_add_hash(Font_Set *set, String name, i16 font_id){
Font_Table_Entry entry;
entry.hash = font_hash(name);
entry.name = name;
entry.font_id = font_id;
u32 i = entry.hash % set->max;
u32 j = i - 1;
if (i <= 1) j += set->max;
for (; i != j; ++i){
if (i == set->max) i = 0;
if (set->entries[i].font_id == 0){
set->entries[i] = entry;
break;
}
}
Assert(i != j);
}
inline b32
font_set_can_load(Font_Set *set){
b32 result = (set->free_slots.next != &set->free_slots);
return(result);
}
internal void
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);
font__remove(slot);
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);
info->font = font;
slot->font_id = font_id;
}
internal void
font_set_evict_lru(Font_Set *set){
Font_Slot *slot = set->used_slots.prev;
Assert(slot != &set->used_slots);
i16 font_id = slot->font_id;
Font_Info *info = get_font_info(set, font_id);
Assert(((Font_Slot*)info->font) - 1 == slot);
set->release_font(info->font);
info->font = 0;
slot->font_id = 0;
font__remove(slot);
font__insert(&set->free_slots, slot);
}
internal void
font_set_use(Font_Set *set, i16 font_id){
b8 already_used = set->font_used_flags[font_id-1];
if (!already_used){
if (set->used_this_frame < set->live_max){
++set->used_this_frame;
set->font_used_flags[font_id-1] = 1;
already_used = 1;
}
}
if (already_used){
// TODO(allen): optimize if you don't mind!!!!
Font_Info *info = get_font_info(set, font_id);
Font_Slot *slot;
if (info->font == 0){
if (!font_set_can_load(set)){
font_set_evict_lru(set);
}
font_set_load(set, font_id);
}
slot = ((Font_Slot*)info->font) - 1;
font__remove(slot);
font__insert(&set->used_slots, slot);
}
}
internal b32
font_set_add(Font_Set *set, String filename, String name, i32 pt_size){
b32 result = false;
if (font_set_can_add(set)){
Render_Font dummy_font = {0};
i16 font_id = (i16)(++set->count);
Font_Info *info = get_font_info(set, font_id);
info->filename = filename;
info->name = name;
info->pt_size = pt_size;
set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false);
font_set_add_hash(set, name, font_id);
if (font_set_can_load(set)){
font_set_load(set, font_id);
}
result = true;
}
return(result);
}
internal b32
font_set_find_pos(Font_Set *set, String name, u32 *position){
u32 hash = font_hash(name);
u32 i = hash % set->max;
u32 j = i - 1;
if (j <= 1){
j += set->max;
}
b32 result = 0;
for (; i != j; ++i){
if (i == set->max){
i = 0;
}
Font_Table_Entry *entry = set->entries + i;
if (entry->hash == hash){
if (match_ss(name, entry->name)){
result = 1;
*position = i;
break;
}
}
}
return(result);
}
internal b32
font_set_get_name(Font_Set *set, i16 font_id, String *name){
Font_Info *info = get_font_info(set, font_id);
b32 result = copy_checked_ss(name, info->name);
return(result);
}
internal b32
font_set_extract(Font_Set *set, String name, i16 *font_id){
u32 position;
b32 result = font_set_find_pos(set, name, &position);
if (result){
*font_id = set->entries[position].font_id;
}
return(result);
}
//////////////////////////////////
internal b32
get_codepoint_can_render(Render_Font *font, u32 codepoint){
b32 exists = false;
if (codepoint < 0x10FFFF){
exists = true;
}
return(exists);
}
struct Codepoint_Indexes{
b32 exists;
u32 page_number;
u32 glyph_index;
};
internal Codepoint_Indexes
get_codepoint_page_number(Render_Font *font, u32 codepoint){
Codepoint_Indexes result = {0};
u32 page_number = (codepoint >> 8);
if (page_number <= 0x10FF){
result.exists = true;
result.page_number = page_number;
result.glyph_index = (codepoint & 0x000000FF);
}
return(result);
}
#define MAX_PAGE_COUNT (u32)(0x1100)
#define GLYPH_PAGE_EMPTY ((Glyph_Page*)(0))
#define GLYPH_PAGE_DELETED ((Glyph_Page*)(max_u64))
#define IS_REAL_FONT_PAGE(p) (((p) != GLYPH_PAGE_EMPTY) && ((p) != GLYPH_PAGE_DELETED))
internal Glyph_Page**
font_lookup_page(Render_Font *font, u32 page_number, b32 find_empty_slot){
Glyph_Page **result = 0;
if (font->page_max > 0){
u32 first_index = page_number % font->page_max;
u32 range_count = 0;
u32 ranges[4];
if (first_index == 0){
ranges[0] = 0;
ranges[1] = font->page_max;
range_count = 2;
}
else{
ranges[0] = first_index;
ranges[1] = font->page_max;
ranges[2] = 0;
ranges[3] = first_index;
range_count = 4;
}
if (find_empty_slot){
for(u32 j = 0; j < range_count; j += 2){
u32 start = ranges[j];
u32 stop = ranges[j+1];
for (u32 i = start; i < stop; ++i){
Glyph_Page *ptr = font->pages[i];
if (ptr == GLYPH_PAGE_EMPTY || ptr == GLYPH_PAGE_DELETED){
result = &font->pages[i];
goto break2;
}
if (ptr->page_number == page_number){
goto break2;
}
}
}
}
else{
for(u32 j = 0; j < range_count; j += 2){
u32 start = ranges[j];
u32 stop = ranges[j+1];
for (u32 i = start; i < stop; ++i){
Glyph_Page *ptr = font->pages[i];
if (ptr == GLYPH_PAGE_EMPTY){
goto break2;
}
if (ptr != GLYPH_PAGE_DELETED){
if (ptr->page_number == page_number){
result = &font->pages[i];
goto break2;
}
}
}
}
}
break2:;
}
return(result);
}
internal Glyph_Page*
font_get_or_make_page(Render_Font *font, u32 page_number){
Glyph_Page *page = 0;
if (page_number <= 0x10FF){
Glyph_Page **page_ptr = font_lookup_page(font, page_number, false);
page = 0;
if (page_ptr != 0){
page = *page_ptr;
}
if (page == 0){
u32 new_count = 1;
if (font->page_max < MAX_PAGE_COUNT && (font->page_count+new_count)*3 < font->page_max*2){
u32 new_page_max = (font->page_count+new_count)*3;
new_page_max = clamp_top(new_page_max, MAX_PAGE_COUNT);
Glyph_Page **new_pages = (Glyph_Page**)ALLOCATE(new_page_max * sizeof(Glyph_Page*));
u32 old_page_max = font->page_max;
Glyph_Page **pages = font->pages;
for (u32 i = 0; i < old_page_max; ++i){
Glyph_Page *current_page = pages[i];
if (current_page != GLYPH_PAGE_EMPTY && current_page != GLYPH_PAGE_DELETED){
Glyph_Page **dest = font_lookup_page(font, current_page->page_number, true);
Assert(dest != 0);
*dest = current_page;
}
}
FREE(font->pages);
font->pages = new_pages;
font->page_max = new_page_max;
}
Glyph_Page *new_page = (Glyph_Page*)ALLOCATE(sizeof(Glyph_Page));
Glyph_Page **dest = font_lookup_page(font, page_number, true);
*dest = new_page;
++font->page_count;
//set->font_load_page(font, new_page, );
}
}
return(page);
}
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)){
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
bounds = &page->glyphs[indexes.glyph_index];
advance = &page->advance[indexes.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)){
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
data_out->bounds = page->glyphs[indexes.glyph_index];
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)){
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
advance = page->advance[indexes.glyph_index];
}
return(advance);
}
internal b32
set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){
b32 success = false;
if (get_codepoint_can_render(font, codepoint)){
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
page->advance[indexes.glyph_index] = value;
success = true;
}
return(success);
}
// BOTTOM

View File

@ -103,7 +103,6 @@
#endif
#define SUPPORT_DPI 1
#define LINUX_FONTS 1
#define InterlockedCompareExchange(dest, ex, comp) __sync_val_compare_and_swap((dest), (comp), (ex))
@ -1359,27 +1358,14 @@ Font_Load_Sig(system_draw_font_load){
linuxvars.font_part = sysshared_scratch_partition(MB(8));
}
i32 oversample = 2;
#if SUPPORT_DPI
pt_size = round32(pt_size * size_change(linuxvars.dpi_x, linuxvars.dpi_y));
#endif
for(; attempts < 3; ++attempts){
#if LINUX_FONTS
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = linux_font_load(&linuxvars.font_part, font_out, filename, pt_size, tab_width,
linuxvars.settings.use_hinting);
#else
success = font_load(
&linuxvars.font_part,
font_out,
filename,
pt_size,
tab_width,
oversample,
store_texture
);
#endif
if(success){
break;
@ -1389,7 +1375,7 @@ Font_Load_Sig(system_draw_font_load){
}
}
return success;
return(success);
}
//

View File

@ -1,3 +1,14 @@
/*
* Insofaras
*
* ??.??.2016
*
* For getting the font files on Linux.
*
*/
// TOP
#undef internal
#include <fontconfig/fontconfig.h>
#define internal static
@ -8,26 +19,26 @@ static FcConfig* fc;
internal char*
linux_get_sys_font(char* name, i32 pt_size){
char* result = 0;
if(!fc){
fc = FcInitLoadConfigAndFonts();
}
FcPattern* pat = FcPatternBuild(
NULL,
FC_POSTSCRIPT_NAME, FcTypeString, name,
FC_SIZE, FcTypeDouble, (double)pt_size,
FC_FONTFORMAT, FcTypeString, "TrueType",
NULL
);
);
FcConfigSubstitute(fc, pat, FcMatchPattern);
FcDefaultSubstitute(pat);
FcResult res;
FcPattern* font = FcFontMatch(fc, pat, &res);
FcChar8* fname = 0;
if(font){
FcPatternGetString(font, FC_FILE, 0, &fname);
if(fname){
@ -36,9 +47,9 @@ linux_get_sys_font(char* name, i32 pt_size){
}
FcPatternDestroy(font);
}
FcPatternDestroy(pat);
if(!result){
char space[1024];
String str = make_fixed_width_string(space);
@ -48,16 +59,16 @@ linux_get_sys_font(char* name, i32 pt_size){
result = strdup(name);
}
}
return result;
}
internal b32
linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){
b32 result = 0;
Temp_Memory temp = begin_temp_memory(part);
#if 0
char* filename = linux_get_sys_font(name, pt_size);
#else
@ -67,22 +78,25 @@ linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 t
sysshared_to_binary_path(&str, name);
}
#endif
if (filename != 0){
struct stat st;
if(stat(filename, &st) == -1 || S_ISDIR(st.st_mode)){
char buff[1024];
// NOTE(inso): if/when you can load fonts from anywhere, the message should be changed.
snprintf(buff, sizeof(buff), "Unable to load font '%s'. Make sure this file is in the same directory as the '4ed' executable.", filename);
LinuxFatalErrorMsg(buff);
exit(1);
}
result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting);
}
end_temp_memory(temp);
return(result);
}
// BOTTOM

View File

@ -67,7 +67,6 @@
#include "4ed_system_shared.h"
#define SUPPORT_DPI 1
#define USE_FT_FONTS 1
#define FPS 60
#define frame_useconds (1000000 / FPS)
@ -1392,9 +1391,7 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
#include "4ed_system_shared.cpp"
#if USE_FT_FONTS
# include "win32_ft_font.cpp"
#endif
#include "win32_ft_font.cpp"
internal f32
size_change(i32 dpi_x, i32 dpi_y){
@ -1406,60 +1403,29 @@ size_change(i32 dpi_x, i32 dpi_y){
}
internal
Font_Load_Sig(system_draw_font_load){
Font_Load_Sig(font_load){
if (win32vars.font_part.base == 0){
win32vars.font_part = Win32ScratchPartition(MB(8));
}
i32 oversample = 2;
AllowLocal(oversample);
#if SUPPORT_DPI
pt_size = round32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y));
#endif
for (b32 success = 0; success == 0;){
#if USE_WIN32_FONTS
// TODO(allen): Make the growable partition something that can just be passed directly to font load and let it be grown there.
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = win32_ft_font_load(&win32vars.font_part, font_out, filename, pt_size, tab_width,win32vars.settings.use_hinting);
success = win32_font_load(&win32vars.font_part,
font_out,
filename,
fontname,
pt_size,
tab_width,
oversample,
store_texture);
#elif USE_FT_FONTS
success = win32_ft_font_load(&win32vars.font_part,
font_out,
filename,
pt_size,
tab_width,
win32vars.settings.use_hinting);
#else
success = stb_font_load(&win32vars.font_part,
font_out,
filename,
pt_size,
tab_width,
oversample,
store_texture);
#endif
// TODO(allen): Make the growable partition something
// that can just be passed directly to font load and
// let it be grown there.
if (!success){
if (success){
break;
}
else{
Win32ScratchPartitionDouble(&win32vars.font_part);
}
}
return(1);
return(success);
}
//
@ -1541,7 +1507,7 @@ Win32LoadRenderCode(){
win32vars.target.pop_clip = draw_pop_clip;
win32vars.target.push_piece = draw_push_piece;
win32vars.target.font_set.font_load = system_draw_font_load;
win32vars.target.font_set.font_load = font_load;
win32vars.target.font_set.release_font = draw_release_font;
}

View File

@ -1,29 +1,29 @@
// NOTE(allen): Thanks to insofaras.
// This is copy-pasted from some work he
// did to get free type working on linux.
// Once it is working on both sides it might
// be possible to pull some parts out as
// portable FT rendering.
/*
* Mr. 4th Dimention - Allen Webster
*
* ??.??.2016
*
* For getting the font files on Linux.
*
*/
// TOP
// TODO(allen): Get system fonts
internal b32
win32_ft_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){
b32 result = 0;
Temp_Memory temp = begin_temp_memory(part);
char* filename = push_array(part, char, 256);
b32 result = false;
if (filename != 0){
String str = make_string_cap(filename, 0, 256);
sysshared_to_binary_path(&str, name);
result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting);
}
end_temp_memory(temp);
return(result);
}
// BOTTOM