Changeset 2414 for toilet


Ignore:
Timestamp:
Jun 15, 2008, 4:46:54 PM (11 years ago)
Author:
Sam Hocevar
Message:
  • Get rid of all the FIGlet font handling: everything is moving into libcucul.
Location:
toilet/trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • toilet/trunk/src/figlet.c

    r1461 r2414  
    3838static int end_figlet(context_t *);
    3939
    40 static int open_font(context_t *cx);
    41 static uint32_t hsmush(uint32_t, uint32_t, unsigned int);
    42 
    4340int init_figlet(context_t *cx)
    4441{
    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))
    4646        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         else
    72             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));
    8247
    8348    cx->feed = feed_figlet;
     
    9055static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
    9156{
    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);
    20858}
    20959
    21060static int flush_figlet(context_t *cx)
    21161{
    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);
    23263}
    23364
    23465static int end_figlet(context_t *cx)
    23566{
    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);
    24368}
    24469
    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 > 32767
    286         || ((cx->full_layout & 0x80) && (cx->full_layout & 0x3f) == 0
    287             && 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         else
    322         {
    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             else
    350                 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 any
    382      * 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  
    5050    cucul_canvas_t *cv;
    5151    char *line;
    52     unsigned int i, len;
     52    int i, len;
    5353
    5454    /* FIXME: we can't read longer lines */
     
    8181}
    8282
    83 int render_list(context_t *cx, unsigned int argc, char *argv[])
     83int render_list(context_t *cx, int argc, char *argv[])
    8484{
    8585    cucul_canvas_t *cv;
    86     unsigned int i, j, len;
     86    int i, j, len;
    8787    char *parser = NULL;
    8888
     
    130130    render_flush(cx);
    131131
     132    cucul_free_canvas(cv);
     133
    132134    return 0;
    133135}
     
    154156    filter_do(cx);
    155157
    156     cx->lines += cucul_get_canvas_height(cx->torender);
    157 
    158158    /* Output line */
    159     buffer = cucul_export_memory(cx->torender, cx->export, &len);
     159    buffer = cucul_export_memory(cx->cv, cx->export, &len);
    160160    if(!buffer)
    161161        return -1;
    162162    fwrite(buffer, len, 1, stdout);
    163163    free(buffer);
    164     cucul_free_canvas(cx->torender);
    165164
    166165    return 0;
  • toilet/trunk/src/render.h

    r1461 r2414  
    2222extern int render_init(context_t *);
    2323extern int render_stdin(context_t *);
    24 extern int render_list(context_t *, unsigned int, char *[]);
     24extern int render_list(context_t *, int, char *[]);
    2525extern int render_end(context_t *);
    2626
Note: See TracChangeset for help on using the changeset viewer.