Ignore:
Timestamp:
May 21, 2009, 10:54:59 PM (12 years ago)
Author:
Sam Hocevar
Message:

Split import.c and export.c to create a new text.c codec file in order
to keep source files under 1,000 lines of code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/caca/codec/export.c

    r3491 r3492  
    11/*
    22 *  libcaca       Colour ASCII-Art library
    3  *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
     3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
    44 *                2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
    55 *                All Rights Reserved
     
    2828#include "caca.h"
    2929#include "caca_internals.h"
     30#include "codec.h"
    3031
    3132static inline int sprintu32(char *s, uint32_t x)
     
    4647
    4748static void *export_caca(caca_canvas_t const *, size_t *);
    48 static void *export_ansi(caca_canvas_t const *, size_t *);
    49 static void *export_utf8(caca_canvas_t const *, size_t *, int);
    5049static void *export_html(caca_canvas_t const *, size_t *);
    5150static void *export_html3(caca_canvas_t const *, size_t *);
    5251static void *export_bbfr(caca_canvas_t const *, size_t *);
    53 static void *export_irc(caca_canvas_t const *, size_t *);
    5452static void *export_ps(caca_canvas_t const *, size_t *);
    5553static void *export_svg(caca_canvas_t const *, size_t *);
     
    9088
    9189    if(!strcasecmp("ansi", format))
    92         return export_ansi(cv, bytes);
     90        return _export_ansi(cv, bytes);
    9391
    9492    if(!strcasecmp("utf8", format))
    95         return export_utf8(cv, bytes, 0);
     93        return _export_utf8(cv, bytes, 0);
    9694
    9795    if(!strcasecmp("utf8cr", format))
    98         return export_utf8(cv, bytes, 1);
     96        return _export_utf8(cv, bytes, 1);
    9997
    10098    if(!strcasecmp("html", format))
     
    108106
    109107    if(!strcasecmp("irc", format))
    110         return export_irc(cv, bytes);
     108        return _export_irc(cv, bytes);
    111109
    112110    if(!strcasecmp("ps", format))
     
    208206        }
    209207    }
    210 
    211     return data;
    212 }
    213 
    214 /* Generate UTF-8 representation of current canvas. */
    215 static void *export_utf8(caca_canvas_t const *cv, size_t *bytes,
    216                          int cr)
    217 {
    218     static uint8_t const palette[] =
    219     {
    220         0,  4,  2,  6, 1,  5,  3,  7,
    221         8, 12, 10, 14, 9, 13, 11, 15
    222     };
    223 
    224     char *data, *cur;
    225     int x, y;
    226 
    227     /* 23 bytes assumed for max length per pixel ('\e[5;1;3x;4y;9x;10ym' plus
    228      * 4 max bytes for a UTF-8 character).
    229      * Add height*9 to that (zeroes color at the end and jump to next line) */
    230     *bytes = (cv->height * 9) + (cv->width * cv->height * 23);
    231     cur = data = malloc(*bytes);
    232 
    233     for(y = 0; y < cv->height; y++)
    234     {
    235         uint32_t *lineattr = cv->attrs + y * cv->width;
    236         uint32_t *linechar = cv->chars + y * cv->width;
    237 
    238         uint8_t prevfg = 0x10;
    239         uint8_t prevbg = 0x10;
    240 
    241         for(x = 0; x < cv->width; x++)
    242         {
    243             uint32_t attr = lineattr[x];
    244             uint32_t ch = linechar[x];
    245             uint8_t ansifg, ansibg, fg, bg;
    246 
    247             if(ch == CACA_MAGIC_FULLWIDTH)
    248                 continue;
    249 
    250             ansifg = caca_attr_to_ansi_fg(attr);
    251             ansibg = caca_attr_to_ansi_bg(attr);
    252 
    253             fg = ansifg < 0x10 ? palette[ansifg] : 0x10;
    254             bg = ansibg < 0x10 ? palette[ansibg] : 0x10;
    255 
    256             /* TODO: the [0 could be omitted in some cases */
    257             if(fg != prevfg || bg != prevbg)
    258             {
    259                 cur += sprintf(cur, "\033[0");
    260 
    261                 if(fg < 8)
    262                     cur += sprintf(cur, ";3%d", fg);
    263                 else if(fg < 16)
    264                     cur += sprintf(cur, ";1;3%d;9%d", fg - 8, fg - 8);
    265 
    266                 if(bg < 8)
    267                     cur += sprintf(cur, ";4%d", bg);
    268                 else if(bg < 16)
    269                     cur += sprintf(cur, ";5;4%d;10%d", bg - 8, bg - 8);
    270 
    271                 cur += sprintf(cur, "m");
    272             }
    273 
    274             cur += caca_utf32_to_utf8(cur, ch);
    275 
    276             prevfg = fg;
    277             prevbg = bg;
    278         }
    279 
    280         if(prevfg != 0x10 || prevbg != 0x10)
    281             cur += sprintf(cur, "\033[0m");
    282 
    283         cur += sprintf(cur, cr ? "\r\n" : "\n");
    284     }
    285 
    286     /* Crop to really used size */
    287     debug("utf8 export: alloc %lu bytes, realloc %lu",
    288           (unsigned long int)*bytes, (unsigned long int)(cur - data));
    289     *bytes = (uintptr_t)(cur - data);
    290     data = realloc(data, *bytes);
    291 
    292     return data;
    293 }
    294 
    295 /* Generate ANSI representation of current canvas. */
    296 static void *export_ansi(caca_canvas_t const *cv, size_t *bytes)
    297 {
    298     static uint8_t const palette[] =
    299     {
    300         0,  4,  2,  6, 1,  5,  3,  7,
    301         8, 12, 10, 14, 9, 13, 11, 15
    302     };
    303 
    304     char *data, *cur;
    305     int x, y;
    306 
    307     uint8_t prevfg = -1;
    308     uint8_t prevbg = -1;
    309 
    310     /* 16 bytes assumed for max length per pixel ('\e[5;1;3x;4ym' plus
    311      * 1 byte for a CP437 character).
    312      * Add height*9 to that (zeroes color at the end and jump to next line) */
    313     *bytes = (cv->height * 9) + (cv->width * cv->height * 16);
    314     cur = data = malloc(*bytes);
    315 
    316     for(y = 0; y < cv->height; y++)
    317     {
    318         uint32_t *lineattr = cv->attrs + y * cv->width;
    319         uint32_t *linechar = cv->chars + y * cv->width;
    320 
    321         for(x = 0; x < cv->width; x++)
    322         {
    323             uint8_t ansifg = caca_attr_to_ansi_fg(lineattr[x]);
    324             uint8_t ansibg = caca_attr_to_ansi_bg(lineattr[x]);
    325             uint8_t fg = ansifg < 0x10 ? palette[ansifg] : CACA_LIGHTGRAY;
    326             uint8_t bg = ansibg < 0x10 ? palette[ansibg] : CACA_BLACK;
    327             uint32_t ch = linechar[x];
    328 
    329             if(ch == CACA_MAGIC_FULLWIDTH)
    330                 ch = '?';
    331 
    332             if(fg != prevfg || bg != prevbg)
    333             {
    334                 cur += sprintf(cur, "\033[0;");
    335 
    336                 if(fg < 8)
    337                     if(bg < 8)
    338                         cur += sprintf(cur, "3%d;4%dm", fg, bg);
    339                     else
    340                         cur += sprintf(cur, "5;3%d;4%dm", fg, bg - 8);
    341                 else
    342                     if(bg < 8)
    343                         cur += sprintf(cur, "1;3%d;4%dm", fg - 8, bg);
    344                     else
    345                         cur += sprintf(cur, "5;1;3%d;4%dm", fg - 8, bg - 8);
    346             }
    347 
    348             *cur++ = caca_utf32_to_cp437(ch);
    349 
    350             prevfg = fg;
    351             prevbg = bg;
    352         }
    353 
    354         if(cv->width == 80)
    355         {
    356             cur += sprintf(cur, "\033[s\n\033[u");
    357         }
    358         else
    359         {
    360             cur += sprintf(cur, "\033[0m\r\n");
    361             prevfg = -1;
    362             prevbg = -1;
    363         }
    364     }
    365 
    366     /* Crop to really used size */
    367     debug("ansi export: alloc %lu bytes, realloc %lu",
    368           (unsigned long int)*bytes, (unsigned long int)(cur - data));
    369     *bytes = (uintptr_t)(cur - data);
    370     data = realloc(data, *bytes);
    371208
    372209    return data;
     
    842679}
    843680
    844 /* Export a text file with IRC colours */
    845 static void *export_irc(caca_canvas_t const *cv, size_t *bytes)
    846 {
    847     static uint8_t const palette[] =
    848     {
    849         1, 2, 3, 10, 5, 6, 7, 15, /* Dark */
    850         14, 12, 9, 11, 4, 13, 8, 0, /* Light */
    851     };
    852 
    853     char *data, *cur;
    854     int x, y;
    855 
    856     /* 14 bytes assumed for max length per pixel. Worst case scenario:
    857      * ^Cxx,yy   6 bytes
    858      * ^B^B      2 bytes
    859      * ch        6 bytes
    860      * 3 bytes for max length per line. Worst case scenario:
    861      * <spc>     1 byte (for empty lines)
    862      * \r\n      2 bytes
    863      * In real life, the average bytes per pixel value will be around 5.
    864      */
    865 
    866     *bytes = 2 + cv->height * (3 + cv->width * 14);
    867     cur = data = malloc(*bytes);
    868 
    869     for(y = 0; y < cv->height; y++)
    870     {
    871         uint32_t *lineattr = cv->attrs + y * cv->width;
    872         uint32_t *linechar = cv->chars + y * cv->width;
    873 
    874         uint8_t prevfg = 0x10;
    875         uint8_t prevbg = 0x10;
    876 
    877         for(x = 0; x < cv->width; x++)
    878         {
    879             uint32_t attr = lineattr[x];
    880             uint32_t ch = linechar[x];
    881             uint8_t ansifg, ansibg, fg, bg;
    882 
    883             if(ch == CACA_MAGIC_FULLWIDTH)
    884                 continue;
    885 
    886             ansifg = caca_attr_to_ansi_fg(attr);
    887             ansibg = caca_attr_to_ansi_bg(attr);
    888 
    889             fg = ansifg < 0x10 ? palette[ansifg] : 0x10;
    890             bg = ansibg < 0x10 ? palette[ansibg] : 0x10;
    891 
    892             /* TODO: optimise series of same fg / same bg
    893              *       don't change fg value if ch == ' '
    894              *       make sure the \x03,%d trick works everywhere */
    895             if(bg != prevbg || fg != prevfg)
    896             {
    897                 int need_escape = 0;
    898 
    899                 if(bg == 0x10)
    900                 {
    901                     if(fg == 0x10)
    902                         cur += sprintf(cur, "\x0f");
    903                     else
    904                     {
    905                         if(prevbg == 0x10)
    906                             cur += sprintf(cur, "\x03%d", fg);
    907                         else
    908                             cur += sprintf(cur, "\x0f\x03%d", fg);
    909 
    910                         if(ch == (uint32_t)',')
    911                             need_escape = 1;
    912                     }
    913                 }
    914                 else
    915                 {
    916                     if(fg == 0x10)
    917                         cur += sprintf(cur, "\x0f\x03,%d", bg);
    918                     else
    919                         cur += sprintf(cur, "\x03%d,%d", fg, bg);
    920                 }
    921 
    922                 if(ch >= (uint32_t)'0' && ch <= (uint32_t)'9')
    923                     need_escape = 1;
    924 
    925                 if(need_escape)
    926                     cur += sprintf(cur, "\x02\x02");
    927             }
    928 
    929             cur += caca_utf32_to_utf8(cur, ch);
    930             prevfg = fg;
    931             prevbg = bg;
    932         }
    933 
    934         /* TODO: do the same the day we optimise whole lines above */
    935         if(!cv->width)
    936             *cur++ = ' ';
    937 
    938         *cur++ = '\r';
    939         *cur++ = '\n';
    940     }
    941 
    942     /* Crop to really used size */
    943     debug("IRC export: alloc %lu bytes, realloc %lu",
    944           (unsigned long int)*bytes, (unsigned long int)(cur - data));
    945     *bytes = (uintptr_t)(cur - data);
    946     data = realloc(data, *bytes);
    947 
    948     return data;
    949 }
    950 
    951681/* Export a PostScript document. */
    952682static void *export_ps(caca_canvas_t const *cv, size_t *bytes)
Note: See TracChangeset for help on using the changeset viewer.