utf8 encoded buffers fully working on windows

master
Allen Webster 2017-02-20 16:05:42 -05:00
parent 59267a6418
commit 67f6e7b743
18 changed files with 915 additions and 519 deletions

View File

@ -19,7 +19,7 @@
/* DOC(bool32 is an alias name to signal that an integer parameter or field is for true/false values.) */
TYPEDEF int32_t bool32;
/* DOC(int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.) */
/* DOC(int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 32 bit integers (8 bit + 24 bit) with 3 channels: 0x**RRGGBB.) */
TYPEDEF uint32_t int_color;
/* DOC(Buffer_ID is used to name a 4coder buffer. Each buffer has a unique id but when a buffer is closed it's id may be recycled by future, different buffers.) */

View File

@ -25,16 +25,17 @@ CUSTOM_COMMAND_SIG(write_character){
User_Input in = get_command_input(app);
char character = 0;
uint8_t character[4];
uint32_t length = 0;
if (in.type == UserInputKey){
character = to_writable_char(in.key.character);
u32_to_utf8_unchecked(in.key.character, character, &length);
}
if (character != 0){
if (length != 0){
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
int32_t pos = view.cursor.pos;
buffer_replace_range(app, &buffer, pos, pos, &character, 1);
view_set_cursor(app, &view, seek_pos(view.cursor.pos + 1), true);
buffer_replace_range(app, &buffer, pos, pos, (char*)character, length);
view_set_cursor(app, &view, seek_character_pos(view.cursor.character_pos + 1), true);
}
}

View File

@ -151,7 +151,7 @@ inline char
buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
char result = ' ';
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
if (pos >= 0 && pos < buffer->size){
if (pos < buffer->size){
buffer_read_range(app, buffer, pos, pos+1, &result);
}
return(result);

View File

@ -17,7 +17,7 @@ struct Stream_Chunk{
int32_t start, end;
int32_t min_start, max_end;
bool32 add_null;
int32_t data_size;
uint32_t data_size;
char *data;
};
@ -42,7 +42,7 @@ round_up(int32_t x, int32_t b){
static bool32
init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer,
int32_t pos, char *data, int32_t size){
int32_t pos, char *data, uint32_t size){
bool32 result = 0;
refresh_buffer(app, buffer);

View File

@ -41,31 +41,137 @@ typedef int32_t b32_4tech;
// standard preamble end
static u32_4tech
utf8_to_u32_unchecked(u8_4tech *buffer){
utf8_to_u32_length_unchecked(u8_4tech *buffer, u32_4tech *length_out){
u32_4tech result = 0;
if (buffer[0] <= 0x7F){
result = (u32_4tech)buffer[0];
*length_out = 1;
}
else if (buffer[0] <= 0xE0){
result = ((u32_4tech)((buffer[0])&0x1F)) << 6;
result |= ((u32_4tech)((buffer[1])&0x3F));
*length_out = 2;
}
else if (buffer[0] <= 0xF0){
result = ((u32_4tech)((buffer[0])&0x0F)) << 12;
result |= ((u32_4tech)((buffer[1])&0x3F)) << 6;
result |= ((u32_4tech)((buffer[2])&0x3F));
*length_out = 3;
}
else{
result = ((u32_4tech)((buffer[0])&0x07)) << 18;
result |= ((u32_4tech)((buffer[1])&0x3F)) << 12;
result |= ((u32_4tech)((buffer[2])&0x3F)) << 6;
result |= ((u32_4tech)((buffer[3])&0x3F));
*length_out = 4;
}
return(result);
}
static u32_4tech
utf8_to_u32_unchecked(u8_4tech *buffer){
u32_4tech ignore;
u32_4tech result = utf8_to_u32_length_unchecked(buffer, &ignore);
return(result);
}
static u32_4tech
utf8_to_u32(u8_4tech **buffer_ptr, u8_4tech *end){
u8_4tech *buffer = *buffer_ptr;
u32_4tech limit = (u32_4tech)(end - buffer);
u32_4tech length = 0;
if (buffer[0] < 0x80){
length = 1;
}
else if (buffer[0] < 0xC0){
length = 0;
}
else if (buffer[0] < 0xE0){
length = 2;
}
else if (buffer[0] < 0xF0){
length = 3;
}
else{
length = 4;
}
for (u32_4tech i = 1; i < length; ++i){
if ((buffer[i] & 0xC0) != 0x80){
length = 0;
break;
}
}
u32_4tech result = 0;
if (length != 0 && length <= limit){
switch (length){
case 1:
{
result = (u32_4tech)buffer[0];
}break;
case 2:
{
result = ((u32_4tech)((buffer[0])&0x1F)) << 6;
result |= ((u32_4tech)((buffer[1])&0x3F));
}break;
case 3:
{
result = ((u32_4tech)((buffer[0])&0x0F)) << 12;
result |= ((u32_4tech)((buffer[1])&0x3F)) << 6;
result |= ((u32_4tech)((buffer[2])&0x3F));
}break;
case 4:
{
result = ((u32_4tech)((buffer[0])&0x07)) << 18;
result |= ((u32_4tech)((buffer[1])&0x3F)) << 12;
result |= ((u32_4tech)((buffer[2])&0x3F)) << 6;
result |= ((u32_4tech)((buffer[3])&0x3F));
}break;
}
*buffer_ptr = buffer + length;
}
else{
*buffer_ptr = end;
}
return(result);
}
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;
*length_out = 1;
}
else if (code_point <= 0x7FF){
buffer[0] = (u8_4tech)(0xC0 | (code_point >> 6));
buffer[1] = (u8_4tech)(0x80 | (code_point & 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));
*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));
*length_out = 4;
}
}
static umem_4tech
utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *src, umem_4tech length, b32_4tech *error){
u8_4tech *s = src;
@ -247,6 +353,22 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
return(needed_max);
}
static void
byte_to_ascii(u8_4tech n, u8_4tech *out){
u8_4tech C = '0' + (n / 0x10);
if ((n / 0x10) > 0x9){
C = ('A' - 0xA) + (n / 0x10);
}
out[0] = C;
n = (n % 0x10);
C = '0' + n;
if (n > 0x9){
C = ('A' - 0xA) + n;
}
out[1] = C;
}
#endif
// BOTTOM

