Compare commits

...

5 Commits

Author SHA1 Message Date
mintycube
33db255a2d Apply keyboard select patch 2024-07-10 11:34:03 +05:00
mintycube
3181d6876b add transparency and change font size
This takes effect only when using st as a scratchpad in dwm.
Otherwise transparency value from xresources is used.
Bug or a Feature??
2024-07-10 11:34:03 +05:00
Minty Cube
15639f8e0e
Merge branch 'bakkeby:master' into master 2024-07-10 10:42:52 +05:00
veltza
7a581fe4e1
sixel: improve the renderer (#143)
In the current implementation, when text is written over an image, we
have to cut the entire text line out of the image, regardless of how
long the text is. It doesn't look good, but it was a design choice for
the following reasons:
1) To keep the sixel engine as fast as possible
2) Most applications do not write text on the images anyway

To bring the st terminal in line with other terminals that support
sixels, I have now improved the sixel renderer so that the images can
now have gaps, which allows the text to be printed inside the images.
The changes should not affect performance in normal cases. Only when the
renderer has to deal with the text there might be some performance hits
depending on how many gaps there are in the images.
2024-07-07 21:18:09 +02:00
veltza
48c85cdcf5
sixel: refactor the sixel display mode (#142)
This does not change the current behavior of SDM.
2024-07-05 11:30:55 +02:00
6 changed files with 106 additions and 73 deletions

View File

@ -44,6 +44,9 @@ Personal build of st generated using [st-flexipatch](https://github.com/bakkeby/
- [iso14755](https://st.suckless.org/patches/iso14755/)
- pressing the default binding Ctrl+Shift-i will popup dmenu, asking you to enter a unicode codepoint that will be converted to a glyph and then pushed to st
- [keyboard-select](https://st.suckless.org/patches/keyboard_select/)
- allows you to select text on the terminal using keyboard shortcuts
- [ligatures](https://st.suckless.org/patches/ligatures/)
- adds support for drawing ligatures using the Harfbuzz library to transform original text of a single line to a list of glyphs with ligatures included

View File

@ -5,7 +5,7 @@
*
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
*/
static char *font = "JetBrains Mono:pixelsize=12:antialias=true:autohint=true";
static char *font = "JetBrains Mono:pixelsize=13:antialias=true:autohint=true";
#if FONT2_PATCH
/* Spare fonts */
static char *font2[] = {
@ -166,7 +166,7 @@ unsigned int tabspaces = 8;
#if ALPHA_PATCH
/* bg opacity */
float alpha = 1.0;
float alpha = 0.50;
#if ALPHA_GRADIENT_PATCH
float grad_alpha = 0.54; //alpha value that'll change
float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha

View File

@ -77,7 +77,7 @@ treflow_moveimages(int oldy, int newy)
void
treflow(int col, int row)
{
int i, j, x, x2;
int i, j;
int oce, nce, bot, scr;
int ox = 0, oy = -term.histf, nx = 0, ny = -1, len;
int cy = -1; /* proxy for new y coordinate of cursor */
@ -220,13 +220,12 @@ treflow(int col, int row)
}
/* expand images into new text cells */
for (im = term.images; im; im = next) {
next = im->next;
if (im->x < col) {
line = TLINE(im->y);
x2 = MIN(im->x + im->cols, col);
for (x = im->x; x < x2; x++)
line[x].mode |= ATTR_SIXEL;
for (im = term.images; im; im = im->next) {
j = MIN(im->x + im->cols, col);
line = TLINE(im->y);
for (i = im->x; i < j; i++) {
if (!(line[i].mode & ATTR_SET))
line[i].mode |= ATTR_SIXEL;
}
}
#endif // SIXEL_PATCH

View File

@ -223,7 +223,7 @@
*
* https://st.suckless.org/patches/keyboard_select/
*/
#define KEYBOARDSELECT_PATCH 0
#define KEYBOARDSELECT_PATCH 1
/* This patch adds support for drawing ligatures using the Harfbuzz library to transform
* original text of a single line to a list of glyphs with ligatures included.

77
st.c
View File

@ -220,6 +220,9 @@ static void tsetattr(const int *, int);
static void tsetchar(Rune, const Glyph *, int, int);
static void tsetdirt(int, int);
static void tsetscroll(int, int);
#if SIXEL_PATCH
static inline void tsetsixelattr(Line line, int x1, int x2);
#endif // SIXEL_PATCH
static void tswapscreen(void);
static void tsetmode(int, int, const int *, int);
static int twrite(const char *, int, int);
@ -1149,6 +1152,15 @@ tsetdirtattr(int attr)
}
}
#if SIXEL_PATCH
void
tsetsixelattr(Line line, int x1, int x2)
{
for (; x1 <= x2; x1++)
line[x1].mode |= ATTR_SIXEL;
}
#endif // SIXEL_PATCH
void
tfulldirt(void)
{
@ -2592,7 +2604,7 @@ strhandle(void)
};
#if SIXEL_PATCH
ImageList *im, *newimages, *next, *tail;
int i, x, y, x1, y1, x2, y2, numimages;
int i, x1, y1, x2, y2, numimages;
int cx, cy;
Line line;
#if SCROLLBACK_PATCH || REFLOW_PATCH
@ -2736,36 +2748,44 @@ strhandle(void)
} else {
term.images = newimages;
}
x2 = MIN(x2, term.col);
for (i = 0, im = newimages; im; im = next, i++) {
next = im->next;
#if SCROLLBACK_PATCH || REFLOW_PATCH
scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr;
#endif // SCROLLBACK_PATCH
if (IS_SET(MODE_SIXEL_SDM)) {
#if COLUMNS_PATCH && !REFLOW
x2 = MIN(x2, term.maxcol) - 1;
#else
x2 = MIN(x2, term.col) - 1;
#endif // COLUMNS_PATCH
if (IS_SET(MODE_SIXEL_SDM)) {
/* Sixel display mode: put the sixel in the upper left corner of
* the screen, disable scrolling (the sixel will be truncated if
* it is too long) and do not change the cursor position. */
for (i = 0, im = newimages; im; im = next, i++) {
next = im->next;
if (i >= term.row) {
delete_image(im);
continue;
}
im->y = i + scr;
line = term.line[i];
} else {
tsetsixelattr(term.line[i], x1, x2);
term.dirty[MIN(im->y, term.row-1)] = 1;
}
} else {
for (i = 0, im = newimages; im; im = next, i++) {
next = im->next;
#if SCROLLBACK_PATCH || REFLOW_PATCH
scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr;
#endif // SCROLLBACK_PATCH
im->y = term.c.y + scr;
line = term.line[term.c.y];
}
for (x = im->x; x < x2; x++) {
line[x].mode |= ATTR_SIXEL;
}
term.dirty[MIN(im->y, term.row-1)] = 1;
if (!IS_SET(MODE_SIXEL_SDM) && i < numimages-1) {
im->next = NULL;
tnewline(0);
im->next = next;
tsetsixelattr(term.line[term.c.y], x1, x2);
term.dirty[MIN(im->y, term.row-1)] = 1;
if (i < numimages-1) {
im->next = NULL;
tnewline(0);
im->next = next;
}
}
/* if mode 8452 is set, sixel scrolling leaves cursor to right of graphic */
if (IS_SET(MODE_SIXEL_CUR_RT))
term.c.x = MIN(term.c.x + newimages->cols, term.col-1);
}
/* if mode 8452 is set, sixel scrolling leaves cursor to right of graphic */
if (!IS_SET(MODE_SIXEL_SDM) && IS_SET(MODE_SIXEL_CUR_RT))
term.c.x = MIN(term.c.x + newimages->cols, term.col-1);
}
#endif // SIXEL_PATCH
#if SYNC_PATCH
@ -3505,7 +3525,7 @@ tresize(int col, int row)
#endif // COLUMNS_PATCH
int *bp;
#if SIXEL_PATCH
int x, x2;
int x2;
Line line;
ImageList *im, *next;
#endif // SIXEL_PATCH
@ -3612,8 +3632,7 @@ tresize(int col, int row)
}
#if SIXEL_PATCH
/* expand images into new text cells to prevent them from being deleted in
* xfinishdraw() that draws the images */
/* expand images into new text cells */
for (i = 0; i < 2; i++) {
for (im = term.images; im; im = next) {
next = im->next;
@ -3638,9 +3657,9 @@ tresize(int col, int row)
}
line = term.line[im->y];
#endif // SCROLLBACK_PATCH
x2 = MIN(im->x + im->cols, term.col);
for (x = im->x; x < x2; x++)
line[x].mode |= ATTR_SIXEL;
x2 = MIN(im->x + im->cols, col) - 1;
if (mincol < col && x2 >= mincol && im->x < col)
tsetsixelattr(line, MAX(im->x, mincol), x2);
}
tswapscreen();
}

78
x.c
View File

@ -3167,9 +3167,14 @@ xfinishdraw(void)
ImageList *im, *next;
Imlib_Image origin, scaled;
XGCValues gcvalues;
GC gc;
GC gc = NULL;
int width, height;
int x, x2, del, destx, desty;
int del, desty, mode, x1, x2, xend;
#if ANYSIZE_PATCH
int bw = win.hborderpx, bh = win.vborderpx;
#else
int bw = borderpx, bh = borderpx;
#endif // ANYSIZE_PATCH
Line line;
#endif // SIXEL_PATCH
@ -3260,43 +3265,50 @@ xfinishdraw(void)
}
}
/* clip the image so it does not go over to borders */
x2 = MIN(im->x + im->cols, term.col);
width = MIN(width, (x2 - im->x) * win.cw);
/* delete the image if the text cells behind it have been changed */
#if SCROLLBACK_PATCH || REFLOW_PATCH
line = TLINE(im->y);
#else
line = term.line[im->y];
#endif // SCROLLBACK_PATCH | REFLOW_PATCH
for (del = 0, x = im->x; x < x2; x++) {
if ((del = !(line[x].mode & ATTR_SIXEL)))
break;
}
if (del) {
delete_image(im);
continue;
/* create GC */
if (!gc) {
memset(&gcvalues, 0, sizeof(gcvalues));
gcvalues.graphics_exposures = False;
gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, &gcvalues);
}
/* draw the image */
memset(&gcvalues, 0, sizeof(gcvalues));
gcvalues.graphics_exposures = False;
gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, &gcvalues);
#if ANYSIZE_PATCH
destx = win.hborderpx + im->x * win.cw;
desty = win.vborderpx + im->y * win.ch;
#else
destx = borderpx + im->x * win.cw;
desty = borderpx + im->y * win.ch;
#endif // ANYSIZE_PATCH
/* set the clip mask */
desty = bh + im->y * win.ch;
if (im->clipmask) {
XSetClipMask(xw.dpy, gc, (Drawable)im->clipmask);
XSetClipOrigin(xw.dpy, gc, destx, desty);
XSetClipOrigin(xw.dpy, gc, bw + im->x * win.cw, desty);
}
XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, width, height, destx, desty);
XFreeGC(xw.dpy, gc);
/* draw only the parts of the image that are not erased */
#if SCROLLBACK_PATCH || REFLOW_PATCH
line = TLINE(im->y) + im->x;
#else
line = term.line[im->y] + im->x;
#endif // SCROLLBACK_PATCH || REFLOW_PATCH
xend = MIN(im->x + im->cols, term.col);
for (del = 1, x1 = im->x; x1 < xend; x1 = x2) {
mode = line->mode & ATTR_SIXEL;
for (x2 = x1 + 1; x2 < xend; x2++) {
if (((++line)->mode & ATTR_SIXEL) != mode)
break;
}
if (mode) {
XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc,
(x1 - im->x) * win.cw, 0,
MIN((x2 - x1) * win.cw, width - (x1 - im->x) * win.cw), height,
bw + x1 * win.cw, desty);
del = 0;
}
}
if (im->clipmask)
XSetClipMask(xw.dpy, gc, None);
/* if all the parts are erased, we can delete the entire image */
if (del && im->x + im->cols <= term.col)
delete_image(im);
}
if (gc)
XFreeGC(xw.dpy, gc);
#endif // SIXEL_PATCH
#if !SINGLE_DRAWABLE_BUFFER_PATCH