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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
update_cli_handle_with_file(System_Functions *system, Models *models,
 | 
			
		||||
                            CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){
 | 
			
		||||
| 
						 | 
				
			
			@ -1880,6 +1898,10 @@ App_Step_Sig(app_step){
 | 
			
		|||
                    --i;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
                update_cli_handle_without_file(
 | 
			
		||||
                    system, models, &proc->cli, dest, max);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1494,13 +1494,13 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){
 | 
			
		|||
    DWORD remaining = loop->remaining_amount;
 | 
			
		||||
    u32 pos = 0;
 | 
			
		||||
    DWORD read_amount = 0;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    for (;;){
 | 
			
		||||
        if (remaining == 0){
 | 
			
		||||
            if (!PeekNamedPipe(handle, 0, 0, 0, &remaining, 0)) break;
 | 
			
		||||
            if (remaining == 0) break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        if (remaining + pos < max){
 | 
			
		||||
            has_more = 1;
 | 
			
		||||
            ReadFile(handle, dest + pos, remaining, &read_amount, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1518,8 +1518,8 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    *amount = pos;
 | 
			
		||||
 | 
			
		||||
    return has_more;
 | 
			
		||||
    
 | 
			
		||||
    return(has_more);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal
 | 
			
		||||
| 
						 | 
				
			
			@ -1527,13 +1527,13 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
 | 
			
		|||
    b32 close_me = 0;
 | 
			
		||||
    HANDLE proc = *(HANDLE*)&cli->proc;
 | 
			
		||||
    DWORD result = 0;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    if (WaitForSingleObject(proc, 0) == WAIT_OBJECT_0){
 | 
			
		||||
        if (GetExitCodeProcess(proc, &result) == 0)
 | 
			
		||||
            cli->exit = -1;
 | 
			
		||||
        else
 | 
			
		||||
            cli->exit = (i32)result;
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        close_me = 1;
 | 
			
		||||
        CloseHandle(*(HANDLE*)&cli->proc);
 | 
			
		||||
        CloseHandle(*(HANDLE*)&cli->out_read);
 | 
			
		||||
| 
						 | 
				
			
			@ -1541,7 +1541,7 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
 | 
			
		|||
        
 | 
			
		||||
        --win32vars.running_cli;
 | 
			
		||||
    }
 | 
			
		||||
    return close_me;
 | 
			
		||||
    return(close_me);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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