View File

@ -2361,6 +2361,10 @@ App_Step_Sig(app_step){
"If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n"
"\n"
"Newest features:\n"
"-New support for extended ascii input.\n"
"-Extended ascii encoded in buffers as utf8.\n"
"\n"
"New in alpha 4.0.16:\n"
"-<alt 2> If the current file is a C++ code file, this opens the matching header.\n"" If the current file is a C++ header, this opens the matching code file.\n"
"-Option to automatically save changes on build in the config file.\n"
" This works for builds triggered by <alt m>.\n"

View File

@ -786,7 +786,7 @@ 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_display_width_and_fix_cursor(models, file, new_value, (f32)font->height, font->advance_data);
file_set_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
}
}break;
@ -799,7 +799,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_minimum_base_display_width_and_fix_cursor(models, file, new_value, (f32)font->height, font->advance_data);
file_set_min_base_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
}
}break;
@ -888,7 +888,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->advance_data);
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
file_update_cursor_positions(models, file);
}
}break;
@ -2071,12 +2071,9 @@ Set_Theme_Colors(Application_Links *app, Theme_Color *colors, int32_t count)
/*
DOC_PARAM(colors, The colors pointer provides an array of color structs pairing differet style tags to color codes.)
DOC_PARAM(count, The count parameter specifies the number of Theme_Color structs in the colors array.)
DOC
(
For each struct in the array, the slot in the main color pallet specified by the
struct's tag is set to the color code in the struct. If the tag value is invalid
no change is made to the color pallet.
)
DOC(
For each struct in the array, the slot in the main color pallet specified by the struct's tag is set to the color code in the struct. If the tag value is invalid no change is made to the color pallet.)
DOC_SEE(Theme_Color)
*/{
Command_Data *cmd = (Command_Data*)app->cmd_context;
Style *style = main_style(cmd->models);
@ -2098,11 +2095,8 @@ Get_Theme_Colors(Application_Links *app, Theme_Color *colors, int32_t count)
/*
DOC_PARAM(colors, an array of color structs listing style tags to get color values for)
DOC_PARAM(count, the number of color structs in the colors array)
DOC(
For each struct in the array, the color field of the struct is filled with the
color from the slot in the main color pallet specified by the tag. If the tag
value is invalid the color is filled with black.
)
DOC(For each struct in the array, the color field of the struct is filled with the color from the slot in the main color pallet specified by the tag. If the tag value is invalid the color is filled with black.)
DOC_SEE(Theme_Color)
*/{
Command_Data *cmd = (Command_Data*)app->cmd_context;
Style *style = main_style(cmd->models);

View File

@ -28,6 +28,7 @@
#include "4coder_lib/4coder_string.h"
#include "4coder_lib/4coder_mem.h"
#include "4coder_lib/4coder_table.h"
#include "4coder_lib/4coder_utf8.h"
#if defined(USE_DEBUG_MEMORY)
# include "4ed_debug_mem.h"
#endif

View File

@ -396,7 +396,8 @@ view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){
params.buffer = &file->state.buffer;
params.seek = seek;
params.font_height = (f32)font->height;
params.adv = font->advance_data;
params.cp_adv = font->codepoint_advance_data;
params.byte_adv = font->byte_advance;
params.wrap_line_index = file->state.wrap_line_index;
params.character_starts = file->state.character_starts;
params.virtual_white = file->settings.virtual_white;
@ -1007,14 +1008,18 @@ struct Code_Wrap_State{
b32 consume_newline;
Gap_Buffer_Stream stream;
i32 size;
i32 i;
f32 *adv;
f32 *cp_adv;
f32 byte_adv;
f32 tab_indent_amount;
Buffer_Translating_State tran;
};
internal void
wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *adv){
wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byte_adv){
state->token_array = file->state.token_array;
state->token_ptr = state->token_array.tokens;
state->end_token = state->token_ptr + state->token_array.count;
@ -1025,9 +1030,14 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *adv){
Gap_Buffer *buffer = &file->state.buffer;
i32 size = buffer_size(buffer);
buffer_stringify_loop(&state->stream, buffer, 0, size);
state->size = size;
state->i = 0;
state->adv = adv;
state->tab_indent_amount = adv['\t'];
state->cp_adv = cp_adv;
state->byte_adv = byte_adv;
state->tab_indent_amount = cp_adv['\t'];
state->tran = null_buffer_translating_state;
}
internal void
@ -1085,11 +1095,11 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){
}
}
b32 skipping_whitespace = 0;
b32 skipping_whitespace = false;
if (i >= state->next_line_start){
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
skipping_whitespace = 1;
skipping_whitespace = true;
}
// TODO(allen): exponential search this shit!
@ -1111,34 +1121,49 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){
}
if (i == line_start){
skipping_whitespace = 1;
skipping_whitespace = true;
}
b32 recorded_start_x = 0;
b32 recorded_start_x = false;
do{
for (; i < state->stream.end; ++i){
if (!(i < end)){
Assert(state->tran.fill_expected == 0);
goto doublebreak;
}
u8 ch = (u8)state->stream.data[i];
if (ch != ' ' && ch != '\t'){
skipping_whitespace = 0;
}
translating_consume_byte(&state->tran, ch, i, state->size);
if (!skipping_whitespace){
if (ch == '\n'){
for (TRANSLATION_OUTPUT(&state->tran)){
TRANSLATION_GET_STEP(&state->tran);
if (state->tran.do_newline){
state->consume_newline = 1;
goto doublebreak;
}
else{
if (!recorded_start_x){
result.start_x = state->x;
recorded_start_x = 1;
else if(state->tran.do_number_advance || state->tran.do_codepoint_advance){
u32 n = state->tran.step_current.value;
f32 adv = 0;
if (state->tran.do_codepoint_advance){
adv = state->cp_adv[n];
if (n != ' ' && n != '\t'){
skipping_whitespace = false;
}
}
else{
adv = state->byte_adv;
skipping_whitespace = false;
}
state->x += state->adv[ch];
if (!skipping_whitespace){
if (!recorded_start_x){
result.start_x = state->x;
recorded_start_x = 1;
}
state->x += adv;
}
}
}
}
@ -1425,7 +1450,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 *adv){
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){
General_Memory *general = &models->mem.general;
Partition *part = &models->mem.part;
@ -1438,7 +1463,8 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
Buffer_Measure_Wrap_Params params;
params.buffer = &file->state.buffer;
params.wrap_line_index = file->state.wrap_line_index;
params.adv = adv;
params.cp_adv = cp_adv;
params.byte_adv = byte_adv;
params.virtual_white = file->settings.virtual_white;
f32 width = (f32)file->settings.display_width;
@ -1468,8 +1494,9 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
Wrap_Indent_Pair *wrap_indent_marks = 0;
Potential_Wrap_Indent_Pair *potential_marks = 0;
i32 max_wrap_indent_mark = 0;
if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){
wrap_state_init(&wrap_state, file, adv);
wrap_state_init(&wrap_state, file, cp_adv, byte_adv);
use_tokens = 1;
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width));
@ -1521,7 +1548,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
word_stage = 1;
}
else{
f32 adv = params.adv[ch];
f32 adv = params.cp_adv[ch];
x += adv;
self_x += adv;
if (self_x > width){
@ -1648,7 +1675,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
goto doublebreak_stage1;
}
f32 adv = params.adv[ch];
f32 adv = params.cp_adv[ch];
x += adv;
if (!first_word && x > current_width){
emit_comment_position = 1;
@ -1674,7 +1701,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
goto doublebreak_stage2;
}
f32 adv = params.adv[ch];
f32 adv = params.cp_adv[ch];
x += adv;
}
still_looping = buffer_stringify_next(&stream);
@ -1881,21 +1908,21 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
}
internal void
file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, f32 font_height, f32 *adv){
file_measure_wraps(models, file, font_height, adv);
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_update_cursor_positions(models, file);
}
internal void
file_set_display_width_and_fix_cursor(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *adv){
file_set_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){
file->settings.display_width = display_width;
file_measure_wraps_and_fix_cursor(models, file, font_height, adv);
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
}
internal void
file_set_minimum_base_display_width_and_fix_cursor(Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *adv){
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->settings.minimum_base_display_width = minimum_base_display_width;
file_measure_wraps_and_fix_cursor(models, file, font_height, adv);
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
}
//
@ -1944,7 +1971,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->advance_data);
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
file->settings.read_only = read_only;
if (!read_only){
@ -3215,7 +3242,7 @@ file_do_single_edit(System_Functions *system, Models *models, Editing_File *file
(f32)file->settings.display_width);
#endif
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
// NOTE(allen): cursor fixing
Cursor_Fix_Descriptor desc = {};
@ -3330,16 +3357,14 @@ 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->advance_data);
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
// NOTE(allen): cursor fixing
{
Cursor_Fix_Descriptor desc = {};
desc.is_batch = 1;
desc.batch = batch;
desc.batch_size = batch_size;
file_edit_cursor_fix(system, models, file, layout, desc);
}
Cursor_Fix_Descriptor desc = {0};
desc.is_batch = 1;
desc.batch = batch;
desc.batch_size = batch_size;
file_edit_cursor_fix(system, models, file, layout, desc);
}
inline void
@ -3697,7 +3722,7 @@ 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->advance_data);
file_measure_wraps_and_fix_cursor(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
Editing_Layout *layout = &models->layout;
for (View_Iter iter = file_view_iter_init(layout, file, 0);
@ -5966,7 +5991,6 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
i16 font_id = file->settings.font_id;
Render_Font *font = get_font_info(models->font_set, font_id)->font;
float *advance_data = font->advance_data;
f32 scroll_x = view->edit_pos->scroll.scroll_x;
f32 scroll_y = view->edit_pos->scroll.scroll_y;
@ -6005,7 +6029,8 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
params.start_cursor = render_cursor;
params.wrapped = wrapped;
params.font_height = (f32)line_height;
params.adv = advance_data;
params.cp_adv = font->codepoint_advance_data;
params.byte_adv = font->byte_advance;
params.virtual_white = file->settings.virtual_white;
params.wrap_slashes = file->settings.wrap_indicator;
@ -6162,8 +6187,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
draw_rectangle_outline(target, char_rect, mark_color);
}
if (item->glyphid != 0){
font_draw_glyph(target, font_id, (u8)item->glyphid,
item->x0, item->y0, char_color);
font_draw_glyph(target, font_id, (u8)item->glyphid, item->x0, item->y0, char_color);
}
prev_ind = ind;
}
@ -6194,8 +6218,7 @@ draw_text_field(Render_Target *target, View *view, i16 font_id,
}
internal void
draw_text_with_cursor(Render_Target *target, View *view, i16 font_id,
i32_Rect rect, String s, i32 pos){
draw_text_with_cursor(Render_Target *target, View *view, i16 font_id, i32_Rect rect, String s, i32 pos){
Models *models = view->persistent.models;
Style *style = main_style(models);
@ -6222,8 +6245,9 @@ draw_text_with_cursor(Render_Target *target, View *view, i16 font_id,
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->advance_data[s.str[pos]]);
cursor_rect.x1 = floor32(x) + ceil32(font->codepoint_advance_data[s.str[pos]]);
cursor_rect.y0 = y;
cursor_rect.y1 = y + view->line_height;
draw_rectangle(target, cursor_rect, cursor_color);

View File

@ -28,7 +28,8 @@ struct Render_Font{
b32 loaded;
Glyph_Data glyphs[256];
f32 advance_data[256];
f32 byte_advance;
f32 codepoint_advance_data[256];
i32 height, ascent, descent, line_skip;
i32 advance;
u32 tex;

View File

@ -116,9 +116,9 @@ font_predict_size(i32 pt_size){
}
internal void
font_draw_glyph_mono(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, f32 advance, u32 color){
font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 x, f32 y, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_mono_glyph;
piece.header.type = type;
piece.glyph.pos.x = x;
piece.glyph.pos.y = y;
piece.glyph.color = color;
@ -128,113 +128,111 @@ font_draw_glyph_mono(Render_Target *target, i16 font_id, u8 character, f32 x, f3
font_set_use(target->partition, &target->font_set, font_id);
}
inline void
font_draw_glyph_mono(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, u32 color){
f32 advance = (f32)get_font_info(&target->font_set, font_id)->advance;
font_draw_glyph_mono(target, font_id, character, x, y, advance, color);
}
internal void
font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_glyph;
piece.glyph.pos.x = x;
piece.glyph.pos.y = y;
piece.glyph.color = color;
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_draw_glyph(target, font_id, piece_type_glyph, character, x, y, color);
}
internal f32
font_string_width(Render_Target *target, i16 font_id, char *str){
f32 x = 0;
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;
f32 *advance_data = font->advance_data;
f32 x = 0;
if (font){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
x += advance_data[c];
f32 y = (f32)y_;
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;
for (;str < str_end;){
u8 *byte = str;
u32 codepoint = utf8_to_u32(&str, str_end);
b32 do_codepoint = false;
b32 do_numbers = false;
if (codepoint){
if (codepoint >= ' ' && codepoint <= 0xFF && codepoint != 127){
do_codepoint = true;
}
else{
do_numbers = true;
}
}
else{
do_numbers = true;
}
if (do_codepoint){
if (color != 0){
font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color);
}
x += codepoint_advance_data[codepoint];
}
else if (do_numbers){
for (;byte < str; ++byte){
u8_4tech n = *byte;
if (color != 0){
u8 cs[3];
cs[0] = '\\';
byte_to_ascii(n, cs+1);
f32 xx = x;
for (u32 j = 0; j < 3; ++j){
font_draw_glyph(target, font_id, type, cs[j], xx, y, color);
xx += byte_advance;
}
}
x += byte_advance;
}
}
}
}
return(x);
}
internal f32
draw_string(Render_Target *target, i16 font_id, String str, i32 x, i32 y, u32 color){
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, x, y, color);
return(w);
}
internal f32
draw_string(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, u32 color){
String string = make_string_slowly(str);
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, x, y, color);
return(w);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id, String str, i32 x, i32 y, f32 advance, u32 color){
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, str, x, y, color);
return(w);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, f32 advance, u32 color){
String string = make_string_slowly(str);
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, string, x, y, color);
return(w);
}
internal f32
font_string_width(Render_Target *target, i16 font_id, String str){
f32 x = 0;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
x += advance_data[c];
}
}
return(x);
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, 0, 0, 0);
return(w);
}
internal f32
draw_string(Render_Target *target, i16 font_id,
char *str, i32 x_, i32 y, u32 color){
f32 x = (f32)x_;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += advance_data[c];
}
}
return(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id, char *str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return(x);
}
internal f32
draw_string(Render_Target *target, i16 font_id, String str, i32 x_, i32 y, u32 color){
f32 x = (f32)x_;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += advance_data[c];
}
}
return(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id, String str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i] % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return(x);
font_string_width(Render_Target *target, i16 font_id, char *str){
String string = make_string_slowly(str);
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, 0, 0, 0);
return(w);
}
// BOTTOM

