locales
This commit is contained in:
parent
c2206e5830
commit
0aa1df3da0
|
@ -2,18 +2,20 @@
|
|||
* Example use of customization API
|
||||
*/
|
||||
|
||||
#define FCPP_STRING_IMPLEMENTATION
|
||||
#include "4coder_string.h"
|
||||
|
||||
#include "4coder_custom.h"
|
||||
#include "4coder_helper.h"
|
||||
|
||||
#define exec_command_keep_stack app.exec_command_keep_stack
|
||||
#define clear_parameters app.clear_parameters
|
||||
#define get_active_buffer app.get_active_buffer
|
||||
#define exec_command_keep_stack app->exec_command_keep_stack
|
||||
#define clear_parameters app->clear_parameters
|
||||
#define get_active_buffer app->get_active_buffer
|
||||
|
||||
#define exec_command(cmd_context, id) \
|
||||
exec_command_keep_stack(cmd_context, id); \
|
||||
clear_parameters(cmd_context)
|
||||
#define push_parameter(cmd_context, ...) push_parameter_helper(cmd_context, app, __VA_ARGS__)
|
||||
#define push_memory(cmd_context, len) app.push_memory(cmd_context, len)
|
||||
#define push_memory(cmd_context, len) app->push_memory(cmd_context, len)
|
||||
|
||||
#define literal(s) s, (sizeof(s)-1)
|
||||
|
||||
|
@ -21,6 +23,7 @@
|
|||
// I recommend enumerating your own map ids as shown here.
|
||||
enum My_Maps{
|
||||
my_code_map = mapid_user_custom,
|
||||
my_html_map
|
||||
};
|
||||
|
||||
HOOK_SIG(my_start){
|
||||
|
@ -64,9 +67,9 @@ HOOK_SIG(my_file_settings){
|
|||
else if (str_match(extension, extension_len, literal("hpp"))) treat_as_code = 1;
|
||||
}
|
||||
|
||||
push_parameter(cmd_context, par_lex_as_cpp_file, treat_as_code);
|
||||
push_parameter(cmd_context, par_wrap_lines, !treat_as_code);
|
||||
push_parameter(cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file));
|
||||
push_parameter(app, cmd_context, par_lex_as_cpp_file, treat_as_code);
|
||||
push_parameter(app, cmd_context, par_wrap_lines, !treat_as_code);
|
||||
push_parameter(app, cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file));
|
||||
exec_command(cmd_context, cmdid_set_settings);
|
||||
}
|
||||
|
||||
|
@ -79,7 +82,7 @@ CUSTOM_COMMAND_SIG(open_my_files){
|
|||
// NOTE(allen|a3.1): The command cmdid_interactive_open can now open
|
||||
// a file specified on the parameter stack. If the file does not
|
||||
// exist cmdid_interactive_open behaves as usual.
|
||||
push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||
push_parameter(app, cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
|
@ -93,12 +96,82 @@ CUSTOM_COMMAND_SIG(open_my_files){
|
|||
}
|
||||
|
||||
// NOTE(allen|a3.1): null terminators are not needed for strings.
|
||||
push_parameter(cmd_context, par_name, my_file, my_file_len);
|
||||
push_parameter(app, cmd_context, par_name, my_file, my_file_len);
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(build_at_launch_location){
|
||||
// NOTE(allen|a3.3): An example of calling build by setting all
|
||||
// parameters directly. This only works if build.bat can be called
|
||||
// from the starting directory
|
||||
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 1);
|
||||
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
|
||||
push_parameter(app, cmd_context, par_cli_path, literal("."));
|
||||
push_parameter(app, cmd_context, par_cli_command, literal("build"));
|
||||
exec_command(cmd_context, cmdid_build);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(build_search){
|
||||
// NOTE(allen|a3.3): An example of traversing the filesystem through parent
|
||||
// directories looking for a file, in this case a batch file to execute.
|
||||
//
|
||||
//
|
||||
// Step 1: push_directory returns a String containing the current "hot" directory
|
||||
// (whatever directory you most recently visited in the 4coder file browsing interface)
|
||||
//
|
||||
// Step 2: app->directory_has_file queries the file system to see if "build.bat" exists
|
||||
// If it does exist several parameters are pushed:
|
||||
// - par_cli_overlap_with_conflict: whether to launch this process if an existing process
|
||||
// is already being used for output on the same buffer
|
||||
//
|
||||
// - par_target_buffer_name: the name of the buffer to fill with the output from the process
|
||||
//
|
||||
// - par_cli_path: sets the path from which the command is executed
|
||||
//
|
||||
// - par_cli_command: sets the actual command to be executed, this can be almost any command
|
||||
// that you could execute through a command line interface
|
||||
//
|
||||
//
|
||||
// To set par_cli_path: push_parameter makes a copy of the dir string on the stack
|
||||
// because the string allocated by push_directory is going to change again
|
||||
// To set par_cli_command: app->push_parameter does not make a copy of the dir because
|
||||
// dir isn't going to change again.
|
||||
//
|
||||
// Step 3: If the batch file did not exist try to move to the parent directory using
|
||||
// app->directory_cd. The cd function can also be used to navigate to subdirectories.
|
||||
// It returns true if it can actually move in the specified direction, and false otherwise.
|
||||
|
||||
int keep_going = 1;
|
||||
String dir = push_directory(app, cmd_context);
|
||||
while (keep_going){
|
||||
if (app->directory_has_file(dir, "build.bat")){
|
||||
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 0);
|
||||
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
|
||||
push_parameter(app, cmd_context, par_cli_path, dir.str, dir.size);
|
||||
|
||||
if (append(&dir, "build")){
|
||||
app->push_parameter(cmd_context,
|
||||
dynamic_int(par_cli_command),
|
||||
dynamic_string(dir.str, dir.size));
|
||||
exec_command(cmd_context, cmdid_build);
|
||||
}
|
||||
else{
|
||||
clear_parameters(cmd_context);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->directory_cd(&dir, "..") == 0){
|
||||
keep_going = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): feedback message - couldn't find build.bat
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
||||
exec_command(cmd_context, cmdid_write_character);
|
||||
exec_command(cmd_context, cmdid_auto_tab_line_at_cursor);
|
||||
|
@ -126,9 +199,12 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
|
||||
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
|
||||
bind_me(context, 'o', MDFR_ALT, open_in_other);
|
||||
// NOTE(allen|a3.1): Go look at open_my_files, that's the only point of this being here,
|
||||
// it won't actually be useful for you.
|
||||
|
||||
// NOTE(allen): These callbacks may not actually be useful to you, but
|
||||
// go look at them and see what they do.
|
||||
bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
|
||||
bind_me(context, 'M', MDFR_ALT, build_at_launch_location);
|
||||
bind_me(context, 'm', MDFR_ALT, build_search);
|
||||
|
||||
end_map(context);
|
||||
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
#define MDFR_SHIFT 4
|
||||
#define MDFR_NUMPAD 8
|
||||
|
||||
// NOTE(allen): These need not be used direct
|
||||
#define MDFR_EXACT 128
|
||||
|
||||
typedef u16 Code;
|
||||
typedef unsigned char Code;
|
||||
|
||||
struct Key_Codes{
|
||||
Code back;
|
||||
|
@ -121,6 +118,7 @@ enum Command_ID{
|
|||
cmdid_cursor_mark_swap,
|
||||
cmdid_open_menu,
|
||||
cmdid_set_settings,
|
||||
cmdid_build,
|
||||
//
|
||||
cmdid_count
|
||||
};
|
||||
|
@ -130,6 +128,10 @@ enum Param_ID{
|
|||
par_lex_as_cpp_file,
|
||||
par_wrap_lines,
|
||||
par_key_mapid,
|
||||
par_target_buffer_name,
|
||||
par_cli_path,
|
||||
par_cli_command,
|
||||
par_cli_overlap_with_conflict,
|
||||
// never below this
|
||||
par_type_count
|
||||
};
|
||||
|
@ -230,10 +232,19 @@ struct Buffer_Summary{
|
|||
int map_id;
|
||||
};
|
||||
|
||||
#ifndef FRED_STRING_STRUCT
|
||||
#define FRED_STRING_STRUCT
|
||||
struct String{
|
||||
char *str;
|
||||
int size;
|
||||
int memory_size;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define GET_BINDING_DATA(name) int name(void *data, int size, Key_Codes *codes)
|
||||
#define SET_EXTRA_FONT_SIG(name) void name(Extra_Font *font_out)
|
||||
#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links app)
|
||||
#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links app)
|
||||
#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links *app)
|
||||
#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links *app)
|
||||
|
||||
extern "C"{
|
||||
typedef CUSTOM_COMMAND_SIG(Custom_Command_Function);
|
||||
|
@ -247,6 +258,9 @@ extern "C"{
|
|||
#define EXECUTE_COMMAND_SIG(name) void name(void *cmd_context, int command_id)
|
||||
#define CLEAR_PARAMETERS_SIG(name) void name(void *cmd_context)
|
||||
#define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context)
|
||||
#define DIRECTORY_GET_HOT_SIG(name) int name(void *cmd_context, char *buffer, int max)
|
||||
#define DIRECTORY_HAS_FILE_SIG(name) int name(String dir, char *filename)
|
||||
#define DIRECTORY_CD_SIG(name) int name(String *dir, char *rel_path)
|
||||
|
||||
extern "C"{
|
||||
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
|
||||
|
@ -254,6 +268,9 @@ extern "C"{
|
|||
typedef PUSH_MEMORY_SIG(Push_Memory_Function);
|
||||
typedef CLEAR_PARAMETERS_SIG(Clear_Parameters_Function);
|
||||
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
|
||||
typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot);
|
||||
typedef DIRECTORY_HAS_FILE_SIG(Directory_Has_File);
|
||||
typedef DIRECTORY_CD_SIG(Directory_CD);
|
||||
}
|
||||
|
||||
struct Application_Links{
|
||||
|
@ -262,6 +279,9 @@ struct Application_Links{
|
|||
Push_Memory_Function *push_memory;
|
||||
Clear_Parameters_Function *clear_parameters;
|
||||
Get_Active_Buffer_Function *get_active_buffer;
|
||||
Directory_Get_Hot *directory_get_hot;
|
||||
Directory_Has_File *directory_has_file;
|
||||
Directory_CD *directory_cd;
|
||||
};
|
||||
|
||||
struct Config_API{
|
||||
|
|
|
@ -97,14 +97,6 @@ struct Bind_Target{
|
|||
unsigned char modifiers;
|
||||
};
|
||||
|
||||
inline Bind_Target
|
||||
ekey(short code, unsigned char modifiers){
|
||||
Bind_Target target;
|
||||
target.code = code;
|
||||
target.modifiers = modifiers | MDFR_EXACT;
|
||||
return target;
|
||||
}
|
||||
|
||||
inline Bind_Target
|
||||
tkey(short code, unsigned char modifiers){
|
||||
Bind_Target target;
|
||||
|
@ -144,14 +136,14 @@ bind_me(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){
|
|||
inline void
|
||||
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
|
||||
Bind_Target target;
|
||||
target.code = tkey(code, modifiers);
|
||||
target = tkey(code, modifiers);
|
||||
bind(helper, target, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
|
||||
Bind_Target target;
|
||||
target.code = tkey(code, modifiers);
|
||||
target = tkey(code, modifiers);
|
||||
bind_me(helper, target, func);
|
||||
}
|
||||
|
||||
|
@ -207,30 +199,46 @@ end_bind_helper(Bind_Helper *helper){
|
|||
|
||||
// NOTE(allen): Useful functions and overloads on app links
|
||||
inline void
|
||||
push_parameter_helper(void *cmd_context, Application_Links app, int param, int value){
|
||||
app.push_parameter(cmd_context, dynamic_int(param), dynamic_int(value));
|
||||
push_parameter(Application_Links *app, void *cmd_context, int param, int value){
|
||||
app->push_parameter(cmd_context, dynamic_int(param), dynamic_int(value));
|
||||
}
|
||||
|
||||
inline void
|
||||
push_parameter_helper(void *cmd_context, Application_Links app, int param, const char *value, int value_len){
|
||||
char *value_copy = app.push_memory(cmd_context, value_len);
|
||||
push_parameter(Application_Links *app, void *cmd_context, int param, const char *value, int value_len){
|
||||
char *value_copy = app->push_memory(cmd_context, value_len+1);
|
||||
copy(value_copy, value, value_len);
|
||||
app.push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len));
|
||||
value_copy[value_len] = 0;
|
||||
app->push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len));
|
||||
}
|
||||
|
||||
inline void
|
||||
push_parameter_helper(void *cmd_context, Application_Links app, const char *param, int param_len, int value){
|
||||
char *param_copy = app.push_memory(cmd_context, param_len);
|
||||
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, int value){
|
||||
char *param_copy = app->push_memory(cmd_context, param_len+1);
|
||||
copy(param_copy, param, param_len);
|
||||
app.push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value));
|
||||
param_copy[param_len] = 0;
|
||||
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value));
|
||||
}
|
||||
|
||||
inline void
|
||||
push_parameter_helper(void *cmd_context, Application_Links app, const char *param, int param_len, const char *value, int value_len){
|
||||
char *param_copy = app.push_memory(cmd_context, param_len);
|
||||
char *value_copy = app.push_memory(cmd_context, value_len);
|
||||
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, const char *value, int value_len){
|
||||
char *param_copy = app->push_memory(cmd_context, param_len+1);
|
||||
char *value_copy = app->push_memory(cmd_context, value_len+1);
|
||||
copy(param_copy, param, param_len);
|
||||
copy(value_copy, value, value_len);
|
||||
app.push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len));
|
||||
value_copy[value_len] = 0;
|
||||
param_copy[param_len] = 0;
|
||||
|
||||
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len));
|
||||
}
|
||||
|
||||
inline String
|
||||
push_directory(Application_Links *app, void *cmd_context){
|
||||
String result;
|
||||
result.memory_size = 512;
|
||||
result.str = app->push_memory(cmd_context, result.memory_size);
|
||||
result.size = app->directory_get_hot(cmd_context, result.str, result.memory_size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define dir_string(d) ((d).str), ((d).size)
|
||||
|
||||
|
|
|
@ -24,16 +24,19 @@ NOTES ON USE:
|
|||
// - memcpy / memmove replacements (different file for optimization options?)
|
||||
//
|
||||
|
||||
#include "4cpp_config.h"
|
||||
#include "4coder_config.h"
|
||||
|
||||
#ifndef FCPP_STRING_INC
|
||||
#define FCPP_STRING_INC
|
||||
|
||||
#ifndef FRED_STRING_STRUCT
|
||||
#define FRED_STRING_STRUCT
|
||||
struct String{
|
||||
char *str;
|
||||
int size;
|
||||
int memory_size;
|
||||
};
|
||||
#endif
|
||||
|
||||
inline bool char_not_slash(char c) { return (c != '\\' && c != '/'); }
|
||||
inline bool char_is_slash(char c) { return (c == '\\' || c == '/'); }
|
||||
|
@ -147,12 +150,14 @@ inline int compare(char *a, String b) { return -compare(b,a); }
|
|||
FCPP_LINK int compare(String a, String b);
|
||||
|
||||
FCPP_LINK int reverse_seek_slash(String str);
|
||||
FCPP_LINK int reverse_seek_slash(String str, int start_pos);
|
||||
inline bool get_front_of_directory(String *dest, String dir) { return append_checked(dest, substr(dir, reverse_seek_slash(dir) + 1)); }
|
||||
inline bool get_path_of_directory(String *dest, String dir) { return append_checked(dest, substr(dir, 0, reverse_seek_slash(dir) + 1)); }
|
||||
FCPP_LINK bool set_last_folder(String *dir, char *folder_name);
|
||||
FCPP_LINK bool set_last_folder(String *dir, String folder_name);
|
||||
FCPP_LINK String file_extension(String str);
|
||||
FCPP_LINK String file_extension_slowly(char *str);
|
||||
FCPP_LINK bool remove_last_folder(String *str);
|
||||
|
||||
inline String make_string(char *str, int size, int mem_size){
|
||||
String result;
|
||||
|
@ -834,14 +839,19 @@ compare(String a, String b){
|
|||
}
|
||||
|
||||
FCPP_LINK int
|
||||
reverse_seek_slash(String str){
|
||||
int i = str.size - 1;
|
||||
reverse_seek_slash(String str, int pos){
|
||||
int i = str.size - 1 - pos;
|
||||
while (i >= 0 && char_not_slash(str.str[i])){
|
||||
--i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
FCPP_LINK int
|
||||
reverse_seek_slash(String str){
|
||||
return(reverse_seek_slash(str, 0));
|
||||
}
|
||||
|
||||
FCPP_LINK bool
|
||||
set_last_folder(String *dir, char *folder_name){
|
||||
bool result = 0;
|
||||
|
@ -886,7 +896,7 @@ file_extension(String str){
|
|||
|
||||
FCPP_LINK String
|
||||
file_extension_slowly(char *str){
|
||||
i32 s, i;
|
||||
int s, i;
|
||||
for (s = 0; str[s]; ++s);
|
||||
for (i = s - 1; i >= 0; --i){
|
||||
if (str[i] == '.') break;
|
||||
|
@ -895,9 +905,24 @@ file_extension_slowly(char *str){
|
|||
return make_string(str+i, s-i);
|
||||
}
|
||||
|
||||
FCPP_LINK bool
|
||||
remove_last_folder(String *str){
|
||||
bool result = 0;
|
||||
int end = reverse_seek_slash(*str, 1);
|
||||
if (end >= 0){
|
||||
result = 1;
|
||||
str->size = end + 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// NOTE(allen): experimental section, things below here are
|
||||
// not promoted to public API level yet.
|
||||
|
||||
#ifndef ArrayCount
|
||||
#define ArrayCount(a) ((sizeof(a))/sizeof(a))
|
||||
#endif
|
||||
|
||||
struct Absolutes{
|
||||
String a[8];
|
||||
int count;
|
|
@ -58,7 +58,7 @@ NOTES ON USE:
|
|||
// - lex in chunks
|
||||
//
|
||||
|
||||
#include "4cpp_config.h"
|
||||
#include "4coder_config.h"
|
||||
|
||||
#ifndef FCPP_LEXER_INC
|
||||
#define FCPP_LEXER_INC
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,7 @@ NOTES ON USE:
|
|||
// TODO(allen):
|
||||
// - create non stdint.h version in case someone wants to exclude that header
|
||||
|
||||
#include "4cpp_config.h"
|
||||
#include "4coder_config.h"
|
||||
|
||||
#ifndef FCPP_TYPES
|
||||
#define FCPP_TYPES
|
||||
|
|
53
4ed.h
53
4ed.h
|
@ -31,10 +31,10 @@ enum Key_Control{
|
|||
};
|
||||
|
||||
struct Key_Event_Data{
|
||||
u16 keycode;
|
||||
u16 loose_keycode;
|
||||
u16 character;
|
||||
u16 character_no_caps_lock;
|
||||
u8 keycode;
|
||||
//u8 apply_shift;
|
||||
u8 character;
|
||||
u8 character_no_caps_lock;
|
||||
};
|
||||
|
||||
struct Key_Input_Data{
|
||||
|
@ -97,14 +97,44 @@ struct Clipboard_Contents{
|
|||
i32 size;
|
||||
};
|
||||
|
||||
struct Thread_Context;
|
||||
#define FileNameMax (1 << 9)
|
||||
|
||||
struct File_Slot{
|
||||
File_Slot *next, *prev;
|
||||
byte *data;
|
||||
i32 size, max;
|
||||
char *filename;
|
||||
i32 filename_len;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
enum File_Exchange_Flag{
|
||||
FEx_Request = 0x1,
|
||||
FEx_Ready = 0x2,
|
||||
FEx_Not_Exist = 0x4,
|
||||
FEx_Save = 0x8,
|
||||
FEx_Save_Complete = 0x10
|
||||
};
|
||||
|
||||
struct File_Exchange{
|
||||
File_Slot available, active, free_list;
|
||||
File_Slot *files;
|
||||
i32 num_active, max;
|
||||
};
|
||||
|
||||
struct Exchange{
|
||||
Thread_Exchange thread;
|
||||
File_Exchange file;
|
||||
};
|
||||
|
||||
#define App_Init_Sig(name) \
|
||||
b32 name(System_Functions *system, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Exchange *exchange, \
|
||||
Key_Codes *loose_codes, \
|
||||
Clipboard_Contents clipboard, \
|
||||
String current_directory, \
|
||||
Config_API api)
|
||||
|
||||
typedef App_Init_Sig(App_Init);
|
||||
|
@ -131,16 +161,29 @@ struct Application_Step_Result{
|
|||
Mouse_State *mouse, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Exchange *exchange, \
|
||||
Clipboard_Contents clipboard, \
|
||||
b32 time_step, b32 first_step, b32 force_redraw)
|
||||
|
||||
typedef App_Step_Sig(App_Step);
|
||||
|
||||
#define App_Alloc_Sig(name) void *name(void *handle, i32 size)
|
||||
typedef App_Alloc_Sig(App_Alloc);
|
||||
|
||||
#define App_Free_Sig(name) void name(void *handle, void *block)
|
||||
typedef App_Free_Sig(App_Free);
|
||||
|
||||
struct App_Functions{
|
||||
App_Init *init;
|
||||
App_Step *step;
|
||||
|
||||
App_Alloc *alloc;
|
||||
App_Free *free;
|
||||
};
|
||||
|
||||
#define App_Get_Functions_Sig(name) App_Functions name()
|
||||
typedef App_Get_Functions_Sig(App_Get_Functions);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
#include "4cpp_types.h"
|
||||
#define FCPP_STRING_IMPLEMENTATION
|
||||
#include "4cpp_string.h"
|
||||
#include "4coder_string.h"
|
||||
|
||||
#include "4ed_mem.cpp"
|
||||
|
||||
#include "4ed_math.cpp"
|
||||
|
||||
#include "4coder_custom.h"
|
||||
#include "4ed_system.h"
|
||||
#include "4ed_rendering.h"
|
||||
|
@ -32,6 +32,8 @@
|
|||
#define FCPP_LEXER_IMPLEMENTATION
|
||||
#include "4cpp_lexer.h"
|
||||
|
||||
#include "4ed_exchange.cpp"
|
||||
#include "4ed_font_set.cpp"
|
||||
#include "4ed_rendering_helper.cpp"
|
||||
#include "4ed_command.cpp"
|
||||
#include "4ed_layout.cpp"
|
||||
|
|
|
@ -15,6 +15,7 @@ enum Color_View_Mode{
|
|||
CV_MODE_EXPORT_FILE,
|
||||
CV_MODE_IMPORT,
|
||||
CV_MODE_EXPORT,
|
||||
CV_MODE_IMPORT_WAIT,
|
||||
CV_MODE_ADJUSTING
|
||||
};
|
||||
|
||||
|
@ -104,7 +105,7 @@ struct Color_View{
|
|||
Style *main_style;
|
||||
Style_Library *styles;
|
||||
File_View *hot_file_view;
|
||||
Font_Set *fonts;
|
||||
Font_Set *font_set;
|
||||
u32 *palette;
|
||||
Working_Set *working_set;
|
||||
i32 palette_size;
|
||||
|
@ -112,9 +113,10 @@ struct Color_View{
|
|||
UI_State state;
|
||||
Super_Color color;
|
||||
Color_Highlight highlight;
|
||||
bool32 p4c_only;
|
||||
b32 p4c_only;
|
||||
Style_Library inspecting_styles;
|
||||
bool8 import_export_check[64];
|
||||
b8 import_export_check[64];
|
||||
i32 import_file_id;
|
||||
};
|
||||
|
||||
inline Color_View*
|
||||
|
@ -188,10 +190,11 @@ draw_rgb_slider(Render_Target *target, Vec4 base, i32 channel,
|
|||
}
|
||||
|
||||
internal void
|
||||
do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){
|
||||
do_label(UI_State *state, UI_Layout *layout, char *text, f32 height = 2.f){
|
||||
Style *style = state->style;
|
||||
Render_Font *font = style->font;
|
||||
i32_Rect label = layout_rect(layout, FLOOR32(font->height * height));
|
||||
i16 font_id = style->font_id;
|
||||
i32 line_height = get_font_info(state->font_set, font_id)->height;
|
||||
i32_Rect label = layout_rect(layout, FLOOR32(line_height * height));
|
||||
|
||||
if (!state->input_stage){
|
||||
Render_Target *target = state->target;
|
||||
|
@ -199,8 +202,8 @@ do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){
|
|||
u32 fore = style->main.default_color;
|
||||
draw_rectangle(target, label, back);
|
||||
i32 height = label.y1 - label.y0;
|
||||
draw_string(target, font, text, label.x0,
|
||||
label.y0 + (height - font->height)/2, fore);
|
||||
draw_string(target, font_id, text, label.x0,
|
||||
label.y0 + (height - line_height)/2, fore);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,18 +224,18 @@ do_scroll_bar(UI_State *state, i32_Rect rect){
|
|||
bottom_arrow.y1 = rect.y1;
|
||||
bottom_arrow.y0 = bottom_arrow.y1 - w;
|
||||
|
||||
real32 space_h = (real32)(bottom_arrow.y0 - top_arrow.y1);
|
||||
f32 space_h = (f32)(bottom_arrow.y0 - top_arrow.y1);
|
||||
if (space_h <= w) return;
|
||||
|
||||
i32 slider_h = w;
|
||||
|
||||
real32 view_hmin = 0;
|
||||
real32 view_hmax = state->height - h;
|
||||
real32 L = unlerp(view_hmin, state->view_y, view_hmax);
|
||||
f32 view_hmin = 0;
|
||||
f32 view_hmax = state->height - h;
|
||||
f32 L = unlerp(view_hmin, state->view_y, view_hmax);
|
||||
|
||||
real32 slider_hmin = (real32)top_arrow.y1;
|
||||
real32 slider_hmax = (real32)bottom_arrow.y0 - slider_h;
|
||||
real32 S = lerp(slider_hmin, L, slider_hmax);
|
||||
f32 slider_hmin = (f32)top_arrow.y1;
|
||||
f32 slider_hmax = (f32)bottom_arrow.y0 - slider_h;
|
||||
f32 S = lerp(slider_hmin, L, slider_hmax);
|
||||
|
||||
i32_Rect slider;
|
||||
slider.x0 = rect.x0;
|
||||
|
@ -244,16 +247,17 @@ do_scroll_bar(UI_State *state, i32_Rect rect){
|
|||
|
||||
if (state->input_stage){
|
||||
state->view_y =
|
||||
ui_do_vscroll_input(state, top_arrow, bottom_arrow, slider,
|
||||
wid, state->view_y, (real32)state->font->height,
|
||||
ui_do_vscroll_input(state, top_arrow, bottom_arrow, slider, wid, state->view_y,
|
||||
(f32)(get_font_info(state->font_set, state->font_id)->height),
|
||||
slider_hmin, slider_hmax, view_hmin, view_hmax);
|
||||
}
|
||||
else{
|
||||
else{
|
||||
Render_Target *target = state->target;
|
||||
real32 x0, y0, x1, y1, x2, y2;
|
||||
real32 w_1_2 = w*.5f;
|
||||
real32 w_1_3 = w*.333333f;
|
||||
real32 w_2_3 = w*.666667f;
|
||||
|
||||
f32 x0, y0, x1, y1, x2, y2;
|
||||
f32 w_1_2 = w*.5f;
|
||||
f32 w_1_3 = w*.333333f;
|
||||
f32 w_2_3 = w*.666667f;
|
||||
|
||||
|
||||
UI_Style ui_style = get_ui_style(state->style);
|
||||
|
@ -403,22 +407,24 @@ fill_buffer_color_channel(char *buffer, u8 x, Channel_Field_Type ftype){
|
|||
}
|
||||
}
|
||||
|
||||
internal bool32
|
||||
internal b32
|
||||
do_channel_field(i32 sub_id, Color_UI *ui, u8 *channel, Channel_Field_Type ftype,
|
||||
i32 y, u32 color, u32 back, i32 x0, i32 x1){
|
||||
bool32 result = 0;
|
||||
Render_Target *target = ui->state.target;
|
||||
Render_Font *font = ui->state.font;
|
||||
|
||||
b32 result = 0;
|
||||
|
||||
i16 font_id = ui->state.font_id;
|
||||
i32 line_height = get_font_info(ui->state.font_set, font_id)->height;
|
||||
i32_Rect hit_region;
|
||||
hit_region.x0 = x0;
|
||||
hit_region.x1 = x1;
|
||||
hit_region.y0 = y;
|
||||
hit_region.y1 = y + font->height;
|
||||
hit_region.y1 = y + line_height;
|
||||
|
||||
i32 digit_count;
|
||||
if (ftype == CF_DEC) digit_count = 3;
|
||||
else digit_count = 2;
|
||||
|
||||
Render_Target *target = ui->state.target;
|
||||
|
||||
if (ui->state.input_stage){
|
||||
i32 indx;
|
||||
|
@ -515,7 +521,7 @@ do_channel_field(i32 sub_id, Color_UI *ui, u8 *channel, Channel_Field_Type ftype
|
|||
}
|
||||
|
||||
if (!ui->state.input_stage)
|
||||
draw_string_mono(target, font, string_buffer,
|
||||
draw_string_mono(target, font_id, string_buffer,
|
||||
(real32)x0 + 1, (real32)y, ui->hex_advance,
|
||||
color);
|
||||
|
||||
|
@ -688,8 +694,7 @@ do_palette(Color_UI *ui, i32_Rect rect){
|
|||
|
||||
if (!ui->state.input_stage){
|
||||
Render_Target *target = ui->state.target;
|
||||
Render_Font *font = style->font;
|
||||
draw_string(target, font, "Global Palette: right click to save color",
|
||||
draw_string(target, style->font_id, "Global Palette: right click to save color",
|
||||
layout.x, layout.rect.y0, style->main.default_color);
|
||||
}
|
||||
|
||||
|
@ -709,15 +714,16 @@ do_palette(Color_UI *ui, i32_Rect rect){
|
|||
|
||||
internal void
|
||||
do_sub_button(i32 id, Color_UI *ui, char *text){
|
||||
Render_Font *font = ui->state.font;
|
||||
|
||||
i32_Rect rect = layout_rect(&ui->layout, font->height + 2);
|
||||
i16 font_id = ui->state.font_id;
|
||||
i32 line_height = get_font_info(ui->state.font_set, font_id)->height;
|
||||
i32_Rect rect = layout_rect(&ui->layout, line_height + 2);
|
||||
|
||||
if (ui->state.input_stage){
|
||||
ui_do_button_input(&ui->state, rect, make_sub0(&ui->state, id), 1);
|
||||
}
|
||||
else{
|
||||
Render_Target *target = ui->state.target;
|
||||
|
||||
u32 back_color, text_color;
|
||||
text_color = 0xFFDDDDDD;
|
||||
if (ui->state.selected.sub_id0 == id){
|
||||
|
@ -731,7 +737,7 @@ do_sub_button(i32 id, Color_UI *ui, char *text){
|
|||
}
|
||||
|
||||
draw_rectangle(target, rect, back_color);
|
||||
draw_string(target, font, text, rect.x0, rect.y0 + 1,
|
||||
draw_string(target, font_id, text, rect.x0, rect.y0 + 1,
|
||||
text_color);
|
||||
}
|
||||
}
|
||||
|
@ -740,9 +746,8 @@ internal void
|
|||
do_color_adjuster(Color_UI *ui, u32 *color,
|
||||
u32 text_color, u32 back_color, char *name){
|
||||
i32 id = raw_ptr_dif(color, ui->state.style);
|
||||
Render_Target *target = ui->state.target;
|
||||
Render_Font *font = ui->state.font;
|
||||
i32 character_h = font->height;
|
||||
i16 font_id = ui->state.font_id;
|
||||
i32 character_h = get_font_info(ui->state.font_set, font_id)->height;
|
||||
u32 text = 0, back = 0;
|
||||
|
||||
i32_Rect bar = layout_rect(&ui->layout, character_h);
|
||||
|
@ -755,6 +760,7 @@ do_color_adjuster(Color_UI *ui, u32 *color,
|
|||
}
|
||||
|
||||
else{
|
||||
Render_Target *target = ui->state.target;
|
||||
u32 text_hover = 0xFF101010;
|
||||
u32 back_hover = 0xFF999999;
|
||||
if (ui->state.selected.id != id && ui->state.hover.id == id){
|
||||
|
@ -767,7 +773,7 @@ do_color_adjuster(Color_UI *ui, u32 *color,
|
|||
}
|
||||
|
||||
draw_rectangle(target, bar, back);
|
||||
i32 end_pos = draw_string(target, font, name, bar.x0, bar.y0, text);
|
||||
i32 end_pos = draw_string(target, font_id, name, bar.x0, bar.y0, text);
|
||||
|
||||
real32 x_spacing = ui->hex_advance;
|
||||
i32_Rect temp_rect = bar;
|
||||
|
@ -780,8 +786,8 @@ do_color_adjuster(Color_UI *ui, u32 *color,
|
|||
n >>= 4;
|
||||
full_hex_string[i] = int_to_hexchar(m);
|
||||
}
|
||||
draw_string_mono(target, font, full_hex_string,
|
||||
(real32)temp_rect.x0, (real32)bar.y0,
|
||||
draw_string_mono(target, font_id, full_hex_string,
|
||||
(f32)temp_rect.x0, (f32)bar.y0,
|
||||
x_spacing, text);
|
||||
}
|
||||
|
||||
|
@ -794,6 +800,7 @@ do_color_adjuster(Color_UI *ui, u32 *color,
|
|||
}
|
||||
|
||||
if (ui->state.selected.id == id){
|
||||
Render_Target *target = ui->state.target;
|
||||
i32_Rect expanded = layout_rect(&ui->layout, 115 + (character_h + 2));
|
||||
UI_Layout_Restore restore = begin_sub_layout(&ui->layout, expanded);
|
||||
|
||||
|
@ -830,12 +837,14 @@ do_color_adjuster(Color_UI *ui, u32 *color,
|
|||
internal void
|
||||
do_style_name(Color_UI *ui){
|
||||
i32 id = -3;
|
||||
Render_Font *font = ui->state.font;
|
||||
|
||||
i32_Rect srect = layout_rect(&ui->layout, font->height);
|
||||
i16 font_id = ui->state.font_id;
|
||||
i32 line_height = get_font_info(ui->state.font_set, font_id)->height;
|
||||
|
||||
i32_Rect srect = layout_rect(&ui->layout, line_height);
|
||||
|
||||
Widget_ID wid = make_id(&ui->state, id);
|
||||
bool32 selected = is_selected(&ui->state, wid);
|
||||
b32 selected = is_selected(&ui->state, wid);
|
||||
|
||||
if (ui->state.input_stage){
|
||||
if (!selected){
|
||||
|
@ -868,18 +877,20 @@ do_style_name(Color_UI *ui){
|
|||
|
||||
draw_rectangle(target, srect, back);
|
||||
i32 x = srect.x0;
|
||||
x = draw_string(target, font, "NAME: ",
|
||||
x = draw_string(target, font_id, "NAME: ",
|
||||
x, srect.y0, fore_label);
|
||||
x = draw_string(target, font, style->name.str,
|
||||
x = draw_string(target, font_id, style->name.str,
|
||||
x, srect.y0, fore_text);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool32
|
||||
do_font_option(Color_UI *ui, Render_Font *font){
|
||||
bool32 result = 0;
|
||||
i32 sub_id = (i32)(font);
|
||||
i32_Rect orect = layout_rect(&ui->layout, font->height);
|
||||
internal b32
|
||||
do_font_option(Color_UI *ui, i16 font_id){
|
||||
b32 result = 0;
|
||||
Font_Info *info = get_font_info(ui->state.font_set, font_id);
|
||||
|
||||
i32 sub_id = (i32)(info);
|
||||
i32_Rect orect = layout_rect(&ui->layout, info->height);
|
||||
|
||||
Widget_ID wid = make_sub0(&ui->state, sub_id);
|
||||
if (ui->state.input_stage){
|
||||
|
@ -900,10 +911,8 @@ do_font_option(Color_UI *ui, Render_Font *font){
|
|||
}
|
||||
draw_rectangle(target, orect, back);
|
||||
i32 x = orect.x0;
|
||||
x = draw_string(target, font, "->",
|
||||
x, orect.y0, fore);
|
||||
x = draw_string(target, font, font->name.str,
|
||||
x, orect.y0, fore);
|
||||
x = draw_string(target, font_id, "->", x, orect.y0, fore);
|
||||
draw_string(target, font_id, info->name.str, x, orect.y0, fore);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -913,11 +922,13 @@ internal void
|
|||
do_font_switch(Color_UI *ui){
|
||||
i32 id = -2;
|
||||
Render_Target *target = ui->state.target;
|
||||
Render_Font *font = ui->state.font;
|
||||
i32 character_h = font->height;
|
||||
Font_Set *font_set = ui->state.font_set;
|
||||
|
||||
i16 font_id = ui->state.font_id;
|
||||
Font_Info *info = get_font_info(font_set, font_id);
|
||||
i32 character_h = info->height;
|
||||
|
||||
i32_Rect srect = layout_rect(&ui->layout, character_h);
|
||||
|
||||
Widget_ID wid = make_id(&ui->state, id);
|
||||
|
||||
if (ui->state.input_stage){
|
||||
|
@ -936,24 +947,23 @@ do_font_switch(Color_UI *ui){
|
|||
}
|
||||
draw_rectangle(target, srect, back);
|
||||
i32 x = srect.x0;
|
||||
x = draw_string(target, font, "FONT: ",
|
||||
x = draw_string(target, font_id, "FONT: ",
|
||||
x, srect.y0, fore);
|
||||
x = draw_string(target, font, font->name.str,
|
||||
x = draw_string(target, font_id, info->name.str,
|
||||
x, srect.y0, fore);
|
||||
}
|
||||
|
||||
if (is_selected(&ui->state, wid)){
|
||||
Font_Set *fonts = ui->fonts;
|
||||
Render_Font *font_opt = fonts->fonts;
|
||||
i32 count = fonts->count;
|
||||
srect = layout_rect(&ui->layout, character_h/2);
|
||||
if (!ui->state.input_stage)
|
||||
draw_rectangle(target, srect, 0xFF000000);
|
||||
|
||||
for (i32 i = 0; i < count; ++i, ++font_opt){
|
||||
if (font_opt == font) continue;
|
||||
if (do_font_option(ui, font_opt)){
|
||||
ui->state.style->font = font_opt;
|
||||
i32 count = font_set->count + 1;
|
||||
|
||||
for (i16 i = 1; i < count; ++i){
|
||||
if (i == font_id) continue;
|
||||
if (do_font_option(ui, i)){
|
||||
ui->state.style->font_id = i;
|
||||
ui->state.style->font_changed = 1;
|
||||
}
|
||||
}
|
||||
|
@ -974,16 +984,17 @@ step_draw_adjusting(Color_View *color_view, i32_Rect rect, View_Message message,
|
|||
|
||||
Color_UI ui;
|
||||
ui.state = ui_state_init(&color_view->state, target, user_input,
|
||||
style, color_view->working_set, (message == VMSG_STEP));
|
||||
style, color_view->font_set, color_view->working_set,
|
||||
(message == VMSG_STEP));
|
||||
|
||||
begin_layout(&ui.layout, rect);
|
||||
|
||||
ui.fonts = color_view->fonts;
|
||||
ui.fonts = color_view->font_set;
|
||||
ui.highlight = color_view->highlight;
|
||||
ui.color = color_view->color;
|
||||
ui.has_hover_color = 0;
|
||||
ui.state.sub_id1_change = 0;
|
||||
ui.hex_advance = font_get_max_width(ui.state.font, "0123456789abcdefx");
|
||||
ui.hex_advance = font_get_max_width(ui.fonts, ui.state.font_id, "0123456789abcdefx");
|
||||
ui.palette = color_view->palette;
|
||||
ui.palette_size = color_view->palette_size;
|
||||
|
||||
|
@ -1119,15 +1130,15 @@ update_highlighting(Color_View *color_view){
|
|||
Style *style = color_view->main_style;
|
||||
Editing_File *file = file_view->file;
|
||||
i32 pos = view_get_cursor_pos(file_view);
|
||||
char c = file->buffer.data[pos];
|
||||
char c = file->state.buffer.data[pos];
|
||||
|
||||
if (c == '\r'){
|
||||
color_view->highlight.ids[0] =
|
||||
raw_ptr_dif(&style->main.special_character_color, style);
|
||||
}
|
||||
|
||||
else if (file->tokens_complete){
|
||||
Cpp_Token_Stack *tokens = &file->token_stack;
|
||||
else if (file->state.tokens_complete){
|
||||
Cpp_Token_Stack *tokens = &file->state.token_stack;
|
||||
Cpp_Get_Token_Result result = cpp_get_token(tokens, pos);
|
||||
Cpp_Token token = tokens->tokens[result.token_index];
|
||||
if (!result.in_whitespace){
|
||||
|
@ -1183,15 +1194,17 @@ update_highlighting(Color_View *color_view){
|
|||
#endif
|
||||
}
|
||||
|
||||
internal bool32
|
||||
internal b32
|
||||
do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
||||
bool32 result = 0;
|
||||
Render_Font *font = style->font;
|
||||
b32 result = 0;
|
||||
i32 id;
|
||||
if (style == ui->state.style) id = 2;
|
||||
else id = raw_ptr_dif(style, ui->styles->styles) + 100;
|
||||
|
||||
i16 font_id = style->font_id;
|
||||
Font_Info *info = get_font_info(ui->state.font_set, font_id);
|
||||
|
||||
i32_Rect prect = layout_rect(&ui->layout, font->height*3 + 6);
|
||||
i32_Rect prect = layout_rect(&ui->layout, info->height*3 + 6);
|
||||
|
||||
Widget_ID wid = make_id(&ui->state, id);
|
||||
|
||||
|
@ -1202,7 +1215,6 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
|||
}
|
||||
else{
|
||||
Render_Target *target = ui->state.target;
|
||||
|
||||
u32 margin_color = style->main.margin_color;
|
||||
if (is_hover(&ui->state, wid)){
|
||||
margin_color = style->main.margin_active_color;
|
||||
|
@ -1211,7 +1223,7 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
|||
i32_Rect inner;
|
||||
if (toggle != -1){
|
||||
i32_Rect toggle_box = prect;
|
||||
toggle_box.x1 = toggle_box.x0 + font->height*2 + 6;
|
||||
toggle_box.x1 = toggle_box.x0 + info->height*2 + 6;
|
||||
prect.x0 = toggle_box.x1;
|
||||
|
||||
inner = get_inner_rect(toggle_box, 3);
|
||||
|
@ -1219,12 +1231,12 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
|||
draw_rectangle(target, inner, style->main.back_color);
|
||||
|
||||
i32 d;
|
||||
d = font->height/2;
|
||||
d = info->height/2;
|
||||
i32_Rect b;
|
||||
b.x0 = (inner.x1 + inner.x0)/2 - d;
|
||||
b.y0 = (inner.y1 + inner.y0)/2 - d;
|
||||
b.x1 = b.x0 + font->height;
|
||||
b.y1 = b.y0 + font->height;
|
||||
b.x1 = b.x0 + info->height;
|
||||
b.y1 = b.y0 + info->height;
|
||||
if (toggle) draw_rectangle(target, b, margin_color);
|
||||
else draw_rectangle_outline(target, b, margin_color);
|
||||
}
|
||||
|
@ -1235,33 +1247,33 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
|||
|
||||
i32 text_y = inner.y0;
|
||||
i32 text_x = inner.x0;
|
||||
text_x = draw_string(target, font, style->name.str,
|
||||
text_x = draw_string(target, font_id, style->name.str,
|
||||
text_x, text_y, style->main.default_color);
|
||||
i32 font_x = (i32)(inner.x1 - font_string_width(font, font->name.str));
|
||||
i32 font_x = (i32)(inner.x1 - font_string_width(target, font_id, info->name.str));
|
||||
if (font_x > text_x + 10)
|
||||
draw_string(target, font, font->name.str,
|
||||
draw_string(target, font_id, info->name.str,
|
||||
font_x, text_y, style->main.default_color);
|
||||
|
||||
text_x = inner.x0;
|
||||
text_y += font->height;
|
||||
text_x = draw_string(target, font, "if ", text_x, text_y,
|
||||
text_y += info->height;
|
||||
text_x = draw_string(target, font_id, "if ", text_x, text_y,
|
||||
style->main.keyword_color);
|
||||
text_x = draw_string(target, font, "(x < ", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, "(x < ", text_x, text_y,
|
||||
style->main.default_color);
|
||||
text_x = draw_string(target, font, "0", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, "0", text_x, text_y,
|
||||
style->main.int_constant_color);
|
||||
text_x = draw_string(target, font, ") { x = ", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, ") { x = ", text_x, text_y,
|
||||
style->main.default_color);
|
||||
text_x = draw_string(target, font, "0", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, "0", text_x, text_y,
|
||||
style->main.int_constant_color);
|
||||
text_x = draw_string(target, font, "; } ", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, "; } ", text_x, text_y,
|
||||
style->main.default_color);
|
||||
text_x = draw_string(target, font, "// comment", text_x, text_y,
|
||||
text_x = draw_string(target, font_id, "// comment", text_x, text_y,
|
||||
style->main.comment_color);
|
||||
|
||||
text_x = inner.x0;
|
||||
text_y += font->height;
|
||||
text_x = draw_string(target, font, "[] () {}; * -> +-/ <>= ! && || % ^",
|
||||
text_y += info->height;
|
||||
text_x = draw_string(target, font_id, "[] () {}; * -> +-/ <>= ! && || % ^",
|
||||
text_x, text_y, style->main.default_color);
|
||||
}
|
||||
|
||||
|
@ -1269,13 +1281,15 @@ do_style_preview(Library_UI *ui, Style *style, i32 toggle = -1){
|
|||
return result;
|
||||
}
|
||||
|
||||
internal bool32
|
||||
internal b32
|
||||
do_main_file_box(System_Functions *system, UI_State *state, UI_Layout *layout, Hot_Directory *hot_directory, char *end = 0){
|
||||
bool32 result = 0;
|
||||
b32 result = 0;
|
||||
Style *style = state->style;
|
||||
Render_Font *font = style->font;
|
||||
i32_Rect box = layout_rect(layout, font->height + 2);
|
||||
String *string = &hot_directory->string;
|
||||
|
||||
i16 font_id = style->font_id;
|
||||
i32 line_height = get_font_info(state->font_set, font_id)->height;
|
||||
i32_Rect box = layout_rect(layout, line_height + 2);
|
||||
|
||||
if (state->input_stage){
|
||||
if (ui_do_file_field_input(system, state, hot_directory)){
|
||||
|
@ -1289,8 +1303,8 @@ do_main_file_box(System_Functions *system, UI_State *state, UI_Layout *layout, H
|
|||
u32 special = style->main.special_character_color;
|
||||
draw_rectangle(target, box, back);
|
||||
i32 x = box.x0;
|
||||
x = draw_string(target, font, string->str, x, box.y0, fore);
|
||||
if (end) draw_string(target, font, end, x, box.y0, special);
|
||||
x = draw_string(target, font_id, string->str, x, box.y0, fore);
|
||||
if (end) draw_string(target, font_id, end, x, box.y0, special);
|
||||
}
|
||||
|
||||
layout->y = box.y1;
|
||||
|
@ -1301,8 +1315,10 @@ internal bool32
|
|||
do_main_string_box(System_Functions *system, UI_State *state, UI_Layout *layout, String *string){
|
||||
bool32 result = 0;
|
||||
Style *style = state->style;
|
||||
Render_Font *font = style->font;
|
||||
i32_Rect box = layout_rect(layout, font->height + 2);
|
||||
|
||||
i16 font_id = style->font_id;
|
||||
i32 line_height = get_font_info(state->font_set, font_id)->height;
|
||||
i32_Rect box = layout_rect(layout, line_height + 2);
|
||||
|
||||
if (state->input_stage){
|
||||
if (ui_do_line_field_input(system, state, string)){
|
||||
|
@ -1315,7 +1331,7 @@ do_main_string_box(System_Functions *system, UI_State *state, UI_Layout *layout,
|
|||
u32 fore = style->main.default_color;
|
||||
draw_rectangle(target, box, back);
|
||||
i32 x = box.x0;
|
||||
x = draw_string(target, font, string->str, x, box.y0, fore);
|
||||
x = draw_string(target, font_id, string->str, x, box.y0, fore);
|
||||
}
|
||||
|
||||
layout->y = box.y1;
|
||||
|
@ -1326,10 +1342,11 @@ internal bool32
|
|||
do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){
|
||||
bool32 result = 0;
|
||||
Style *style = state->style;
|
||||
Render_Font *font = style->font;
|
||||
i32 character_h = font->height;
|
||||
|
||||
i16 font_id = style->font_id;
|
||||
i32 character_h = get_font_info(state->font_set, font_id)->height;
|
||||
|
||||
i32_Rect box = layout_rect(layout, font->height*2);
|
||||
i32_Rect box = layout_rect(layout, character_h*2);
|
||||
Widget_ID wid = make_id(state, id);
|
||||
|
||||
if (state->input_stage){
|
||||
|
@ -1349,7 +1366,7 @@ do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){
|
|||
|
||||
draw_rectangle(target, inner, back);
|
||||
i32 x = inner.x0, y = box.y0 + character_h/2;
|
||||
x = draw_string(target, font, text, x, y, fore);
|
||||
x = draw_string(target, font_id, text, x, y, fore);
|
||||
draw_margin(target, box, inner, outline);
|
||||
}
|
||||
|
||||
|
@ -1359,14 +1376,14 @@ do_list_option(i32 id, UI_State *state, UI_Layout *layout, String text){
|
|||
|
||||
#define do_list_option_lit(id,state,layout,str) do_list_option(id, state, layout, make_lit_string(str))
|
||||
|
||||
internal bool32
|
||||
do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool32 is_folder, String extra){
|
||||
bool32 result = 0;
|
||||
internal b32
|
||||
do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, b32 is_folder, String extra){
|
||||
b32 result = 0;
|
||||
Style *style = state->style;
|
||||
Render_Font *font = style->font;
|
||||
i32 character_h = font->height;
|
||||
i16 font_id = style->font_id;
|
||||
i32 character_h = get_font_info(state->font_set, font_id)->height;
|
||||
|
||||
i32_Rect box = layout_rect(layout, font->height*2);
|
||||
i32_Rect box = layout_rect(layout, character_h*2);
|
||||
Widget_ID wid = make_id(state, id);
|
||||
|
||||
if (state->input_stage){
|
||||
|
@ -1386,9 +1403,9 @@ do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool
|
|||
|
||||
draw_rectangle(target, inner, back);
|
||||
i32 x = inner.x0, y = box.y0 + character_h/2;
|
||||
x = draw_string(target, font, filename, x, y, fore);
|
||||
if (is_folder) x = draw_string(target, font, "\\", x, y, fore);
|
||||
draw_string(target, font, extra, x, y, pop);
|
||||
x = draw_string(target, font_id, filename, x, y, fore);
|
||||
if (is_folder) x = draw_string(target, font_id, "\\", x, y, fore);
|
||||
draw_string(target, font_id, extra, x, y, pop);
|
||||
draw_margin(target, box, inner, outline);
|
||||
}
|
||||
|
||||
|
@ -1397,10 +1414,10 @@ do_file_option(i32 id, UI_State *state, UI_Layout *layout, String filename, bool
|
|||
}
|
||||
|
||||
internal b32
|
||||
do_file_list_box(System_Functions *system,
|
||||
UI_State *state, UI_Layout *layout, Hot_Directory *hot_dir, bool32 has_filter,
|
||||
bool32 *new_dir, bool32 *selected, char *end){
|
||||
bool32 result = 0;
|
||||
do_file_list_box(System_Functions *system, UI_State *state,
|
||||
UI_Layout *layout, Hot_Directory *hot_dir, b32 has_filter,
|
||||
b32 *new_dir, b32 *selected, char *end){
|
||||
b32 result = 0;
|
||||
File_List *files = &hot_dir->file_list;
|
||||
|
||||
if (do_main_file_box(system, state, layout, hot_dir, end)){
|
||||
|
@ -1437,10 +1454,10 @@ do_file_list_box(System_Functions *system,
|
|||
Editing_File *file = working_set_contains(state->working_set, full_path);
|
||||
full_path.size = restore_size;
|
||||
|
||||
bool8 is_folder = (info->folder != 0);
|
||||
bool8 ext_match = (match(file_extension(filename), p4c_extension) != 0);
|
||||
bool8 name_match = (filename_match(front_name, &absolutes, filename) != 0);
|
||||
bool8 is_loaded = (file != 0);
|
||||
b8 is_folder = (info->folder != 0);
|
||||
b8 ext_match = (match(file_extension(filename), p4c_extension) != 0);
|
||||
b8 name_match = (filename_match(front_name, &absolutes, filename) != 0);
|
||||
b8 is_loaded = (file != 0);
|
||||
|
||||
String message = message_nothing;
|
||||
if (is_loaded){
|
||||
|
@ -1494,18 +1511,18 @@ do_live_file_list_box(System_Functions *system, UI_State *state, UI_Layout *layo
|
|||
for (i32 i = 0; i < count; ++i){
|
||||
Editing_File *file = files + i;
|
||||
|
||||
if (!file->is_dummy){
|
||||
if (!file->state.is_dummy){
|
||||
String message = message_nothing;
|
||||
switch (buffer_get_sync(file)){
|
||||
case SYNC_BEHIND_OS: message = message_unsynced; break;
|
||||
case SYNC_UNSAVED: message = message_unsaved; break;
|
||||
}
|
||||
|
||||
if (filename_match(*string, &absolutes, file->live_name)){
|
||||
if (do_file_option(100+i, state, layout, file->live_name, 0, message)){
|
||||
if (filename_match(*string, &absolutes, file->state.live_name)){
|
||||
if (do_file_option(100+i, state, layout, file->state.live_name, 0, message)){
|
||||
result = 1;
|
||||
*selected = 1;
|
||||
copy(string, file->live_name);
|
||||
copy(string, file->state.live_name);
|
||||
terminate_with_null(string);
|
||||
}
|
||||
}
|
||||
|
@ -1517,16 +1534,17 @@ do_live_file_list_box(System_Functions *system, UI_State *state, UI_Layout *layo
|
|||
}
|
||||
|
||||
internal i32
|
||||
step_draw_library(System_Functions *system,
|
||||
step_draw_library(System_Functions *system, Exchange *exchange, Mem_Options *mem,
|
||||
Color_View *color_view, i32_Rect rect, View_Message message,
|
||||
Render_Target *target, Input_Summary *user_input){
|
||||
i32 result = 0;
|
||||
|
||||
Library_UI ui;
|
||||
ui.state = ui_state_init(&color_view->state, target, user_input,
|
||||
color_view->main_style, color_view->working_set, (message == VMSG_STEP));
|
||||
color_view->main_style, color_view->font_set,
|
||||
color_view->working_set, (message == VMSG_STEP));
|
||||
|
||||
ui.fonts = color_view->fonts;
|
||||
ui.fonts = color_view->font_set;
|
||||
ui.hot_directory = color_view->hot_directory;
|
||||
ui.styles = color_view->styles;
|
||||
|
||||
|
@ -1591,7 +1609,7 @@ step_draw_library(System_Functions *system,
|
|||
do_label(&ui.state, &ui.layout, "Current Theme");
|
||||
do_style_preview(&ui, color_view->main_style);
|
||||
|
||||
bool32 file_selected = 0;
|
||||
b32 file_selected = 0;
|
||||
|
||||
do_label(&ui.state, &ui.layout, "Import Which File?");
|
||||
begin_row(&ui.layout, 2);
|
||||
|
@ -1602,7 +1620,7 @@ step_draw_library(System_Functions *system,
|
|||
color_view->mode = CV_MODE_LIBRARY;
|
||||
}
|
||||
|
||||
bool32 new_dir = 0;
|
||||
b32 new_dir = 0;
|
||||
if (do_file_list_box(system,
|
||||
&ui.state, &ui.layout, ui.hot_directory, color_view->p4c_only,
|
||||
&new_dir, &file_selected, 0)){
|
||||
|
@ -1614,19 +1632,40 @@ step_draw_library(System_Functions *system,
|
|||
}
|
||||
if (file_selected){
|
||||
memset(&color_view->inspecting_styles, 0, sizeof(Style_Library));
|
||||
memset(color_view->import_export_check, 1, sizeof(color_view->import_export_check));
|
||||
Style *styles = color_view->inspecting_styles.styles;
|
||||
i32 count, max;
|
||||
max = ArrayCount(color_view->inspecting_styles.styles);
|
||||
if (style_library_import(system,
|
||||
color_view->hot_directory->string.str,
|
||||
ui.fonts, styles, max, &count)){
|
||||
color_view->mode = CV_MODE_IMPORT;
|
||||
memset(color_view->import_export_check, 1,
|
||||
sizeof(color_view->import_export_check));
|
||||
|
||||
color_view->import_file_id =
|
||||
exchange_request_file(exchange,
|
||||
color_view->hot_directory->string.str,
|
||||
color_view->hot_directory->string.size);
|
||||
color_view->mode = CV_MODE_IMPORT_WAIT;
|
||||
|
||||
}
|
||||
}break;
|
||||
|
||||
case CV_MODE_IMPORT_WAIT:
|
||||
{
|
||||
Style *styles = color_view->inspecting_styles.styles;
|
||||
Data file;
|
||||
i32 file_max;
|
||||
|
||||
i32 count, max;
|
||||
max = ArrayCount(color_view->inspecting_styles.styles);
|
||||
|
||||
if (exchange_file_ready(exchange, color_view->import_file_id,
|
||||
&file.data, &file.size, &file_max)){
|
||||
if (file.data){
|
||||
if (style_library_import(file, ui.fonts, styles, max, &count))
|
||||
color_view->mode = CV_MODE_IMPORT;
|
||||
else color_view->mode = CV_MODE_LIBRARY;
|
||||
color_view->inspecting_styles.count = count;
|
||||
}
|
||||
else{
|
||||
color_view->mode = CV_MODE_LIBRARY;
|
||||
Assert(!"this shouldn't happen!");
|
||||
}
|
||||
color_view->inspecting_styles.count = count;
|
||||
|
||||
exchange_free_file(exchange, color_view->import_file_id);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -1635,7 +1674,7 @@ step_draw_library(System_Functions *system,
|
|||
do_label(&ui.state, &ui.layout, "Current Theme");
|
||||
do_style_preview(&ui, color_view->main_style);
|
||||
|
||||
bool32 file_selected = 0;
|
||||
b32 file_selected = 0;
|
||||
|
||||
do_label(&ui.state, &ui.layout, "Export File Name?");
|
||||
begin_row(&ui.layout, 2);
|
||||
|
@ -1646,7 +1685,7 @@ step_draw_library(System_Functions *system,
|
|||
color_view->mode = CV_MODE_LIBRARY;
|
||||
}
|
||||
|
||||
bool32 new_dir = 0;
|
||||
b32 new_dir = 0;
|
||||
if (do_file_list_box(system,
|
||||
&ui.state, &ui.layout, ui.hot_directory, 1,
|
||||
&new_dir, &file_selected, ".p4c")){
|
||||
|
@ -1659,8 +1698,9 @@ step_draw_library(System_Functions *system,
|
|||
}
|
||||
if (file_selected){
|
||||
i32 count = ui.styles->count;
|
||||
// TODO(allen): pass the transient memory in here
|
||||
Style **styles = (Style**)system->get_memory(sizeof(Style*)*count);
|
||||
Temp_Memory temp = begin_temp_memory(&mem->part);
|
||||
Style **styles = push_array(&mem->part, Style*, sizeof(Style*)*count);
|
||||
|
||||
Style *style = ui.styles->styles;
|
||||
bool8 *export_check = color_view->import_export_check;
|
||||
i32 export_count = 0;
|
||||
|
@ -1669,13 +1709,13 @@ step_draw_library(System_Functions *system,
|
|||
styles[export_count++] = style;
|
||||
}
|
||||
}
|
||||
char *mem = (char*)system->get_memory(ui.hot_directory->string.size + 5);
|
||||
String str = make_string(mem, 0, ui.hot_directory->string.size + 5);
|
||||
char *data = push_array(&mem->part, char, ui.hot_directory->string.size + 5);
|
||||
String str = make_string(data, 0, ui.hot_directory->string.size + 5);
|
||||
copy(&str, ui.hot_directory->string);
|
||||
append(&str, make_lit_string(".p4c"));
|
||||
style_library_export(system, str.str, styles, export_count);
|
||||
system->free_memory(mem);
|
||||
system->free_memory(styles);
|
||||
style_library_export(system, exchange, mem, &target->font_set, str.str, styles, export_count);
|
||||
|
||||
end_temp_memory(temp);
|
||||
color_view->mode = CV_MODE_LIBRARY;
|
||||
}
|
||||
}break;
|
||||
|
@ -1757,14 +1797,17 @@ Do_View_Sig(do_color_view){
|
|||
case CV_MODE_EXPORT_FILE:
|
||||
case CV_MODE_IMPORT:
|
||||
case CV_MODE_EXPORT:
|
||||
case CV_MODE_IMPORT_WAIT:
|
||||
switch (message){
|
||||
case VMSG_STEP:
|
||||
{
|
||||
result = step_draw_library(system, color_view, rect, message, target, user_input);
|
||||
result = step_draw_library(system, exchange, view->mem,
|
||||
color_view, rect, message, target, user_input);
|
||||
}break;
|
||||
case VMSG_DRAW:
|
||||
{
|
||||
step_draw_library(system, color_view, rect, message, target, user_input);
|
||||
step_draw_library(system, exchange, view->mem,
|
||||
color_view, rect, message, target, user_input);
|
||||
}break;
|
||||
}break;
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ map_hash(u16 event_code, u8 modifiers){
|
|||
}
|
||||
|
||||
internal b32
|
||||
map_add(Command_Map *map, u16 event_code, u8 modifiers, Command_Function function,
|
||||
Custom_Command_Function *custom = 0){
|
||||
map_add(Command_Map *map, u16 event_code, u8 modifiers,
|
||||
Command_Function function, Custom_Command_Function *custom = 0){
|
||||
Assert(map->count * 8 < map->max * 7);
|
||||
Command_Binding bind;
|
||||
bind.function = function;
|
||||
|
@ -61,7 +61,8 @@ map_add(Command_Map *map, u16 event_code, u8 modifiers, Command_Function functio
|
|||
}
|
||||
|
||||
internal b32
|
||||
map_find_entry(Command_Map *map, u16 event_code, u8 modifiers, i32 *index_out){
|
||||
map_find_entry(Command_Map *map, u16 event_code, u8 modifiers,
|
||||
i32 *index_out){
|
||||
i64 hash = map_hash(event_code, modifiers);
|
||||
i32 max = map->max;
|
||||
i32 index = hash % map->max;
|
||||
|
@ -77,7 +78,8 @@ map_find_entry(Command_Map *map, u16 event_code, u8 modifiers, i32 *index_out){
|
|||
}
|
||||
|
||||
internal b32
|
||||
map_find(Command_Map *map, u16 event_code, u8 modifiers, Command_Binding *bind_out){
|
||||
map_find(Command_Map *map, u16 event_code, u8 modifiers,
|
||||
Command_Binding *bind_out){
|
||||
b32 result;
|
||||
i32 index;
|
||||
result = map_find_entry(map, event_code, modifiers, &index);
|
||||
|
@ -100,7 +102,8 @@ map_drop(Command_Map *map, u16 event_code, u8 modifiers){
|
|||
}
|
||||
|
||||
internal void
|
||||
map_init(Command_Map *commands, Partition *part, i32 max, Command_Map *parent){
|
||||
map_init(Command_Map *commands, Partition *part, i32 max,
|
||||
Command_Map *parent){
|
||||
commands->parent = parent;
|
||||
commands->commands = push_array(part, Command_Binding, max);
|
||||
memset(commands->commands, 0, max*sizeof(*commands->commands));
|
||||
|
@ -110,31 +113,35 @@ map_init(Command_Map *commands, Partition *part, i32 max, Command_Map *parent){
|
|||
}
|
||||
|
||||
internal void
|
||||
map_get_vanilla_keyboard_default(Command_Map *map, u8 command, Command_Binding *bind_out){
|
||||
map_get_vanilla_keyboard_default(Command_Map *map, u8 command,
|
||||
Command_Binding *bind_out){
|
||||
if (command == MDFR_NONE){
|
||||
*bind_out = map->vanilla_keyboard_default;
|
||||
}
|
||||
}
|
||||
|
||||
inline u8
|
||||
apply_shift_to_code(u8 keycode){
|
||||
return !(keycode >= 0x20 && keycode < 0x7F && keycode != ' ');
|
||||
}
|
||||
|
||||
internal Command_Binding
|
||||
map_extract(Command_Map *map, Key_Single key){
|
||||
Command_Binding bind = {};
|
||||
|
||||
b32 ctrl = key.modifiers[CONTROL_KEY_CONTROL];
|
||||
b32 alt = key.modifiers[CONTROL_KEY_ALT];
|
||||
b32 shift = key.modifiers[CONTROL_KEY_SHIFT] && key.key.loose_keycode;
|
||||
b32 shift = key.modifiers[CONTROL_KEY_SHIFT];
|
||||
u16 code;
|
||||
u8 command = MDFR_NONE;
|
||||
|
||||
if (key.key.character_no_caps_lock != 0 &&
|
||||
key.key.character_no_caps_lock != ' ') shift = 0;
|
||||
|
||||
if (shift) command |= MDFR_SHIFT;
|
||||
if (ctrl) command |= MDFR_CTRL;
|
||||
if (alt) command |= MDFR_ALT;
|
||||
|
||||
command |= MDFR_EXACT;
|
||||
code = key.key.keycode;
|
||||
map_find(map, code, command, &bind);
|
||||
|
||||
command &= ~(MDFR_EXACT);
|
||||
|
||||
code = key.key.character_no_caps_lock;
|
||||
if (code == 0){
|
||||
code = key.key.keycode;
|
||||
|
|
|
@ -23,7 +23,7 @@ struct Dbg_Past_Key{
|
|||
|
||||
struct Debug_View{
|
||||
View view_base;
|
||||
Render_Font *font;
|
||||
i16 font_id;
|
||||
Debug_Mode mode;
|
||||
Dbg_Past_Key past_keys[32];
|
||||
i32 past_key_count, past_key_pos;
|
||||
|
@ -38,8 +38,8 @@ view_to_debug_view(View *view){
|
|||
|
||||
internal i32
|
||||
draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 y){
|
||||
Render_Font *font = view->font;
|
||||
i32 y_advance = font->height;
|
||||
i16 font_id = view->font_id;
|
||||
i32 y_advance = get_font_info(&target->font_set, font_id)->height;
|
||||
Bubble *sentinel = &view->view_base.mem->general.sentinel;
|
||||
|
||||
for (Bubble *bubble = sentinel->next;
|
||||
|
@ -70,7 +70,7 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32
|
|||
append_int_to_str(bubble->size, &s);
|
||||
terminate_with_null(&s);
|
||||
|
||||
draw_string(target, font, str, rect.x0, y, color);
|
||||
draw_string(target, font_id, str, rect.x0, y, color);
|
||||
y += y_advance;
|
||||
|
||||
Bubble *next = bubble->next;
|
||||
|
@ -83,7 +83,7 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32
|
|||
append(&s, "discontinuity");
|
||||
terminate_with_null(&s);
|
||||
|
||||
draw_string(target, font, str, rect.x0, y, color);
|
||||
draw_string(target, font_id, str, rect.x0, y, color);
|
||||
y += y_advance;
|
||||
}
|
||||
}
|
||||
|
@ -93,9 +93,10 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32
|
|||
}
|
||||
|
||||
internal i32
|
||||
draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect, Render_Target *target, i32 y){
|
||||
Render_Font *font = view->font;
|
||||
i32 y_advance = font->height;
|
||||
draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect,
|
||||
Render_Target *target, i32 y){
|
||||
i16 font_id = view->font_id;
|
||||
i32 y_advance = get_font_info(&target->font_set, font_id)->height;
|
||||
Bubble *sentinel = system->internal_sentinel();
|
||||
|
||||
for (Bubble *bubble = sentinel->next;
|
||||
|
@ -114,7 +115,7 @@ draw_system_memory(System_Functions *system, Debug_View *view, i32_Rect rect, Re
|
|||
append_int_to_str(bubble->size, &s);
|
||||
terminate_with_null(&s);
|
||||
|
||||
draw_string(target, font, str, rect.x0, y, color);
|
||||
draw_string(target, font_id, str, rect.x0, y, color);
|
||||
|
||||
y += y_advance;
|
||||
}
|
||||
|
@ -152,7 +153,7 @@ draw_background_threads(System_Functions *system,
|
|||
String s = make_fixed_width_string(str);
|
||||
append_int_to_str(pending, &s);
|
||||
terminate_with_null(&s);
|
||||
draw_string(target, view->font, str, trect.x1, trect.y1, light);
|
||||
draw_string(target, view->font_id, str, trect.x1, trect.y1, light);
|
||||
}
|
||||
|
||||
struct Dbg_Modifier{
|
||||
|
@ -174,7 +175,7 @@ draw_modifiers(Debug_View *view, Render_Target *target,
|
|||
if (modifiers[m.modifier]) color = on_color;
|
||||
else color = off_color;
|
||||
|
||||
*x = draw_string(target, view->font, m.name, *x, y, color);
|
||||
*x = draw_string(target, view->font_id, m.name, *x, y, color);
|
||||
*x += 5;
|
||||
}
|
||||
}
|
||||
|
@ -182,15 +183,17 @@ draw_modifiers(Debug_View *view, Render_Target *target,
|
|||
internal i32
|
||||
draw_key_event(Debug_View *view, Render_Target *target,
|
||||
Dbg_Past_Key *key, i32 x, i32 y, u32 on_color, u32 off_color){
|
||||
Render_Font *font = view->font;
|
||||
draw_modifiers(view, target, key->modifiers,
|
||||
on_color, off_color, &x, y);
|
||||
|
||||
i16 font_id = view->font_id;
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
|
||||
if (font->glyphs[key->key.character].exists){
|
||||
if (font && font->glyphs[key->key.character].exists){
|
||||
char c[2];
|
||||
c[0] = (char)key->key.character;
|
||||
c[1] = 0;
|
||||
x = draw_string(target, font, c, x, y, on_color);
|
||||
x = draw_string(target, font_id, c, x, y, on_color);
|
||||
}
|
||||
else{
|
||||
char c[10] = {};
|
||||
|
@ -198,7 +201,7 @@ draw_key_event(Debug_View *view, Render_Target *target,
|
|||
append(&str, "\\");
|
||||
append_int_to_str(key->key.keycode, &str);
|
||||
terminate_with_null(&str);
|
||||
x = draw_string(target, font, c, x, y, on_color);
|
||||
x = draw_string(target, font_id, c, x, y, on_color);
|
||||
}
|
||||
|
||||
return x;
|
||||
|
@ -212,14 +215,15 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target,
|
|||
i32 x, y, max_x, max_y;
|
||||
x = rect.x0;
|
||||
y = rect.y0;
|
||||
|
||||
Render_Font *font = view->font;
|
||||
|
||||
i16 font_id = view->font_id;
|
||||
i32 line_height = get_font_info(&target->font_set, font_id)->height;
|
||||
|
||||
draw_modifiers(view, target, active_input->keys.modifiers,
|
||||
0xFFFFFFFF, 0xFF444444, &x, y);
|
||||
max_x = x;
|
||||
x = rect.x0;
|
||||
y += font->height;
|
||||
y += line_height;
|
||||
|
||||
for (i32 j = 0; j < view->past_key_count; ++j){
|
||||
Dbg_Past_Key *key = view->past_keys + j;
|
||||
|
@ -236,7 +240,7 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target,
|
|||
|
||||
if (max_x < x) max_x = x;
|
||||
x = rect.x0;
|
||||
y += font->height;
|
||||
y += line_height;
|
||||
}
|
||||
|
||||
i32_Rect mrect = rect;
|
||||
|
@ -250,13 +254,13 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target,
|
|||
u32 color;
|
||||
if (active_input->mouse.out_of_window){
|
||||
color = 0xFFFF0000;
|
||||
draw_string(target, font, "OUT", x, y, color);
|
||||
draw_string(target, font_id, "OUT", x, y, color);
|
||||
}
|
||||
else{
|
||||
color = 0xFF008800;
|
||||
draw_string(target, font, "IN", x, y, color);
|
||||
draw_string(target, font_id, "IN", x, y, color);
|
||||
}
|
||||
y += font->height;
|
||||
y += line_height;
|
||||
|
||||
char c[16];
|
||||
String s = make_fixed_width_string(c);
|
||||
|
@ -264,20 +268,20 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target,
|
|||
append(&s, ", ");
|
||||
append_int_to_str(active_input->mouse.my, &s);
|
||||
terminate_with_null(&s);
|
||||
draw_string(target, font, c, x, y, color);
|
||||
y += font->height;
|
||||
draw_string(target, font_id, c, x, y, color);
|
||||
y += line_height;
|
||||
|
||||
u32 btn_color;
|
||||
if (active_input->mouse.l) btn_color = color;
|
||||
else btn_color = 0xFF444444;
|
||||
x = draw_string(target, font, "L ", x, y, btn_color);
|
||||
x = draw_string(target, font_id, "L ", x, y, btn_color);
|
||||
|
||||
if (active_input->mouse.r) btn_color = color;
|
||||
else btn_color = 0xFF444444;
|
||||
x = draw_string(target, font, "R", x, y, btn_color);
|
||||
x = draw_string(target, font_id, "R", x, y, btn_color);
|
||||
|
||||
x = mrect.x0;
|
||||
y += font->height;
|
||||
y += line_height;
|
||||
|
||||
s = make_fixed_width_string(c);
|
||||
append_int_to_str(view->prev_mouse_wheel, &s);
|
||||
|
@ -285,9 +289,9 @@ draw_os_events(Debug_View *view, i32_Rect rect, Render_Target *target,
|
|||
|
||||
if (active_input->mouse.wheel_used) btn_color = color;
|
||||
else btn_color = 0xFF444444;
|
||||
draw_string(target, font, c, x, y, btn_color);
|
||||
draw_string(target, font_id, c, x, y, btn_color);
|
||||
|
||||
y += font->height;
|
||||
y += line_height;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 9.12.2015
|
||||
*
|
||||
* Exchange stuff
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal void
|
||||
ex__file_insert(File_Slot *pos, File_Slot *file){
|
||||
pos->next->prev = file;
|
||||
file->next = pos->next;
|
||||
pos->next = file;
|
||||
file->prev = pos;
|
||||
}
|
||||
|
||||
internal void
|
||||
ex__file_remove(File_Slot *file){
|
||||
file->next->prev = file->prev;
|
||||
file->prev->next = file->next;
|
||||
}
|
||||
|
||||
internal void
|
||||
ex__check_file(File_Slot *pos){
|
||||
File_Slot *file = pos;
|
||||
|
||||
Assert(pos == pos->next->prev);
|
||||
|
||||
for (pos = pos->next;
|
||||
file != pos;
|
||||
pos = pos->next){
|
||||
Assert(pos == pos->next->prev);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
ex__check(File_Exchange *file_exchange){
|
||||
ex__check_file(&file_exchange->available);
|
||||
ex__check_file(&file_exchange->active);
|
||||
ex__check_file(&file_exchange->free_list);
|
||||
}
|
||||
|
||||
internal void
|
||||
ex__clear(File_Slot *file){
|
||||
file->data = 0;
|
||||
file->size = 0;
|
||||
file->max = 0;
|
||||
file->flags = 0;
|
||||
}
|
||||
|
||||
internal File_Slot*
|
||||
ex__get_file(Exchange *exchange){
|
||||
File_Exchange *files = &exchange->file;
|
||||
File_Slot *file;
|
||||
|
||||
++files->num_active;
|
||||
|
||||
file = files->available.next;
|
||||
ex__file_remove(file);
|
||||
ex__clear(file);
|
||||
ex__file_insert(&files->active, file);
|
||||
ex__check(files);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
internal void
|
||||
ex__set_filename(File_Slot *file, char *filename, int len){
|
||||
memcpy(file->filename, filename, len);
|
||||
file->filename[len] = 0;
|
||||
file->filename_len = len;
|
||||
}
|
||||
|
||||
internal i32
|
||||
exchange_request_file(Exchange *exchange, char *filename, int len){
|
||||
File_Exchange *files = &exchange->file;
|
||||
i32 result = 0;
|
||||
|
||||
if (len+1 < FileNameMax){
|
||||
if (files->num_active < files->max){
|
||||
File_Slot *file = ex__get_file(exchange);
|
||||
ex__set_filename(file, filename, len);
|
||||
|
||||
file->flags |= FEx_Request;
|
||||
result = (int)(file - files->files) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
exchange_file_ready(Exchange *exchange, i32 file_id, byte **data, int *size, int *max){
|
||||
File_Exchange *files = &exchange->file;
|
||||
b32 result = 0;
|
||||
|
||||
if (file_id > 0 && file_id <= files->max){
|
||||
File_Slot *file = files->files + file_id - 1;
|
||||
if (file->flags & FEx_Ready){
|
||||
*data = file->data;
|
||||
*size = file->size;
|
||||
*max = file->max;
|
||||
result = 1;
|
||||
}
|
||||
if (file->flags & FEx_Not_Exist){
|
||||
*data = 0;
|
||||
*size = 0;
|
||||
*max = 0;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal i32
|
||||
exchange_save_file(Exchange *exchange, char *filename, int len,
|
||||
byte *data, int size, int max){
|
||||
File_Exchange *files = &exchange->file;
|
||||
i32 result = 0;
|
||||
|
||||
if (len+1 < FileNameMax){
|
||||
if (files->num_active < files->max){
|
||||
File_Slot *file = ex__get_file(exchange);
|
||||
ex__set_filename(file, filename, len);
|
||||
|
||||
file->flags |= FEx_Save;
|
||||
file->data = data;
|
||||
file->size = size;
|
||||
file->max = max;
|
||||
|
||||
result = (int)(file - files->files) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
exchange_file_save_complete(Exchange *exchange, i32 file_id, byte **data, int *size, int *max){
|
||||
File_Exchange *files = &exchange->file;
|
||||
b32 result = 0;
|
||||
|
||||
if (file_id > 0 && file_id <= files->max){
|
||||
File_Slot *file = files->files + file_id - 1;
|
||||
if (file->flags & FEx_Save_Complete){
|
||||
*data = file->data;
|
||||
*size = file->size;
|
||||
*max = file->max;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal char*
|
||||
exchange_file_filename(Exchange *exchange, i32 file_id, i32 *size = 0){
|
||||
File_Exchange *files = &exchange->file;
|
||||
char *result = 0;
|
||||
|
||||
if (file_id > 0 && file_id <= files->max){
|
||||
File_Slot *file = files->files + file_id - 1;
|
||||
result = file->filename;
|
||||
if (size) *size = file->filename_len;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
exchange_free_file(Exchange *exchange, i32 file_id){
|
||||
File_Exchange *files = &exchange->file;
|
||||
|
||||
if (file_id > 0 && file_id <= files->max){
|
||||
File_Slot *file = files->files + file_id - 1;
|
||||
ex__file_remove(file);
|
||||
ex__file_insert(&files->free_list, file);
|
||||
ex__check(files);
|
||||
--files->num_active;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
exchange_clear_file(Exchange *exchange, i32 file_id){
|
||||
File_Exchange *files = &exchange->file;
|
||||
|
||||
if (file_id > 0 && file_id <= files->max){
|
||||
File_Slot *file = files->files + file_id - 1;
|
||||
ex__clear(file);
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
queue_job_is_pending(Work_Queue *queue, u32 job_id){
|
||||
b32 result;
|
||||
u32 job_index;
|
||||
Full_Job_Data *full_job;
|
||||
|
||||
job_index = job_id % QUEUE_WRAP;
|
||||
full_job = queue->jobs + job_index;
|
||||
|
||||
Assert(full_job->id == job_id);
|
||||
|
||||
result = 0;
|
||||
if (full_job->running_thread != 0){
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
1244
4ed_file_view.cpp
1244
4ed_file_view.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 18.12.2015
|
||||
*
|
||||
* Font set for 4coder
|
||||
*
|
||||
*/
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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 = {};
|
||||
set->used_slots = {};
|
||||
|
||||
set->free_slots.next = &set->free_slots;
|
||||
set->free_slots.prev = &set->free_slots;
|
||||
set->used_slots.next = &set->used_slots;
|
||||
set->used_slots.prev = &set->used_slots;
|
||||
|
||||
char *ptr = (char*)set->font_block;
|
||||
for (i32 i = 0; i < live_max; ++i){
|
||||
font__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(Partition *partition, 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(partition, font, info->filename.str, info->pt_size, 4);
|
||||
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(Partition *partition, Font_Set *set, i16 font_id){
|
||||
b8 already_used;
|
||||
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(partition, set, font_id);
|
||||
}
|
||||
slot = ((Font_Slot*)info->font) - 1;
|
||||
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_add(Partition *partition, Font_Set *set,
|
||||
String filename, String name, i32 pt_size){
|
||||
b32 result = 0;
|
||||
if (font_set_can_add(set)){
|
||||
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_info_load(partition, filename.str, pt_size, &info->height, &info->advance);
|
||||
font_set_add_hash(set, name, font_id);
|
||||
|
||||
if (font_set_can_load(set)){
|
||||
font_set_load(partition, set, font_id);
|
||||
}
|
||||
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_find_pos(Font_Set *set, String name, u32 *position){
|
||||
b32 result;
|
||||
u32 hash, i, j;
|
||||
hash = font_hash(name);
|
||||
i = hash % set->max;
|
||||
j = i - 1;
|
||||
if (j <= 1) j += set->max;
|
||||
|
||||
result = 0;
|
||||
Font_Table_Entry *entry;
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max) i = 0;
|
||||
entry = set->entries + i;
|
||||
if (entry->hash == hash){
|
||||
if (match(name, entry->name)){
|
||||
result = 1;
|
||||
*position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_extract(Font_Set *set, String name, i16 *font_id){
|
||||
b32 result;
|
||||
u32 position;
|
||||
|
||||
result = font_set_find_pos(set, name, &position);
|
||||
if (result){
|
||||
*font_id = set->entries[position].font_id;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -30,6 +30,7 @@ struct Interactive_View{
|
|||
Style *style;
|
||||
Working_Set *working_set;
|
||||
Delay *delay;
|
||||
Font_Set *font_set;
|
||||
UI_State state;
|
||||
Interactive_View_Interaction interaction;
|
||||
Interactive_View_Action action;
|
||||
|
@ -97,19 +98,20 @@ interactive_view_complete(Interactive_View *view){
|
|||
}
|
||||
|
||||
internal i32
|
||||
step_draw_int_view(System_Functions *system,
|
||||
Interactive_View *view, Render_Target *target, i32_Rect rect,
|
||||
Input_Summary *user_input, bool32 input_stage){
|
||||
step_draw_int_view(System_Functions *system, Interactive_View *view,
|
||||
Render_Target *target, i32_Rect rect,
|
||||
Input_Summary *user_input, b32 input_stage){
|
||||
i32 result = 0;
|
||||
|
||||
UI_State state =
|
||||
ui_state_init(&view->state, target, user_input, view->style, view->working_set, input_stage);
|
||||
ui_state_init(&view->state, target, user_input,
|
||||
view->style, view->font_set, view->working_set, input_stage);
|
||||
|
||||
UI_Layout layout;
|
||||
begin_layout(&layout, rect);
|
||||
|
||||
bool32 new_dir = 0;
|
||||
bool32 complete = 0;
|
||||
b32 new_dir = 0;
|
||||
b32 complete = 0;
|
||||
|
||||
terminate_with_null(&view->query);
|
||||
do_label(&state, &layout, view->query.str, 1.f);
|
||||
|
@ -202,8 +204,9 @@ Do_View_Sig(do_interactive_view){
|
|||
}
|
||||
|
||||
internal Interactive_View*
|
||||
interactive_view_init(System_Functions *system, View *view, Hot_Directory *hot_dir, Style *style,
|
||||
Working_Set *working_set, Delay *delay){
|
||||
interactive_view_init(System_Functions *system, View *view,
|
||||
Hot_Directory *hot_dir, Style *style,
|
||||
Working_Set *working_set, Font_Set *font_set, Delay *delay){
|
||||
Interactive_View *result = (Interactive_View*)view;
|
||||
view->type = VIEW_TYPE_INTERACTIVE;
|
||||
view->do_view = do_interactive_view;
|
||||
|
@ -214,6 +217,7 @@ interactive_view_init(System_Functions *system, View *view, Hot_Directory *hot_d
|
|||
result->dest = make_fixed_width_string(result->dest_);
|
||||
result->style = style;
|
||||
result->working_set = working_set;
|
||||
result->font_set = font_set;
|
||||
result->delay = delay;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -9,85 +9,27 @@
|
|||
|
||||
// TOP
|
||||
|
||||
globalvar u16 keycode_lookup_table[255];
|
||||
globalvar u16 loose_keycode_lookup_table[255];
|
||||
globalvar u8 keycode_lookup_table[255];
|
||||
|
||||
internal void
|
||||
set_dynamic_key_names(Key_Codes *codes){
|
||||
u16 code = 1;
|
||||
u16 *codes_array = (u16*)codes;
|
||||
u8 code = 1;
|
||||
u8 *codes_array = (u8*)codes;
|
||||
for (i32 i = 0; i < sizeof(*codes)/sizeof(codes->up);){
|
||||
switch (code){
|
||||
case '\n': code++; break;
|
||||
case '\t': code++; break;
|
||||
case 0x20: code = 0x7F; break;
|
||||
default:
|
||||
codes_array[i++] = code++;
|
||||
}
|
||||
codes_array[i++] = code++;
|
||||
}
|
||||
}
|
||||
|
||||
inline u16
|
||||
inline u8
|
||||
keycode_lookup(u8 system_code){
|
||||
return keycode_lookup_table[system_code];
|
||||
}
|
||||
|
||||
inline u16
|
||||
loose_keycode_lookup(u8 system_code){
|
||||
return loose_keycode_lookup_table[system_code];
|
||||
}
|
||||
|
||||
inline b32
|
||||
keycode_has_ascii(u16 keycode){
|
||||
return (keycode >= 0x20 && keycode < 0x7F) || keycode == '\n' || keycode == '\t';
|
||||
}
|
||||
|
||||
internal u8
|
||||
translate_key(u16 keycode,
|
||||
b32 shift,
|
||||
b32 caps_lock){
|
||||
u8 character = 0;
|
||||
if (keycode >= 'A' && keycode <= 'Z'){
|
||||
if (caps_lock) shift = !shift;
|
||||
if (!shift) character = char_to_lower((char)keycode);
|
||||
else character = (u8)keycode;
|
||||
}
|
||||
else if (keycode >= '0' && keycode <= '9'){
|
||||
persist u8 shift_number_table[10] = {
|
||||
')', '!', '@', '#', '$', '%', '^', '&', '*', '('
|
||||
//0 1 2 3 4 5 6 7 8 9
|
||||
};
|
||||
if (shift){
|
||||
character = shift_number_table[keycode - '0'];
|
||||
}
|
||||
else{
|
||||
character = (u8)keycode;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (keycode_has_ascii(keycode)){
|
||||
character = (u8)keycode;
|
||||
u8 shift_character = character;
|
||||
switch (keycode){
|
||||
case '-': character = '-'; shift_character = '_'; break;
|
||||
case '=': character = '='; shift_character = '+'; break;
|
||||
case '`': character = '`'; shift_character = '~'; break;
|
||||
case '\\': character = '\\'; shift_character = '|'; break;
|
||||
case '[': character = '['; shift_character = '{'; break;
|
||||
case ']': character = ']'; shift_character = '}'; break;
|
||||
case '\'': character = '\''; shift_character = '"'; break;
|
||||
case ';': character = ';'; shift_character = ':'; break;
|
||||
case '/': character = '/'; shift_character = '?'; break;
|
||||
case '.': character = '.'; shift_character = '>'; break;
|
||||
case ',': character = ','; shift_character = '<'; break;
|
||||
case ' ': character = ' '; shift_character = ' '; break;
|
||||
case '\n': character = '\n'; shift_character = '\n'; break;
|
||||
case '\t': character = '\t'; shift_character = '\t'; break;
|
||||
}
|
||||
if (shift) character = shift_character;
|
||||
}
|
||||
}
|
||||
return character;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ struct Interactive_Bar{
|
|||
real32 pos_x, pos_y;
|
||||
real32 text_shift_x, text_shift_y;
|
||||
i32_Rect rect;
|
||||
Render_Font *font;
|
||||
i16 font_id;
|
||||
};
|
||||
|
||||
enum View_Message{
|
||||
|
@ -39,7 +39,7 @@ enum View_Message{
|
|||
|
||||
struct View;
|
||||
#define Do_View_Sig(name) \
|
||||
i32 (name)(System_Functions *system, \
|
||||
i32 (name)(System_Functions *system, Exchange *exchange, \
|
||||
View *view, i32_Rect rect, View *active, \
|
||||
View_Message message, Render_Target *target, \
|
||||
Input_Summary *user_input, Input_Summary *active_input)
|
||||
|
@ -78,8 +78,8 @@ struct View{
|
|||
i32 type;
|
||||
i32 block_size;
|
||||
Application_Mouse_Cursor mouse_cursor_type;
|
||||
bool32 is_active;
|
||||
bool32 is_minor;
|
||||
b32 is_active;
|
||||
b32 is_minor;
|
||||
};
|
||||
|
||||
struct Live_Views{
|
||||
|
@ -133,31 +133,30 @@ struct Editing_Layout{
|
|||
};
|
||||
|
||||
internal void
|
||||
intbar_draw_string(Render_Target *target, Interactive_Bar *bar,
|
||||
u8 *str, u32 char_color){
|
||||
Render_Font *font = bar->font;
|
||||
intbar_draw_string(Render_Target *target,
|
||||
Interactive_Bar *bar, u8 *str, u32 char_color){
|
||||
i16 font_id = bar->font_id;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
char c = str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
font_draw_glyph(target, font_id, c,
|
||||
bar->pos_x + bar->text_shift_x,
|
||||
bar->pos_y + bar->text_shift_y,
|
||||
char_color);
|
||||
bar->pos_x += font_get_glyph_width(font, c);
|
||||
bar->pos_x += font_get_glyph_width(target, font_id, c);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
intbar_draw_string(Render_Target *target,
|
||||
Interactive_Bar *bar, String str,
|
||||
u32 char_color){
|
||||
Render_Font *font = bar->font;
|
||||
intbar_draw_string(Render_Target *target, Interactive_Bar *bar,
|
||||
String str, u32 char_color){
|
||||
i16 font_id = bar->font_id;
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
char c = str.str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
font_draw_glyph(target, font_id, c,
|
||||
bar->pos_x + bar->text_shift_x,
|
||||
bar->pos_y + bar->text_shift_y,
|
||||
char_color);
|
||||
bar->pos_x += font_get_glyph_width(font, c);
|
||||
bar->pos_x += font_get_glyph_width(target, font_id, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,9 +190,9 @@ live_set_alloc_view(Live_Views *live_set, Mem_Options *mem){
|
|||
}
|
||||
|
||||
inline void
|
||||
live_set_free_view(System_Functions *system, Live_Views *live_set, View *view){
|
||||
live_set_free_view(System_Functions *system, Exchange *exchange, Live_Views *live_set, View *view){
|
||||
Assert(live_set->count > 0);
|
||||
view->do_view(system, view, {}, 0, VMSG_FREE, 0, {}, 0);
|
||||
view->do_view(system, exchange, view, {}, 0, VMSG_FREE, 0, {}, 0);
|
||||
view->next_free = live_set->free_view;
|
||||
live_set->free_view = view;
|
||||
--live_set->count;
|
||||
|
@ -201,13 +200,14 @@ live_set_free_view(System_Functions *system, Live_Views *live_set, View *view){
|
|||
}
|
||||
|
||||
inline void
|
||||
view_replace_major(System_Functions *system, View *new_view, Panel *panel, Live_Views *live_set){
|
||||
view_replace_major(System_Functions *system, Exchange *exchange,
|
||||
View *new_view, Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
if (view){
|
||||
if (view->is_minor && view->major){
|
||||
live_set_free_view(system, live_set, view->major);
|
||||
live_set_free_view(system, exchange, live_set, view->major);
|
||||
}
|
||||
live_set_free_view(system, live_set, view);
|
||||
live_set_free_view(system, exchange, live_set, view);
|
||||
}
|
||||
new_view->panel = panel;
|
||||
new_view->minor = 0;
|
||||
|
@ -215,13 +215,14 @@ view_replace_major(System_Functions *system, View *new_view, Panel *panel, Live_
|
|||
}
|
||||
|
||||
inline void
|
||||
view_replace_minor(System_Functions *system, View *new_view, Panel *panel, Live_Views *live_set){
|
||||
view_replace_minor(System_Functions *system, Exchange *exchange,
|
||||
View *new_view, Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
new_view->is_minor = 1;
|
||||
if (view){
|
||||
if (view->is_minor){
|
||||
new_view->major = view->major;
|
||||
live_set_free_view(system, live_set, view);
|
||||
live_set_free_view(system, exchange, live_set, view);
|
||||
}
|
||||
else{
|
||||
new_view->major = view;
|
||||
|
@ -236,40 +237,43 @@ view_replace_minor(System_Functions *system, View *new_view, Panel *panel, Live_
|
|||
}
|
||||
|
||||
inline void
|
||||
view_remove_major(System_Functions *system, Panel *panel, Live_Views *live_set){
|
||||
view_remove_major(System_Functions *system, Exchange *exchange,
|
||||
Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
if (view){
|
||||
if (view->is_minor && view->major){
|
||||
live_set_free_view(system, live_set, view->major);
|
||||
live_set_free_view(system, exchange, live_set, view->major);
|
||||
}
|
||||
live_set_free_view(system, live_set, view);
|
||||
live_set_free_view(system, exchange, live_set, view);
|
||||
}
|
||||
panel->view = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
view_remove_major_leave_minor(System_Functions *system, Panel *panel, Live_Views *live_set){
|
||||
view_remove_major_leave_minor(System_Functions *system, Exchange *exchange,
|
||||
Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
if (view){
|
||||
if (view->is_minor && view->major){
|
||||
live_set_free_view(system, live_set, view->major);
|
||||
live_set_free_view(system, exchange, live_set, view->major);
|
||||
view->major = 0;
|
||||
}
|
||||
else{
|
||||
live_set_free_view(system, live_set, view);
|
||||
live_set_free_view(system, exchange, live_set, view);
|
||||
panel->view = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
view_remove_minor(System_Functions *system, Panel *panel, Live_Views *live_set){
|
||||
view_remove_minor(System_Functions *system, Exchange *exchange,
|
||||
Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
View *major = 0;
|
||||
if (view){
|
||||
if (view->is_minor){
|
||||
major = view->major;
|
||||
live_set_free_view(system, live_set, view);
|
||||
live_set_free_view(system, exchange, live_set, view);
|
||||
}
|
||||
}
|
||||
panel->view = major;
|
||||
|
@ -277,10 +281,11 @@ view_remove_minor(System_Functions *system, Panel *panel, Live_Views *live_set){
|
|||
}
|
||||
|
||||
inline void
|
||||
view_remove(System_Functions *system, Panel *panel, Live_Views *live_set){
|
||||
view_remove(System_Functions *system, Exchange *exchange,
|
||||
Panel *panel, Live_Views *live_set){
|
||||
View *view = panel->view;
|
||||
if (view->is_minor) view_remove_minor(system, panel, live_set);
|
||||
else view_remove_major(system, panel, live_set);
|
||||
if (view->is_minor) view_remove_minor(system, exchange, panel, live_set);
|
||||
else view_remove_major(system, exchange, panel, live_set);
|
||||
}
|
||||
|
||||
struct Divider_And_ID{
|
||||
|
|
64
4ed_mem.cpp
64
4ed_mem.cpp
|
@ -14,6 +14,36 @@ struct Partition{
|
|||
i32 pos, max;
|
||||
};
|
||||
|
||||
struct Temp_Memory{
|
||||
void *handle;
|
||||
int pos;
|
||||
};
|
||||
|
||||
enum Memory_Bubble_Flag{
|
||||
MEM_BUBBLE_USED = 0x1,
|
||||
MEM_BUBBLE_DEBUG = 0xD3000000,
|
||||
MEM_BUBBLE_SYS_DEBUG = 0x5D000000,
|
||||
MEM_BUBBLE_DEBUG_MASK = 0xFF000000
|
||||
};
|
||||
|
||||
struct Bubble{
|
||||
Bubble *prev;
|
||||
Bubble *next;
|
||||
u32 flags;
|
||||
i32 size;
|
||||
u32 type;
|
||||
u32 _unused_;
|
||||
};
|
||||
|
||||
struct General_Memory{
|
||||
Bubble sentinel;
|
||||
};
|
||||
|
||||
struct Mem_Options{
|
||||
Partition part;
|
||||
General_Memory general;
|
||||
};
|
||||
|
||||
inline Partition
|
||||
partition_open(void *memory, i32 size){
|
||||
Partition partition;
|
||||
|
@ -60,26 +90,6 @@ partition_sub_part(Partition *data, i32 size){
|
|||
#define push_array(part, T, size) (T*)partition_allocate(part, sizeof(T)*(size))
|
||||
#define push_block(part, size) partition_allocate(part, size)
|
||||
|
||||
enum Memory_Bubble_Flag{
|
||||
MEM_BUBBLE_USED = 0x1,
|
||||
MEM_BUBBLE_DEBUG = 0xD3000000,
|
||||
MEM_BUBBLE_SYS_DEBUG = 0x5D000000,
|
||||
MEM_BUBBLE_DEBUG_MASK = 0xFF000000
|
||||
};
|
||||
|
||||
struct Bubble{
|
||||
Bubble *prev;
|
||||
Bubble *next;
|
||||
u32 flags;
|
||||
i32 size;
|
||||
u32 type;
|
||||
u32 _unused_;
|
||||
};
|
||||
|
||||
struct General_Memory{
|
||||
Bubble sentinel;
|
||||
};
|
||||
|
||||
inline void
|
||||
insert_bubble(Bubble *prev, Bubble *bubble){
|
||||
bubble->prev = prev;
|
||||
|
@ -226,28 +236,18 @@ general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u
|
|||
return general_memory_reallocate(general, old, 0, size, type);
|
||||
}
|
||||
|
||||
struct Temp_Memory{
|
||||
Partition *part;
|
||||
i32 pos;
|
||||
};
|
||||
|
||||
internal Temp_Memory
|
||||
begin_temp_memory(Partition *data){
|
||||
Temp_Memory result;
|
||||
result.part = data;
|
||||
result.handle = data;
|
||||
result.pos = data->pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
end_temp_memory(Temp_Memory temp){
|
||||
temp.part->pos = temp.pos;
|
||||
((Partition*)temp.handle)->pos = temp.pos;
|
||||
}
|
||||
|
||||
struct Mem_Options{
|
||||
Partition part;
|
||||
General_Memory general;
|
||||
};
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ step_draw_menu_view(Menu_View *view, Render_Target *target, i32_Rect rect,
|
|||
|
||||
UI_State state =
|
||||
ui_state_init(&view->state, target, user_input,
|
||||
view->style, view->working_set, input_stage);
|
||||
view->style, &target->font_set, view->working_set, input_stage);
|
||||
|
||||
UI_Layout layout;
|
||||
begin_layout(&layout, rect);
|
||||
|
|
|
@ -187,10 +187,10 @@ LargeRoundUp(i32 x, i32 granularity){
|
|||
#define Byte_7 (0xFFU << 56)
|
||||
|
||||
#define bytes(n) (n)
|
||||
#define Kbytes(n) (bytes(n) * 1024)
|
||||
#define Mbytes(n) (Kbytes(n) * 1024)
|
||||
#define Gbytes(n) (Mbytes((u64)n) * 1024)
|
||||
#define Tbytes(n) (Gbytes((u64)n) * 1024)
|
||||
#define Kbytes(n) ((n) << 10)
|
||||
#define Mbytes(n) ((n) << 20)
|
||||
#define Gbytes(n) (((u64)n) << 30)
|
||||
#define Tbytes(n) (((u64)n) << 40)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ private_draw_gradient(Render_Target *target, f32_Rect rect,
|
|||
|
||||
inline void
|
||||
private_draw_glyph(Render_Target *target, Render_Font *font,
|
||||
u16 character, f32 x, f32 y, u32 color){
|
||||
u8 character, f32 x, f32 y, u32 color){
|
||||
f32 x_shift, y_shift;
|
||||
x_shift = 0;
|
||||
y_shift = (f32)font->ascent;
|
||||
|
@ -147,8 +147,8 @@ private_draw_glyph(Render_Target *target, Render_Font *font,
|
|||
y += y_shift;
|
||||
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height,
|
||||
character, &x, &y, &q, 1);
|
||||
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
|
||||
character, &x, &y, &q, 1);
|
||||
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, font->tex);
|
||||
|
@ -163,7 +163,7 @@ private_draw_glyph(Render_Target *target, Render_Font *font,
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
||||
f32 x, f32 y, f32 advance, u32 color){
|
||||
f32 x_shift, y_shift;
|
||||
i32 left = font->chardata[character].x0;
|
||||
|
@ -176,7 +176,8 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
|||
y += y_shift;
|
||||
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1);
|
||||
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
|
||||
character, &x, &y, &q, 1);
|
||||
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, font->tex);
|
||||
|
@ -191,7 +192,7 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
||||
real32 x, real32 y, u32 color){
|
||||
private_draw_glyph_mono(target, font, character, x, y, (f32)font->advance, color);
|
||||
}
|
||||
|
@ -233,31 +234,34 @@ launch_rendering(Render_Target *target){
|
|||
{
|
||||
Render_Piece_Glyph *glyph =
|
||||
ExtractStruct(Render_Piece_Glyph);
|
||||
Render_Font *font = glyph->font_id;
|
||||
|
||||
private_draw_glyph(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font)
|
||||
private_draw_glyph(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}break;
|
||||
|
||||
case piece_type_mono_glyph:
|
||||
{
|
||||
Render_Piece_Glyph *glyph =
|
||||
ExtractStruct(Render_Piece_Glyph);
|
||||
Render_Font *font = glyph->font_id;
|
||||
|
||||
private_draw_glyph_mono(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font)
|
||||
private_draw_glyph_mono(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}break;
|
||||
|
||||
case piece_type_mono_glyph_advance:
|
||||
{
|
||||
Render_Piece_Glyph_Advance *glyph =
|
||||
ExtractStruct(Render_Piece_Glyph_Advance);
|
||||
Render_Font *font = glyph->font_id;
|
||||
|
||||
private_draw_glyph_mono(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y,
|
||||
glyph->advance, glyph->color);
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font)
|
||||
private_draw_glyph_mono(target, font, glyph->character,
|
||||
glyph->pos.x, glyph->pos.y,
|
||||
glyph->advance, glyph->color);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
@ -265,18 +269,99 @@ launch_rendering(Render_Target *target){
|
|||
|
||||
#undef ExtractStruct
|
||||
|
||||
internal i32
|
||||
draw_font_load(System_Functions *system,
|
||||
Render_Font *font_out,
|
||||
char *filename,
|
||||
i32 pt_size,
|
||||
void *font_block,
|
||||
i32 font_block_size,
|
||||
i32 *memory_used_out,
|
||||
i32 tab_width){
|
||||
internal
|
||||
Font_Info_Load_Sig(draw_font_info_load){
|
||||
i32 result = 1;
|
||||
Data file;
|
||||
file = system->load_file(filename);
|
||||
file = system_load_file(filename);
|
||||
Temp_Memory temp = begin_temp_memory(partition);
|
||||
stbtt_packedchar *chardata = push_array(partition, stbtt_packedchar, 256);
|
||||
|
||||
i32 oversample = 2;
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128*oversample;
|
||||
tex_height = pt_size*2*oversample;
|
||||
void *block = push_block(partition, tex_width * tex_height);
|
||||
|
||||
if (!file.data){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
i32 ascent, descent, line_gap;
|
||||
f32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
scaled_line_gap = scale*line_gap;
|
||||
|
||||
i32 font_height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
||||
|
||||
stbtt_pack_context spc;
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (stbtt_PackFontRange(&spc, (u8*)file.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
||||
// do nothing
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (result){
|
||||
i32 max_advance = 0;
|
||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
i32 adv = CEIL32(chardata[code_point].xadvance);
|
||||
if (max_advance < adv){
|
||||
max_advance = adv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*height = font_height;
|
||||
*advance = max_advance - 1;
|
||||
}
|
||||
}
|
||||
|
||||
system_free_memory(file.data);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Font_Load_Sig(draw_font_load){
|
||||
i32 result = 1;
|
||||
Data file;
|
||||
file = system_load_file(filename);
|
||||
Temp_Memory temp = begin_temp_memory(partition);
|
||||
stbtt_packedchar *chardata = font_out->chardata;
|
||||
|
||||
i32 oversample = 2;
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128*oversample;
|
||||
tex_height = pt_size*2*oversample;
|
||||
void *block = push_block(partition, tex_width * tex_height);
|
||||
|
||||
if (!file.data){
|
||||
result = 0;
|
||||
|
@ -289,12 +374,12 @@ draw_font_load(System_Functions *system,
|
|||
}
|
||||
else{
|
||||
i32 ascent, descent, line_gap;
|
||||
real32 scale;
|
||||
f32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
real32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
|
@ -305,167 +390,36 @@ draw_font_load(System_Functions *system,
|
|||
font_out->descent = (i32)(scaled_descent);
|
||||
font_out->line_skip = (i32)(scaled_line_gap);
|
||||
|
||||
u8 *memory_cursor = (u8*)font_block;
|
||||
Assert(pt_size*pt_size*128 <= font_block_size);
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128;
|
||||
tex_height = pt_size*2;
|
||||
|
||||
font_out->tex_width = tex_width;
|
||||
font_out->tex_height = tex_height;
|
||||
|
||||
if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size,
|
||||
memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
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, memory_cursor);
|
||||
|
||||
font_out->tex = font_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
i32 max_advance = 0;
|
||||
for (u16 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
font_out->glyphs[code_point].exists = 1;
|
||||
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
}
|
||||
system->free_file(file);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
stbtt_pack_context spc;
|
||||
|
||||
#if 0
|
||||
|
||||
internal void
|
||||
draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glVertex2i(rect.x0, rect.y0);
|
||||
glVertex2i(rect.x0, rect.y1);
|
||||
glVertex2i(rect.x1, rect.y1);
|
||||
glVertex2i(rect.x1, rect.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_triangle_3corner(Render_Target *target,
|
||||
real32 x0, real32 y0,
|
||||
real32 x1, real32 y1,
|
||||
real32 x2, real32 y2,
|
||||
u32 color){
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_TRIANGLES);
|
||||
{
|
||||
glVertex2f(x0, y0);
|
||||
glVertex2f(x1, y1);
|
||||
glVertex2f(x2, y2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_gradient_2corner_clipped(Render_Target *target, real32 l, real32 t, real32 r, real32 b,
|
||||
Vec4 color_left, Vec4 color_right){
|
||||
draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right);
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){
|
||||
draw_rectangle_outline(target, f32R(rect), color);
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
|
||||
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
|
||||
draw_rectangle(target, i32R(outer.x0, inner.y1, outer.x1, outer.y1), color);
|
||||
draw_rectangle(target, i32R(outer.x0, inner.y0, inner.x0, inner.y1), color);
|
||||
draw_rectangle(target, i32R(inner.x1, inner.y0, outer.x1, inner.y1), color);
|
||||
}
|
||||
|
||||
inline internal i32
|
||||
font_predict_size(i32 pt_size){
|
||||
return pt_size*pt_size*128;
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_load(System_Functions *system,
|
||||
Render_Font *font_out, char *filename, i32 pt_size,
|
||||
void *font_block, i32 font_block_size,
|
||||
i32 *memory_used_out, i32 tab_width){
|
||||
i32 result = 1;
|
||||
File_Data file;
|
||||
file = system->load_file(filename);
|
||||
|
||||
if (!file.data){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
i32 ascent, descent, line_gap;
|
||||
real32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size);
|
||||
|
||||
real32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
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);
|
||||
|
||||
u8 *memory_cursor = (u8*)font_block;
|
||||
Assert(pt_size*pt_size*128 <= font_block_size);
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128;
|
||||
tex_height = pt_size*2;
|
||||
|
||||
font_out->tex_width = tex_width;
|
||||
font_out->tex_height = tex_height;
|
||||
|
||||
if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size,
|
||||
memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){
|
||||
if (stbtt_BakeFontBitmap((u8*)file.data, 0, (f32)pt_size,
|
||||
memory_cursor, tex_width, tex_height, 0, 128,
|
||||
font_out->chardata, partition) <= 0){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (stbtt_PackFontRange(&spc, (u8*)file.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
||||
// do nothing
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (result){
|
||||
GLuint font_tex;
|
||||
glGenTextures(1, &font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||||
|
@ -474,120 +428,45 @@ font_load(System_Functions *system,
|
|||
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, memory_cursor);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
|
||||
|
||||
font_out->tex = font_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
i32 max_advance = 0;
|
||||
for (u16 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
font_out->glyphs[code_point].exists = 1;
|
||||
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
i32 max_advance = 0;
|
||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
font_out->glyphs[code_point].exists = 1;
|
||||
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
|
||||
}
|
||||
system->free_file(file);
|
||||
system_free_memory(file.data);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_tabwidth(Render_Font *font, i32 tab_width){
|
||||
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
|
||||
internal
|
||||
Release_Font_Sig(draw_release_font){
|
||||
glDeleteTextures(1, &font->tex);
|
||||
font->tex = 0;
|
||||
}
|
||||
|
||||
inline real32
|
||||
font_get_glyph_width(Render_Font *font, u16 character){
|
||||
return font->chardata[character].xadvance;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_string_width(Render_Font *font, char *str){
|
||||
real32 x = 0;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
x += font_get_glyph_width(font, str[i]);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, char *str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
char c = str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, char *str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
font_draw_glyph_mono(target, font, str[i],
|
||||
x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, String str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
char c = str.str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, String str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
font_draw_glyph_mono(target, font, str.str[i],
|
||||
x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_max_width(Render_Font *font, char *characters){
|
||||
stbtt_bakedchar *chardata = font->chardata;
|
||||
real32 cx, x = 0;
|
||||
for (i32 i = 0; characters[i]; ++i){
|
||||
cx = chardata[characters[i]].xadvance;
|
||||
if (x < cx) x = cx;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_string_width(Render_Font *font, String string){
|
||||
real32 result = 0;
|
||||
for (i32 i = 0; i < string.size; ++i){
|
||||
font_get_glyph_width(font, string.str[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -12,6 +12,20 @@
|
|||
#ifndef FRED_RENDERING_H
|
||||
#define FRED_RENDERING_H
|
||||
|
||||
internal void*
|
||||
part_alloc(int size, void *context){
|
||||
Partition *part = (Partition*)context;
|
||||
void *result = push_block(part, size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
part_free(void *ptr, void *context){
|
||||
}
|
||||
|
||||
#define STBTT_malloc part_alloc
|
||||
#define STBTT_free part_free
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
|
||||
|
@ -25,7 +39,7 @@ struct Render_Font{
|
|||
b32 loaded;
|
||||
|
||||
Glyph_Data glyphs[256];
|
||||
stbtt_bakedchar chardata[256];
|
||||
stbtt_packedchar chardata[256];
|
||||
float advance_data[256];
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
|
@ -67,16 +81,16 @@ struct Render_Piece_Gradient{
|
|||
struct Render_Piece_Glyph{
|
||||
Vec2 pos;
|
||||
u32 color;
|
||||
Render_Font *font_id;
|
||||
u16 character;
|
||||
i16 font_id;
|
||||
u8 character;
|
||||
};
|
||||
|
||||
struct Render_Piece_Glyph_Advance{
|
||||
Vec2 pos;
|
||||
u32 color;
|
||||
f32 advance;
|
||||
Render_Font *font_id;
|
||||
u16 character;
|
||||
i16 font_id;
|
||||
u8 character;
|
||||
};
|
||||
|
||||
struct Render_Piece_Combined{
|
||||
|
@ -93,16 +107,62 @@ struct Render_Piece_Combined{
|
|||
typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
|
||||
|
||||
#define Font_Load_Sig(name) i32 name( \
|
||||
System_Functions *system, \
|
||||
Partition *partition, \
|
||||
Render_Font *font_out, \
|
||||
char *filename, \
|
||||
i32 pt_size, \
|
||||
void *font_block, \
|
||||
i32 font_block_size, \
|
||||
i32 *memory_used_out, \
|
||||
i32 tab_width)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Font_Info_Load_Sig(name) i32 name( \
|
||||
Partition *partition, \
|
||||
char *filename, \
|
||||
i32 pt_size, \
|
||||
i32 *height, \
|
||||
i32 *advance)
|
||||
typedef Font_Info_Load_Sig(Font_Info_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;
|
||||
};
|
||||
|
||||
struct Render_Target{
|
||||
void *handle;
|
||||
void *context;
|
||||
|
@ -115,10 +175,12 @@ struct Render_Target{
|
|||
byte *push_buffer;
|
||||
i32 size, max;
|
||||
|
||||
Font_Set font_set;
|
||||
Partition *partition;
|
||||
|
||||
Draw_Push_Clip *push_clip;
|
||||
Draw_Pop_Clip *pop_clip;
|
||||
Draw_Push_Piece *push_piece;
|
||||
Font_Load *font_load;
|
||||
};
|
||||
|
||||
inline i32_Rect
|
||||
|
@ -126,6 +188,12 @@ rect_from_target(Render_Target *target){
|
|||
return i32R(0, 0, target->width, target->height);
|
||||
}
|
||||
|
||||
inline Font_Info*
|
||||
get_font_info(Font_Set *set, i16 font_id){
|
||||
Font_Info *result = set->info + font_id - 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -19,6 +19,18 @@ draw_pop_clip(Render_Target *target){
|
|||
target->pop_clip(target);
|
||||
}
|
||||
|
||||
internal void
|
||||
begin_render_section(Render_Target *target){
|
||||
Font_Set *font_set = &target->font_set;
|
||||
font_set->used_this_frame = 0;
|
||||
memset(font_set->font_used_flags, 0, font_set->max);
|
||||
}
|
||||
|
||||
internal void
|
||||
end_render_section(Render_Target *target){
|
||||
//Font_Set *font_set = &target->font_set;
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){
|
||||
Render_Piece_Combined piece;
|
||||
|
@ -81,87 +93,80 @@ font_predict_size(i32 pt_size){
|
|||
return pt_size*pt_size*128;
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_load(Render_Target *target, System_Functions *system,
|
||||
Render_Font *font_out, char *filename, i32 pt_size,
|
||||
void *font_block, i32 font_block_size,
|
||||
i32 *memory_used_out, i32 tab_width){
|
||||
i32 result =
|
||||
target->font_load(system, font_out, filename, pt_size,
|
||||
font_block, font_block_size, memory_used_out, tab_width);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_tabwidth(Render_Font *font, i32 tab_width){
|
||||
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
|
||||
}
|
||||
|
||||
// TODO(allen): Abstract Render_Font all the fucking way out of the app side code.
|
||||
internal void
|
||||
font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
f32 x, f32 y, f32 advance, u32 color){
|
||||
font_draw_glyph_mono(Render_Target *target, i16 font_id,
|
||||
u8 character, f32 x, f32 y, f32 advance, u32 color){
|
||||
Render_Piece_Combined piece;
|
||||
piece.header.type = piece_type_mono_glyph;
|
||||
piece.glyph.pos.x = x;
|
||||
piece.glyph.pos.y = y;
|
||||
piece.glyph.color = color;
|
||||
piece.glyph.font_id = font;
|
||||
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);
|
||||
}
|
||||
|
||||
inline void
|
||||
font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
real32 x, real32 y, u32 color){
|
||||
font_draw_glyph_mono(target, font, character, x, y, (real32)font->advance, color);
|
||||
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, Render_Font *font, u16 character,
|
||||
f32 x, f32 y, u32 color){
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
inline real32
|
||||
font_get_glyph_width(Render_Font *font, u16 character){
|
||||
return font->chardata[character].xadvance;
|
||||
inline f32
|
||||
font_get_glyph_width(Render_Target *target, i16 font_id, u16 character){
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
f32 result = 0.f;
|
||||
if (font) result = font->chardata[character].xadvance;
|
||||
return (result);
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_string_width(Render_Font *font, char *str){
|
||||
real32 x = 0;
|
||||
internal f32
|
||||
font_string_width(Render_Target *target, i16 font_id, char *str){
|
||||
f32 x = 0;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
x += font_get_glyph_width(font, str[i]);
|
||||
x += font_get_glyph_width(target, font_id, str[i]);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, char *str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
draw_string(Render_Target *target, i16 font_id,
|
||||
char *str, i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
char c = str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
font_draw_glyph(target, font_id, c, x, (f32)y, color);
|
||||
x += font_get_glyph_width(target, font_id, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, char *str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
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){
|
||||
font_draw_glyph_mono(target, font, str[i],
|
||||
font_draw_glyph_mono(target, font_id, str[i],
|
||||
x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
|
@ -169,47 +174,51 @@ draw_string_mono(Render_Target *target, Render_Font *font, char *str,
|
|||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, String str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
draw_string(Render_Target *target, i16 font_id,
|
||||
String str, i32 x_, i32 y, u32 color){
|
||||
f32 x = (f32)x_;
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
char c = str.str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
font_draw_glyph(target, font_id, c,
|
||||
x, (f32)y, color);
|
||||
x += font_get_glyph_width(target, font_id, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, String str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
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){
|
||||
font_draw_glyph_mono(target, font, str.str[i],
|
||||
x, y, advance, color);
|
||||
font_draw_glyph_mono(target, font_id,
|
||||
str.str[i], x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_max_width(Render_Font *font, char *characters){
|
||||
stbtt_bakedchar *chardata = font->chardata;
|
||||
real32 cx, x = 0;
|
||||
for (i32 i = 0; characters[i]; ++i){
|
||||
cx = chardata[characters[i]].xadvance;
|
||||
if (x < cx) x = cx;
|
||||
internal f32
|
||||
font_get_max_width(Font_Set *font_set, i16 font_id, char *characters){
|
||||
Render_Font *font = get_font_info(font_set, font_id)->font;
|
||||
f32 cx, x = 0;
|
||||
if (font){
|
||||
stbtt_packedchar *chardata = font->chardata;
|
||||
for (i32 i = 0; characters[i]; ++i){
|
||||
cx = chardata[characters[i]].xadvance;
|
||||
if (x < cx) x = cx;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_string_width(Render_Font *font, String string){
|
||||
real32 result = 0;
|
||||
internal f32
|
||||
font_get_string_width(Render_Target *target, i16 font_id, String string){
|
||||
f32 result = 0;
|
||||
for (i32 i = 0; i < string.size; ++i){
|
||||
font_get_glyph_width(font, string.str[i]);
|
||||
font_get_glyph_width(target, font_id, string.str[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -1,405 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 12.17.2014
|
||||
*
|
||||
* Rendering layer for project codename "4ed"
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if 0
|
||||
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);
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_push_clip(Render_Target *target, i32_Rect clip_box){
|
||||
Assert(target->clip_top == -1 ||
|
||||
fits_inside(clip_box, target->clip_boxes[target->clip_top]));
|
||||
Assert(target->clip_top+1 < ArrayCount(target->clip_boxes));
|
||||
target->clip_boxes[++target->clip_top] = clip_box;
|
||||
draw_set_clip(target, clip_box);
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_pop_clip(Render_Target *target){
|
||||
Assert(target->clip_top > 0);
|
||||
--target->clip_top;
|
||||
draw_set_clip(target, target->clip_boxes[target->clip_top]);
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_bind_texture(Render_Target *target, i32 texid){
|
||||
if (target->bound_texture != texid){
|
||||
glBindTexture(GL_TEXTURE_2D, texid);
|
||||
target->bound_texture = texid;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_set_color(Render_Target *target, u32 color){
|
||||
if (target->color != color){
|
||||
target->color = color;
|
||||
Vec4 c = unpack_color4(color);
|
||||
glColor4f(c.r, c.g, c.b, c.a);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glVertex2i(rect.x0, rect.y0);
|
||||
glVertex2i(rect.x0, rect.y1);
|
||||
glVertex2i(rect.x1, rect.y1);
|
||||
glVertex2i(rect.x1, rect.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_rectangle(Render_Target *target, real32_Rect rect, u32 color){
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glVertex2f(rect.x0, rect.y0);
|
||||
glVertex2f(rect.x0, rect.y1);
|
||||
glVertex2f(rect.x1, rect.y1);
|
||||
glVertex2f(rect.x1, rect.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_triangle_3corner(Render_Target *target,
|
||||
real32 x0, real32 y0,
|
||||
real32 x1, real32 y1,
|
||||
real32 x2, real32 y2,
|
||||
u32 color){
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_TRIANGLES);
|
||||
{
|
||||
glVertex2f(x0, y0);
|
||||
glVertex2f(x1, y1);
|
||||
glVertex2f(x2, y2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_gradient_2corner_clipped(Render_Target *target, real32_Rect rect,
|
||||
Vec4 color_left, Vec4 color_right){
|
||||
Vec4 cl = color_left;
|
||||
Vec4 cr = color_right;
|
||||
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glColor4f(cl.r, cl.g, cl.b, cl.a);
|
||||
glVertex2f(rect.x0, rect.y0);
|
||||
glVertex2f(rect.x0, rect.y1);
|
||||
|
||||
glColor4f(cr.r, cr.g, cr.b, cr.a);
|
||||
glVertex2f(rect.x1, rect.y1);
|
||||
glVertex2f(rect.x1, rect.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_gradient_2corner_clipped(Render_Target *target, real32 l, real32 t, real32 r, real32 b,
|
||||
Vec4 color_left, Vec4 color_right){
|
||||
draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right);
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_rectangle_outline(Render_Target *target, real32_Rect rect, u32 color){
|
||||
real32_Rect r;
|
||||
r.x0 = rect.x0 + .5f;
|
||||
r.y0 = rect.y0 + .5f;
|
||||
r.x1 = rect.x1 - .5f;
|
||||
r.y1 = rect.y1 - .5f;
|
||||
|
||||
draw_set_color(target, color);
|
||||
draw_bind_texture(target, 0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
{
|
||||
glVertex2f(r.x0, r.y0);
|
||||
glVertex2f(r.x1, r.y0);
|
||||
glVertex2f(r.x1, r.y1);
|
||||
glVertex2f(r.x0, r.y1);
|
||||
glVertex2f(r.x0, r.y0);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){
|
||||
draw_rectangle_outline(target, f32R(rect), color);
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
|
||||
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
|
||||
draw_rectangle(target, i32R(outer.x0, inner.y1, outer.x1, outer.y1), color);
|
||||
draw_rectangle(target, i32R(outer.x0, inner.y0, inner.x0, inner.y1), color);
|
||||
draw_rectangle(target, i32R(inner.x1, inner.y0, outer.x1, inner.y1), color);
|
||||
}
|
||||
|
||||
// TODO(allen): eliminate this?
|
||||
internal i32
|
||||
font_init(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline internal i32
|
||||
font_predict_size(i32 pt_size){
|
||||
return pt_size*pt_size*128;
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_load(System_Functions *system,
|
||||
Render_Font *font_out, char *filename, i32 pt_size,
|
||||
void *font_block, i32 font_block_size,
|
||||
i32 *memory_used_out, i32 tab_width){
|
||||
i32 result = 1;
|
||||
File_Data file;
|
||||
file = system->load_file(filename);
|
||||
|
||||
if (!file.data){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
i32 ascent, descent, line_gap;
|
||||
real32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (real32)pt_size);
|
||||
|
||||
real32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
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);
|
||||
|
||||
u8 *memory_cursor = (u8*)font_block;
|
||||
Assert(pt_size*pt_size*128 <= font_block_size);
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128;
|
||||
tex_height = pt_size*2;
|
||||
|
||||
font_out->tex_width = tex_width;
|
||||
font_out->tex_height = tex_height;
|
||||
|
||||
if (stbtt_BakeFontBitmap((u8*)file.data, 0, (real32)pt_size,
|
||||
memory_cursor, tex_width, tex_height, 0, 128, font_out->chardata) <= 0){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
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, memory_cursor);
|
||||
|
||||
font_out->tex = font_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
i32 max_advance = 0;
|
||||
for (u16 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
font_out->glyphs[code_point].exists = 1;
|
||||
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
}
|
||||
system->free_file(file);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_tabwidth(Render_Font *font, i32 tab_width){
|
||||
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
real32 x_shift, y_shift;
|
||||
i32 left = font->chardata[character].x0;
|
||||
i32 right = font->chardata[character].x1;
|
||||
i32 width = (right - left);
|
||||
x_shift = (real32)(advance - width) * .5f - font->chardata[character].xoff;
|
||||
y_shift = (real32)font->ascent;
|
||||
|
||||
x += x_shift;
|
||||
y += y_shift;
|
||||
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1);
|
||||
|
||||
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);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline void
|
||||
font_draw_glyph_mono(Render_Target *target, Render_Font *font, u16 character,
|
||||
real32 x, real32 y, u32 color){
|
||||
font_draw_glyph_mono(target, font, character, x, y, (real32)font->advance, color);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph(Render_Target *target, Render_Font *font, u16 character,
|
||||
real32 x, real32 y, u32 color){
|
||||
real32 x_shift, y_shift;
|
||||
x_shift = 0;
|
||||
y_shift = (real32)font->ascent;
|
||||
|
||||
x += x_shift;
|
||||
y += y_shift;
|
||||
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuadUnrounded(font->chardata, font->tex_width, font->tex_height, character, &x, &y, &q, 1);
|
||||
|
||||
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);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
inline real32
|
||||
font_get_glyph_width(Render_Font *font, u16 character){
|
||||
return font->chardata[character].xadvance;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_string_width(Render_Font *font, char *str){
|
||||
real32 x = 0;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
x += font_get_glyph_width(font, str[i]);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, char *str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
char c = str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, char *str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
font_draw_glyph_mono(target, font, str[i],
|
||||
x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal i32
|
||||
draw_string(Render_Target *target, Render_Font *font, String str,
|
||||
i32 x_, i32 y, u32 color){
|
||||
real32 x = (real32)x_;
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
char c = str.str[i];
|
||||
font_draw_glyph(target, font, c,
|
||||
x, (real32)y, color);
|
||||
x += font_get_glyph_width(font, c);
|
||||
}
|
||||
return CEIL32(x);
|
||||
}
|
||||
|
||||
internal real32
|
||||
draw_string_mono(Render_Target *target, Render_Font *font, String str,
|
||||
real32 x, real32 y, real32 advance, u32 color){
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
font_draw_glyph_mono(target, font, str.str[i],
|
||||
x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_max_width(Render_Font *font, char *characters){
|
||||
stbtt_bakedchar *chardata = font->chardata;
|
||||
real32 cx, x = 0;
|
||||
for (i32 i = 0; characters[i]; ++i){
|
||||
cx = chardata[characters[i]].xadvance;
|
||||
if (x < cx) x = cx;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
internal real32
|
||||
font_get_string_width(Render_Font *font, String string){
|
||||
real32 result = 0;
|
||||
for (i32 i = 0; i < string.size; ++i){
|
||||
font_get_glyph_width(font, string.str[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
|
@ -214,9 +214,9 @@ struct Style_File_Format{
|
|||
struct Style{
|
||||
char name_[24];
|
||||
String name;
|
||||
Render_Font *font;
|
||||
Style_Main_Data main;
|
||||
bool32 font_changed;
|
||||
b32 font_changed;
|
||||
i16 font_id;
|
||||
};
|
||||
|
||||
struct Style_Library{
|
||||
|
@ -224,11 +224,6 @@ struct Style_Library{
|
|||
i32 count, max;
|
||||
};
|
||||
|
||||
struct Font_Set{
|
||||
Render_Font *fonts;
|
||||
i32 count, max;
|
||||
};
|
||||
|
||||
internal void
|
||||
style_copy(Style *dst, Style *src){
|
||||
*dst = *src;
|
||||
|
@ -243,21 +238,6 @@ style_set_name(Style *style, String name){
|
|||
copy(&style->name, name);
|
||||
}
|
||||
|
||||
internal Render_Font*
|
||||
font_set_extract(Font_Set *fonts, char *name, i32 size){
|
||||
String n = make_string(name, size);
|
||||
i32 count = fonts->count;
|
||||
Render_Font *result = 0;
|
||||
Render_Font *font = fonts->fonts;
|
||||
for (i32 i = 0; i < count; ++i, ++font){
|
||||
if (match(n, font->name)){
|
||||
result = font;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
style_form_convert(Style_File_Format_v2 *o, Style_File_Format_v1 *i){
|
||||
o->name_size = i->name_size;
|
||||
|
@ -415,7 +395,11 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format *style){
|
|||
out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1);
|
||||
out->name_[ArrayCount(out->name_) - 1] = 0;
|
||||
copy(&out->name, style->name);
|
||||
out->font = font_set_extract(fonts, style->font_name, style->font_name_size);
|
||||
if (!font_set_extract(fonts,
|
||||
make_string(style->font_name, style->font_name_size),
|
||||
&out->font_id)){
|
||||
out->font_id = 0;
|
||||
}
|
||||
|
||||
i32 spec_count = style->color_specifier_count;
|
||||
Style_Color_Specifier *spec = (Style_Color_Specifier*)(style + 1);
|
||||
|
@ -443,7 +427,11 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v4 *style){
|
|||
out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1);
|
||||
out->name_[ArrayCount(out->name_) - 1] = 0;
|
||||
copy(&out->name, style->name);
|
||||
out->font = font_set_extract(fonts, style->font_name, style->font_name_size);
|
||||
if (!font_set_extract(fonts,
|
||||
make_string(style->font_name, style->font_name_size),
|
||||
&out->font_id)){
|
||||
out->font_id = 0;
|
||||
}
|
||||
out->main = style->main;
|
||||
}
|
||||
|
||||
|
@ -475,11 +463,9 @@ style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v3 *style){
|
|||
}
|
||||
|
||||
internal b32
|
||||
style_library_import(System_Functions *system,
|
||||
char *filename, Font_Set *fonts, Style *out, i32 max,
|
||||
style_library_import(Data file, Font_Set *fonts, Style *out, i32 max,
|
||||
i32 *count_opt, i32 *total_opt = 0){
|
||||
b32 result = 1;
|
||||
Data file = system->load_file(filename);
|
||||
Style_Page_Header *h = 0;
|
||||
|
||||
if (!file.data){
|
||||
|
@ -540,13 +526,26 @@ style_library_import(System_Functions *system,
|
|||
default: result = 0; break;
|
||||
}
|
||||
|
||||
early_exit:
|
||||
system->free_file(file);
|
||||
early_exit:;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal b32
|
||||
style_library_import(System_Functions *system,
|
||||
char *filename, Font_Set *fonts, Style *out, i32 max,
|
||||
i32 *count_opt, i32 *total_opt = 0){
|
||||
b32 result;
|
||||
Data file = system->load_file(filename);
|
||||
result = style_library_import(file, fonts, out, max, count_opt, total_opt);
|
||||
system->free_file(file);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
internal b32
|
||||
style_library_add(Style_Library *library, Style *style){
|
||||
b32 result = 0;
|
||||
|
@ -572,12 +571,13 @@ style_library_add(Style_Library *library, Style *style){
|
|||
}
|
||||
|
||||
internal Style_File_Format*
|
||||
style_format_for_file(Style *style, Style_File_Format *out){
|
||||
Render_Font *font = style->font;
|
||||
style_format_for_file(Font_Set *set, Style *style, Style_File_Format *out){
|
||||
out->name_size = style->name.size;
|
||||
memcpy(out->name, style->name.str, ArrayCount(out->name));
|
||||
out->font_name_size = font->name.size;
|
||||
memcpy(out->font_name, font->name.str, ArrayCount(out->font_name));
|
||||
|
||||
String font_name = get_font_info(set, style->font_id)->name;
|
||||
out->font_name_size = font_name.size;
|
||||
memcpy(out->font_name, font_name.str, font_name.size);
|
||||
|
||||
Style_Color_Specifier *spec = (Style_Color_Specifier*)(out + 1);
|
||||
i32 count = 0;
|
||||
|
@ -597,10 +597,12 @@ style_format_for_file(Style *style, Style_File_Format *out){
|
|||
}
|
||||
|
||||
internal void
|
||||
style_library_export(System_Functions *system, char *filename, Style **styles, i32 count){
|
||||
style_library_export(System_Functions *system, Exchange *exchange, Mem_Options *mem,
|
||||
Font_Set *set, char *filename, Style **styles, i32 count){
|
||||
i32 size = count*(sizeof(Style_File_Format) + STAG_COUNT*sizeof(Style_Color_Specifier)) +
|
||||
sizeof(P4C_Page_Header) + sizeof(Style_Page_Header);
|
||||
void *data = system->get_memory(size);
|
||||
Temp_Memory temp = begin_temp_memory(&mem->part);
|
||||
void *data = push_block(&mem->part, size);
|
||||
void *cursor = data;
|
||||
|
||||
{
|
||||
|
@ -620,10 +622,17 @@ style_library_export(System_Functions *system, char *filename, Style **styles, i
|
|||
Style_File_Format *out = (Style_File_Format*)cursor;
|
||||
Style **in = styles;
|
||||
for (i32 i = 0; i < count; ++i){
|
||||
out = style_format_for_file(*in++, out);
|
||||
out = style_format_for_file(set, *in++, out);
|
||||
}
|
||||
|
||||
int filename_len = str_size(filename);
|
||||
exchange_save_file(exchange, filename, filename_len,
|
||||
(byte*)data, size, size);
|
||||
#if 0
|
||||
system->save_file(filename, data, size);
|
||||
system->free_memory(data);
|
||||
#endif
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
134
4ed_system.h
134
4ed_system.h
|
@ -9,72 +9,34 @@
|
|||
|
||||
// TOP
|
||||
|
||||
struct System_Functions;
|
||||
|
||||
struct Plat_Handle{
|
||||
u32 d[4];
|
||||
};
|
||||
|
||||
struct Time_Stamp{
|
||||
u64 time;
|
||||
b32 success;
|
||||
};
|
||||
|
||||
#define Sys_Load_File_Sig(name) Data name(char *filename)
|
||||
typedef Sys_Load_File_Sig(System_Load_File);
|
||||
|
||||
#define Sys_Save_File_Sig(name) i32 name(char *filename, void *data, i32 size)
|
||||
typedef Sys_Save_File_Sig(System_Save_File);
|
||||
|
||||
#define Sys_File_Size_Sig(name) i32 name(char *filename)
|
||||
typedef Sys_File_Size_Sig(System_File_Size);
|
||||
|
||||
#define Sys_File_Time_Stamp_Sig(name) Time_Stamp name(char *filename)
|
||||
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
|
||||
|
||||
#define Sys_Time_Stamp_Now_Sig(name) u64 name()
|
||||
typedef Sys_Time_Stamp_Now_Sig(System_Time_Stamp_Now);
|
||||
|
||||
#define Sys_Free_File_Sig(name) void name(Data file)
|
||||
typedef Sys_Free_File_Sig(System_Free_File);
|
||||
|
||||
#define Sys_Get_Current_Directory_Sig(name) i32 name(char *out, i32 max)
|
||||
typedef Sys_Get_Current_Directory_Sig(System_Get_Current_Directory);
|
||||
|
||||
#define Sys_Get_Easy_Directory_Sig(name) i32 name(char *destination)
|
||||
typedef Sys_Get_Easy_Directory_Sig(System_Get_Easy_Directory);
|
||||
|
||||
struct File_Info{
|
||||
String filename;
|
||||
b32 folder;
|
||||
};
|
||||
|
||||
struct File_List{
|
||||
File_Info *infos;
|
||||
void *block;
|
||||
i32 count;
|
||||
File_Info *infos;
|
||||
i32 count, block_size;
|
||||
};
|
||||
|
||||
#define Sys_Get_File_List_Sig(name) File_List name(String directory)
|
||||
typedef Sys_Get_File_List_Sig(System_Get_File_List);
|
||||
#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename)
|
||||
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
|
||||
|
||||
#define Sys_Free_File_List_Sig(name) void name(File_List list)
|
||||
typedef Sys_Free_File_List_Sig(System_Free_File_List);
|
||||
|
||||
#define Sys_Get_Memory_Sig(name) void* name(i32 size, i32 line_number, char *filename)
|
||||
typedef Sys_Get_Memory_Sig(System_Get_Memory);
|
||||
|
||||
#define get_memory(size) get_memory_full(size, __LINE__, __FILE__)
|
||||
|
||||
#define Sys_Free_Memory_Sig(name) void name(void *block)
|
||||
typedef Sys_Free_Memory_Sig(System_Free_Memory);
|
||||
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory)
|
||||
typedef Sys_Set_File_List_Sig(System_Set_File_List);
|
||||
|
||||
#define Sys_Post_Clipboard_Sig(name) void name(String str)
|
||||
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
|
||||
|
||||
#define Sys_Time_Sig(name) i64 name()
|
||||
#define Sys_Time_Sig(name) u64 name()
|
||||
typedef Sys_Time_Sig(System_Time);
|
||||
|
||||
// cli
|
||||
struct CLI_Handles{
|
||||
Plat_Handle proc;
|
||||
Plat_Handle out_read;
|
||||
|
@ -82,7 +44,7 @@ struct CLI_Handles{
|
|||
u32 scratch_space[4];
|
||||
};
|
||||
|
||||
#define Sys_CLI_Call_Sig(name) b32 name(char *path, char *script, CLI_Handles *cli)
|
||||
#define Sys_CLI_Call_Sig(name) b32 name(char *path, char *script_name, CLI_Handles *cli_out)
|
||||
typedef Sys_CLI_Call_Sig(System_CLI_Call);
|
||||
|
||||
#define Sys_CLI_Begin_Update_Sig(name) void name(CLI_Handles *cli)
|
||||
|
@ -94,6 +56,7 @@ typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step);
|
|||
#define Sys_CLI_End_Update_Sig(name) b32 name(CLI_Handles *cli)
|
||||
typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update);
|
||||
|
||||
// thread
|
||||
struct Thread_Context;
|
||||
|
||||
enum Lock_ID{
|
||||
|
@ -120,8 +83,12 @@ struct Thread_Memory{
|
|||
i32 id;
|
||||
};
|
||||
|
||||
#define Job_Callback_Sig(name) void name(\
|
||||
System_Functions *system, Thread_Context *thread, Thread_Memory *memory, void *data[2])
|
||||
struct Thread_Exchange;
|
||||
struct System_Functions;
|
||||
|
||||
#define Job_Callback_Sig(name) void name( \
|
||||
System_Functions *system, Thread_Context *thread, Thread_Memory *memory, \
|
||||
Thread_Exchange *exchange, void *data[2])
|
||||
typedef Job_Callback_Sig(Job_Callback);
|
||||
|
||||
struct Job_Data{
|
||||
|
@ -130,21 +97,38 @@ struct Job_Data{
|
|||
i32 memory_request;
|
||||
};
|
||||
|
||||
#define Sys_Thread_Get_ID_Sig(name) u32 name(Thread_Context *thread)
|
||||
typedef Sys_Thread_Get_ID_Sig(System_Thread_Get_ID);
|
||||
struct Full_Job_Data{
|
||||
Job_Data job;
|
||||
|
||||
u32 job_memory_index;
|
||||
u32 running_thread;
|
||||
b32 finished;
|
||||
u32 id;
|
||||
};
|
||||
|
||||
#define Sys_Thread_Current_Job_ID_Sig(name) u32 name(Thread_Context *thread)
|
||||
typedef Sys_Thread_Current_Job_ID_Sig(System_Thread_Current_Job_ID);
|
||||
struct Work_Queue{
|
||||
Full_Job_Data jobs[256];
|
||||
Plat_Handle semaphore;
|
||||
volatile u32 write_position;
|
||||
volatile u32 read_position;
|
||||
};
|
||||
|
||||
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID id, Job_Data job)
|
||||
#define THREAD_NOT_ASSIGNED 0xFFFFFFFF
|
||||
|
||||
#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4)
|
||||
#define QUEUE_WRAP (ArrayCount(queue->jobs))
|
||||
|
||||
struct Thread_Exchange{
|
||||
Work_Queue queues[THREAD_GROUP_COUNT];
|
||||
volatile u32 force_redraw;
|
||||
};
|
||||
|
||||
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job)
|
||||
typedef Sys_Post_Job_Sig(System_Post_Job);
|
||||
|
||||
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID id, u32 job_id)
|
||||
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id)
|
||||
typedef Sys_Cancel_Job_Sig(System_Cancel_Job);
|
||||
|
||||
#define Sys_Job_Is_Pending_Sig(name) b32 name(Thread_Group_ID id, u32 job_id)
|
||||
typedef Sys_Job_Is_Pending_Sig(System_Job_Is_Pending);
|
||||
|
||||
#define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory)
|
||||
typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory);
|
||||
|
||||
|
@ -154,9 +138,7 @@ typedef Sys_Acquire_Lock_Sig(System_Acquire_Lock);
|
|||
#define Sys_Release_Lock_Sig(name) void name(i32 id)
|
||||
typedef Sys_Release_Lock_Sig(System_Release_Lock);
|
||||
|
||||
#define Sys_Force_Redraw_Sig(name) void name()
|
||||
typedef Sys_Force_Redraw_Sig(System_Force_Redraw);
|
||||
|
||||
// debug
|
||||
#define INTERNAL_Sys_Sentinel_Sig(name) Bubble* name()
|
||||
typedef INTERNAL_Sys_Sentinel_Sig(INTERNAL_System_Sentinel);
|
||||
|
||||
|
@ -167,40 +149,34 @@ typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
|
|||
typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message);
|
||||
|
||||
struct System_Functions{
|
||||
System_Load_File *load_file;
|
||||
System_Save_File *save_file;
|
||||
// files: 2
|
||||
System_File_Time_Stamp *file_time_stamp;
|
||||
System_Time_Stamp_Now *time_stamp_now;
|
||||
System_Free_File *free_file;
|
||||
|
||||
System_Get_Current_Directory *get_current_directory;
|
||||
System_Get_Easy_Directory *get_easy_directory;
|
||||
System_Set_File_List *set_file_list;
|
||||
|
||||
System_Get_File_List *get_file_list;
|
||||
System_Free_File_List *free_file_list;
|
||||
|
||||
System_Get_Memory *get_memory_full;
|
||||
System_Free_Memory *free_memory;
|
||||
// file system navigation (4coder_custom.h): 2
|
||||
Directory_Has_File *directory_has_file;
|
||||
Directory_CD *directory_cd;
|
||||
|
||||
// clipboard: 1
|
||||
System_Post_Clipboard *post_clipboard;
|
||||
|
||||
// time: 1
|
||||
System_Time *time;
|
||||
|
||||
// cli: 4
|
||||
System_CLI_Call *cli_call;
|
||||
System_CLI_Begin_Update *cli_begin_update;
|
||||
System_CLI_Update_Step *cli_update_step;
|
||||
System_CLI_End_Update *cli_end_update;
|
||||
|
||||
System_Thread_Get_ID *thread_get_id;
|
||||
System_Thread_Current_Job_ID *thread_current_job_id;
|
||||
// threads: 5
|
||||
System_Post_Job *post_job;
|
||||
System_Cancel_Job *cancel_job;
|
||||
System_Job_Is_Pending *job_is_pending;
|
||||
System_Grow_Thread_Memory *grow_thread_memory;
|
||||
System_Acquire_Lock *acquire_lock;
|
||||
System_Release_Lock *release_lock;
|
||||
|
||||
System_Force_Redraw *force_redraw;
|
||||
|
||||
|
||||
// debug: 3
|
||||
INTERNAL_System_Sentinel *internal_sentinel;
|
||||
INTERNAL_System_Get_Thread_States *internal_get_thread_states;
|
||||
INTERNAL_System_Debug_Message *internal_debug_message;
|
||||
|
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* YOUR INFO HERE!
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
typedef unsigned int Fixed16_16;
|
||||
|
||||
struct Offset_Table{
|
||||
Fixed16_16 version;
|
||||
unsigned short num_tables;
|
||||
unsigned short search_range;
|
||||
unsigned short entry_selector;
|
||||
unsigned short range_shift;
|
||||
};
|
||||
|
||||
struct Table_Directory_Entry{
|
||||
unsigned long tag;
|
||||
unsigned long check_sum;
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct Data{
|
||||
char *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
Data
|
||||
open_file(const char *filename){
|
||||
Data result = {};
|
||||
FILE *file;
|
||||
file = fopen(filename, "rb");
|
||||
if (file){
|
||||
fseek(file, 0, SEEK_END);
|
||||
result.size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
if (result.size > 0){
|
||||
result.data = (char*)malloc(result.size);
|
||||
fread(result.data, result.size, 1, file);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
print(Offset_Table *offset){
|
||||
printf("version %d\n", offset->version >> 16);
|
||||
printf("number of tables %d\n", (int)(offset->num_tables));
|
||||
printf("search range %d\n", (int)(offset->search_range));
|
||||
printf("entry selector %d\n", (int)(offset->entry_selector));
|
||||
printf("range shift %d\n", (int)(offset->range_shift));
|
||||
}
|
||||
|
||||
void
|
||||
print(Table_Directory_Entry *entry){
|
||||
printf("tag %.4s\n", &entry->tag);
|
||||
printf("check sum %08x\n", entry->check_sum);
|
||||
printf("offset %d\n", entry->offset);
|
||||
printf("length %d\n", entry->length);
|
||||
}
|
||||
|
||||
void
|
||||
byte_reverse(void *ptr, int len){
|
||||
char *c;
|
||||
int i,j;
|
||||
char t;
|
||||
c = (char*)ptr;
|
||||
for (i = 0, j = len-1; i < j; ++i, --j){
|
||||
t = c[i];
|
||||
c[i] = c[j];
|
||||
c[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
byte_fix(Offset_Table *offset){
|
||||
byte_reverse(&offset->version, 4);
|
||||
byte_reverse(&offset->num_tables, 2);
|
||||
byte_reverse(&offset->search_range, 2);
|
||||
byte_reverse(&offset->entry_selector, 2);
|
||||
byte_reverse(&offset->range_shift, 2);
|
||||
}
|
||||
|
||||
void
|
||||
byte_fix(Table_Directory_Entry *entry){
|
||||
byte_reverse(&entry->check_sum, 4);
|
||||
byte_reverse(&entry->offset, 4);
|
||||
byte_reverse(&entry->length, 4);
|
||||
}
|
||||
|
||||
struct cmap_Header{
|
||||
unsigned short version;
|
||||
unsigned short num_subtables;
|
||||
};
|
||||
|
||||
struct cmap_Subtable_Entry{
|
||||
unsigned short plat_id;
|
||||
unsigned short plat_encoding_id;
|
||||
unsigned long offset_from_cmap;
|
||||
};
|
||||
|
||||
void
|
||||
byte_fix(cmap_Header *header){
|
||||
byte_reverse(&header->version, 2);
|
||||
byte_reverse(&header->num_subtables, 2);
|
||||
}
|
||||
|
||||
void
|
||||
print(cmap_Header *header){
|
||||
printf("cmap tables:\n");
|
||||
printf("\tversion %d\n", (int)(header->version));
|
||||
printf("\tsubtables %d\n", (int)(header->num_subtables));
|
||||
}
|
||||
|
||||
void
|
||||
byte_fix(cmap_Subtable_Entry *entry){
|
||||
byte_reverse(&entry->plat_id, 2);
|
||||
byte_reverse(&entry->plat_encoding_id, 2);
|
||||
byte_reverse(&entry->offset_from_cmap, 4);
|
||||
}
|
||||
|
||||
struct cmap_Subtable_Format4_Header{
|
||||
unsigned short format;
|
||||
unsigned short length;
|
||||
unsigned short version;
|
||||
unsigned short segment_count_2;
|
||||
unsigned short search_range;
|
||||
unsigned short entry_selector;
|
||||
unsigned short range_shift;
|
||||
};
|
||||
|
||||
void
|
||||
print(cmap_Subtable_Entry *entry){
|
||||
printf("\tplatform id %d\n", (int)(entry->plat_id));
|
||||
printf("\tencoding id %d\n", (int)(entry->plat_encoding_id));
|
||||
printf("\toffset from cmap %d\n", (int)(entry->offset_from_cmap));
|
||||
}
|
||||
|
||||
void
|
||||
byte_fix(cmap_Subtable_Format4_Header *header){
|
||||
byte_reverse(&header->length, 2);
|
||||
byte_reverse(&header->version, 2);
|
||||
byte_reverse(&header->segment_count_2, 2);
|
||||
byte_reverse(&header->search_range, 2);
|
||||
byte_reverse(&header->entry_selector, 2);
|
||||
byte_reverse(&header->range_shift, 2);
|
||||
}
|
||||
|
||||
void
|
||||
print(cmap_Subtable_Format4_Header *header){
|
||||
printf("\t\tlength %d\n", header->length);
|
||||
printf("\t\tversion %d\n", header->version);
|
||||
printf("\t\tsegment count doubled %d\n", header->segment_count_2);
|
||||
printf("\t\tsearch range %d\n", header->search_range);
|
||||
printf("\t\tentry selector %d\n", header->entry_selector);
|
||||
printf("\t\trange shift %d\n", header->range_shift);
|
||||
}
|
||||
|
||||
struct cmap_Subtable_Format4_Segments{
|
||||
unsigned short *end_code, *start_code;
|
||||
unsigned short *id_delta, *id_range_offset;
|
||||
};
|
||||
|
||||
void
|
||||
byte_fix(cmap_Subtable_Format4_Segments segs, int segment_count){
|
||||
for (int i = 0; i < segment_count; ++i){
|
||||
byte_reverse(segs.end_code + i, 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < segment_count; ++i){
|
||||
byte_reverse(segs.start_code + i, 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < segment_count; ++i){
|
||||
byte_reverse(segs.id_delta + i, 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < segment_count; ++i){
|
||||
byte_reverse(segs.id_range_offset + i, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print(cmap_Subtable_Format4_Segments segs, int i){
|
||||
printf("\t\tsegment %d\n", i);
|
||||
printf("\t\tend code %d\n", (int)(segs.end_code[i]));
|
||||
printf("\t\tstart code %d\n", (int)(segs.start_code[i]));
|
||||
printf("\t\tid delta %d\n", (int)(segs.id_delta[i]));
|
||||
printf("\t\tid range offset %d\n", (int)(segs.id_range_offset[i]));
|
||||
}
|
||||
|
||||
void
|
||||
parse_cmap_subtable4(char *start){
|
||||
char *cursor = start;
|
||||
cmap_Subtable_Format4_Header *header =
|
||||
(cmap_Subtable_Format4_Header*)cursor;
|
||||
cursor = (char*)(header + 1);
|
||||
|
||||
byte_fix(header);
|
||||
print(header);
|
||||
|
||||
int segment_count = (header->segment_count_2 >> 1);
|
||||
|
||||
cmap_Subtable_Format4_Segments segs;
|
||||
|
||||
segs.end_code = (unsigned short*)cursor;
|
||||
cursor = (char*)(segs.end_code + segment_count);
|
||||
cursor = cursor + sizeof(unsigned short);
|
||||
|
||||
segs.start_code = (unsigned short*)cursor;
|
||||
cursor = (char*)(segs.start_code + segment_count);
|
||||
|
||||
segs.id_delta = (unsigned short*)cursor;
|
||||
cursor = (char*)(segs.id_delta + segment_count);
|
||||
|
||||
segs.id_range_offset = (unsigned short*)cursor;
|
||||
cursor = (char*)(segs.id_range_offset + segment_count);
|
||||
|
||||
byte_fix(segs, segment_count);
|
||||
for (int i = 0; i < segment_count; ++i){
|
||||
printf("\n");
|
||||
print(segs, i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_cmap_subtable(char *start){
|
||||
char *cursor = start;
|
||||
short *format = (short*)cursor;
|
||||
byte_reverse(format, 2);
|
||||
printf("\t\tformat %d\n", (int)(*format));
|
||||
|
||||
switch (*format){
|
||||
case 4:
|
||||
parse_cmap_subtable4(start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_cmap(char *start){
|
||||
char *cursor = start;
|
||||
cmap_Header *header = (cmap_Header*)cursor;
|
||||
cursor = (char*)(header + 1);
|
||||
|
||||
byte_fix(header);
|
||||
print(header);
|
||||
|
||||
cmap_Subtable_Entry *entry = (cmap_Subtable_Entry*)cursor;
|
||||
for (int i = 0; i < header->num_subtables; ++i, ++entry){
|
||||
byte_fix(entry);
|
||||
printf("\n");
|
||||
print(entry);
|
||||
|
||||
if (entry->plat_id == 3 && entry->plat_encoding_id == 1){
|
||||
printf("\n\tMicrosoft Unicode table:\n");
|
||||
parse_cmap_subtable(start + entry->offset_from_cmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct glyf_Glyph_Header{
|
||||
short num_contours;
|
||||
short x_min;
|
||||
short x_max;
|
||||
short y_min;
|
||||
short y_max;
|
||||
};
|
||||
|
||||
void
|
||||
byte_fix(glyf_Glyph_Header *header){
|
||||
byte_reverse(&header->num_contours, 2);
|
||||
byte_reverse(&header->x_min, 2);
|
||||
byte_reverse(&header->x_max, 2);
|
||||
byte_reverse(&header->y_min, 2);
|
||||
byte_reverse(&header->y_max, 2);
|
||||
}
|
||||
|
||||
void
|
||||
print(glyf_Glyph_Header *header){
|
||||
printf("\tcontours %d\n", (int)(header->num_contours));
|
||||
printf("\tx min %d\n", (int)(header->x_min));
|
||||
printf("\tx max %d\n", (int)(header->x_max));
|
||||
printf("\ty min %d\n", (int)(header->y_min));
|
||||
printf("\ty max %d\n", (int)(header->y_max));
|
||||
}
|
||||
|
||||
void
|
||||
parse_glyf(char *start){
|
||||
char *cursor = start;
|
||||
glyf_Glyph_Header *header = (glyf_Glyph_Header*)cursor;
|
||||
cursor = (char*)(header + 1);
|
||||
|
||||
byte_fix(header);
|
||||
print(header);
|
||||
}
|
||||
|
||||
#define TTF_Tag(a,b,c,d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
|
||||
#define TTF_Tag_cmap TTF_Tag('c', 'm', 'a', 'p')
|
||||
|
||||
#define TTF_Tag_glyf TTF_Tag('g', 'l', 'y', 'f')
|
||||
#define TTF_Tag_fpgm TTF_Tag('f', 'p', 'g', 'm')
|
||||
#define TTF_Tag_prep TTF_Tag('p', 'r', 'e', 'p')
|
||||
#define TTF_Tag_cvt TTF_Tag('c', 'v', 't', ' ')
|
||||
#define TTF_Tag_maxp TTF_Tag('m', 'a', 'x', 'p')
|
||||
|
||||
|
||||
int
|
||||
main(){
|
||||
Data file;
|
||||
char *filename;
|
||||
|
||||
filename = "test.ttf";
|
||||
file = open_file(filename);
|
||||
if (file.data == 0){
|
||||
printf("could not open %s\n", filename);
|
||||
return (1);
|
||||
}
|
||||
|
||||
char *cursor;
|
||||
Offset_Table *offset;
|
||||
|
||||
cursor = file.data;
|
||||
offset = (Offset_Table*)cursor;
|
||||
cursor = (char*)(offset + 1);
|
||||
|
||||
|
||||
Table_Directory_Entry *directory_entries = (Table_Directory_Entry*)cursor;
|
||||
|
||||
byte_fix(offset);
|
||||
print(offset);
|
||||
|
||||
int table_number = offset->num_tables;
|
||||
|
||||
Table_Directory_Entry *entry = directory_entries;
|
||||
for (int i = 0; i < table_number; ++i, ++entry){
|
||||
printf("\n");
|
||||
byte_fix(entry);
|
||||
print(entry);
|
||||
|
||||
switch (entry->tag){
|
||||
case TTF_Tag_cmap:
|
||||
parse_cmap(file.data + entry->offset);
|
||||
break;
|
||||
|
||||
case TTF_Tag_glyf:
|
||||
parse_glyf(file.data + entry->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
// BOTTOM
|
|
@ -14,66 +14,19 @@
|
|||
internal void
|
||||
keycode_init(Key_Codes *codes){
|
||||
set_dynamic_key_names(codes);
|
||||
|
||||
u16 code, loose;
|
||||
for (u8 i = 0; i < 255; ++i){
|
||||
if ((i >= '0' && i <= '9') ||
|
||||
(i >= 'A' && i <= 'Z')){
|
||||
keycode_lookup_table[i] = i;
|
||||
loose_keycode_lookup_table[i] = 0;
|
||||
}
|
||||
|
||||
else{
|
||||
loose = 0;
|
||||
switch (i){
|
||||
case VK_SPACE: code = loose = ' '; break;
|
||||
case VK_BACK: code = loose = codes->back; break;
|
||||
case VK_OEM_MINUS: code = '-'; break;
|
||||
case VK_OEM_PLUS: code = '='; break;
|
||||
case VK_SUBTRACT: code = '-'; break;
|
||||
case VK_ADD: code = '+'; break;
|
||||
case VK_MULTIPLY: code = '*'; break;
|
||||
case VK_DIVIDE: code = '/'; break;
|
||||
|
||||
case VK_OEM_3: code = '`'; break;
|
||||
case VK_OEM_5: code = '\\'; break;
|
||||
case VK_OEM_4: code = '['; break;
|
||||
case VK_OEM_6: code = ']'; break;
|
||||
case VK_TAB: code = loose = '\t'; break;
|
||||
case VK_RETURN: code = loose = '\n'; break;
|
||||
case VK_OEM_7: code = '\''; break;
|
||||
|
||||
case VK_OEM_1: code = ';'; break;
|
||||
case VK_OEM_2: code = '/'; break;
|
||||
case VK_OEM_PERIOD: code = '.'; break;
|
||||
case VK_OEM_COMMA: code = ','; break;
|
||||
|
||||
case VK_DELETE: code = loose = codes->del; break;
|
||||
case VK_UP: code = loose = codes->up; break;
|
||||
case VK_DOWN: code = loose = codes->down; break;
|
||||
case VK_LEFT: code = loose = codes->left; break;
|
||||
case VK_RIGHT: code = loose = codes->right; break;
|
||||
|
||||
case VK_INSERT: code = loose = codes->insert; break;
|
||||
case VK_HOME: code = loose = codes->home; break;
|
||||
case VK_END: code = loose = codes->end; break;
|
||||
case VK_PRIOR: code = loose = codes->page_up; break;
|
||||
case VK_NEXT: code = loose = codes->page_down; break;
|
||||
case VK_ESCAPE: code = loose = codes->esc; break;
|
||||
|
||||
case VK_NUMPAD0:
|
||||
case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3:
|
||||
case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6:
|
||||
case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9:
|
||||
code = (i - VK_NUMPAD0) + '0'; break;
|
||||
|
||||
default: code = 0; break;
|
||||
}
|
||||
|
||||
keycode_lookup_table[i] = code;
|
||||
loose_keycode_lookup_table[i] = loose;
|
||||
}
|
||||
}
|
||||
|
||||
keycode_lookup_table[VK_BACK] = codes->back;
|
||||
keycode_lookup_table[VK_DELETE] = codes->del;
|
||||
keycode_lookup_table[VK_UP] = codes->up;
|
||||
keycode_lookup_table[VK_DOWN] = codes->down;
|
||||
keycode_lookup_table[VK_LEFT] = codes->left;
|
||||
keycode_lookup_table[VK_RIGHT] = codes->right;
|
||||
keycode_lookup_table[VK_INSERT] = codes->insert;
|
||||
keycode_lookup_table[VK_HOME] = codes->home;
|
||||
keycode_lookup_table[VK_END] = codes->end;
|
||||
keycode_lookup_table[VK_PRIOR] = codes->page_up;
|
||||
keycode_lookup_table[VK_NEXT] = codes->page_down;
|
||||
keycode_lookup_table[VK_ESCAPE] = codes->esc;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -494,59 +494,8 @@ typedef struct Buffer_Measure_Starts{
|
|||
} Buffer_Measure_Starts;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
internal_4tech int
|
||||
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||
Buffer_Stringify_Type loop;
|
||||
int *starts;
|
||||
int max;
|
||||
char *data;
|
||||
int size, end;
|
||||
int start, count, i;
|
||||
int result;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
starts = buffer->line_starts;
|
||||
max = buffer->line_max;
|
||||
|
||||
result = 1;
|
||||
|
||||
i = state->i;
|
||||
count = state->count;
|
||||
start = state->start;
|
||||
|
||||
for (loop = buffer_stringify_loop(buffer, i, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
if (data[i] == '\n'){
|
||||
if (count == max) goto buffer_measure_starts_end;
|
||||
|
||||
starts[count++] = start;
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_4tech(i == size);
|
||||
|
||||
if (count == max) goto buffer_measure_starts_end;
|
||||
starts[count++] = start;
|
||||
result = 0;
|
||||
|
||||
buffer_measure_starts_end:
|
||||
state->i = i;
|
||||
state->count = count;
|
||||
state->start = start;
|
||||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal_4tech int
|
||||
buffer_measure_starts_widths(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){
|
||||
buffer_measure_starts_widths_(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){
|
||||
Buffer_Stringify_Type loop;
|
||||
int *start_ptr, *start_end;
|
||||
float *width_ptr;
|
||||
|
@ -612,6 +561,80 @@ buffer_measure_starts_widths_end:
|
|||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_measure_starts_zero_widths_(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||
Buffer_Stringify_Type loop;
|
||||
int *start_ptr, *start_end;
|
||||
float *width_ptr;
|
||||
debug_4tech(int widths_max);
|
||||
debug_4tech(int max);
|
||||
char *data;
|
||||
int size, end;
|
||||
int start, i;
|
||||
int result;
|
||||
char ch;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
|
||||
debug_4tech(max = buffer->line_max);
|
||||
debug_4tech(widths_max = buffer->widths_max);
|
||||
assert_4tech(max == widths_max);
|
||||
|
||||
result = 1;
|
||||
|
||||
i = state->i;
|
||||
start = state->start;
|
||||
|
||||
start_ptr = buffer->line_starts + state->count;
|
||||
width_ptr = buffer->line_widths + state->count;
|
||||
start_end = buffer->line_starts + buffer->line_max;
|
||||
|
||||
for (loop = buffer_stringify_loop(buffer, i, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
ch = data[i];
|
||||
if (ch == '\n'){
|
||||
if (start_ptr == start_end) goto buffer_measure_starts_zero_widths_end;
|
||||
|
||||
*width_ptr++ = 0;
|
||||
*start_ptr++ = start;
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_4tech(i == size);
|
||||
|
||||
if (start_ptr == start_end) goto buffer_measure_starts_zero_widths_end;
|
||||
*start_ptr++ = start;
|
||||
*width_ptr++ = 0;
|
||||
result = 0;
|
||||
|
||||
buffer_measure_starts_zero_widths_end:
|
||||
state->i = i;
|
||||
state->count = (int)(start_ptr - buffer->line_starts);
|
||||
state->start = start;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_measure_starts_widths(Buffer_Measure_Starts *state, Buffer_Type *buffer, float *advance_data){
|
||||
int result;
|
||||
|
||||
if (advance_data){
|
||||
result = buffer_measure_starts_widths_(state, buffer, advance_data);
|
||||
}
|
||||
else{
|
||||
result = buffer_measure_starts_zero_widths_(state, buffer);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_remeasure_starts(Buffer_Type *buffer, int line_start, int line_end, int line_shift, int text_shift){
|
||||
Buffer_Stringify_Type loop;
|
||||
|
@ -942,28 +965,33 @@ buffer_cursor_seek(Buffer_Type *buffer, Buffer_Seek seek, float max_width,
|
|||
|
||||
Seek_State state;
|
||||
int xy_seek;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||
|
||||
state.cursor = cursor;
|
||||
|
||||
result = 1;
|
||||
i = cursor.pos;
|
||||
for (loop = buffer_stringify_loop(buffer, i, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, data[i]);
|
||||
if (!result) goto buffer_cursor_seek_end;
|
||||
if (advance_data){
|
||||
|
||||
size = buffer_size(buffer);
|
||||
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||
|
||||
result = 1;
|
||||
i = cursor.pos;
|
||||
for (loop = buffer_stringify_loop(buffer, i, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; i < end; ++i){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, data[i]);
|
||||
if (!result) goto buffer_cursor_seek_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, 0);
|
||||
assert_4tech(result == 0);
|
||||
if (result){
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width,
|
||||
font_height, advance_data, size, 0);
|
||||
assert_4tech(result == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buffer_cursor_seek_end:
|
||||
|
@ -1110,7 +1138,7 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
int i, item_i;
|
||||
float ch_width, ch_width_sub;
|
||||
char ch;
|
||||
|
||||
|
||||
size = buffer_size(buffer);
|
||||
|
||||
shift_x = port_x - scroll_x;
|
||||
|
@ -1131,84 +1159,94 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
item_i = 0;
|
||||
item = items + item_i;
|
||||
|
||||
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
if (advance_data){
|
||||
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
|
||||
for (i = loop.absolute_pos; i < end; ++i){
|
||||
ch = data[i];
|
||||
ch_width = measure_character(advance_data, ch);
|
||||
for (i = loop.absolute_pos; i < end; ++i){
|
||||
ch = data[i];
|
||||
ch_width = measure_character(advance_data, ch);
|
||||
|
||||
if (ch_width + x > width + shift_x && wrapped){
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
if (ch_width + x > width + shift_x && wrapped){
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
|
||||
switch (ch){
|
||||
case '\n':
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
switch (ch){
|
||||
case '\n':
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
break;
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
case 0:
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
case '\r':
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
case '\t':
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
default:
|
||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
default:
|
||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_get_render_data_end:
|
||||
if (y <= height + shift_y || item == items){
|
||||
if (y <= height + shift_y || item == items){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
else{
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
ch_width = 0;
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
@echo off
|
||||
|
||||
REM this is here to prevent the spammation of PATH
|
||||
IF NOT DEFINED clset (call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x64)
|
||||
SET clset=64
|
||||
|
||||
SET WARNINGS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /WX
|
||||
SET STUFF=/GR- /nologo
|
||||
SET DEBUG=/Zi
|
||||
SET EXPORTS=/EXPORT:get_bindings /EXPORT:set_extra_font
|
||||
|
||||
cl %WARNINGS% %STUFF% %DEBUG% 4coder_custom.cpp /Fe4coder_custom /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS%
|
||||
|
||||
REM more spammation preventation
|
||||
del *.exp
|
||||
del *.obj
|
||||
del *.lib
|
22
temp.cpp
22
temp.cpp
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* YOUR INFO HERE!
|
||||
*/
|
||||
|
||||
// a b c d e f g
|
||||
|
||||
#define swap(a,b) {auto t=a; a=b; b=t;}
|
||||
|
||||
struct Thing{
|
||||
int x, y, z;
|
||||
};
|
||||
|
||||
struct Stuff{
|
||||
Thing x;
|
||||
int a, b, c;
|
||||
};
|
||||
|
||||
void insert_sort(int *items, int size){
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 1.21.2015
|
||||
* 21.1.2015
|
||||
*
|
||||
* Test for CPP lexer & parser layer for project codename "4ed"
|
||||
*
|
||||
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "../4ed_meta.h"
|
||||
|
||||
#define Debug(x) x
|
||||
|
||||
#include "../4cpp_types.h"
|
||||
#define FCPP_STRING_IMPLEMENTATION
|
||||
#include "../4cpp_string.h"
|
||||
|
@ -22,8 +24,6 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define FCPP_PREPROCESSOR_DBG_LEVEL 1
|
||||
|
||||
internal bool
|
||||
system_is_absoute_path(char *path){
|
||||
bool is_absolute = 0;
|
||||
|
@ -72,7 +72,32 @@ quickie_file(String filename){
|
|||
return quickie_file(buffer);
|
||||
}
|
||||
|
||||
#define STRICT_MEM_TEST 1
|
||||
internal void
|
||||
preproc_init(Cpp_PP_State *state, Cpp_PP_Definitions *definitions){
|
||||
*state = {};
|
||||
state->max = (32 << 10);
|
||||
state->base = (byte*)malloc(state->max);
|
||||
memset(state->base, 0, state->max);
|
||||
|
||||
*definitions = {};
|
||||
definitions->max = 128 << 10;
|
||||
definitions->items = (byte*)malloc(definitions->max);
|
||||
memset(definitions->items, 0, definitions->max);
|
||||
|
||||
definitions->table.count = 0;
|
||||
definitions->table.max = 4 << 10;
|
||||
definitions->table.entries = (Cpp_PP_Table_Entry*)
|
||||
malloc(definitions->table.max*sizeof(Cpp_PP_Table_Entry));
|
||||
memset(definitions->table.entries, 0, definitions->table.max*sizeof(Cpp_PP_Table_Entry));
|
||||
|
||||
int str_size = 16 << 10;
|
||||
int token_size = 16 << 10;
|
||||
void *str_mem = malloc(str_size);
|
||||
void *token_mem = malloc(token_size);
|
||||
cpp_preproc_set_spare_space(definitions,
|
||||
str_size, str_mem,
|
||||
token_size, token_mem);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if (argc < 2){
|
||||
|
@ -83,169 +108,48 @@ int main(int argc, char **argv){
|
|||
|
||||
Cpp_File target_file;
|
||||
target_file = quickie_file(TEST_FILE);
|
||||
|
||||
|
||||
if (target_file.data == 0){
|
||||
printf("could not open file %s\n", TEST_FILE);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Cpp_Token_Stack target_tokens = {};
|
||||
cpp_lex_file(target_file, &target_tokens);
|
||||
|
||||
Cpp_PP_State state = {};
|
||||
Cpp_PP_Definitions definitions = {};
|
||||
|
||||
preproc_init(&state, &definitions);
|
||||
|
||||
Cpp_Parse_Context context = {};
|
||||
Cpp_Parse_Definitions definitions = {};
|
||||
Cpp_Preproc_State state = {};
|
||||
cpp_preproc_target(&state, &definitions, target_file, target_tokens);
|
||||
|
||||
context.preserve_chunk_size = (200 << 10);
|
||||
|
||||
definitions.table.size = 0;
|
||||
#if STRICT_MEM_TEST
|
||||
definitions.table.max_size = 16;
|
||||
#else
|
||||
definitions.table.max_size = 100;
|
||||
#endif
|
||||
definitions.table.table = (Table_Entry*)malloc(sizeof(Table_Entry)*definitions.table.max_size);
|
||||
memset(definitions.table.table, 0, sizeof(Table_Entry)*definitions.table.max_size);
|
||||
|
||||
definitions.count = 0;
|
||||
#if STRICT_MEM_TEST
|
||||
definitions.max = 16;
|
||||
#else
|
||||
definitions.max = 100;
|
||||
#endif
|
||||
definitions.slots = (Cpp_Def_Slot*)malloc(sizeof(Cpp_Def_Slot)*definitions.max);
|
||||
|
||||
{
|
||||
String string_filename = make_lit_string("~ string space");
|
||||
Cpp_File string_file;
|
||||
#if STRICT_MEM_TEST
|
||||
string_file.size = 100;
|
||||
#else
|
||||
string_file.size = (128 << 10);
|
||||
#endif
|
||||
string_file.data = (char*)malloc(string_file.size);
|
||||
Cpp_Token_Stack string_tokens;
|
||||
string_tokens.count = 0;
|
||||
#if STRICT_MEM_TEST
|
||||
string_tokens.max_count = 2;
|
||||
#else
|
||||
string_tokens.max_count = (128 << 10)/sizeof(Cpp_Token);
|
||||
#endif
|
||||
string_tokens.tokens = (Cpp_Token*)malloc(sizeof(Cpp_Token)*string_tokens.max_count);
|
||||
for (Cpp_PP_Step step = {};
|
||||
step.finished == 0;){
|
||||
step = cpp_preproc_step_nonalloc(&state, &definitions);
|
||||
|
||||
Cpp_File_Data string_parse_file;
|
||||
string_parse_file.file = string_file;
|
||||
string_parse_file.tokens = string_tokens;
|
||||
string_parse_file.filename = string_filename;
|
||||
|
||||
int string_index = cpp_defs_add(&definitions, {}, CPP_DEFTYPE_FILE);
|
||||
cpp_set_parse_file(&definitions, string_index, string_parse_file);
|
||||
|
||||
definitions.string_file_index = string_index;
|
||||
definitions.string_write_pos = 0;
|
||||
|
||||
{
|
||||
Cpp_Token eof_token = {};
|
||||
eof_token.type = CPP_TOKEN_EOF;
|
||||
definitions.eof_token = cpp__preserve_token(&definitions, eof_token);
|
||||
if (step.error_code){
|
||||
printf("error: %s\n", cpp_preproc_error_str(step.error_code));
|
||||
if (cpp_preproc_recommend_termination(step.error_code)){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (step.mem_size != 0){
|
||||
void *memory = malloc(step.mem_size);
|
||||
memory = cpp_preproc_provide_memory(&state, &definitions,
|
||||
step.mem_type, step.mem_size, memory);
|
||||
free(memory);
|
||||
}
|
||||
|
||||
{
|
||||
String string_va_args = make_lit_string("__VA_ARGS__");
|
||||
Cpp_Token va_args_token;
|
||||
va_args_token.type = CPP_TOKEN_IDENTIFIER;
|
||||
va_args_token.start = definitions.string_write_pos;
|
||||
va_args_token.size = string_va_args.size;
|
||||
cpp__preserve_string(&definitions, string_va_args);
|
||||
definitions.va_args_token = cpp__preserve_token(&definitions, va_args_token);
|
||||
if (step.emit){
|
||||
Cpp_File file = *cpp_preproc_get_file(&definitions, step.file_index);
|
||||
Cpp_Token token = *cpp_preproc_get_token(&definitions, step.file_index, step.token_index);
|
||||
|
||||
printf("TOKEN: %.*s\n", token.size, file.data + token.start);
|
||||
}
|
||||
}
|
||||
|
||||
state.tokens.count = 0;
|
||||
#if STRICT_MEM_TEST
|
||||
state.tokens.max = 5;
|
||||
#else
|
||||
state.tokens.max = 100;
|
||||
#endif
|
||||
state.tokens.tokens = (Cpp_Loose_Token*)malloc(sizeof(Cpp_Loose_Token)*state.tokens.max);
|
||||
|
||||
state.spare_string_write_pos = 0;
|
||||
#if STRICT_MEM_TEST
|
||||
state.spare_string_size = 1;
|
||||
#else
|
||||
state.spare_string_size = (10 << 10);
|
||||
#endif
|
||||
state.spare_string = (char*)malloc(state.spare_string_size);
|
||||
|
||||
String target_filename = make_lit_string(TEST_FILE);
|
||||
cpp_set_target(&state, &definitions, target_file, target_tokens, target_filename);
|
||||
|
||||
while (!state.finished){
|
||||
Cpp_Preproc_Result result;
|
||||
result = cpp_preproc_step_nonalloc(&state, &definitions, &context);
|
||||
|
||||
if (result.memory_request){
|
||||
Cpp_Memory_Request request = cpp_get_memory_request(&state, &definitions, result);
|
||||
void *memory = malloc(request.size);
|
||||
void *old_memory = cpp_provide_memory(request, memory);
|
||||
free(old_memory);
|
||||
}
|
||||
|
||||
if (result.file_request){
|
||||
Cpp_File_Request request = cpp_get_file_request(&state, result);
|
||||
for (; cpp_has_more_files(&request); cpp_get_next_file(&request)){
|
||||
if (!cpp_try_reuse_file(&request)){
|
||||
Cpp_File new_file = quickie_file(request.filename);
|
||||
if (new_file.data == 0){
|
||||
printf("could not open file %s\n", request.filename);
|
||||
exit(1);
|
||||
}
|
||||
Cpp_Token_Stack new_tokens = {};
|
||||
cpp_lex_file(new_file, &new_tokens);
|
||||
cpp_provide_file(&request, new_file, new_tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.error_code){
|
||||
String error_message = cpp_get_error(result.error_code);
|
||||
Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.file_index);
|
||||
Cpp_Token token = file.tokens.tokens[result.token_index];
|
||||
bool terminate = cpp_recommend_termination(result.error_code);
|
||||
|
||||
if (terminate){
|
||||
printf("FATAL ");
|
||||
}
|
||||
|
||||
printf("ERROR IN %.*s AT %.*s\n%.*s\n",
|
||||
file.filename.size, file.filename.str,
|
||||
token.size, file.file.data + token.start,
|
||||
error_message.size, error_message.str);
|
||||
|
||||
if (terminate){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.emit){
|
||||
Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.file_index);
|
||||
Cpp_Token token = file.tokens.tokens[result.token_index];
|
||||
|
||||
if (result.from_macro){
|
||||
Cpp_File_Data file = *cpp_get_parse_file(&definitions, result.invoking_file_index);
|
||||
Cpp_Token token = file.tokens.tokens[result.invoking_token_index];
|
||||
|
||||
printf("EXPANDING %.*s => ", token.size, file.file.data + token.start);
|
||||
}
|
||||
|
||||
printf("TOKEN %.*s\n", token.size, file.file.data + token.start);
|
||||
}
|
||||
}
|
||||
|
||||
assert(state.finished == 0 || state.expansion_level == 0);
|
||||
assert(state.finished == 0 || state.param_info_used == 0);
|
||||
assert(state.finished == 0 || state.state == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
754
win32_4ed.cpp
754
win32_4ed.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue