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
|
||||
|
||||
20
x.c
20
x.c
@ -2949,29 +2949,20 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!im->pixmap) {
|
||||
im->pixmap = (void *)XCreatePixmap(xw.dpy, xw.win, im->width, im->height,
|
||||
@ -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