Ignore:
Timestamp:
May 5, 2006, 12:00:52 AM (14 years ago)
Author:
Sam Hocevar
Message:
  • Added "utf8" export that is like ANSI but exports UTF-8 encoded coloured text.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/cucul/export.c

    r920 r925  
    3434static void export_caca(cucul_canvas_t *, cucul_buffer_t *);
    3535static void export_ansi(cucul_canvas_t *, cucul_buffer_t *);
     36static void export_utf8(cucul_canvas_t *, cucul_buffer_t *);
    3637static void export_html(cucul_canvas_t *, cucul_buffer_t *);
    3738static void export_html3(cucul_canvas_t *, cucul_buffer_t *);
     
    9697    else if(!strcasecmp("ansi", format))
    9798        export_ansi(cv, ex);
     99    else if(!strcasecmp("utf8", format))
     100        export_utf8(cv, ex);
    98101    else if(!strcasecmp("html", format))
    99102        export_html(cv, ex);
     
    138141        "caca", "native libcaca format",
    139142        "ansi", "ANSI",
     143        "utf8", "UTF-8 with ANSI escape codes",
    140144        "html", "HTML",
    141145        "html3", "backwards-compatible HTML",
     
    191195        *cur++ = a & 0xff;
    192196    }
     197}
     198
     199/* Generate UTF-8 representation of current canvas. */
     200static void export_utf8(cucul_canvas_t *cv, cucul_buffer_t *ex)
     201{
     202    static uint8_t const palette[] =
     203    {
     204        0,  4,  2,  6, 1,  5,  3,  7,
     205        8, 12, 10, 14, 9, 13, 11, 15
     206    };
     207
     208    char *cur;
     209    unsigned int x, y;
     210
     211    /* 23 bytes assumed for max length per pixel ('\e[5;1;3x;4y;9x;10ym' plus
     212     * 4 max bytes for a UTF-8 character).
     213     * Add height*9 to that (zeroes color at the end and jump to next line) */
     214    ex->size = (cv->height * 9) + (cv->width * cv->height * 23);
     215    ex->data = malloc(ex->size);
     216
     217    cur = ex->data;
     218
     219    for(y = 0; y < cv->height; y++)
     220    {
     221        uint32_t *lineattr = cv->attr + y * cv->width;
     222        uint32_t *linechar = cv->chars + y * cv->width;
     223
     224        uint8_t prevfg = -1;
     225        uint8_t prevbg = -1;
     226
     227        for(x = 0; x < cv->width; x++)
     228        {
     229            static const uint8_t mark[7] =
     230            {
     231                0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
     232            };
     233
     234            uint8_t fg = palette[_cucul_argb32_to_ansi4fg(lineattr[x])];
     235            uint8_t bg = palette[_cucul_argb32_to_ansi4bg(lineattr[x])];
     236            uint32_t ch = linechar[x];
     237
     238            if(fg != prevfg || bg != prevbg)
     239            {
     240                cur += sprintf(cur, "\033[0;");
     241
     242                if(fg < 8)
     243                    if(bg < 8)
     244                        cur += sprintf(cur, "3%d;4%dm", fg, bg);
     245                    else
     246                        cur += sprintf(cur, "5;3%d;4%d;10%dm",
     247                                            fg, bg - 8, bg - 8);
     248                else
     249                    if(bg < 8)
     250                        cur += sprintf(cur, "1;3%d;4%d;9%dm",
     251                                            fg - 8, bg, fg - 8);
     252                    else
     253                        cur += sprintf(cur, "5;1;3%d;4%d;9%d;10%dm",
     254                                            fg - 8, bg - 8, fg - 8, bg - 8);
     255            }
     256
     257            if(ch < 0x80)
     258            {
     259                *cur++ = (ch >= 0x20) ? ch : '?';
     260            }
     261            else
     262            {
     263                int bytes = (ch < 0x800) ? 2 : (ch < 0x10000) ? 3 : 4;
     264                char *parser;
     265
     266                cur += bytes;
     267                parser = cur;
     268
     269                switch(bytes)
     270                {
     271                    case 4: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
     272                    case 3: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
     273                    case 2: *--parser = (ch | 0x80) & 0xbf; ch >>= 6;
     274                }
     275                *--parser = ch | mark[bytes];
     276            }
     277
     278            prevfg = fg;
     279            prevbg = bg;
     280        }
     281
     282        cur += sprintf(cur, "\033[0m\r\n");
     283    }
     284
     285    /* Crop to really used size */
     286    ex->size = (uintptr_t)(cur - ex->data);
     287    ex->data = realloc(ex->data, ex->size);
    193288}
    194289
Note: See TracChangeset for help on using the changeset viewer.