- Timestamp:
- Jun 15, 2008, 4:46:54 PM (14 years ago)
- Location:
- toilet/trunk/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
toilet/trunk/src/figlet.c
r1461 r2414 38 38 static int end_figlet(context_t *); 39 39 40 static int open_font(context_t *cx);41 static uint32_t hsmush(uint32_t, uint32_t, unsigned int);42 43 40 int init_figlet(context_t *cx) 44 41 { 45 if(open_font(cx)) 42 char path[2048]; 43 44 snprintf(path, 2047, "%s/%s", cx->dir, cx->font); 45 if(cucul_canvas_set_figfont(cx->cv, path)) 46 46 return -1; 47 48 if(cx->full_layout & 0x3f)49 cx->hsmushrule = cx->full_layout & 0x3f;50 else if(cx->old_layout > 0)51 cx->hsmushrule = cx->old_layout;52 53 switch(cx->hmode)54 {55 case H_DEFAULT:56 if(cx->old_layout == -1)57 cx->hmode = H_NONE;58 else if(cx->old_layout == 0 && (cx->full_layout & 0xc0) == 0x40)59 cx->hmode = H_KERN;60 else if((cx->old_layout & 0x3f) && (cx->full_layout & 0x3f)61 && (cx->full_layout & 0x80))62 {63 cx->hmode = H_SMUSH;64 cx->hsmushrule = cx->full_layout & 0x3f;65 }66 else if(cx->old_layout == 0 && (cx->full_layout & 0xbf) == 0x80)67 {68 cx->hmode = H_SMUSH;69 cx->hsmushrule = 0x3f;70 }71 else72 cx->hmode = H_OVERLAP;73 break;74 default:75 break;76 }77 78 cx->charcv = cucul_create_canvas(cx->max_length - 2, cx->height);79 80 cx->left = malloc(cx->height * sizeof(int));81 cx->right = malloc(cx->height * sizeof(int));82 47 83 48 cx->feed = feed_figlet; … … 90 55 static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr) 91 56 { 92 unsigned int c, w, h, x, y, overlap, extra, xleft, xright; 93 94 switch(ch) 95 { 96 case (uint32_t)'\r': 97 return 0; 98 case (uint32_t)'\n': 99 cx->x = 0; 100 cx->y += cx->height; 101 return 0; 102 /* FIXME: handle '\t' */ 103 } 104 105 /* Look whether our glyph is available */ 106 for(c = 0; c < cx->glyphs; c++) 107 if(cx->lookup[c * 2] == ch) 108 break; 109 110 if(c == cx->glyphs) 111 return 0; 112 113 w = cx->lookup[c * 2 + 1]; 114 h = cx->height; 115 116 cucul_set_canvas_handle(cx->fontcv, 0, c * cx->height); 117 cucul_blit(cx->charcv, 0, 0, cx->fontcv, NULL); 118 119 /* Check whether we reached the end of the screen */ 120 if(cx->x && cx->x + w > cx->term_width) 121 { 122 cx->x = 0; 123 cx->y += h; 124 } 125 126 /* Compute how much the next character will overlap */ 127 switch(cx->hmode) 128 { 129 case H_SMUSH: 130 case H_KERN: 131 case H_OVERLAP: 132 extra = (cx->hmode == H_OVERLAP); 133 overlap = w; 134 for(y = 0; y < h; y++) 135 { 136 /* Compute how much spaces we can eat from the new glyph */ 137 for(xright = 0; xright < overlap; xright++) 138 if(cucul_get_char(cx->charcv, xright, y) != ' ') 139 break; 140 141 /* Compute how much spaces we can eat from the previous glyph */ 142 for(xleft = 0; xright + xleft < overlap && xleft < cx->x; xleft++) 143 if(cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y) != ' ') 144 break; 145 146 /* Handle overlapping */ 147 if(cx->hmode == H_OVERLAP && xleft < cx->x) 148 xleft++; 149 150 /* Handle smushing */ 151 if(cx->hmode == H_SMUSH) 152 { 153 if(xleft < cx->x && 154 hsmush(cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y), 155 cucul_get_char(cx->charcv, xright, y), 156 cx->hsmushrule)) 157 xleft++; 158 } 159 160 if(xleft + xright < overlap) 161 overlap = xleft + xright; 162 } 163 break; 164 case H_NONE: 165 overlap = 0; 166 break; 167 default: 168 return -1; 169 } 170 171 /* Check whether the current canvas is large enough */ 172 if(cx->x + w - overlap > cx->w) 173 cx->w = cx->x + w - overlap < cx->term_width 174 ? cx->x + w - overlap : cx->term_width; 175 176 if(cx->y + h > cx->h) 177 cx->h = cx->y + h; 178 179 if(attr) 180 cucul_set_attr(cx->cv, attr); 181 cucul_set_canvas_size(cx->cv, cx->w, cx->h); 182 183 /* Render our char (FIXME: create a rect-aware cucul_blit_canvas?) */ 184 for(y = 0; y < h; y++) 185 for(x = 0; x < w; x++) 186 { 187 uint32_t ch1, ch2; 188 //uint32_t tmpat = cucul_get_attr(cx->fontcv, x, y + c * cx->height); 189 ch2 = cucul_get_char(cx->charcv, x, y); 190 if(ch2 == ' ') 191 continue; 192 ch1 = cucul_get_char(cx->cv, cx->x + x - overlap, cx->y + y); 193 /* FIXME: this could be changed to cucul_put_attr() when the 194 * function is fixed in libcucul */ 195 //cucul_set_attr(cx->cv, tmpat); 196 if(ch1 == ' ' || cx->hmode != H_SMUSH) 197 cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y, ch2); 198 else 199 cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y, 200 hsmush(ch1, ch2, cx->hsmushrule)); 201 //cucul_put_attr(cx->cv, cx->x + x, cx->y + y, tmpat); 202 } 203 204 /* Advance cursor */ 205 cx->x += w - overlap; 206 207 return 0; 57 return cucul_put_figchar(cx->cv, ch); 208 58 } 209 59 210 60 static int flush_figlet(context_t *cx) 211 61 { 212 unsigned int x, y; 213 214 cx->torender = cx->cv; 215 cucul_set_canvas_size(cx->torender, cx->w, cx->h); 216 217 /* FIXME: do this somewhere else, or record hardblank positions */ 218 for(y = 0; y < cx->h; y++) 219 for(x = 0; x < cx->w; x++) 220 if(cucul_get_char(cx->torender, x, y) == 0xa0) 221 { 222 uint32_t attr = cucul_get_attr(cx->torender, x, y); 223 cucul_put_char(cx->torender, x, y, ' '); 224 cucul_put_attr(cx->torender, x, y, attr); 225 } 226 227 cx->x = cx->y = 0; 228 cx->w = cx->h = 0; 229 cx->cv = cucul_create_canvas(1, 1); 230 231 return 0; 62 return cucul_flush_figlet(cx->cv); 232 63 } 233 64 234 65 static int end_figlet(context_t *cx) 235 66 { 236 free(cx->left); 237 free(cx->right); 238 cucul_free_canvas(cx->charcv); 239 cucul_free_canvas(cx->fontcv); 240 free(cx->lookup); 241 242 return 0; 67 return cucul_canvas_set_figfont(cx->cv, NULL); 243 68 } 244 69 245 static int open_font(context_t *cx)246 {247 char *data = NULL;248 char path[2048];249 char buf[2048];250 char hardblank[10];251 TOIFILE *f;252 unsigned int i, j, size, comment_lines;253 254 /* Open font: try .tlf, then .flf */255 snprintf(path, 2047, "%s/%s.tlf", cx->dir, cx->font);256 path[2047] = '\0';257 f = toiopen(path, "r");258 if(!f)259 {260 snprintf(path, 2047, "%s/%s.flf", cx->dir, cx->font);261 path[2047] = '\0';262 f = toiopen(path, "r");263 if(!f)264 {265 fprintf(stderr, "font `%s' not found\n", path);266 return -1;267 }268 }269 270 /* Read header */271 cx->print_direction = 0;272 cx->full_layout = 0;273 cx->codetag_count = 0;274 toigets(buf, 2048, f);275 if(sscanf(buf, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank,276 &cx->height, &cx->baseline, &cx->max_length,277 &cx->old_layout, &comment_lines, &cx->print_direction,278 &cx->full_layout, &cx->codetag_count) < 6)279 {280 fprintf(stderr, "font `%s' has invalid header: %s\n", path, buf);281 toiclose(f);282 return -1;283 }284 285 if(cx->old_layout < -1 || cx->old_layout > 63 || cx->full_layout > 32767286 || ((cx->full_layout & 0x80) && (cx->full_layout & 0x3f) == 0287 && cx->old_layout))288 {289 fprintf(stderr, "font `%s' has invalid layout %i/%u\n",290 path, cx->old_layout, cx->full_layout);291 toiclose(f);292 return -1;293 }294 295 cx->hardblank = cucul_utf8_to_utf32(hardblank, NULL);296 297 /* Skip comment lines */298 for(i = 0; i < comment_lines; i++)299 toigets(buf, 2048, f);300 301 /* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223)302 * then read additional characters. */303 cx->glyphs = 0;304 cx->lookup = NULL;305 306 for(i = 0, size = 0; !toieof(f); cx->glyphs++)307 {308 if((cx->glyphs % 2048) == 0)309 cx->lookup = realloc(cx->lookup,310 (cx->glyphs + 2048) * 2 * sizeof(int));311 312 if(cx->glyphs < STD_GLYPHS)313 {314 cx->lookup[cx->glyphs * 2] = 32 + cx->glyphs;315 }316 else if(cx->glyphs < EXT_GLYPHS)317 {318 static int const tab[7] = { 196, 214, 220, 228, 246, 252, 223 };319 cx->lookup[cx->glyphs * 2] = tab[cx->glyphs - STD_GLYPHS];320 }321 else322 {323 if(toigets(buf, 2048, f) == NULL)324 break;325 326 /* Ignore blank lines, as in jacky.flf */327 if(buf[0] == '\n' || buf[0] == '\r')328 continue;329 330 /* Ignore negative indices for now, as in ivrit.flf */331 if(buf[0] == '-')332 {333 for(j = 0; j < cx->height; j++)334 toigets(buf, 2048, f);335 continue;336 }337 338 if(!buf[0] || buf[0] < '0' || buf[0] > '9')339 {340 free(data);341 free(cx->lookup);342 fprintf(stderr, "read error at glyph #%u in `%s'\n",343 cx->glyphs, path);344 return -1;345 }346 347 if(buf[1] == 'x')348 sscanf(buf, "%x", &cx->lookup[cx->glyphs * 2]);349 else350 sscanf(buf, "%u", &cx->lookup[cx->glyphs * 2]);351 }352 353 cx->lookup[cx->glyphs * 2 + 1] = 0;354 355 for(j = 0; j < cx->height; j++)356 {357 if(i + 2048 >= size)358 data = realloc(data, size += 2048);359 360 toigets(data + i, 2048, f);361 i = (uintptr_t)strchr(data + i, 0) - (uintptr_t)data;362 }363 }364 365 toiclose(f);366 367 if(cx->glyphs < EXT_GLYPHS)368 {369 free(data);370 free(cx->lookup);371 fprintf(stderr, "only %u glyphs in `%s', expected at least %u\n",372 cx->glyphs, path, EXT_GLYPHS);373 return -1;374 }375 376 /* Import buffer into canvas */377 cx->fontcv = cucul_create_canvas(0, 0);378 cucul_import_memory(cx->fontcv, data, i, "utf8");379 free(data);380 381 /* Remove EOL characters. For now we ignore hardblanks, don’t do any382 * smushing, nor any kind of error checking. */383 for(j = 0; j < cx->height * cx->glyphs; j++)384 {385 unsigned long int ch, oldch = 0;386 387 for(i = cx->max_length; i--;)388 {389 ch = cucul_get_char(cx->fontcv, i, j);390 391 /* Replace hardblanks with U+00A0 NO-BREAK SPACE */392 if(ch == cx->hardblank)393 cucul_put_char(cx->fontcv, i, j, ch = 0xa0);394 395 if(oldch && ch != oldch)396 {397 if(!cx->lookup[j / cx->height * 2 + 1])398 cx->lookup[j / cx->height * 2 + 1] = i + 1;399 }400 else if(oldch && ch == oldch)401 cucul_put_char(cx->fontcv, i, j, ' ');402 else if(ch != ' ')403 {404 oldch = ch;405 cucul_put_char(cx->fontcv, i, j, ' ');406 }407 }408 }409 410 return 0;411 }412 413 static uint32_t hsmush(uint32_t ch1, uint32_t ch2, unsigned int rule)414 {415 /* Rule 1 */416 if((rule & 0x01) && ch1 == ch2 && ch1 != 0xa0)417 return ch2;418 419 if(ch1 < 0x80 && ch2 < 0x80)420 {421 char const charlist[] = "|/\\[]{}()<>";422 char *tmp1, *tmp2;423 424 /* Rule 2 */425 if(rule & 0x02)426 {427 if(ch1 == '_' && strchr(charlist, ch2))428 return ch2;429 430 if(ch2 == '_' && strchr(charlist, ch1))431 return ch1;432 }433 434 /* Rule 3 */435 if((rule & 0x04) &&436 (tmp1 = strchr(charlist, ch1)) && (tmp2 = strchr(charlist, ch2)))437 {438 int cl1 = (tmp1 + 1 - charlist) / 2;439 int cl2 = (tmp2 + 1 - charlist) / 2;440 441 if(cl1 < cl2)442 return ch2;443 if(cl1 > cl2)444 return ch1;445 }446 447 /* Rule 4 */448 if(rule & 0x08)449 {450 uint16_t s = ch1 + ch2;451 uint16_t p = ch1 * ch2;452 453 if(p == 15375 /* '{' * '}' */454 || p == 8463 /* '[' * ']' */455 || (p == 1640 && s == 81)) /* '(' *|+ ')' */456 return '|';457 }458 459 /* Rule 5 */460 if(rule & 0x10)461 {462 switch((ch1 << 8) | ch2)463 {464 case 0x2f5c: return '|'; /* /\ */465 case 0x5c2f: return 'Y'; /* \/ */466 case 0x3e3c: return 'X'; /* >< */467 }468 }469 470 /* Rule 6 */471 if((rule & 0x20) && ch1 == ch2 && ch1 == 0xa0)472 return 0xa0;473 }474 475 return 0;476 }477 -
toilet/trunk/src/render.c
r1461 r2414 50 50 cucul_canvas_t *cv; 51 51 char *line; 52 unsignedint i, len;52 int i, len; 53 53 54 54 /* FIXME: we can't read longer lines */ … … 81 81 } 82 82 83 int render_list(context_t *cx, unsignedint argc, char *argv[])83 int render_list(context_t *cx, int argc, char *argv[]) 84 84 { 85 85 cucul_canvas_t *cv; 86 unsignedint i, j, len;86 int i, j, len; 87 87 char *parser = NULL; 88 88 … … 130 130 render_flush(cx); 131 131 132 cucul_free_canvas(cv); 133 132 134 return 0; 133 135 } … … 154 156 filter_do(cx); 155 157 156 cx->lines += cucul_get_canvas_height(cx->torender);157 158 158 /* Output line */ 159 buffer = cucul_export_memory(cx-> torender, cx->export, &len);159 buffer = cucul_export_memory(cx->cv, cx->export, &len); 160 160 if(!buffer) 161 161 return -1; 162 162 fwrite(buffer, len, 1, stdout); 163 163 free(buffer); 164 cucul_free_canvas(cx->torender);165 164 166 165 return 0; -
toilet/trunk/src/render.h
r1461 r2414 22 22 extern int render_init(context_t *); 23 23 extern int render_stdin(context_t *); 24 extern int render_list(context_t *, unsignedint, char *[]);24 extern int render_list(context_t *, int, char *[]); 25 25 extern int render_end(context_t *); 26 26
Note: See TracChangeset
for help on using the changeset viewer.