| @@ -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_ps(caca_canvas_t const *, size_t *); | ||||
| static void *export_svg(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_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. | /** \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 "ps": export a PostScript document. | ||||
| * - \c "svg": export an SVG vector image. | * - \c "svg": export an SVG vector image. | ||||
| * - \c "tga": export a TGA 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: | * If an error occurs, NULL is returned and \b errno is set accordingly: | ||||
| * - \c EINVAL Unsupported format requested. | * - \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)) | if(!strcasecmp("tga", format)) | ||||
| return export_tga(cv, bytes); | return export_tga(cv, bytes); | ||||
| if(!strcasecmp("troff", format)) | |||||
| return export_troff(cv, bytes); | |||||
| seterrno(EINVAL); | seterrno(EINVAL); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| @@ -189,6 +194,7 @@ char const * const * caca_get_export_list(void) | |||||
| "ps", "PostScript document", | "ps", "PostScript document", | ||||
| "svg", "SVG vector image", | "svg", "SVG vector image", | ||||
| "tga", "TGA image", | "tga", "TGA image", | ||||
| "troff", "troff source", | |||||
| NULL, NULL | NULL, NULL | ||||
| }; | }; | ||||
| @@ -975,6 +981,73 @@ static void *export_tga(caca_canvas_t const *cv, size_t *bytes) | |||||
| return data; | 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. | * XXX: The following functions are aliases. | ||||
| */ | */ | ||||