Changeset 1196 for toilet


Ignore:
Timestamp:
Oct 10, 2006, 9:20:15 AM (14 years ago)
Author:
Sam Hocevar
Message:
  • Fixed the FIGlet renderer. It now has char wrapping and stdin input.
Location:
toilet/trunk/src
Files:
4 edited

Legend:

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

    r1193 r1196  
    3232#define EXT_GLYPHS (STD_GLYPHS + 7)
    3333
    34 struct figfont
    35 {
    36     /* From the font format */
    37     unsigned long int hardblank;
    38     unsigned int height, baseline, max_length;
    39     int old_layout;
    40     unsigned int print_direction, full_layout, codetag_count;
    41 
    42     unsigned int glyphs;
    43     cucul_canvas_t *image;
    44     unsigned int *lookup;
    45 };
    46 
    47 static struct figfont *open_font(context_t *cx);
    48 static void free_font(struct figfont *);
    49 
    50 cucul_canvas_t *render_figlet(context_t *cx, uint32_t const *string,
    51                               unsigned int length)
    52 {
    53     cucul_canvas_t *cv;
    54     struct figfont *font;
    55     unsigned int x, i, c;
    56 
    57     font = open_font(cx);
    58 
    59     if(!font)
    60         return NULL;
    61 
    62     cv = cucul_create_canvas(length * font->max_length, font->height);
    63 
    64     for(x = 0, i = 0; i < length; i++)
    65     {
    66         for(c = 0; c < font->glyphs; c++)
    67             if(font->lookup[c * 2] == string[i])
    68                 break;
    69 
    70         if(c == font->glyphs)
    71             continue;
    72 
    73         cucul_blit(cv, x, - (int)(c * font->height), font->image, NULL);
    74 
    75         x += font->lookup[c * 2 + 1];
    76     }
    77 
    78     cucul_set_canvas_boundaries(cv, 0, 0, x, font->height);
    79 
    80     free_font(font);
    81 
    82     return cv;
    83 }
    84 
    85 static struct figfont *open_font(context_t *cx)
     34static int feed_figlet(context_t *, uint32_t);
     35static int end_figlet(context_t *);
     36
     37static int open_font(context_t *cx);
     38
     39int init_figlet(context_t *cx)
     40{
     41    if(open_font(cx))
     42        return -1;
     43
     44    cx->x = cx->y = 0;
     45    cx->w = cx->h = 0;
     46    cx->cv = cucul_create_canvas(1, 1);
     47
     48    cx->feed = feed_figlet;
     49    cx->end = end_figlet;
     50
     51    return 0;
     52}
     53
     54static int feed_figlet(context_t *cx, uint32_t ch)
     55{
     56    unsigned int c, w, h, x, y;
     57
     58    switch(ch)
     59    {
     60        case (uint32_t)'\r':
     61            return 0;
     62        case (uint32_t)'\n':
     63            cx->x = 0;
     64            cx->y += cx->height;
     65            return 0;
     66        /* FIXME: handle '\t' */
     67    }
     68
     69    /* Look whether our glyph is available */
     70    for(c = 0; c < cx->glyphs; c++)
     71        if(cx->lookup[c * 2] == ch)
     72            break;
     73
     74    if(c == cx->glyphs)
     75        return 0;
     76
     77    w = cx->lookup[c * 2 + 1];
     78    h = cx->height;
     79
     80    /* Check whether we reached the end of the screen */
     81    if(cx->x && cx->x + w > cx->term_width)
     82    {
     83        cx->x = 0;
     84        cx->y += h;
     85    }
     86
     87    /* Check whether the current canvas is large enough */
     88    if(cx->x + w > cx->w)
     89        cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width;
     90
     91    if(cx->y + h > cx->h)
     92        cx->h = cx->y + h;
     93
     94    cucul_set_canvas_size(cx->cv, cx->w, cx->h);
     95
     96    /* Render our char (FIXME: create a rect-aware cucul_blit_canvas?) */
     97    for(y = 0; y < h; y++)
     98        for(x = 0; x < w; x++)
     99    {
     100        uint32_t tmp = cucul_getchar(cx->image, x, y + c * cx->height);
     101        cucul_putchar(cx->cv, cx->x + x, cx->y + y, tmp);
     102    }
     103
     104    /* Advance cursor */
     105    cx->x += w;
     106
     107    return 0;
     108}
     109
     110static int end_figlet(context_t *cx)
     111{
     112    cucul_free_canvas(cx->image);
     113    free(cx->lookup);
     114
     115    return 0;
     116}
     117
     118static int open_font(context_t *cx)
    86119{
    87120    char *data = NULL;
    88121    char path[2048];
    89122    char hardblank[10];
    90     struct figfont *font;
    91123    cucul_buffer_t *b;
    92124    FILE *f;
     
    105137        {
    106138            fprintf(stderr, "font `%s' not found\n", path);
    107             return NULL;
    108         }
    109     }
    110 
    111     font = malloc(sizeof(struct figfont));
     139            return -1;
     140        }
     141    }
    112142
    113143    /* Read header */
    114     font->print_direction = 0;
    115     font->full_layout = 0;
    116     font->codetag_count = 0;
     144    cx->print_direction = 0;
     145    cx->full_layout = 0;
     146    cx->codetag_count = 0;
    117147    if(fscanf(f, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank,
    118               &font->height, &font->baseline, &font->max_length,
    119               &font->old_layout, &comment_lines, &font->print_direction,
    120               &font->full_layout, &font->codetag_count) < 6)
     148              &cx->height, &cx->baseline, &cx->max_length,
     149              &cx->old_layout, &comment_lines, &cx->print_direction,
     150              &cx->full_layout, &cx->codetag_count) < 6)
    121151    {
    122152        fprintf(stderr, "font `%s' has invalid header\n", path);
    123         free(font);
    124153        fclose(f);
    125         return NULL;
    126     }
    127 
    128     font->hardblank = cucul_utf8_to_utf32(hardblank, NULL);
     154        return -1;
     155    }
     156
     157    cx->hardblank = cucul_utf8_to_utf32(hardblank, NULL);
    129158
    130159    /* Skip comment lines */
     
    137166    /* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223)
    138167     * then read additional characters. */
    139     font->glyphs = 0;
    140     font->lookup = NULL;
    141 
    142     for(i = 0, size = 0; !feof(f); font->glyphs++)
    143     {
    144         if((font->glyphs % 2048) == 0)
    145             font->lookup = realloc(font->lookup,
    146                                    (font->glyphs + 2048) * 2 * sizeof(int));
    147 
    148         if(font->glyphs < STD_GLYPHS)
    149         {
    150             font->lookup[font->glyphs * 2] = 32 + font->glyphs;
    151         }
    152         else if(font->glyphs < EXT_GLYPHS)
     168    cx->glyphs = 0;
     169    cx->lookup = NULL;
     170
     171    for(i = 0, size = 0; !feof(f); cx->glyphs++)
     172    {
     173        if((cx->glyphs % 2048) == 0)
     174            cx->lookup = realloc(cx->lookup,
     175                                   (cx->glyphs + 2048) * 2 * sizeof(int));
     176
     177        if(cx->glyphs < STD_GLYPHS)
     178        {
     179            cx->lookup[cx->glyphs * 2] = 32 + cx->glyphs;
     180        }
     181        else if(cx->glyphs < EXT_GLYPHS)
    153182        {
    154183            static int const tab[7] = { 196, 214, 220, 228, 246, 252, 223 };
    155             font->lookup[font->glyphs * 2] = tab[font->glyphs - STD_GLYPHS];
     184            cx->lookup[cx->glyphs * 2] = tab[cx->glyphs - STD_GLYPHS];
    156185        }
    157186        else
     
    166195            {
    167196                free(data);
    168                 free(font->lookup);
    169                 free(font);
     197                free(cx->lookup);
    170198                fprintf(stderr, "read error at glyph %u in `%s'\n",
    171                                 font->glyphs, path);
    172                 return NULL;
     199                                cx->glyphs, path);
     200                return -1;
    173201            }
    174202
    175203            if(number[1] == 'x')
    176                 sscanf(number, "%x", &font->lookup[font->glyphs * 2]);
     204                sscanf(number, "%x", &cx->lookup[cx->glyphs * 2]);
    177205            else
    178                 sscanf(number, "%u", &font->lookup[font->glyphs * 2]);
     206                sscanf(number, "%u", &cx->lookup[cx->glyphs * 2]);
    179207
    180208            fscanf(f, "%*c");
    181209        }
    182210
    183         font->lookup[font->glyphs * 2 + 1] = 0;
    184 
    185         for(j = 0; j < font->height; j++)
     211        cx->lookup[cx->glyphs * 2 + 1] = 0;
     212
     213        for(j = 0; j < cx->height; j++)
    186214        {
    187215            if(i + 2048 >= size)
     
    195223    fclose(f);
    196224
    197     if(font->glyphs < EXT_GLYPHS)
     225    if(cx->glyphs < EXT_GLYPHS)
    198226    {
    199227        free(data);
    200         free(font->lookup);
    201         free(font);
     228        free(cx->lookup);
    202229        fprintf(stderr, "only %u glyphs in `%s', expected at least %u\n",
    203                         font->glyphs, path, EXT_GLYPHS);
    204         return NULL;
     230                        cx->glyphs, path, EXT_GLYPHS);
     231        return -1;
    205232    }
    206233
    207234    /* Import buffer into canvas */
    208235    b = cucul_load_memory(data, i);
    209     font->image = cucul_import_canvas(b, "utf8");
     236    cx->image = cucul_import_canvas(b, "utf8");
    210237    cucul_free_buffer(b);
    211238    free(data);
    212239
    213     if(!font->image)
    214     {
    215         free(font->lookup);
    216         free(font);
     240    if(!cx->image)
     241    {
     242        free(cx->lookup);
    217243        fprintf(stderr, "libcucul could not load data in `%s'\n", path);
    218         return NULL;
     244        return -1;
    219245    }
    220246
    221247    /* Remove EOL characters. For now we ignore hardblanks, don’t do any
    222248     * smushing, nor any kind of error checking. */
    223     for(j = 0; j < font->height * font->glyphs; j++)
     249    for(j = 0; j < cx->height * cx->glyphs; j++)
    224250    {
    225251        unsigned long int ch, oldch = 0;
    226252
    227         for(i = font->max_length; i--;)
    228         {
    229             ch = cucul_getchar(font->image, i, j);
    230 
    231             /* Replace hardblanks with U+00A0 NO-BREAK SPACE */
    232             if(ch == font->hardblank)
    233                 cucul_putchar(font->image, i, j, ch = ' ');
    234                 //cucul_putchar(font->image, i, j, ch = 0xa0);
     253        for(i = cx->max_length; i--;)
     254        {
     255            ch = cucul_getchar(cx->image, i, j);
     256
     257            /* TODO: Replace hardblanks with U+00A0 NO-BREAK SPACE */
     258            if(ch == cx->hardblank)
     259                cucul_putchar(cx->image, i, j, ch = ' ');
     260                //cucul_putchar(cx->image, i, j, ch = 0xa0);
    235261
    236262            if(oldch && ch != oldch)
    237263            {
    238                 if(!font->lookup[j / font->height * 2 + 1])
    239                     font->lookup[j / font->height * 2 + 1] = i + 1;
     264                if(!cx->lookup[j / cx->height * 2 + 1])
     265                    cx->lookup[j / cx->height * 2 + 1] = i + 1;
    240266            }
    241267            else if(oldch && ch == oldch)
    242                 cucul_putchar(font->image, i, j, ' ');
     268                cucul_putchar(cx->image, i, j, ' ');
    243269            else if(ch != ' ')
    244270            {
    245271                oldch = ch;
    246                 cucul_putchar(font->image, i, j, ' ');
     272                cucul_putchar(cx->image, i, j, ' ');
    247273            }
    248274        }
    249275    }
    250276
    251     return font;
    252 }
    253 
    254 static void free_font(struct figfont *font)
    255 {
    256     cucul_free_canvas(font->image);
    257     free(font->lookup);
    258     free(font);
    259 }
    260 
     277    return 0;
     278}
     279
  • toilet/trunk/src/figlet.h

    r1193 r1196  
    1515 * This header defines functions for handling FIGlet fonts.
    1616 */
    17 extern cucul_canvas_t *render_figlet(context_t *, uint32_t const *,
    18                                      unsigned int);
     17extern int init_figlet(context_t *);
    1918
  • toilet/trunk/src/main.c

    r1194 r1196  
    172172    if(!strcasecmp(cx->font, "mono9"))
    173173        init_big(cx);
    174     else /* if(!strcasecmp(cx->font, "term")) */
     174    else if(!strcasecmp(cx->font, "term"))
    175175        init_tiny(cx);
     176    else
     177        init_figlet(cx);
    176178
    177179    if(optind >= argc)
  • toilet/trunk/src/toilet.h

    r1194 r1196  
    3535    cucul_canvas_t *onechar;
    3636    unsigned char *buf;
     37
     38    /* Used by the FIGlet driver */
     39    unsigned long int hardblank;
     40    unsigned int height, baseline, max_length;
     41    int old_layout;
     42    unsigned int print_direction, full_layout, codetag_count;
     43    unsigned int glyphs;
     44    cucul_canvas_t *image;
     45    unsigned int *lookup;
    3746};
    3847
Note: See TracChangeset for help on using the changeset viewer.