#include #include #include #define BUF_SIZE 100 typedef struct font { char *name, ic; int width; int height; int numsegs; char ***segs; int *segx, *segy; int **map, **move; } font; void merge(char **out, int outw, int outh, font *fnt, int sn, int x, int y) { int x2, y2, x3, y3; y2 = 0; while(fnt->segs[sn][y2]) { x2 = 0; while(fnt->segs[sn][y2][x2]) { x3 = x + x2 + fnt->segx[sn]; y3 = y + y2 + fnt->segy[sn]; if(x3 < 0 || x3 >= outw || y3 < 0 || y3 >= outh) { fprintf(stderr, "Attempt to draw outside buffer: %d, %d of %dx%d (char %d, %d) (in %d, %d).\n", x3, y3, outw, outh, x2, y2, x, y); exit(1); } if(fnt->segs[sn][y2][x2] != ' ') out[y3][x3] = fnt->segs[sn][y2][x2]; x2++; } y2++; } } int main(int argc, char **argv) { FILE *f; int mode = 0, numfonts = 0, sn, lines, fn, mc, nm, t, u, inc, inlen, mv, posx, posy, hadmove, outw, outh; char buf[BUF_SIZE], *del, *bp, *in, **out; font *fonts = NULL; f = fopen("7segfont.txt", "r"); while(!feof(f)) { fgets(buf, BUF_SIZE-2, f); if(feof(f)) break; if(!strtok(buf, "\r\n")) continue; if(!strlen(buf)) continue; if(0) fprintf(stderr, "Read: %s\n", buf); switch(mode) { case 0: fonts = realloc(fonts, sizeof(font) * (numfonts + 1)); bp = strtok(buf, " "); if(!strlen(bp)) { fprintf(stderr, "Unable to read font name.\n"); exit(1); } fonts[numfonts].name = strdup(bp); bp = strtok(NULL, " "); fonts[numfonts].numsegs = atol(bp); bp = strtok(NULL, "x"); fonts[numfonts].width = atol(bp); bp = strtok(NULL, ""); fonts[numfonts].height = atol(bp); fprintf(stderr, "Loading font '%s' with %d segments using %d by %d characters.\n", fonts[numfonts].name, fonts[numfonts].numsegs, fonts[numfonts].width, fonts[numfonts].height); fonts[numfonts].segs = malloc(sizeof(char **) * fonts[numfonts].numsegs); fonts[numfonts].segx = malloc(sizeof(int) * fonts[numfonts].numsegs); fonts[numfonts].segy = malloc(sizeof(int) * fonts[numfonts].numsegs); fonts[numfonts].map = malloc(sizeof(int *) * 256); fonts[numfonts].move = malloc(sizeof(int *) * 256); for(t = 0; t < 256; t++) fonts[numfonts].map[t] = NULL; mode = 1; break; case 1: bp = strtok(buf, " "); sn = atol(bp) - 1; if(sn < 0 || sn >= fonts[numfonts].numsegs) { fprintf(stderr, "Attempted to read segment %d of %d. D'oh!\n", sn + 1, fonts[numfonts].numsegs); exit(1); } bp = strtok(NULL, ","); fonts[numfonts].segx[sn] = atol(bp); bp = strtok(NULL, ""); fonts[numfonts].segy[sn] = atol(bp); fonts[numfonts].segs[sn] = NULL; fprintf(stderr, "Loading segment %d, offset (%d,%d).\n", sn + 1, fonts[numfonts].segx[sn], fonts[numfonts].segy[sn]); lines = 0; mode = 2; break; case 2: del = strdup(buf); fprintf(stderr, "Delimiter line is '%s'.\n", del); mode = 3; break; case 3: if(!strcmp(buf, del)) { fprintf(stderr, "Delimiter line found, ending segment.\n"); free(del); fonts[numfonts].segs[sn] = realloc(fonts[numfonts].segs[sn], sizeof(char *) * (lines + 1)); fonts[numfonts].segs[sn][lines] = NULL; if(sn == fonts[numfonts].numsegs - 1) { fprintf(stderr, "Done loading segments for font '%s'.\n", fonts[numfonts].name); mode = 4; } else { mode = 1; } break; } fonts[numfonts].segs[sn] = realloc(fonts[numfonts].segs[sn], sizeof(char *) * (lines + 1)); fonts[numfonts].segs[sn][lines] = strdup(buf); fprintf(stderr, "Line %d is '%s'.\n", lines, fonts[numfonts].segs[sn][lines]); lines++; break; case 4: if(!strcmp(buf, "map")) { fprintf(stderr, "Starting to read map.\n"); mode = 5; break; } fprintf(stderr, "Map not found?\n"); exit(1); case 5: if(!strcmp(buf, "endmap")) { fprintf(stderr, "Done reading map, done reading font '%s'.\n", fonts[numfonts].name); numfonts++; mode = 0; break; } if(*buf != ':') bp = strtok(buf, " :"); else bp = strtok(buf, " "); if(!bp) { fprintf(stderr, "Map character not found.\n"); exit(1); } mc = *bp; fprintf(stderr, "Reading map for '%c':", mc); nm = 0; while(bp = strtok(NULL, " :,")) { if(!strlen(bp)) continue; mv = 0; if(*bp == '-') { mv = -1; bp++; } else if(*bp == '+') { mv = 1; bp++; } if(!strlen(bp)) continue; sn = atol(bp) - 1; if(sn < 0 || sn >= fonts[numfonts].numsegs) { fprintf(stderr, "Map has '%d' of '%d'. D'oh.\n", sn, fonts[numfonts].numsegs); exit(1); } fonts[numfonts].map[mc] = realloc(fonts[numfonts].map[mc], sizeof(int) * (nm + 2)); fonts[numfonts].move[mc] = realloc(fonts[numfonts].move[mc], sizeof(int) * (nm + 2)); fonts[numfonts].map[mc][nm] = sn; fonts[numfonts].move[mc][nm] = mv; nm++; fonts[numfonts].map[mc][nm] = -1; fprintf(stderr, " (%d)%d", mv, sn + 1); } fprintf(stderr, "\n"); break; } } if(mode != 0) { fprintf(stderr, "End of input file reached before end of font reached?\n"); } if(argc < 3) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } for(fn = 0; fn < numfonts; fn++) { if(!strcmp(argv[1], fonts[fn].name)) break; } if(fn == numfonts) { fprintf(stderr, "Unable to find font '%s'.\n", argv[1]); exit(1); } fprintf(stderr, "Building string with font '%s', #%d.\n", argv[1], fn); in = strdup(argv[2]); inlen = strlen(in); if(inlen <= 0) { fprintf(stderr, "Null input?\n"); exit(1); } outh = 0; outw = 0; t = 0; for(inc = 0; inc < inlen; inc++) { if(t == 0) outh += fonts[fn].height; if(in[inc] == '\n') { t = 0; continue; } t += fonts[fn].width; if(t > outw) outw = t; } out = malloc(sizeof(char *) * outh); for(t = 0; t < outh; t++) { out[t] = malloc(sizeof(char) * outw + 1); for(u = 0; u < outw; u++) out[t][u] = ' '; out[t][u] = '\x0'; } posx = 0; posy = 0; for(inc = 0; inc < inlen; inc++) { if(0) fprintf(stderr, "Processing '%c'.\n", in[inc]); if(in[inc] == '\n') { posy++; posx = 0; continue; } if(in[inc] == ' ') { posx++; continue; } if(!fonts[fn].map[in[inc]]) { fprintf(stderr, "No map found for '%c', skipping.\n", in[inc]); posx++; continue; } nm = 0; hadmove = 0; while((sn = fonts[fn].map[in[inc]][nm]) >= 0) { if(0) fprintf(stderr, "Adding segment %d, offset %d.\n", sn, fonts[fn].move[in[inc]][nm]); merge(out, outw, outh, &(fonts[fn]), sn, (posx + fonts[fn].move[in[inc]][nm]) * fonts[fn].width, posy * fonts[fn].height); if(fonts[fn].move[in[inc]][nm] != 0) hadmove++; nm++; } if(!hadmove) posx++; } for(t = 0; t < outh; t++) { u = outw; while(u >=0 && (out[t][u] == ' ' || out[t][u] == '\x0')) { out[t][u] = '\x0'; u--; } printf("%s\n", out[t]); } return 0; }