Binary file not shown.

View File

@ -544,6 +544,7 @@ launch_rendering(Render_Target *target){
#undef ExtractStruct
#if 0
internal void*
part_alloc(i32 size, void *context){
Partition *part = (Partition*)context;
@ -552,8 +553,7 @@ part_alloc(i32 size, void *context){
}
internal void
part_free(void *ptr, void *context){
}
part_free(void *ptr, void *context){}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
@ -561,34 +561,28 @@ part_free(void *ptr, void *context){
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
internal i32
stb_font_load(Partition *part,
Render_Font *font_out,
char *filename_untranslated,
i32 pt_size,
i32 tab_width,
i32 oversample,
b32 store_texture){
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;
i32 result = 1;
b32 result = true;
stbtt_packedchar chardata[256];
File_Data file = sysshared_load_file(filename.str);
if (!file.data){
result = 0;
result = false;
}
else{
stbtt_fontinfo font;
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
result = 0;
result = false;
}
else{
memset(font_out, 0, sizeof(*font_out));
@ -620,19 +614,16 @@ stb_font_load(Partition *part,
/////////////////////////////////////////////////////////////////
stbtt_pack_context spc;
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
tex_width, 1, part)){
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 = 0;
if (!stbtt_PackFontRange(&spc, (u8*)file.data, 0, STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
result = false;
}
stbtt_PackEnd(&spc);
}
else{
result = 0;
result = false;
}
/////////////////////////////////////////////////////////////////
@ -694,6 +685,7 @@ stb_font_load(Partition *part,
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.
@ -826,11 +818,11 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
// TODO(allen): maybe advance data should be integers for a while...
// I require the actual values to be integers anyway... hmm...
rf->advance_data[i] = (f32)ceil32(face->glyph->advance.x / 64.0f);
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
@ -865,40 +857,23 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
pen_x = ceil32(c->x1 + 1);
}
// TODO(allen): advance data is still too stupid.
// Provide an "unedited" version, then generate these
// on the fly. Maybe later introduce a caching system or whatevs.
f32 *adv = rf->advance_data;
for (i32 i = 0; i < 256; ++i){
if (i < ' ' || i == 127){
switch (i){
case '\n':
adv[i] = adv[' '];
break;
case '\r':
adv[i] = adv['\\'] + adv['r'];
break;
case '\t':
adv[i] = adv[' ']*tab_width;
break;
default:
{
int8_t d1 = (int8_t)(i/0x10), d2 = (int8_t)(i%0x10);
char c1 = '0' + d1, c2 = '0' + d2;
if (d1 >= 0xA){
c1 = ('A' - 0xA) + d1;
}
if (d2 >= 0xA){
c2 = ('A' - 0xA) + d2;
}
adv[i] = adv['\\'] + adv[c1] + adv[c2];
}break;
}
}
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;
f32 max_hex_advance = cp_adv['0'];
for (u32 i = '1'; i <= '9'; ++i){
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
}
for (u32 i = 'a'; i <= 'f'; ++i){
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
}
for (u32 i = 'A'; i <= 'F'; ++i){
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
}
rf->byte_advance = cp_adv['\\'] + max_hex_advance*2;
FT_Done_FreeType(ft);

View File

@ -13,5 +13,7 @@ fi
echo "Building custom_4coders.so from $SOURCE ..."
SOURCE=$(readlink -f "$SOURCE")
g++ -I"$CODE_HOME" -Wno-write-strings -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC

File diff suppressed because it is too large Load Diff

View File

@ -357,6 +357,9 @@ Sys_Set_File_List_Sig(system_set_file_list){
if (d){
if (canon_directory_out != 0){
u32 length = copy_fast_unsafe_cc(canon_directory_out, directory);
if (canon_directory_out[length-1] != '/'){
canon_directory_out[length++] = '/';
}
canon_directory_out[length] = 0;
*canon_directory_size_out = length;
}
@ -2653,11 +2656,11 @@ LinuxHandleX11Events(void)
fputs("FIXME: XBufferOverflow from LookupString.\n", stderr);
}
u16 key = utf8_to_u32_unchecked(buff);
u16 key_no_caps = key;
u32 key = utf8_to_u32_unchecked(buff);
u32 key_no_caps = key;
if(mods[MDFR_CAPS_INDEX] && status == XLookupBoth && Event.xkey.keycode){
u8 buff_no_caps[32] = {};
u8 buff_no_caps[32] = {0};
Event.xkey.state &= ~(LockMask);
XLookupString(
@ -2669,7 +2672,7 @@ LinuxHandleX11Events(void)
);
if(*buff_no_caps){
key_no_caps = utf8_to_u16_unchecked(buff_no_caps);
key_no_caps = utf8_to_u32_unchecked(buff_no_caps);
}
}

View File

@ -19,6 +19,7 @@ TYPE: 'build-target'
# define BIND_4CODER_TESTS(context) ((void)context)
#endif
#include <assert.h>
#include <string.h>
static float
@ -1344,6 +1345,27 @@ CUSTOM_COMMAND_SIG(write_explicit_enum_values){
end_temp_memory(temp);
}
CUSTOM_COMMAND_SIG(punishment){
Theme_Color colors[4];
colors[0].tag = Stag_Back;
colors[1].tag = Stag_Margin;
colors[2].tag = Stag_Margin_Hover;
colors[3].tag = Stag_Margin_Active;
get_theme_colors(app, colors, 4);
for (uint32_t i = 0; i < 4; ++i){
int_color color = colors[i].color;
uint8_t *c = (uint8_t*)(&color);
c[0] = 0xFF - c[0];
c[1] = 0xFF - c[1];
c[2] = 0xFF - c[2];
c[3] = 0xFF - c[3];
colors[i].color = color;
}
set_theme_colors(app, colors, 4);
}
extern "C" int32_t
get_bindings(void *data, int32_t size){
Bind_Helper context_ = begin_bind_helper(data, size);
@ -1370,6 +1392,9 @@ get_bindings(void *data, int32_t size){
end_map(context);
begin_map(context, mapid_file);
bind(context, 's', MDFR_CTRL, punishment);
bind(context, 's', MDFR_ALT, save);
bind(context, 'k', MDFR_ALT, kill_rect);
bind(context, ' ', MDFR_ALT | MDFR_CTRL, multi_line_edit);

View File

@ -768,7 +768,7 @@ Sys_Set_File_List_Sig(system_set_file_list){
if (canon_directory_out != 0){
if (final_length+1 < canon_directory_max){
memcpy(canon_directory_out, c_str_dir, final_length);
if (char_is_slash(dir.str[dir.size-1]) && canon_directory_out[final_length-1] != '\\'){
if (canon_directory_out[final_length-1] != '\\'){
canon_directory_out[final_length++] = '\\';
}
canon_directory_out[final_length] = 0;