diff --git a/caca/codec/export.c b/caca/codec/export.c index dee29a7..a1086a2 100644 --- a/caca/codec/export.c +++ b/caca/codec/export.c @@ -52,6 +52,7 @@ static void *export_bbfr(caca_canvas_t const *, size_t *); static void *export_ps(caca_canvas_t const *, size_t *); static void *export_svg(caca_canvas_t const *, size_t *); static void *export_tga(caca_canvas_t const *, size_t *); +static void *export_troff(caca_canvas_t const *, size_t *); /** \brief Export a canvas into a foreign format. * @@ -69,6 +70,7 @@ static void *export_tga(caca_canvas_t const *, size_t *); * - \c "ps": export a PostScript document. * - \c "svg": export an SVG vector image. * - \c "tga": export a TGA image. + * - \c "troff": export a troff source. * * If an error occurs, NULL is returned and \b errno is set accordingly: * - \c EINVAL Unsupported format requested. @@ -116,6 +118,9 @@ void *caca_export_canvas_to_memory(caca_canvas_t const *cv, char const *format, if(!strcasecmp("tga", format)) return export_tga(cv, bytes); + if(!strcasecmp("troff", format)) + return export_troff(cv, bytes); + seterrno(EINVAL); return NULL; } @@ -189,6 +194,7 @@ char const * const * caca_get_export_list(void) "ps", "PostScript document", "svg", "SVG vector image", "tga", "TGA image", + "troff", "troff source", NULL, NULL }; @@ -975,6 +981,73 @@ static void *export_tga(caca_canvas_t const *cv, size_t *bytes) return data; } +/* Generate troff representation of current canvas. */ +static void *export_troff(caca_canvas_t const *cv, size_t *bytes) +{ + char *data, *cur; + int x, y; + + uint32_t prevfg = 0; + uint32_t prevbg = 0; + int started = 0; + + /* 93 bytes assumed for max length per pixel ('\m[xxxxxx]y\m[]') + * + 97 + height + */ + *bytes = 97 + cv->height + (cv->width * cv->height * 87); + cur = data = malloc(*bytes); + + cur += sprintf(cur, ".color 1\n"); + + for(y = 0; y < cv->height; y++) + { + uint32_t *lineattr = cv->attrs + y * cv->width; + uint32_t *linechar = cv->chars + y * cv->width; + + for(x = 0; x < cv->width; x++) + { + + uint32_t fg = _caca_attr_to_rgb24bg(lineattr[x]); + uint32_t bg = _caca_attr_to_rgb24fg(lineattr[x]); + if(started && (fg != prevfg || bg != prevbg)) + cur += sprintf(cur, "\n"); + if(fg != prevfg || !started) + cur += sprintf(cur, ".defcolor %.06x rgb #%.06x\n", fg, fg); + if(bg != prevbg || !started) + cur += sprintf(cur, ".defcolor %.06x rgb #%.06x\n", bg, bg); + if(fg != prevfg || !started) + cur += sprintf(cur, "\\m[%.06x]", fg); + if(bg != prevbg || !started) + cur += sprintf(cur, "\\M[%.06x]", bg); + if(lineattr[x] & CACA_BOLD) + cur += sprintf(cur, "\\fB"); + if(lineattr[x] & CACA_ITALICS) + cur += sprintf(cur, "\\fI"); + + uint32_t ch = linechar[x]; + cur += caca_utf32_to_utf8(cur, ch); + + if(lineattr[x] & (CACA_BOLD|CACA_ITALICS)) + cur += sprintf(cur, "\\fR"); + + prevfg = fg; + prevbg = bg; + + started = 1; + } + + cur += sprintf(cur, "\n"); + } + + /* Crop to really used size */ + debug("troff export: alloc %lu bytes, realloc %lu", + (unsigned long int)*bytes, (unsigned long int)(cur - data)); + *bytes = (uintptr_t)(cur - data); + data = realloc(data, *bytes); + + return data; +} + /* * XXX: The following functions are aliases. */