diff options
author | jaseg <jaseg@jaseg.net> | 2014-03-07 00:49:16 +0100 |
---|---|---|
committer | jaseg <jaseg@jaseg.net> | 2014-03-07 00:49:16 +0100 |
commit | d16223fd257ccc1d7060e372eb3d950cf68f8d37 (patch) | |
tree | 6484e177faff92ed77b2f91acaadaba33131b44d /host/main.c | |
parent | 7878aa1d455ab24d0336fc68eb09f726bcba10b2 (diff) | |
download | matelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.tar.gz matelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.tar.bz2 matelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.zip |
Modified text rendering to something frame based
Diffstat (limited to 'host/main.c')
-rw-r--r-- | host/main.c | 356 |
1 files changed, 0 insertions, 356 deletions
diff --git a/host/main.c b/host/main.c deleted file mode 100644 index d8cb371..0000000 --- a/host/main.c +++ /dev/null @@ -1,356 +0,0 @@ - -#include "config.h" -#include "main.h" -#include "color.h" -#include "font.h" -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <wchar.h> -#include <locale.h> -#include <sys/timeb.h> -#include <sys/queue.h> -#include <netdb.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <unistd.h> - - -void free_framebuffer(framebuffer_t *fb){ - free(fb->data); - free(fb); -} - -/* CAUTION: REQUIRES INPUT TO BE \0-TERMINATED - * ...also, it does a hardcoded setlocale of LC_CTYPE to en_US.utf8 for... reasons. */ -framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){ - unsigned int len = strlen(s); - - color_t *gbuf = NULL; - unsigned int gbufwidth = 0; - unsigned int gbufheight = 0; - char *p = s; - - /* Calculate screen width of string prior to allocating memory for the frame buffer */ - wchar_t c; - mbstate_t ps = {0}; - memset(&ps, 0, sizeof(mbstate_t)); - if(!setlocale(LC_CTYPE, "en_US.utf8")){ - fprintf(stderr, "Cannot set locale\n"); - goto error; - } - for(;;){ - while(*p == '\033'){ - p++; - /* Jump over escape sequences */ - for(;;p++){ - if(!(*p == ';' || *p == '[' || ('0' <= *p && *p <= '9'))){ - p++; - break; - } - } - memset(&ps, 0, sizeof(mbstate_t)); - } - - size_t inc = mbrtowc(&c, p, MB_CUR_MAX, &ps); /* MB_CUR_MAX is safe since p is \0-terminated */ - if(inc == -1 || inc == -2){ - fprintf(stderr, "Error rendering string: No valid UTF-8 input.\n"); - goto error; - } - if(inc == 0) /* Reached end of string */ - break; - p += inc; - - if(c > glyph_table->size){ - fprintf(stderr, "Error rendering string: Codepoint 0x%lx out of valid range (0-%zd).\n", (long int)c, glyph_table->size); - goto error; - } - - glyph_t *g = glyph_table->data[c]; - if(!g){ - fprintf(stderr, "Error rendering string: Codepoint 0x%lx not in font.\n", (long int)c); - goto error; - } - - if(g->height > gbufheight) - gbufheight = g->height; - - - gbufwidth += g->width; - } - /* For easier rendering on the terminal, round up to multiples of two */ - gbufheight += gbufheight&1; - - size_t gbufsize = gbufwidth*gbufheight; - gbuf = calloc(gbufsize, sizeof(color_t)); - if(!gbuf){ - fprintf(stderr, "Cannot malloc() %zu bytes.\n", gbufsize*sizeof(color_t)); - goto error; - } - memset(gbuf, 0, gbufsize*sizeof(color_t)); - - unsigned int x = 0; - p = s; - memset(&ps, 0, sizeof(mbstate_t)); - struct { - color_t fg; - color_t bg; - unsigned int blink:4; - unsigned int bold:1; /* TODO */ - unsigned int underline:1; - unsigned int strikethrough:1; - unsigned int fraktur:1; /* TODO See: Flat10 Fraktur font */ - unsigned int invert:1; - } style = { - colortable[DEFAULT_FG_COLOR], colortable[DEFAULT_BG_COLOR], 0, 0, 0, 0, 0, 0 - }; - /* Render glyphs (now with escape sequence rendering!) */ - for(;;){ - /* NOTE: This nested escape sequence parsing does not contain any unicode-awareness whatsoever */ - if(*p == '\033'){ /* Escape sequence YAY */ - char *sequence_start = ++p; - if(*p == '['){ /* This was a CSI! */ - /* Disassemble the list of numbers, only accept SGR sequences (those ending with 'm') */ - long elems[MAX_CSI_ELEMENTS]; - int nelems; - for(nelems = 0; nelems<MAX_CSI_ELEMENTS; nelems++){ - p++; - char *endptr; - elems[nelems] = strtol(p, &endptr, 10); - if(p == endptr){ - fprintf(stderr, "Invalid escape sequence: \"\\e%s\"\n", sequence_start); - goto error; - } - p = endptr; - if(*endptr == 'm') - break; - if(*endptr != ';'){ - fprintf(stderr, "Invalid escape sequence: \"\\e%s\"\n", sequence_start); - goto error; - } - } - p++; /* gobble up trailing 'm' of "\033[23;42m" */ - nelems++; - /* By now we know it's a SGR since we error'ed out on anything else */ - if(nelems < 1){ - fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); - goto error; - } - /* Parse the sequence numbers */ - for(int i=0; i<nelems; i++){ - switch(elems[i]){ - case 0: /* reset style */ - style.fg = colortable[DEFAULT_FG_COLOR]; - style.bg = colortable[DEFAULT_BG_COLOR]; - style.bold = 0; - style.underline = 0; - style.blink = 0; - style.strikethrough = 0; - style.fraktur = 0; - style.invert = 0; - break; - case 1: /* bold */ - style.bold = 1; - break; - case 4: /* underline */ - style.underline = 1; - break; - case 5: /* slow blink */ - style.blink = 1; - break; - case 6: /* rapid blink */ - style.blink = 8; - break; - case 7: /* color invert on */ - style.invert = 1; - break; - case 9: /* strike-through */ - style.strikethrough = 1; - break; - case 20:/* Fraktur */ - style.fraktur = 1; - break; - case 22:/* Bold off */ - style.bold = 0; - break; - case 24:/* Underline off */ - style.underline = 0; - break; - case 25:/* Blink off */ - style.blink = 0; - break; - case 27:/* color invert off */ - style.invert = 0; - break; - case 29:/* strike-through off */ - style.strikethrough = 0; - break; - case 30: /* Set foreground color, "dim" colors */ - case 31: - case 32: - case 33: - case 34: - case 35: - case 36: - case 37: - style.fg = colortable[elems[i]-30]; - break; - case 38: /* Set xterm-256 foreground color */ - i++; - if(nelems-i < 2 || elems[i] != 5){ - fprintf(stderr, "Invalid ANSI escape code: \"\\e%s\"\n", sequence_start); - goto error; - } - style.fg = colortable[elems[++i]]; - break; - case 39: /* Reset foreground color to default */ - style.bg = colortable[DEFAULT_FG_COLOR]; - break; - case 40: /* Set background color, "dim" colors */ - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - style.bg = colortable[elems[i]-40]; - break; - case 48: /* Set xterm-256 background color */ - i++; - if(nelems-i < 2 || elems[i] != 5){ - fprintf(stderr, "Invalid ANSI escape code: \"\\e%s\"\n", sequence_start); - goto error; - } - style.bg = colortable[elems[++i]]; - break; - case 49: /* Reset background color to default */ - style.bg = colortable[DEFAULT_BG_COLOR]; - break; - case 90: /* Set foreground color, "bright" colors */ - case 91: - case 92: - case 93: - case 94: - case 95: - case 96: - case 97: - style.fg = colortable[elems[i]-90+8]; - break; - case 100: /* Set background color, "bright" colors */ - case 101: - case 102: - case 103: - case 104: - case 105: - case 106: - case 107: - style.bg = colortable[elems[i]-100+8]; - break; - default: - fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); - goto error; - } - } - - }else{ - fprintf(stderr, "Unsupported escape sequence: \"\\e%s\"\n", sequence_start); - goto error; - } - - continue; - } - - size_t inc = mbrtowc(&c, p, (s+len+1)-p, NULL); - /* If p contained */ - if(inc == 0) /* Reached end of string */ - break; - p += inc; - - /* Render glyph into frame buffer */ - struct timeb time = {0}; - ftime(&time); - unsigned long int t = time.time*1000 + time.millitm; - int blink = style.blink && (t % (1000/style.blink) < (333/style.blink)); - int inv = !(style.invert ^ blink); - color_t fg = inv ? style.fg : style.bg; - color_t bg = inv ? style.bg : style.fg; - - glyph_t *g = glyph_table->data[c]; - render_glyph(g, gbuf, gbufwidth, x, 0, fg, bg); - if(style.strikethrough || style.underline){ - int sty = gbufheight/2; - /* g->y usually is a negative index of the glyph's baseline measured from the glyph's bottom */ - int uly = gbufheight + g->y; - for(int i=0; i<g->width; i++){ - if(style.strikethrough) - gbuf[sty*gbufwidth + x + i] = fg; - if(style.underline) - gbuf[uly*gbufwidth + x + i] = fg; - } - } - x += g->width; - } - framebuffer_t *fb = malloc(sizeof(framebuffer_t)); - if(!fb){ - fprintf(stderr, "Cannot malloc() %zu bytes.\n", sizeof(framebuffer_t)); - goto error; - } - fb->w = gbufwidth; - fb->h = gbufheight; - fb->data = gbuf; - return fb; -error: - free(gbuf); - return 0; -} - -void console_render_buffer(color_t *data, size_t w, size_t h){ - /* Render framebuffer to terminal, two pixels per character using Unicode box drawing stuff */ - color_t lastfg = {0, 0, 0}, lastbg = {0, 0, 0}; - printf("\e[38;5;0;48;5;0m\e[K"); - for(size_t y=0; y < h; y+=2){ - for(size_t x=0; x < w; x++){ - /* Da magicks: ▀█▄ */ - color_t ct = data[y*w + x]; /* Top pixel */ - color_t cb = data[(y+1)*w + x]; /* Bottom pixel */ - /* The following, rather convoluted logic tries to "save" escape sequences when rendering. */ - if(!memcmp(&ct, &lastfg, sizeof(color_t))){ - if(!memcmp(&cb, &lastbg, sizeof(color_t))){ - printf("▀"); - }else if(!memcmp(&cb, &lastfg, sizeof(color_t))){ - printf("█"); - }else{ - printf("\033[48;5;%dm▀", xterm_color_index(cb)); - lastbg = cb; - } - }else if(!memcmp(&ct, &lastbg, sizeof(color_t))){ - if(!memcmp(&cb, &lastfg, sizeof(color_t))){ - printf("▄"); - }else if(!memcmp(&cb, &lastbg, sizeof(color_t))){ - printf(" "); - }else{ - printf("\033[38;5;%dm▄", xterm_color_index(cb)); - lastfg = cb; - } - }else{ /* No matches for the upper pixel */ - if(!memcmp(&cb, &lastfg, sizeof(color_t))){ - printf("\033[48;5;%dm▄", xterm_color_index(ct)); - lastbg = ct; - }else if(!memcmp(&cb, &lastbg, sizeof(color_t))){ - printf("\033[38;5;%dm▀", xterm_color_index(ct)); - lastfg = ct; - }else{ - printf("\033[38;5;%d;48;5;%dm▀", xterm_color_index(ct), xterm_color_index(cb)); - lastfg = ct; - lastbg = cb; - } - } - } - printf("\n\e[K"); - } - printf("\033[0m"); -} - |