diff --git a/caca/codec/export.c b/caca/codec/export.c index 704785c..08a8ed3 100644 --- a/caca/codec/export.c +++ b/caca/codec/export.c @@ -459,44 +459,40 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) { char *data, *cur; int x, y, len; - int maxcols; int has_multi_cell_row = 0; + unsigned char *cell_boundary_bitmap; /* Table */ - maxcols = 0; + cell_boundary_bitmap = (unsigned char *) malloc((cv->width + 7) / 8); + if(cell_boundary_bitmap) + memset((void *) cell_boundary_bitmap, 0, (cv->width + 7) / 8); for(y = 0; y < cv->height; y++) { uint32_t *lineattr = cv->attrs + y * cv->width; - uint32_t *linechar = cv->chars + y * cv->width; - int cols = 0; - for(x = 0; x < cv->width; x++) - { - if((! has_multi_cell_row) - && - (x > 1) - && - (caca_attr_to_ansi_bg(lineattr[x - 1]) - != - caca_attr_to_ansi_bg(lineattr[x])) + for(x = 1; x < cv->width; x++) + if((! (cell_boundary_bitmap + ? + (cell_boundary_bitmap[x / 8] & (1 << (x % 8))) + : + has_multi_cell_row)) && - ((caca_attr_to_ansi_bg(lineattr[x]) < 0x10) - ? - (_caca_attr_to_rgb24bg(lineattr[x - 1]) + ((caca_attr_to_ansi_bg(lineattr[x - 1]) != - _caca_attr_to_rgb24bg(lineattr[x])) - : - 0)) + caca_attr_to_ansi_bg(lineattr[x])) + || + ((caca_attr_to_ansi_bg(lineattr[x]) < 0x10) + ? + (_caca_attr_to_rgb24bg(lineattr[x - 1]) + != + _caca_attr_to_rgb24bg(lineattr[x])) + : + 0))) { has_multi_cell_row = 1; + if(cell_boundary_bitmap) + cell_boundary_bitmap[x / 8] |= 1 << (x % 8); } - if(linechar[x] == 0x00000009) - while((cols + 1) % 8) - cols ++; - cols ++; - } - if (cols > maxcols) - maxcols = cols; } /* The HTML table markup: less than 1000 bytes @@ -505,30 +501,37 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) * up to 36 chars for "" * up to 10 chars for "&#xxxxxxx;" (far less for pure ASCII) * 17 chars for "" */ - *bytes = 1000 + cv->height * (10 + maxcols * (48 + 36 + 10 + 17)); + *bytes = 1000 + cv->height * (10 + cv->width * (48 + 36 + 10 + 17)); cur = data = malloc(*bytes); - cur += sprintf(cur, "\n"); + cur += sprintf(cur, "
\n"); for(y = 0; y < cv->height; y++) { uint32_t *lineattr = cv->attrs + y * cv->width; uint32_t *linechar = cv->chars + y * cv->width; - int taboff = 0; cur += sprintf(cur, ""); for(x = 0; x < cv->width; x += len) { int i, needfont = 0; - int thistab = 0; + int nonblank = 0; /* Use colspan option to factor cells with same attributes * (see below) */ len = 1; - while((y || (! has_multi_cell_row) || (cv->height == 1)) + while((x + len < cv->width) && - (x + len < cv->width) + (y + || + (! (cell_boundary_bitmap + ? + (cell_boundary_bitmap[(x + len) / 8] & (1 << ((x + len) % 8))) + : + has_multi_cell_row)) + || + (cv->height == 1)) && (caca_attr_to_ansi_bg(lineattr[x + len]) == @@ -544,9 +547,12 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) len++; for(i = 0; i < len; i++) - if(linechar[x + i] == 0x00000009) - while((x + i + taboff + thistab + 1) % 8) - thistab ++; + if(! ((linechar[x + i] <= 0x00000020) + || + ((linechar[x + i] >= 0x0000007f) + && + (linechar[x + i] <= 0x000000a0)))) + nonblank = 1; cur += sprintf(cur, " 1) - cur += sprintf(cur, " colspan=\"%d\"", len + thistab); + if(has_multi_cell_row && (len > 1)) + { + int colspan; + + colspan = len; + if(cell_boundary_bitmap) + for(i = 0; i < len; i ++) + if(i + && + ! (cell_boundary_bitmap[(x + i) / 8] + & + (1 << ((x + i) % 8)))) + colspan --; + if(colspan > 1) + cur += sprintf(cur, " colspan=\"%d\"", colspan); + } cur += sprintf(cur, ">"); @@ -563,12 +583,19 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) for(i = 0; i < len; i++) { - if((! i) || (lineattr[x + i] != lineattr[x + i - 1])) + if(nonblank + && + ((! i) + || + (lineattr[x + i] != lineattr[x + i - 1]))) { - needfont = (caca_attr_to_ansi_fg(lineattr[x + i]) != CACA_DEFAULT); + needfont = (caca_attr_to_ansi_fg(lineattr[x + i]) + != + CACA_DEFAULT); if(needfont) - cur += sprintf(cur, "", (unsigned long int) + cur += sprintf(cur, "", + (unsigned long int) _caca_attr_to_rgb24fg(lineattr[x + i])); if(lineattr[x + i] & CACA_BOLD) @@ -587,22 +614,13 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) || ((linechar[x + i] >= 0x0000007f) && - (linechar[x + i] <= 0x0000009f))) + (linechar[x + i] <= 0x000000a0))) { /* Control characters and space converted to * U+00A0 NO-BREAK SPACE, a.k.a. " " in HTML, * but we use the equivalent numeric character * reference   so this will work in plain - * XHTML with no DTD too. We also expand tabs - * here, since they are not honored in HTML. */ - if(linechar[x + i] == 0x00000009) - { - while((x + i + taboff + 1) % 8) - { - cur += sprintf(cur, " "); - taboff ++; - } - } + * XHTML with no DTD too. */ cur += sprintf(cur, " "); } else if(linechar[x + i] == '&') @@ -630,7 +648,11 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) * REPLACEMENT CHARACTER */ cur += sprintf(cur, "&#%i;", (unsigned int)0x0000fffd); - if (((i + 1) == len) || (lineattr[x + i + 1] != lineattr[x + i])) + if (nonblank + && + (((i + 1) == len) + || + (lineattr[x + i + 1] != lineattr[x + i]))) { if(lineattr[x + i] & CACA_BLINK) cur += sprintf(cur, ""); @@ -655,6 +677,10 @@ static void *export_html3(caca_canvas_t const *cv, size_t *bytes) /* Footer */ cur += sprintf(cur, "
\n"); + /* Free working memory */ + if (cell_boundary_bitmap) + free((void *) cell_boundary_bitmap); + /* Crop to really used size */ debug("html3 export: alloc %lu bytes, realloc %lu", (unsigned long int)*bytes, (unsigned long int)(cur - data));