fixed bug with child processes being starved so they cannot terminate properly
parent
3d714642ad
commit
e7216b80c6
22
4ed.cpp
22
4ed.cpp
|
@ -1626,6 +1626,24 @@ App_Init_Sig(app_init){
|
||||||
vars->cli_processes.count = 0;
|
vars->cli_processes.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal i32
|
||||||
|
update_cli_handle_without_file(System_Functions *system, Models *models,
|
||||||
|
CLI_Handles *cli, char *dest, i32 max){
|
||||||
|
i32 result = 0;
|
||||||
|
u32 amount = 0;
|
||||||
|
|
||||||
|
system->cli_begin_update(cli);
|
||||||
|
if (system->cli_update_step(cli, dest, max, &amount)){
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system->cli_end_update(cli)){
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
update_cli_handle_with_file(System_Functions *system, Models *models,
|
update_cli_handle_with_file(System_Functions *system, Models *models,
|
||||||
CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){
|
CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){
|
||||||
|
@ -1880,6 +1898,10 @@ App_Step_Sig(app_step){
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
update_cli_handle_without_file(
|
||||||
|
system, models, &proc->cli, dest, max);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vars->cli_processes.count = count;
|
vars->cli_processes.count = count;
|
||||||
|
|
360
4ed_ttf.cpp
360
4ed_ttf.cpp
|
@ -1,360 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
|
@ -1471,7 +1471,7 @@ Sys_CLI_Call_Sig(system_cli_call){
|
||||||
// TODO(allen): failed CreatePipe
|
// TODO(allen): failed CreatePipe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1494,13 +1494,13 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){
|
||||||
DWORD remaining = loop->remaining_amount;
|
DWORD remaining = loop->remaining_amount;
|
||||||
u32 pos = 0;
|
u32 pos = 0;
|
||||||
DWORD read_amount = 0;
|
DWORD read_amount = 0;
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
if (remaining == 0){
|
if (remaining == 0){
|
||||||
if (!PeekNamedPipe(handle, 0, 0, 0, &remaining, 0)) break;
|
if (!PeekNamedPipe(handle, 0, 0, 0, &remaining, 0)) break;
|
||||||
if (remaining == 0) break;
|
if (remaining == 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining + pos < max){
|
if (remaining + pos < max){
|
||||||
has_more = 1;
|
has_more = 1;
|
||||||
ReadFile(handle, dest + pos, remaining, &read_amount, 0);
|
ReadFile(handle, dest + pos, remaining, &read_amount, 0);
|
||||||
|
@ -1518,8 +1518,8 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*amount = pos;
|
*amount = pos;
|
||||||
|
|
||||||
return has_more;
|
return(has_more);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
|
@ -1527,13 +1527,13 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
||||||
b32 close_me = 0;
|
b32 close_me = 0;
|
||||||
HANDLE proc = *(HANDLE*)&cli->proc;
|
HANDLE proc = *(HANDLE*)&cli->proc;
|
||||||
DWORD result = 0;
|
DWORD result = 0;
|
||||||
|
|
||||||
if (WaitForSingleObject(proc, 0) == WAIT_OBJECT_0){
|
if (WaitForSingleObject(proc, 0) == WAIT_OBJECT_0){
|
||||||
if (GetExitCodeProcess(proc, &result) == 0)
|
if (GetExitCodeProcess(proc, &result) == 0)
|
||||||
cli->exit = -1;
|
cli->exit = -1;
|
||||||
else
|
else
|
||||||
cli->exit = (i32)result;
|
cli->exit = (i32)result;
|
||||||
|
|
||||||
close_me = 1;
|
close_me = 1;
|
||||||
CloseHandle(*(HANDLE*)&cli->proc);
|
CloseHandle(*(HANDLE*)&cli->proc);
|
||||||
CloseHandle(*(HANDLE*)&cli->out_read);
|
CloseHandle(*(HANDLE*)&cli->out_read);
|
||||||
|
@ -1541,7 +1541,7 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
||||||
|
|
||||||
--win32vars.running_cli;
|
--win32vars.running_cli;
|
||||||
}
|
}
|
||||||
return close_me;
|
return(close_me);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "system_shared.cpp"
|
#include "system_shared.cpp"
|
||||||
|
|
359
win32_font.cpp
359
win32_font.cpp
|
@ -1,359 +0,0 @@
|
||||||
/*
|
|
||||||
* Mr. 4th Dimention - Allen Webster
|
|
||||||
*
|
|
||||||
* 12.12.2014
|
|
||||||
*
|
|
||||||
* Win32 font rendering for nicer fonts
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TOP
|
|
||||||
|
|
||||||
struct GMetrics{
|
|
||||||
f32 advance;
|
|
||||||
f32 xoff;
|
|
||||||
f32 xoff2;
|
|
||||||
};
|
|
||||||
|
|
||||||
internal b32
|
|
||||||
win32_glyph_metrics(HDC dc, int code, GMetrics *gmetrics){
|
|
||||||
b32 result = false;
|
|
||||||
ABCFLOAT abc = {0};
|
|
||||||
INT width;
|
|
||||||
|
|
||||||
if (GetCharWidth32W(dc, code, code, &width)){
|
|
||||||
gmetrics->advance = (f32)width;
|
|
||||||
if (GetCharABCWidthsFloat(dc, code, code, &abc)){
|
|
||||||
gmetrics->xoff = abc.abcfA;
|
|
||||||
gmetrics->xoff2 = (abc.abcfA + abc.abcfB);
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i32
|
|
||||||
win32_draw_font_load(Partition *part,
|
|
||||||
Render_Font *font_out,
|
|
||||||
char *filename_untranslated,
|
|
||||||
char *fontname,
|
|
||||||
i32 pt_size,
|
|
||||||
i32 tab_width,
|
|
||||||
i32 oversample,
|
|
||||||
b32 store_texture){
|
|
||||||
|
|
||||||
char space_[1024];
|
|
||||||
String filename = make_fixed_width_string(space_);
|
|
||||||
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
|
||||||
|
|
||||||
i32 result = 0;
|
|
||||||
|
|
||||||
if (translate_success){
|
|
||||||
HDC dc = GetDC(win32vars.window_handle);
|
|
||||||
|
|
||||||
AddFontResourceEx(filename.str, FR_PRIVATE, 0);
|
|
||||||
|
|
||||||
HFONT font_handle = CreateFont(
|
|
||||||
pt_size,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
FW_NORMAL,
|
|
||||||
FALSE,
|
|
||||||
FALSE,
|
|
||||||
FALSE,
|
|
||||||
ANSI_CHARSET,
|
|
||||||
OUT_DEFAULT_PRECIS,
|
|
||||||
CLIP_DEFAULT_PRECIS,
|
|
||||||
DEFAULT_QUALITY,
|
|
||||||
FF_DONTCARE | DEFAULT_PITCH,
|
|
||||||
fontname
|
|
||||||
);
|
|
||||||
HBITMAP bmp_handle = CreateBitmap(
|
|
||||||
pt_size*2, pt_size*2,
|
|
||||||
4, 32,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
if (font_handle != 0 && bmp_handle != 0){
|
|
||||||
SelectObject(dc, font_handle);
|
|
||||||
SelectObject(dc, bmp_handle);
|
|
||||||
|
|
||||||
memset(font_out, 0, sizeof(*font_out));
|
|
||||||
|
|
||||||
TEXTMETRIC metric;
|
|
||||||
if (GetTextMetrics(dc, &metric)){
|
|
||||||
|
|
||||||
font_out->height = (i32)(metric.tmHeight + metric.tmExternalLeading);
|
|
||||||
font_out->ascent = (i32)(metric.tmAscent);
|
|
||||||
font_out->descent = (i32)(metric.tmDescent);
|
|
||||||
font_out->line_skip = (i32)(metric.tmExternalLeading);
|
|
||||||
|
|
||||||
if (!store_texture){
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Temp_Memory temp = begin_temp_memory(part);
|
|
||||||
|
|
||||||
i32 tex_width = pt_size*16;
|
|
||||||
i32 tex_height = pt_size*16;
|
|
||||||
void *block = sysshared_push_block(part, tex_width * tex_height);
|
|
||||||
|
|
||||||
font_out->tex_width = tex_width;
|
|
||||||
font_out->tex_height = tex_height;
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
stbtt_pack_context spc_;
|
|
||||||
|
|
||||||
int pack_result;
|
|
||||||
{
|
|
||||||
stbtt_pack_context *spc = &spc_;
|
|
||||||
unsigned char *pixels = (u8*)block;
|
|
||||||
int pw = tex_width;
|
|
||||||
int ph = tex_height;
|
|
||||||
int stride_in_bytes = tex_width;
|
|
||||||
int padding = 1;
|
|
||||||
void *alloc_context = part;
|
|
||||||
|
|
||||||
{
|
|
||||||
stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
|
|
||||||
int num_nodes = pw - padding;
|
|
||||||
stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
|
|
||||||
|
|
||||||
if (context == NULL || nodes == NULL) {
|
|
||||||
if (context != NULL) STBTT_free(context, alloc_context);
|
|
||||||
if (nodes != NULL) STBTT_free(nodes , alloc_context);
|
|
||||||
pack_result = 0;
|
|
||||||
goto packbegin_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
spc->user_allocator_context = alloc_context;
|
|
||||||
spc->width = pw;
|
|
||||||
spc->height = ph;
|
|
||||||
spc->pixels = pixels;
|
|
||||||
spc->pack_info = context;
|
|
||||||
spc->nodes = nodes;
|
|
||||||
spc->padding = padding;
|
|
||||||
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
|
||||||
spc->h_oversample = 1;
|
|
||||||
spc->v_oversample = 1;
|
|
||||||
|
|
||||||
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
|
||||||
|
|
||||||
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
|
|
||||||
|
|
||||||
pack_result = 1;
|
|
||||||
goto packbegin_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
packbegin_end:;
|
|
||||||
|
|
||||||
if (pack_result){
|
|
||||||
|
|
||||||
int pack_font_range_result;
|
|
||||||
|
|
||||||
{
|
|
||||||
stbtt_pack_range range;
|
|
||||||
range.first_unicode_char_in_range = 0;
|
|
||||||
range.num_chars_in_range = 128;
|
|
||||||
range.chardata_for_range = font_out->chardata;
|
|
||||||
range.font_size = STBTT_POINT_SIZE((f32)pt_size);
|
|
||||||
|
|
||||||
stbtt_pack_context *spc = &spc_;
|
|
||||||
stbtt_pack_range *ranges = ⦥
|
|
||||||
int num_ranges = 1;
|
|
||||||
|
|
||||||
{
|
|
||||||
int i,j,k,n, return_value = 1;
|
|
||||||
stbrp_context *context = (stbrp_context *) spc->pack_info;
|
|
||||||
stbrp_rect *rects;
|
|
||||||
|
|
||||||
// flag all characters as NOT packed
|
|
||||||
for (i=0; i < num_ranges; ++i)
|
|
||||||
for (j=0; j < ranges[i].num_chars_in_range; ++j)
|
|
||||||
ranges[i].chardata_for_range[j].x0 =
|
|
||||||
ranges[i].chardata_for_range[j].y0 =
|
|
||||||
ranges[i].chardata_for_range[j].x1 =
|
|
||||||
ranges[i].chardata_for_range[j].y1 = 0;
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
for (i=0; i < num_ranges; ++i)
|
|
||||||
n += ranges[i].num_chars_in_range;
|
|
||||||
|
|
||||||
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
|
|
||||||
if (rects == NULL){
|
|
||||||
pack_font_range_result = 0;
|
|
||||||
goto pack_font_range_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
//info.userdata = spc->user_allocator_context;
|
|
||||||
//stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
|
|
||||||
k=0;
|
|
||||||
for (i=0; i < num_ranges; ++i) {
|
|
||||||
//float fh = ranges[i].font_size;
|
|
||||||
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
|
|
||||||
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
||||||
int w,h;
|
|
||||||
|
|
||||||
GMetrics gmetrics;
|
|
||||||
|
|
||||||
if (!win32_glyph_metrics(dc, ranges[i].first_unicode_char_in_range + j, &gmetrics)){
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
w = CEIL32(gmetrics.xoff2 - gmetrics.xoff);
|
|
||||||
h = font_out->ascent + font_out->descent;
|
|
||||||
|
|
||||||
rects[k].w = (stbrp_coord) (w + spc->padding);
|
|
||||||
rects[k].h = (stbrp_coord) (h + spc->padding);
|
|
||||||
++k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stbrp_pack_rects(context, rects, k);
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
for (i=0; i < num_ranges; ++i) {
|
|
||||||
//float fh = ranges[i].font_size;
|
|
||||||
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
|
|
||||||
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
|
||||||
stbrp_rect *r = &rects[k];
|
|
||||||
if (r->was_packed) {
|
|
||||||
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
|
||||||
//int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
|
|
||||||
int code = ranges[i].first_unicode_char_in_range + j;
|
|
||||||
stbrp_coord pad = (stbrp_coord) spc->padding;
|
|
||||||
|
|
||||||
// pad on left and top
|
|
||||||
r->x += pad;
|
|
||||||
r->y += pad;
|
|
||||||
r->w -= pad;
|
|
||||||
r->h -= pad;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int advance, lsb, x0,y0,x1,y1;
|
|
||||||
|
|
||||||
stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
|
|
||||||
stbtt_GetGlyphBitmapBox(&info, glyph,
|
|
||||||
scale * spc->h_oversample,
|
|
||||||
scale * spc->v_oversample,
|
|
||||||
&x0,&y0,&x1,&y1);
|
|
||||||
stbtt_MakeGlyphBitmapSubpixel(&info,
|
|
||||||
spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
|
||||||
r->w - spc->h_oversample+1,
|
|
||||||
r->h - spc->v_oversample+1,
|
|
||||||
spc->stride_in_bytes,
|
|
||||||
scale * spc->h_oversample,
|
|
||||||
scale * spc->v_oversample,
|
|
||||||
0,0,
|
|
||||||
glyph);
|
|
||||||
#else
|
|
||||||
float advance, x0, y0, x1, y1;
|
|
||||||
|
|
||||||
GMetrics gmetrics;
|
|
||||||
if (!win32_glyph_metrics(dc, code, &gmetrics)){
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
advance = gmetrics.advance;
|
|
||||||
x0 = gmetrics.xoff;
|
|
||||||
y0 = -font_out->ascent;
|
|
||||||
x1 = gmetrics.xoff2;
|
|
||||||
y1 = font_out->descent;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bc->x0 = (stbtt_int16) r->x;
|
|
||||||
bc->y0 = (stbtt_int16) r->y;
|
|
||||||
bc->x1 = (stbtt_int16) (r->x + r->w);
|
|
||||||
bc->y1 = (stbtt_int16) (r->y + r->h);
|
|
||||||
bc->xadvance = (float) advance;
|
|
||||||
bc->xoff = (float) x0;
|
|
||||||
bc->yoff = (float) y0;
|
|
||||||
bc->xoff2 = (float) (x0 + r->w);
|
|
||||||
bc->yoff2 = (float) (y0 + r->h);
|
|
||||||
} else {
|
|
||||||
return_value = 0; // if any fail, report failure
|
|
||||||
}
|
|
||||||
|
|
||||||
++k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
STBTT_free(rects, spc->user_allocator_context);
|
|
||||||
pack_font_range_result = return_value;
|
|
||||||
goto pack_font_range_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pack_font_range_end:;
|
|
||||||
|
|
||||||
|
|
||||||
if (!pack_font_range_result){
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
stbtt_pack_context *spc = &spc_;
|
|
||||||
{
|
|
||||||
STBTT_free(spc->nodes , spc->user_allocator_context);
|
|
||||||
STBTT_free(spc->pack_info, spc->user_allocator_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
if (result){
|
|
||||||
GLuint font_tex;
|
|
||||||
glGenTextures(1, &font_tex);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, font_tex);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
memset(block, 0xFF, tex_width*tex_height);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
|
||||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
|
||||||
}
|
|
||||||
|
|
||||||
i32 max_advance = metric.tmMaxCharWidth;
|
|
||||||
font_out->advance = max_advance - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
end_temp_memory(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteObject(font_handle);
|
|
||||||
DeleteObject(bmp_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseDC(win32vars.window_handle, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue