Fix sixel issues and add a clearing sequence (#99)
This patch fixes the following sixel issues: - The current sixel implementation cleared all cells from the left side of the image when the image was drawn. The fix only clears the cells where the image will be drawn. - The deletion routine didn't work correctly. In certain situations, it left the image or images undrawn. For example, if the first image was marked for deletion, it didn't draw the second one. - The drawing routine caused a high cpu usage, because XCopyArea() triggered the X server to send the NoExpose event, which caused sixels to be redrawn and the X server to send another NoExpose event and so on. This loop caused constant redraw of sixels and high cpu usage. The fix prevents the X server from sending GraphicsExpose and NoExpose events. The patch also adds a control sequence for removing sixels: Because the sixels are implemented as overlay images, they cannot be removed by clearing the underlaying cells. Therefore, we need a control sequence to remove them. I opted to choose ESC[6J as the control sequence because it is not used and the number refers to sixels. So when the lf file manager supports sixels [1], you can use the following minimal scripts to preview images in lf: previewer: #!/bin/sh case "$(readlink -f "$1")" in *.bmp|*.gif|*.jpg|*.jpeg|*.png|*.webp|*.six|*.svg|*.xpm) chafa -s "$(($2-3))x$3" -f sixels "$1" exit 1 ;; *) bat "$1" ;; esac cleaner: #!/bin/sh printf "\033[6J" >/dev/tty [1] https://github.com/gokcehan/lf/pull/1211
This commit is contained in:
parent
1343b29ee5
commit
677f854c05
10
st.c
10
st.c
@ -2297,6 +2297,12 @@ csihandle(void)
|
||||
}
|
||||
#endif // SIXEL_PATCH
|
||||
break;
|
||||
#if SIXEL_PATCH
|
||||
case 6: /* sixels */
|
||||
for (im = term.images; im; im = im->next)
|
||||
im->should_delete = 1;
|
||||
break;
|
||||
#endif // SIXEL_PATCH
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
@ -2658,10 +2664,10 @@ strhandle(void)
|
||||
}
|
||||
for (i = 0; i < (sixel_st.image.height + win.ch-1)/win.ch; ++i) {
|
||||
int x;
|
||||
tclearregion(term.c.x, term.c.y, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw, term.c.y);
|
||||
tclearregion(term.c.x, term.c.y, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw-1, term.c.y);
|
||||
for (x = term.c.x; x < MIN(term.col, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw); x++)
|
||||
term.line[term.c.y][x].mode |= ATTR_SIXEL;
|
||||
tnewline(1);
|
||||
tnewline(0);
|
||||
}
|
||||
}
|
||||
#endif // SIXEL_PATCH
|
||||
|
22
x.c
22
x.c
@ -2949,28 +2949,19 @@ void
|
||||
xfinishdraw(void)
|
||||
{
|
||||
#if SIXEL_PATCH
|
||||
ImageList *im;
|
||||
ImageList *im, *next;
|
||||
XGCValues gcvalues;
|
||||
GC gc;
|
||||
#endif // SIXEL_PATCH
|
||||
|
||||
#if SIXEL_PATCH
|
||||
for (im = term.images; im; im = im->next) {
|
||||
if (term.images == NULL) {
|
||||
/* last image was deleted, bail out */
|
||||
break;
|
||||
}
|
||||
for (im = term.images; im; im = next) {
|
||||
/* get the next image here, because delete_image() will delete the current image */
|
||||
next = im->next;
|
||||
|
||||
if (im->should_delete) {
|
||||
delete_image(im);
|
||||
|
||||
/* prevent the next iteration from accessing an invalid image pointer */
|
||||
im = term.images;
|
||||
if (im == NULL) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!im->pixmap) {
|
||||
@ -3005,7 +2996,8 @@ xfinishdraw(void)
|
||||
}
|
||||
|
||||
memset(&gcvalues, 0, sizeof(gcvalues));
|
||||
gc = XCreateGC(xw.dpy, xw.win, 0, &gcvalues);
|
||||
gcvalues.graphics_exposures = False;
|
||||
gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, &gcvalues);
|
||||
|
||||
#if ANYSIZE_PATCH
|
||||
XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, im->width, im->height, win.hborderpx + im->x * win.cw, win.vborderpx + im->y * win.ch);
|
||||
|
Loading…
Reference in New Issue
Block a user