From 9ef5c135e894b2da95940e2556f4df9ce2205552 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 3 Jan 2014 13:19:44 +0100 Subject: Re-organized the host software directory layout --- host/font.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 host/font.c (limited to 'host/font.c') diff --git a/host/font.c b/host/font.c new file mode 100644 index 0000000..725e039 --- /dev/null +++ b/host/font.c @@ -0,0 +1,194 @@ + +#include "font.h" +#include +#include +#include +#include + +void render_glyph(glyph_t *g, uint8_t *buf, unsigned int bufwidth, unsigned int offx, unsigned int offy, color_t fg, color_t bg){ + unsigned int bitmap_row_width = g->width/8; + uint8_t *bitmap = ((uint8_t *)g) + sizeof(glyph_t); + for(unsigned int y=0; y < g->height; y++){ + long int data = 0; + for(unsigned int i=0; iwidth; x++){ + color_t c = (data&(1<<(g->width-1))) ? fg : bg; + *((color_t *)p) = c; + p += 3; + data <<= 1; + } + } +} + +int read_bdf(FILE *f, glyph_t **glyph_table, unsigned int glyph_table_size){ + char* line = 0; + size_t len = 0; + + glyph_t current_glyph = {-1, -1, -1, -1}; + unsigned int dwidth = -1; + unsigned int encoding = -1; + void *glyph_data = 0; + + // Clear glyph table before use + memset(glyph_table, 0, sizeof(*glyph_table)); + + for(;;){ + size_t read = getline(&line, &len, f); + if(read == -1){ + fprintf(stderr, "Could not read line from font file\n"); + goto error; + } + if(read < 2) // Ignore empty lines + continue; + line[read-1] = '\0'; + char *endptr; + char *args = strchr(line, ' '); + if(args){ + *args = 0; + args++; + } + + if(strcmp("ENDFONT", line) == 0){ + break; + }else if(strcmp("ENCODING", line) == 0){ + if(!args){ + fprintf(stderr, "Invalid ENCODING line: %s %s\n", line, args); + goto error; + } + + encoding = strtol(args, &endptr, 10); + if(args == endptr || *endptr != '\0'){ + fprintf(stderr, "Invalid ENCODING line: %s %s\n", line, args); + goto error; + } + if(encoding > glyph_table_size){ + fprintf(stderr, "Codepoint out of valid range (0-%d): %d", glyph_table_size, encoding); + goto error; + } + + }else if(strcmp("BBX", line) == 0){ + if(!args){ + fprintf(stderr, "Invalid ENCODING line: %s %s\n", line, args); + goto error; + } + + endptr = 0; + char *w = strtok_r(args, " ", &endptr); + char *h = strtok_r(NULL, " ", &endptr); + char *x = strtok_r(NULL, " ", &endptr); + char *y = strtok_r(NULL, " ", &endptr); + if(!w || !h || !x || !y){ + fprintf(stderr, "Invalid BBX line: %s %s\n", line, args); + goto error; + } + current_glyph.width = atoi(w); + current_glyph.height = atoi(h); + current_glyph.x = atoi(x); + current_glyph.y = atoi(y); + + }else if(strcmp("DWIDTH", line) == 0){ + if(!args){ + fprintf(stderr, "Invalid ENCODING line: %s %s\n", line, args); + goto error; + } + + endptr = 0; + char *w = strtok_r(args, " ", &endptr); + char *h = strtok_r(NULL, " ", &endptr); + if(!w || !h){ + fprintf(stderr, "Invalid DWIDTH line: %s %s\n", line, args); + goto error; + } + + dwidth = strtol(w, &endptr, 10); + if(w == endptr || *endptr != '\0'){ + fprintf(stderr, "Invalid DWIDTH line: %s %s\n", line, args); + goto error; + } + + }else if(strcmp("BITMAP", line) == 0){ + unsigned int row_bytes = dwidth/8; + glyph_data = malloc(sizeof(glyph_t) + row_bytes * current_glyph.height); + if(!glyph_data){ + fprintf(stderr, "Cannot malloc() memory.\n"); + goto error; + } + uint8_t *bitmap = (uint8_t *)glyph_data + sizeof(glyph_t); + + if(current_glyph.width < 0 || dwidth < 0 || encoding < 0){ + fprintf(stderr, "Invalid glyph: "); + if(current_glyph.width < 0) + fprintf(stderr, "No bounding box given."); + if(dwidth < 0) + fprintf(stderr, "No data width given."); + if(encoding < 0) + fprintf(stderr, "No codepoint given."); + fprintf(stderr, "\n"); + goto error; + } + + if(current_glyph.width != dwidth){ + fprintf(stderr, "Invalid glyph: bounding box width != dwidth\n"); + goto error; + } + + unsigned int i=0; + while(1){ + read = getline(&line, &len, f); + if(read == -1){ + fprintf(stderr, "Could not read line from font file\n"); + goto error; + } + if(read < 2) // Ignore empty lines + continue; + line[read-1] = '\0'; + + if(strncmp("ENDCHAR", line, read) == 0) + break; + + if(i >= current_glyph.height){ + fprintf(stderr, "Too many rows of bitmap data in glyph %d: %d > %d\n", encoding, i+1, current_glyph.height); + goto error; + } + + //XXX This limits the maximum character width to sizeof(long)*8 (normally 64) piccells. + long int data = strtol(line, &endptr, 16); + if(line == endptr || *endptr != '\0'){ + fprintf(stderr, "Invalid bitmap data in glyph %d: %s\n", encoding, line); + goto error; + } + + // Right-align data + data >>= ((read-1)*4 - dwidth); + // Copy rightmost bytes of data to destination buffer + for(unsigned int j=0; j>= 8; + } + i++; + } + memcpy(glyph_data, ¤t_glyph, sizeof(glyph_t)); + glyph_table[encoding] = glyph_data; + + // Reset things for next iteration + current_glyph.width = -1; + current_glyph.height = -1; + current_glyph.x = -1; + current_glyph.y = -1; + dwidth = -1; + encoding = -1; + } + } + return 0; +error: + // Free malloc()ed glyphs + free(glyph_data); + for(unsigned int i=0; i