[vte/wip/sixels: 82/111] sixel: Refactor the parser
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/sixels: 82/111] sixel: Refactor the parser
- Date: Sat, 8 Aug 2020 18:43:02 +0000 (UTC)
commit f1d24daa3440c13f1b4c6cef3b9d5e6aa168aaf5
Author: Hans Petter Jansson <hpj cl no>
Date: Sat Aug 8 20:42:49 2020 +0200
sixel: Refactor the parser
src/sixel.cc | 940 +++++++++++++++++++++++++++++++----------------------------
1 file changed, 489 insertions(+), 451 deletions(-)
---
diff --git a/src/sixel.cc b/src/sixel.cc
index c708e780..ad3264a5 100644
--- a/src/sixel.cc
+++ b/src/sixel.cc
@@ -25,27 +25,28 @@
#include "sixel.h"
-#define SIXEL_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16))
-#define PALVAL(n,a,m) (((n) * (a) + ((m) / 2)) / (m))
-#define SIXEL_XRGB(r,g,b) SIXEL_RGB(PALVAL(r, 255, 100), PALVAL(g, 255, 100), PALVAL(b, 255, 100))
-
-static int const sixel_default_color_table[] = {
- SIXEL_XRGB(0, 0, 0), /* 0 Black */
- SIXEL_XRGB(20, 20, 80), /* 1 Blue */
- SIXEL_XRGB(80, 13, 13), /* 2 Red */
- SIXEL_XRGB(20, 80, 20), /* 3 Green */
- SIXEL_XRGB(80, 20, 80), /* 4 Magenta */
- SIXEL_XRGB(20, 80, 80), /* 5 Cyan */
- SIXEL_XRGB(80, 80, 20), /* 6 Yellow */
- SIXEL_XRGB(53, 53, 53), /* 7 Gray 50% */
- SIXEL_XRGB(26, 26, 26), /* 8 Gray 25% */
- SIXEL_XRGB(33, 33, 60), /* 9 Blue* */
- SIXEL_XRGB(60, 26, 26), /* 10 Red* */
- SIXEL_XRGB(33, 60, 33), /* 11 Green* */
- SIXEL_XRGB(60, 33, 60), /* 12 Magenta* */
- SIXEL_XRGB(33, 60, 60), /* 13 Cyan* */
- SIXEL_XRGB(60, 60, 33), /* 14 Yellow* */
- SIXEL_XRGB(80, 80, 80), /* 15 Gray 75% */
+#define PACK_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16))
+#define SCALE_VALUE(n,a,m) (((n) * (a) + ((m) / 2)) / (m))
+#define SCALE_AND_PACK_RGB(r,g,b) \
+ PACK_RGB(SCALE_VALUE(r, 255, 100), SCALE_VALUE(g, 255, 100), SCALE_VALUE(b, 255, 100))
+
+static const int sixel_default_color_table[] = {
+ SCALE_AND_PACK_RGB(0, 0, 0), /* 0 Black */
+ SCALE_AND_PACK_RGB(20, 20, 80), /* 1 Blue */
+ SCALE_AND_PACK_RGB(80, 13, 13), /* 2 Red */
+ SCALE_AND_PACK_RGB(20, 80, 20), /* 3 Green */
+ SCALE_AND_PACK_RGB(80, 20, 80), /* 4 Magenta */
+ SCALE_AND_PACK_RGB(20, 80, 80), /* 5 Cyan */
+ SCALE_AND_PACK_RGB(80, 80, 20), /* 6 Yellow */
+ SCALE_AND_PACK_RGB(53, 53, 53), /* 7 Gray 50% */
+ SCALE_AND_PACK_RGB(26, 26, 26), /* 8 Gray 25% */
+ SCALE_AND_PACK_RGB(33, 33, 60), /* 9 Blue* */
+ SCALE_AND_PACK_RGB(60, 26, 26), /* 10 Red* */
+ SCALE_AND_PACK_RGB(33, 60, 33), /* 11 Green* */
+ SCALE_AND_PACK_RGB(60, 33, 60), /* 12 Magenta* */
+ SCALE_AND_PACK_RGB(33, 60, 60), /* 13 Cyan* */
+ SCALE_AND_PACK_RGB(60, 60, 33), /* 14 Yellow* */
+ SCALE_AND_PACK_RGB(80, 80, 80), /* 15 Gray 75% */
};
/*
@@ -61,6 +62,7 @@ hls_to_rgb(int hue, int lum, int sat)
if (sat == 0) {
r = g = b = lum;
+ return SCALE_AND_PACK_RGB(r, g, b);
}
/* https://wikimedia.org/api/rest_v1/media/math/render/svg/17e876f7e3260ea7fed73f69e19c71eb715dd09d */
@@ -69,7 +71,7 @@ hls_to_rgb(int hue, int lum, int sat)
/* https://wikimedia.org/api/rest_v1/media/math/render/svg/f6721b57985ad83db3d5b800dc38c9980eedde1d */
min = lum - sat * (100 - (lum > 50 ? 1 : -1) * ((lum << 1) - 100)) / 200.0;
- /* HLS hue color ring is roteted -120 degree from HSL's one. */
+ /* HLS hue color ring is rotated -120 degree from HSL's one. */
hue = (hue + 240) % 360;
/* https://wikimedia.org/api/rest_v1/media/math/render/svg/937e8abdab308a22ff99de24d645ec9e70f1e384 */
@@ -107,54 +109,48 @@ hls_to_rgb(int hue, int lum, int sat)
break;
}
- return SIXEL_XRGB(r, g, b);
+ return SCALE_AND_PACK_RGB(r, g, b);
}
static int
set_default_color(sixel_image_t *image)
{
- int i;
- int n;
- int r;
- int g;
- int b;
+ int r, g, b;
+ int i, n;
- /* palette initialization */
+ /* Palette initialization */
for (n = 1; n < 17; n++) {
image->palette[n] = sixel_default_color_table[n - 1];
}
- /* colors 17-232 are a 6x6x6 color cube */
+ /* Colors 17-232 are a 6x6x6 color cube */
for (r = 0; r < 6; r++) {
for (g = 0; g < 6; g++) {
for (b = 0; b < 6; b++) {
- image->palette[n++] = SIXEL_RGB(r * 51, g * 51, b * 51);
+ image->palette[n++] = PACK_RGB(r * 51, g * 51, b * 51);
}
}
}
- /* colors 233-256 are a grayscale ramp, intentionally leaving out */
+ /* Colors 233-256 are a grayscale ramp */
for (i = 0; i < 24; i++) {
- image->palette[n++] = SIXEL_RGB(i * 11, i * 11, i * 11);
+ image->palette[n++] = PACK_RGB(i * 11, i * 11, i * 11);
}
for (; n < DECSIXEL_PALETTE_MAX; n++) {
- image->palette[n] = SIXEL_RGB(255, 255, 255);
+ image->palette[n] = PACK_RGB(255, 255, 255);
}
- return (0);
+ return 0;
}
static int
-sixel_image_init(
- sixel_image_t *image,
- int width,
- int height,
- int fgcolor,
- int bgcolor,
- int use_private_register)
+sixel_image_init(sixel_image_t *image,
+ int width, int height,
+ int fgcolor, int bgcolor,
+ int use_private_register)
{
- int status = (-1);
+ int status = -1;
size_t size;
size = (size_t)(width * height) * sizeof(sixel_color_no_t);
@@ -164,10 +160,9 @@ sixel_image_init(
image->ncolors = 2;
image->use_private_register = use_private_register;
- if (image->data == NULL) {
- status = (-1);
- goto end;
- }
+ if (image->data == NULL)
+ goto out;
+
memset(image->data, 0, size);
image->palette[0] = bgcolor;
@@ -177,20 +172,17 @@ sixel_image_init(
image->palette_modified = 0;
- status = (0);
+ status = 0;
-end:
+out:
return status;
}
static int
-image_buffer_resize(
- sixel_image_t *image,
- int width,
- int height)
+image_buffer_resize(sixel_image_t *image, int width, int height)
{
- int status = (-1);
+ int status = -1;
size_t size;
sixel_color_no_t *alt_buffer;
int n;
@@ -202,51 +194,82 @@ image_buffer_resize(
size = (size_t)(width * height) * sizeof(sixel_color_no_t);
alt_buffer = (sixel_color_no_t *)g_malloc(size);
if (alt_buffer == NULL) {
- /* free source image */
- g_free(image->data);
- image->data = NULL;
- status = (-1);
- goto end;
+ status = -1;
+ goto out;
}
min_height = height > image->height ? image->height: height;
- if (width > image->width) { /* if width is extended */
+ if (width > image->width) {
+ /* Wider */
for (n = 0; n < min_height; ++n) {
- /* copy from source image */
+ /* Copy from source image */
memcpy(alt_buffer + width * n,
image->data + image->width * n,
(size_t)image->width * sizeof(sixel_color_no_t));
- /* fill extended area with background color */
+ /* Fill extended area with background color */
memset(alt_buffer + width * n + image->width,
0,
(size_t)(width - image->width) * sizeof(sixel_color_no_t));
}
} else {
+ /* Narrower or the same width */
for (n = 0; n < min_height; ++n) {
- /* copy from source image */
+ /* Copy from source image */
memcpy(alt_buffer + width * n,
image->data + image->width * n,
(size_t)width * sizeof(sixel_color_no_t));
}
}
- if (height > image->height) { /* if height is extended */
- /* fill extended area with background color */
+ if (height > image->height) {
+ /* Fill extended area with background color */
memset(alt_buffer + width * image->height,
0,
(size_t)(width * (height - image->height)) * sizeof(sixel_color_no_t));
}
- /* free source image */
+ /* Free source image */
g_free(image->data);
image->data = alt_buffer;
image->width = width;
image->height = height;
- status = (0);
+ status = 0;
+
+out:
+ if (status < 0) {
+ /* Free source image */
+ g_free(image->data);
+ image->data = NULL;
+ }
+
+ return status;
+}
+
+static int
+image_buffer_ensure_min_size(sixel_image_t *image, int req_width, int req_height)
+{
+ int status = 0;
+
+ if ((image->width < req_width || image->height < req_height)
+ && image->width < DECSIXEL_WIDTH_MAX && image->height < DECSIXEL_HEIGHT_MAX) {
+ int sx = image->width * 2;
+ int sy = image->height * 2;
+
+ while (sx < req_width || sy < req_height) {
+ sx *= 2;
+ sy *= 2;
+ }
+
+ if (sx > DECSIXEL_WIDTH_MAX)
+ sx = DECSIXEL_WIDTH_MAX;
+ if (sy > DECSIXEL_HEIGHT_MAX)
+ sy = DECSIXEL_HEIGHT_MAX;
+
+ status = image_buffer_resize(image, sx, sy);
+ }
-end:
return status;
}
@@ -257,18 +280,400 @@ sixel_image_deinit(sixel_image_t *image)
image->data = NULL;
}
+static int
+parser_transition(sixel_state_t *st, parse_state_t new_state)
+{
+ st->state = new_state;
+ st->nparams = 0;
+ st->param = -1;
+
+ return 0;
+}
+
+static int
+parser_push_param_ascii_dec_digit(sixel_state_t *st, uint32_t ascii_dec_digit)
+{
+ if (st->param < 0)
+ st->param = 0;
+
+ st->param = st->param * 10 + ascii_dec_digit - '0';
+ return 0;
+}
+
+static int
+parser_collect_param(sixel_state_t *st)
+{
+ if (st->param < 0 || st->nparams >= DECSIXEL_PARAMS_MAX)
+ return 0;
+
+ if (st->param > DECSIXEL_PARAMVALUE_MAX)
+ st->param = DECSIXEL_PARAMVALUE_MAX;
+
+ st->params[st->nparams++] = st->param;
+ st->param = -1;
+ return 0;
+}
+
+static int
+parser_collect_param_or_zero(sixel_state_t *st)
+{
+ if (st->param < 0)
+ st->param = 0;
+
+ parser_collect_param (st);
+ return 0;
+}
+
+static int
+parser_action_dcs_attributes(sixel_state_t *st)
+{
+ if (st->nparams > 0) {
+ /* Pn1 */
+ switch (st->params[0]) {
+ case 0:
+ case 1:
+ st->attributed_pad = 2;
+ break;
+ case 2:
+ st->attributed_pad = 5;
+ break;
+ case 3:
+ case 4:
+ st->attributed_pad = 4;
+ break;
+ case 5:
+ case 6:
+ st->attributed_pad = 3;
+ break;
+ case 7:
+ case 8:
+ st->attributed_pad = 2;
+ break;
+ case 9:
+ st->attributed_pad = 1;
+ break;
+ default:
+ st->attributed_pad = 2;
+ break;
+ }
+ }
+
+ if (st->nparams > 2) {
+ /* Pn3 */
+ if (st->params[2] == 0)
+ st->params[2] = 10;
+ st->attributed_pan = st->attributed_pan * st->params[2] / 10;
+ st->attributed_pad = st->attributed_pad * st->params[2] / 10;
+ if (st->attributed_pan <= 0)
+ st->attributed_pan = 1;
+ if (st->attributed_pad <= 0)
+ st->attributed_pad = 1;
+ }
+
+ return 0;
+}
+
+static void
+draw_sixels(sixel_state_t *st, uint32_t bits)
+{
+ sixel_image_t *image = &st->image;
+
+ if (bits == 0)
+ return;
+
+ if (st->repeat_count <= 1) {
+ uint32_t sixel_vertical_mask = 0x01;
+
+ for (int i = 0; i < 6; i++) {
+ if ((bits & sixel_vertical_mask) != 0) {
+ int pos = image->width * (st->pos_y + i) + st->pos_x;
+ image->data[pos] = st->color_index;
+ if (st->max_x < st->pos_x)
+ st->max_x = st->pos_x;
+ if (st->max_y < (st->pos_y + i))
+ st->max_y = st->pos_y + i;
+ }
+ sixel_vertical_mask <<= 1;
+ }
+ } else {
+ uint32_t sixel_vertical_mask = 0x01;
+
+ /* st->repeat_count > 1 */
+ for (int i = 0; i < 6; i++) {
+ if ((bits & sixel_vertical_mask) != 0) {
+ uint32_t c = sixel_vertical_mask << 1;
+ int n;
+
+ for (n = 1; (i + n) < 6; n++) {
+ if ((bits & c) == 0)
+ break;
+ c <<= 1;
+ }
+ for (int y = st->pos_y + i; y < st->pos_y + i + n; ++y) {
+ for (int x = st->pos_x; x < st->pos_x + st->repeat_count; ++x)
+ image->data[image->width * y + x] = st->color_index;
+ }
+ if (st->max_x < (st->pos_x + st->repeat_count - 1))
+ st->max_x = st->pos_x + st->repeat_count - 1;
+ if (st->max_y < (st->pos_y + i + n - 1))
+ st->max_y = st->pos_y + i + n - 1;
+ i += (n - 1);
+ sixel_vertical_mask <<= (n - 1);
+ }
+
+ sixel_vertical_mask <<= 1;
+ }
+ }
+}
+
+static int
+parser_action_sixel_char(sixel_state_t *st, uint32_t raw)
+{
+ sixel_image_t *image = &st->image;
+ int status = -1;
+
+ if (raw >= '?' && raw <= '~') {
+ status = image_buffer_ensure_min_size (image,
+ st->pos_x + st->repeat_count,
+ st->pos_y + 6);
+ if (status < 0)
+ goto out;
+
+ if (st->color_index > image->ncolors)
+ image->ncolors = st->color_index;
+
+ st->repeat_count = MIN(st->repeat_count, image->width - st->pos_x);
+
+ if (st->repeat_count > 0 && st->pos_y + 5 < image->height) {
+ uint32_t bits = raw - '?';
+ draw_sixels(st, bits);
+ }
+
+ if (st->repeat_count > 0)
+ st->pos_x += st->repeat_count;
+ st->repeat_count = 1;
+ }
+
+ status = 0;
+
+out:
+ return status;
+}
+
+static int
+parser_action_decgcr(sixel_state_t *st)
+{
+ st->pos_x = 0;
+ return 0;
+}
+
+static int
+parser_action_decgnl(sixel_state_t *st)
+{
+ st->pos_x = 0;
+
+ if (st->pos_y < DECSIXEL_HEIGHT_MAX - 5 - 6)
+ st->pos_y += 6;
+ else
+ st->pos_y = DECSIXEL_HEIGHT_MAX + 1;
+
+ return 0;
+}
+
+
+static int
+parser_action_decgra(sixel_state_t *st)
+{
+ sixel_image_t *image = &st->image;
+ int status = 0;
+
+ if (st->nparams > 0)
+ st->attributed_pad = st->params[0];
+ if (st->nparams > 1)
+ st->attributed_pan = st->params[1];
+ if (st->nparams > 2 && st->params[2] > 0)
+ st->attributed_ph = st->params[2];
+ if (st->nparams > 3 && st->params[3] > 0)
+ st->attributed_pv = st->params[3];
+
+ if (st->attributed_pan <= 0)
+ st->attributed_pan = 1;
+ if (st->attributed_pad <= 0)
+ st->attributed_pad = 1;
+
+ if (image->width < st->attributed_ph ||
+ image->height < st->attributed_pv) {
+ int sx = MIN (MAX (image->width, st->attributed_ph), DECSIXEL_WIDTH_MAX);
+ int sy = MIN (MAX (image->height, st->attributed_pv), DECSIXEL_HEIGHT_MAX);
+
+ status = image_buffer_resize(image, sx, sy);
+ }
+
+ return status;
+}
+
+static int
+parser_action_decgri(sixel_state_t *st)
+{
+ st->repeat_count = MAX (st->param, 1);
+ return 0;
+}
+
+static int
+parser_action_decgci(sixel_state_t *st)
+{
+ sixel_image_t *image = &st->image;
+
+ if (st->nparams > 0) {
+ st->color_index = 1 + st->params[0]; /* offset 1 (background color) added */
+ if (st->color_index < 0)
+ st->color_index = 0;
+ else if (st->color_index >= DECSIXEL_PALETTE_MAX)
+ st->color_index = DECSIXEL_PALETTE_MAX - 1;
+ }
+
+ if (st->nparams > 4) {
+ st->image.palette_modified = 1;
+ if (st->params[1] == 1) {
+ /* HLS */
+ if (st->params[2] > 360)
+ st->params[2] = 360;
+ if (st->params[3] > 100)
+ st->params[3] = 100;
+ if (st->params[4] > 100)
+ st->params[4] = 100;
+ image->palette[st->color_index]
+ = hls_to_rgb(st->params[2], st->params[3], st->params[4]);
+ } else if (st->params[1] == 2) {
+ /* RGB */
+ if (st->params[2] > 100)
+ st->params[2] = 100;
+ if (st->params[3] > 100)
+ st->params[3] = 100;
+ if (st->params[4] > 100)
+ st->params[4] = 100;
+ image->palette[st->color_index]
+ = SCALE_AND_PACK_RGB(st->params[2], st->params[3], st->params[4]);
+ }
+ }
+
+ return 0;
+}
+
+static int
+parser_feed_char(sixel_state_t *st, uint32_t raw)
+{
+ int status = -1;
+
+ for (;;) {
+ switch (st->state) {
+ case PS_ESC:
+ switch (raw) {
+ case '\\':
+ case 0x9c:
+ return 0;
+ case 'P':
+ return parser_transition(st, PS_DCS);
+ }
+ return 0;
+
+ case PS_DCS:
+ switch (raw) {
+ case 0x1b:
+ return parser_transition(st, PS_ESC);
+ case '0' ... '9':
+ return parser_push_param_ascii_dec_digit(st, raw);
+ case ';':
+ return parser_collect_param_or_zero(st);
+ case 'q':
+ parser_collect_param(st);
+ parser_action_dcs_attributes(st);
+ return parser_transition(st, PS_DECSIXEL);
+ }
+ return 0;
+
+ case PS_DECSIXEL:
+ switch (raw) {
+ case 0x1b:
+ return parser_transition(st, PS_ESC);
+ case '"':
+ return parser_transition(st, PS_DECGRA);
+ case '!':
+ return parser_transition(st, PS_DECGRI);
+ case '#':
+ return parser_transition(st, PS_DECGCI);
+ case '$':
+ /* DECGCR Graphics Carriage Return */
+ return parser_action_decgcr(st);
+ case '-':
+ /* DECGNL Graphics Next Line */
+ return parser_action_decgnl(st);
+ }
+ return parser_action_sixel_char(st, raw);
+
+ case PS_DECGRA:
+ /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */
+ switch (raw) {
+ case 0x1b:
+ return parser_transition(st, PS_ESC);
+ case '0' ... '9':
+ return parser_push_param_ascii_dec_digit(st, raw);
+ case ';':
+ return parser_collect_param(st);
+ }
+
+ parser_collect_param(st);
+ status = parser_action_decgra(st);
+ if (status < 0)
+ return status;
+ parser_transition(st, PS_DECSIXEL);
+ continue;
+
+ case PS_DECGRI:
+ /* DECGRI Graphics Repeat Introducer ! Pn Ch */
+ switch (raw) {
+ case 0x1b:
+ return parser_transition(st, PS_ESC);
+ case '0' ... '9':
+ return parser_push_param_ascii_dec_digit(st, raw);
+ }
+
+ parser_action_decgri(st);
+ parser_transition(st, PS_DECSIXEL);
+ continue;
+
+ case PS_DECGCI:
+ /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */
+ switch (raw) {
+ case 0x1b:
+ return parser_transition(st, PS_ESC);
+ case '0' ... '9':
+ return parser_push_param_ascii_dec_digit(st, raw);
+ case ';':
+ return parser_collect_param_or_zero(st);
+ }
+
+ parser_collect_param(st);
+ parser_action_decgci(st);
+ parser_transition(st, PS_DECSIXEL);
+ continue;
+ }
+ } /* for (;;) */
+}
+
int
sixel_parser_init(sixel_state_t *st,
int fgcolor, int bgcolor,
int use_private_register)
{
- int status = (-1);
+ int status = -1;
/* FIXME-hpj: This used to be PS_DCS, but the VTE sequence parses the
* initial parameters for us, up to and including the leading 'q'. We
* therefore skip directly to the PS_DECSIXEL state.
*
* We may need to pass the initial parameters to this parser. */
+
st->state = PS_DECSIXEL;
st->pos_x = 0;
st->pos_y = 0;
@@ -281,24 +686,23 @@ sixel_parser_init(sixel_state_t *st,
st->repeat_count = 1;
st->color_index = 16;
st->nparams = 0;
- st->param = 0;
+ st->param = -1;
- /* buffer initialization */
status = sixel_image_init(&st->image, 1, 1, fgcolor, bgcolor, use_private_register);
return status;
}
-int
-sixel_parser_set_default_color(sixel_state_t *st)
+void
+sixel_parser_deinit(sixel_state_t *st)
{
- return set_default_color(&st->image);
+ sixel_image_deinit(&st->image);
}
int
sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels)
{
- int status = (-1);
+ int status = -1;
int sx;
int sy;
sixel_image_t *image = &st->image;
@@ -317,15 +721,15 @@ sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels)
sy = st->max_y;
status = image_buffer_resize(image,
- MIN (image->width, sx),
- MIN (image->height, sy));
+ MIN(image->width, sx),
+ MIN(image->height, sy));
if (status < 0)
- goto end;
+ goto out;
if (image->use_private_register && image->ncolors > 2 && !image->palette_modified) {
status = set_default_color(image);
if (status < 0)
- goto end;
+ goto out;
}
src = st->image.data;
@@ -355,378 +759,18 @@ sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels)
}
}
- status = (0);
+ status = 0;
-end:
+out:
return status;
}
-static int
-feed_char(sixel_state_t *st, uint32_t raw)
+int
+sixel_parser_set_default_color(sixel_state_t *st)
{
- sixel_image_t *image = &st->image;
- int n, i, x, y;
- int bits;
- int sixel_vertical_mask;
- int sx, sy;
- int c, pos;
- int status = -1;
-
-again:
- switch (st->state) {
- case PS_ESC:
- switch (raw) {
- case '\\':
- case 0x9c:
- break;
- case 'P':
- st->param = -1;
- st->state = PS_DCS;
- break;
- default:
- break;
- }
- break;
-
- case PS_DCS:
- switch (raw) {
- case 0x1b:
- st->state = PS_ESC;
- break;
-
- case '0' ... '9':
- if (st->param < 0)
- st->param = 0;
- st->param = st->param * 10 + raw - '0';
- break;
-
- case ';':
- if (st->param < 0) {
- st->param = 0;
- }
- if (st->nparams < DECSIXEL_PARAMS_MAX) {
- st->params[st->nparams++] = st->param;
- }
- st->param = 0;
- break;
-
- case 'q':
- if (st->param >= 0 && st->nparams < DECSIXEL_PARAMS_MAX) {
- st->params[st->nparams++] = st->param;
- }
- if (st->nparams > 0) {
- /* Pn1 */
- switch (st->params[0]) {
- case 0:
- case 1:
- st->attributed_pad = 2;
- break;
- case 2:
- st->attributed_pad = 5;
- break;
- case 3:
- case 4:
- st->attributed_pad = 4;
- break;
- case 5:
- case 6:
- st->attributed_pad = 3;
- break;
- case 7:
- case 8:
- st->attributed_pad = 2;
- break;
- case 9:
- st->attributed_pad = 1;
- break;
- default:
- st->attributed_pad = 2;
- break;
- }
- }
-
- if (st->nparams > 2) {
- /* Pn3 */
- if (st->params[2] == 0)
- st->params[2] = 10;
- st->attributed_pan = st->attributed_pan * st->params[2] / 10;
- st->attributed_pad = st->attributed_pad * st->params[2] / 10;
- if (st->attributed_pan <= 0)
- st->attributed_pan = 1;
- if (st->attributed_pad <= 0)
- st->attributed_pad = 1;
- }
- st->nparams = 0;
- st->state = PS_DECSIXEL;
- break;
-
- default:
- break;
- }
- break;
-
- case PS_DECSIXEL:
- switch (raw) {
- case '\x1b':
- st->state = PS_ESC;
- break;
- case '"':
- st->param = 0;
- st->nparams = 0;
- st->state = PS_DECGRA;
- break;
- case '!':
- st->param = 0;
- st->nparams = 0;
- st->state = PS_DECGRI;
- break;
- case '#':
- st->param = 0;
- st->nparams = 0;
- st->state = PS_DECGCI;
- break;
- case '$':
- /* DECGCR Graphics Carriage Return */
- st->pos_x = 0;
- break;
- case '-':
- /* DECGNL Graphics Next Line */
- st->pos_x = 0;
- if (st->pos_y < DECSIXEL_HEIGHT_MAX - 5 - 6)
- st->pos_y += 6;
- else
- st->pos_y = DECSIXEL_HEIGHT_MAX + 1;
- break;
- default:
- if (raw >= '?' && raw <= '~') { /* sixel characters */
- if ((image->width < (st->pos_x + st->repeat_count) || image->height <
(st->pos_y + 6))
- && image->width < DECSIXEL_WIDTH_MAX && image->height <
DECSIXEL_HEIGHT_MAX) {
- sx = image->width * 2;
- sy = image->height * 2;
- while (sx < (st->pos_x + st->repeat_count) || sy < (st->pos_y + 6)) {
- sx *= 2;
- sy *= 2;
- }
-
- if (sx > DECSIXEL_WIDTH_MAX)
- sx = DECSIXEL_WIDTH_MAX;
- if (sy > DECSIXEL_HEIGHT_MAX)
- sy = DECSIXEL_HEIGHT_MAX;
-
- status = image_buffer_resize(image, sx, sy);
- if (status < 0)
- goto out;
- }
-
- if (st->color_index > image->ncolors)
- image->ncolors = st->color_index;
-
- if (st->pos_x + st->repeat_count > image->width)
- st->repeat_count = image->width - st->pos_x;
-
- if (st->repeat_count > 0 && st->pos_y + 5 < image->height) {
- bits = raw - '?';
- if (bits != 0) {
- sixel_vertical_mask = 0x01;
- if (st->repeat_count <= 1) {
- for (i = 0; i < 6; i++) {
- if ((bits & sixel_vertical_mask) != 0) {
- pos = image->width * (st->pos_y + i)
+ st->pos_x;
- image->data[pos] = st->color_index;
- if (st->max_x < st->pos_x)
- st->max_x = st->pos_x;
- if (st->max_y < (st->pos_y + i))
- st->max_y = st->pos_y + i;
- }
- sixel_vertical_mask <<= 1;
- }
- } else {
- /* st->repeat_count > 1 */
- for (i = 0; i < 6; i++) {
- if ((bits & sixel_vertical_mask) != 0) {
- c = sixel_vertical_mask << 1;
- for (n = 1; (i + n) < 6; n++) {
- if ((bits & c) == 0)
- break;
- c <<= 1;
- }
- for (y = st->pos_y + i; y <
st->pos_y + i + n; ++y) {
- for (x = st->pos_x; x <
st->pos_x + st->repeat_count; ++x)
-
image->data[image->width * y + x] = st->color_index;
- }
- if (st->max_x < (st->pos_x +
st->repeat_count - 1))
- st->max_x = st->pos_x +
st->repeat_count - 1;
- if (st->max_y < (st->pos_y + i + n -
1))
- st->max_y = st->pos_y + i +
n - 1;
- i += (n - 1);
- sixel_vertical_mask <<= (n - 1);
- }
- sixel_vertical_mask <<= 1;
- }
- }
- }
- }
- if (st->repeat_count > 0)
- st->pos_x += st->repeat_count;
- st->repeat_count = 1;
- }
- break;
- }
- break;
-
- case PS_DECGRA:
- /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */
- switch (raw) {
- case '\x1b':
- st->state = PS_ESC;
- break;
- case '0' ... '9':
- st->param = st->param * 10 + raw - '0';
- if (st->param > DECSIXEL_PARAMVALUE_MAX)
- st->param = DECSIXEL_PARAMVALUE_MAX;
- break;
- case ';':
- if (st->nparams < DECSIXEL_PARAMS_MAX)
- st->params[st->nparams++] = st->param;
- st->param = 0;
- break;
- default:
- if (st->nparams < DECSIXEL_PARAMS_MAX)
- st->params[st->nparams++] = st->param;
- if (st->nparams > 0)
- st->attributed_pad = st->params[0];
- if (st->nparams > 1)
- st->attributed_pan = st->params[1];
- if (st->nparams > 2 && st->params[2] > 0)
- st->attributed_ph = st->params[2];
- if (st->nparams > 3 && st->params[3] > 0)
- st->attributed_pv = st->params[3];
-
- if (st->attributed_pan <= 0)
- st->attributed_pan = 1;
- if (st->attributed_pad <= 0)
- st->attributed_pad = 1;
-
- if (image->width < st->attributed_ph ||
- image->height < st->attributed_pv) {
- sx = st->attributed_ph;
- if (image->width > st->attributed_ph)
- sx = image->width;
-
- sy = st->attributed_pv;
- if (image->height > st->attributed_pv)
- sy = image->height;
-
- if (sx > DECSIXEL_WIDTH_MAX)
- sx = DECSIXEL_WIDTH_MAX;
- if (sy > DECSIXEL_HEIGHT_MAX)
- sy = DECSIXEL_HEIGHT_MAX;
-
- status = image_buffer_resize(image, sx, sy);
- if (status < 0)
- goto out;
- }
- st->state = PS_DECSIXEL;
- st->param = 0;
- st->nparams = 0;
- /* FIXME: No p++ increment here */
- goto again;
- }
- break;
-
- case PS_DECGRI:
- /* DECGRI Graphics Repeat Introducer ! Pn Ch */
- switch (raw) {
- case '\x1b':
- st->state = PS_ESC;
- break;
- case '0' ... '9':
- st->param = st->param * 10 + raw - '0';
- if (st->param > DECSIXEL_PARAMVALUE_MAX)
- st->param = DECSIXEL_PARAMVALUE_MAX;
- break;
- default:
- st->repeat_count = st->param;
- if (st->repeat_count == 0)
- st->repeat_count = 1;
- st->state = PS_DECSIXEL;
- st->param = 0;
- st->nparams = 0;
- /* FIXME: No p++ increment here */
- goto again;
- }
- break;
-
- case PS_DECGCI:
- /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */
- switch (raw) {
- case '\x1b':
- st->state = PS_ESC;
- break;
- case '0' ... '9':
- st->param = st->param * 10 + raw - '0';
- if (st->param > DECSIXEL_PARAMVALUE_MAX)
- st->param = DECSIXEL_PARAMVALUE_MAX;
- break;
- case ';':
- if (st->nparams < DECSIXEL_PARAMS_MAX)
- st->params[st->nparams++] = st->param;
- st->param = 0;
- break;
- default:
- st->state = PS_DECSIXEL;
- if (st->nparams < DECSIXEL_PARAMS_MAX)
- st->params[st->nparams++] = st->param;
- st->param = 0;
-
- if (st->nparams > 0) {
- st->color_index = 1 + st->params[0]; /* offset 1(background color) added */
- if (st->color_index < 0)
- st->color_index = 0;
- else if (st->color_index >= DECSIXEL_PALETTE_MAX)
- st->color_index = DECSIXEL_PALETTE_MAX - 1;
- }
-
- if (st->nparams > 4) {
- st->image.palette_modified = 1;
- if (st->params[1] == 1) {
- /* HLS */
- if (st->params[2] > 360)
- st->params[2] = 360;
- if (st->params[3] > 100)
- st->params[3] = 100;
- if (st->params[4] > 100)
- st->params[4] = 100;
- image->palette[st->color_index]
- = hls_to_rgb(st->params[2], st->params[3], st->params[4]);
- } else if (st->params[1] == 2) {
- /* RGB */
- if (st->params[2] > 100)
- st->params[2] = 100;
- if (st->params[3] > 100)
- st->params[3] = 100;
- if (st->params[4] > 100)
- st->params[4] = 100;
- image->palette[st->color_index]
- = SIXEL_XRGB(st->params[2], st->params[3], st->params[4]);
- }
- }
- /* FIXME: No p++ increment here */
- goto again;
- }
- break;
-
- default:
- break;
- }
-
- status = 0;
-
-out:
- return status;
+ return set_default_color(&st->image);
}
-/* convert sixel data into indexed pixel bytes and palette data */
int
sixel_parser_feed(sixel_state_t *st, const uint32_t *raw, size_t len)
{
@@ -736,16 +780,10 @@ sixel_parser_feed(sixel_state_t *st, const uint32_t *raw, size_t len)
return -1;
for (const uint32_t *p = raw; p < raw + len; p++) {
- status = feed_char(st, *p);
+ status = parser_feed_char(st, *p);
if (status < 0)
break;
}
return status;
}
-
-void
-sixel_parser_deinit(sixel_state_t *st)
-{
- sixel_image_deinit(&st->image);
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]