mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
sixel: add sixel_split_by_rectangle()
This function splits a sixel image into up to four pieces. The four pieces correspond to the relative complement (set difference) of the sixel image and the specified rectangle. Use this function when (possibly) overwriting existing sixel images when generating a new one, i.e. in sixel_unhook().
This commit is contained in:
parent
f4fcdbf38b
commit
dfc205e706
2 changed files with 74 additions and 58 deletions
131
sixel.c
131
sixel.c
|
|
@ -164,103 +164,102 @@ sixel_delete_in_range(struct terminal *term, int _start, int _end)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
sixel_delete_at_cursor(struct terminal *term)
|
||||
{
|
||||
sixel_delete_at_point(
|
||||
term, term->grid->cursor.point.row, term->grid->cursor.point.col);
|
||||
}
|
||||
|
||||
static void
|
||||
sixel_split(struct terminal *term, struct sixel *six, int row, int col)
|
||||
sixel_split(struct terminal *term, struct sixel *six,
|
||||
int row, int col, int height, int width)
|
||||
{
|
||||
assert(row >= six->pos.row);
|
||||
assert(row < six->pos.row + six->rows);
|
||||
assert(col >= six->pos.col);
|
||||
assert(col < six->pos.col + six->cols);
|
||||
int rel_above = max(row - six->pos.row, 0);
|
||||
int rel_below = min(row + height - six->pos.row, six->rows);
|
||||
int rel_left = max(col - six->pos.col, 0);
|
||||
int rel_right = min(col + width - six->pos.col, six->cols);
|
||||
|
||||
int rel_row = row - six->pos.row;
|
||||
int rel_col = col - six->pos.col;
|
||||
assert(rel_above >= 0);
|
||||
assert(rel_below >= 0);
|
||||
assert(rel_left >= 0);
|
||||
assert(rel_right >= 0);
|
||||
|
||||
if (rel_row > 0) {
|
||||
LOG_DBG("SPLIT: six (%p): %dx%d-%dx%d, %dx%d-%dx%d, rel: above=%d, below=%d, left=%d, right=%d",
|
||||
six, six->pos.row, six->pos.col, six->rows, six->cols,
|
||||
row, col, height, width,
|
||||
rel_above, rel_below, rel_left, rel_right);
|
||||
|
||||
if (rel_above > 0) {
|
||||
struct sixel above = {
|
||||
.width = six->width,
|
||||
.height = rel_row * term->cell_height,
|
||||
.rows = rel_row,
|
||||
.height = rel_above * term->cell_height,
|
||||
.rows = rel_above,
|
||||
.cols = six->cols,
|
||||
.pos = six->pos,
|
||||
};
|
||||
above.data = malloc(above.width * above.height * sizeof(uint32_t));
|
||||
memcpy(above.data, six->data, above.width * above.height * sizeof(uint32_t));
|
||||
|
||||
above.pix = pixman_image_create_bits_no_clear(
|
||||
PIXMAN_a8r8g8b8,
|
||||
above.width, above.height,
|
||||
above.data, above.width * sizeof(uint32_t));
|
||||
|
||||
tll_push_back(term->grid->sixel_images, above);
|
||||
}
|
||||
|
||||
if (rel_row + 1 < six->rows) {
|
||||
if (rel_below < six->rows) {
|
||||
struct sixel below = {
|
||||
.width = six->width,
|
||||
.height = six->height - (rel_row + 1) * term->cell_height,
|
||||
.rows = six->rows - (rel_row + 1),
|
||||
.height = six->height - rel_below * term->cell_height,
|
||||
.rows = six->rows - rel_below,
|
||||
.cols = six->cols,
|
||||
.pos = (struct coord){
|
||||
six->pos.col,
|
||||
(six->pos.row + rel_row + 1) & (term->grid->num_rows - 1)},
|
||||
(six->pos.row + rel_below) & (term->grid->num_rows - 1)},
|
||||
};
|
||||
below.data = malloc(below.width * below.height * sizeof(uint32_t));
|
||||
memcpy(
|
||||
below.data,
|
||||
&((const uint32_t *)six->data)[(rel_row + 1) * term->cell_height * six->width],
|
||||
&((const uint32_t *)six->data)[rel_below * term->cell_height * six->width],
|
||||
below.width * below.height * sizeof(uint32_t));
|
||||
below.pix = pixman_image_create_bits_no_clear(
|
||||
PIXMAN_a8r8g8b8,
|
||||
below.width, below.height,
|
||||
below.data, below.width * sizeof(uint32_t));
|
||||
|
||||
tll_push_back(term->grid->sixel_images, below);
|
||||
}
|
||||
|
||||
if (rel_col > 0) {
|
||||
if (rel_left > 0) {
|
||||
struct sixel left = {
|
||||
.width = rel_col * term->cell_width,
|
||||
.height = min(term->cell_height, six->height - rel_row * term->cell_height),
|
||||
.width = rel_left * term->cell_width,
|
||||
.height = min(term->cell_height, six->height - rel_above * term->cell_height),
|
||||
.rows = 1,
|
||||
.cols = rel_col,
|
||||
.pos = (struct coord){six->pos.col,
|
||||
(six->pos.row + rel_row) & (term->grid->num_rows - 1)},
|
||||
.cols = rel_left,
|
||||
.pos = (struct coord){
|
||||
six->pos.col,
|
||||
(six->pos.row + rel_above) & (term->grid->num_rows - 1)},
|
||||
};
|
||||
left.data = malloc(left.width * left.height * sizeof(uint32_t));
|
||||
for (size_t i = 0; i < term->cell_height; i++)
|
||||
memcpy(
|
||||
&((uint32_t *)left.data)[i * left.width],
|
||||
&((const uint32_t *)six->data)[(rel_row * term->cell_height + i) * six->width],
|
||||
&((const uint32_t *)six->data)[(rel_above * term->cell_height + i) * six->width],
|
||||
left.width * sizeof(uint32_t));
|
||||
left.pix = pixman_image_create_bits_no_clear(
|
||||
PIXMAN_a8r8g8b8,
|
||||
left.width, left.height,
|
||||
left.data, left.width * sizeof(uint32_t));
|
||||
tll_push_back(term->grid->sixel_images, left);
|
||||
|
||||
}
|
||||
|
||||
if (rel_col + 1 < six->cols) {
|
||||
if (rel_right < six->cols) {
|
||||
struct sixel right = {
|
||||
.width = six->width - (rel_col + 1) * term->cell_width,
|
||||
.height = min(term->cell_height, six->height - rel_row * term->cell_height),
|
||||
.width = six->width - rel_right * term->cell_width,
|
||||
.height = min(term->cell_height, six->height - rel_above * term->cell_height),
|
||||
.rows = 1,
|
||||
.cols = six->cols - (rel_col + 1),
|
||||
.pos = (struct coord){six->pos.col + rel_col + 1,
|
||||
(six->pos.row + rel_row) & (term->grid->num_rows - 1)},
|
||||
.cols = six->cols - rel_right,
|
||||
.pos = (struct coord){
|
||||
six->pos.col + rel_right,
|
||||
(six->pos.row + rel_above) & (term->grid->num_rows - 1)},
|
||||
};
|
||||
right.data = malloc(right.width * right.height * sizeof(uint32_t));
|
||||
for (size_t i = 0; i < term->cell_height; i++)
|
||||
memcpy(
|
||||
&((uint32_t *)right.data)[i * right.width],
|
||||
&((const uint32_t *)six->data)[(rel_row * term->cell_height + i) * six->width + (rel_col + 1) * term->cell_width],
|
||||
&((const uint32_t *)six->data)[(rel_above * term->cell_height + i) * six->width + rel_right * term->cell_width],
|
||||
right.width * sizeof(uint32_t));
|
||||
right.pix = pixman_image_create_bits_no_clear(
|
||||
PIXMAN_a8r8g8b8,
|
||||
|
|
@ -270,27 +269,46 @@ sixel_split(struct terminal *term, struct sixel *six, int row, int col)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
sixel_split_at_point(struct terminal *term, int _row, int col)
|
||||
static void
|
||||
sixel_split_by_rectangle(struct terminal *term, int _row,
|
||||
int col, int height, int width)
|
||||
{
|
||||
if (likely(tll_length(term->grid->sixel_images) == 0))
|
||||
return;
|
||||
|
||||
const int row = (term->grid->offset + _row) & (term->grid->num_rows - 1);
|
||||
const int start = (term->grid->offset + _row) & (term->grid->num_rows - 1);
|
||||
const int end = (start + height - 1) & (term->grid->num_rows - 1);
|
||||
const bool wraps = end < start;
|
||||
|
||||
tll_foreach(term->grid->sixel_images, it) {
|
||||
struct sixel *six = &it->item;
|
||||
|
||||
const int six_start = six->pos.row;
|
||||
const int six_end = six_start + six->rows - 1;
|
||||
const int six_end = (six_start + six->rows - 1) & (term->grid->num_rows - 1);
|
||||
const bool six_wraps = six_end < six_start;
|
||||
|
||||
if (row >= six_start && row <= six_end) {
|
||||
if ((six_wraps == wraps &&
|
||||
((start <= six_start && end >= six_start) || /* Crosses sixel start boundary */
|
||||
(start <= six_end && end >= six_end) || /* Crosses sixel end boundary */
|
||||
(start >= six_start && end <= six_end))) || /* Fully within sixel range */
|
||||
(six_wraps && !wraps &&
|
||||
((start <= six_start && end >= six_start) ||
|
||||
(start <= six_end && end >= six_end) ||
|
||||
(start >= six_start || end <= six_end))) ||
|
||||
(!six_wraps && wraps &&
|
||||
((six_start <= start && six_end >= end) || /* Sixel croses region start boundary */
|
||||
(six_start <= end && six_end >= end) || /* Sixel crosses region end boundary */
|
||||
(six_start >= start || six_end <= end))) /* Sixel is fully enclosed by region */
|
||||
)
|
||||
{
|
||||
const int col_start = six->pos.col;
|
||||
const int col_end = six->pos.col + six->cols;
|
||||
const int col_end = six->pos.col + six->cols - 1;
|
||||
|
||||
if (col >= col_start && col < col_end) {
|
||||
//sixel_erase(term, six);
|
||||
sixel_split(term, six, row, col);
|
||||
if ((col <= col_start && col + width - 1 >= col_start) ||
|
||||
(col <= col_end && col + width - 1 >= col_end) ||
|
||||
(col >= col_start && col + width - 1 <= col_end))
|
||||
{
|
||||
sixel_split(term, six, start, col, height, width);
|
||||
sixel_erase(term, six);
|
||||
tll_remove(term->grid->sixel_images, it);
|
||||
}
|
||||
|
|
@ -301,14 +319,13 @@ sixel_split_at_point(struct terminal *term, int _row, int col)
|
|||
void
|
||||
sixel_split_at_cursor(struct terminal *term)
|
||||
{
|
||||
sixel_split_at_point(term, term->grid->cursor.point.row, term->grid->cursor.point.col);
|
||||
sixel_split_by_rectangle(
|
||||
term, term->grid->cursor.point.row, term->grid->cursor.point.col, 1, 1);
|
||||
}
|
||||
|
||||
void
|
||||
sixel_unhook(struct terminal *term)
|
||||
{
|
||||
//sixel_delete_at_cursor(term);
|
||||
|
||||
struct sixel image = {
|
||||
.data = term->sixel.image.data,
|
||||
.width = term->sixel.image.width,
|
||||
|
|
@ -320,12 +337,12 @@ sixel_unhook(struct terminal *term)
|
|||
(term->grid->offset + term->grid->cursor.point.row) & (term->grid->num_rows - 1)},
|
||||
};
|
||||
|
||||
for (int row = 0; row < image.rows; row++) {
|
||||
for (int col = 0; col < image.cols; col++)
|
||||
sixel_split_at_point(term, term->grid->cursor.point.row + row, term->grid->cursor.point.col + col);
|
||||
}
|
||||
sixel_split_by_rectangle(
|
||||
term,
|
||||
term->grid->cursor.point.row, term->grid->cursor.point.col,
|
||||
image.rows, image.cols);
|
||||
|
||||
LOG_DBG("generating %dx%d pixman image", image.width, image.height);
|
||||
LOG_DBG("generating %dx%d pixman image at %d-%d", image.width, image.height, image.pos.row, image.pos.row + image.rows);
|
||||
|
||||
image.pix = pixman_image_create_bits_no_clear(
|
||||
PIXMAN_a8r8g8b8,
|
||||
|
|
|
|||
1
sixel.h
1
sixel.h
|
|
@ -14,7 +14,6 @@ void sixel_destroy(struct sixel *sixel);
|
|||
|
||||
void sixel_delete_in_range(struct terminal *term, int start, int end);
|
||||
void sixel_delete_at_row(struct terminal *term, int _row);
|
||||
void sixel_delete_at_cursor(struct terminal *term);
|
||||
void sixel_split_at_cursor(struct terminal *term);
|
||||
|
||||
void sixel_colors_report_current(struct terminal *term);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue