| @@ -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. | |||
| */ | |||