kitty: draw negative z-index images under the text
Images with a negative z-index are composited between the background and foreground passes of xdrawline, so that text renders on top of them with alpha blending, as the protocol requires.
This commit is contained in:
parent
cb1f41c9ae
commit
a4f4f96c62
129
kitty.c
129
kitty.c
@ -1941,6 +1941,8 @@ kitty_absorb_diacritic(Glyph *gp, Rune u)
|
|||||||
/* rendering */
|
/* rendering */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static int kitty_cmp(const void *a, const void *b);
|
||||||
|
|
||||||
/* nearest-neighbour + bilinear scaling of a source rect to w x h RGBA */
|
/* nearest-neighbour + bilinear scaling of a source rect to w x h RGBA */
|
||||||
static unsigned char *
|
static unsigned char *
|
||||||
kitty_scale(const unsigned char *src, int sw, int sh, int stride,
|
kitty_scale(const unsigned char *src, int sw, int sh, int stride,
|
||||||
@ -2063,6 +2065,96 @@ kitty_prepare(KittyPlacement *p, int *outw, int *outh)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* like kitty_blit but restricted to the cell span [cx1, cx2) on row cy */
|
||||||
|
static void
|
||||||
|
kitty_blit_clipped(KittyPlacement *p, int px, int py, int cx1, int cx2, int cy)
|
||||||
|
{
|
||||||
|
Picture src, dstpic;
|
||||||
|
XRenderPictFormat *fmt;
|
||||||
|
XRenderPictureAttributes pa;
|
||||||
|
int w, h, bx, by;
|
||||||
|
int x0, x1, y0, y1; /* clip rect in window pixels */
|
||||||
|
int ix0, iy0; /* image origin in window pixels */
|
||||||
|
int sxo, syo, cw, chh;
|
||||||
|
|
||||||
|
if (!kitty_prepare(p, &w, &h))
|
||||||
|
return;
|
||||||
|
|
||||||
|
kitty_border(&bx, &by);
|
||||||
|
ix0 = bx + px * win.cw + p->xoff;
|
||||||
|
iy0 = by + (py - kitty_scr()) * win.ch + p->yoff;
|
||||||
|
|
||||||
|
x0 = KMAX(ix0, bx + cx1 * win.cw);
|
||||||
|
x1 = KMIN(ix0 + w, bx + cx2 * win.cw);
|
||||||
|
y0 = KMAX(iy0, by + cy * win.ch);
|
||||||
|
y1 = KMIN(iy0 + h, by + (cy + 1) * win.ch);
|
||||||
|
x1 = KMIN(x1, bx + win.tw);
|
||||||
|
y1 = KMIN(y1, by + win.th);
|
||||||
|
if (x1 <= x0 || y1 <= y0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sxo = x0 - ix0;
|
||||||
|
syo = y0 - iy0;
|
||||||
|
cw = x1 - x0;
|
||||||
|
chh = y1 - y0;
|
||||||
|
|
||||||
|
memset(&pa, 0, sizeof pa);
|
||||||
|
fmt = XRenderFindStandardFormat(xw.dpy, PictStandardARGB32);
|
||||||
|
if (!fmt)
|
||||||
|
return;
|
||||||
|
src = XRenderCreatePicture(xw.dpy, (Drawable)p->pixmap, fmt, 0, &pa);
|
||||||
|
fmt = XRenderFindVisualFormat(xw.dpy, xw.vis);
|
||||||
|
if (fmt) {
|
||||||
|
dstpic = XRenderCreatePicture(xw.dpy, xw.buf, fmt, 0, &pa);
|
||||||
|
XRenderComposite(xw.dpy, PictOpOver, src, None, dstpic,
|
||||||
|
sxo, syo, 0, 0, x0, y0, cw, chh);
|
||||||
|
XRenderFreePicture(xw.dpy, dstpic);
|
||||||
|
}
|
||||||
|
XRenderFreePicture(xw.dpy, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Composite the negative z-index images covering the cell span
|
||||||
|
* [x1, x2) on row y. Called after the background has been painted but
|
||||||
|
* before the glyphs, so that text appears on top of the image.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
kitty_draw_under_cells(int x1, int y, int x2)
|
||||||
|
{
|
||||||
|
KittyPlacement **list = NULL, *p;
|
||||||
|
int n = 0, cap = 0, i;
|
||||||
|
int s = IS_SET(MODE_ALTSCREEN) ? 1 : 0;
|
||||||
|
int scr = kitty_scr();
|
||||||
|
|
||||||
|
for (p = placements[s]; p; p = p->next) {
|
||||||
|
int px, py;
|
||||||
|
if (p->virt || p->z >= 0)
|
||||||
|
continue;
|
||||||
|
if (!kitty_resolve_pos(p, &px, &py, 0))
|
||||||
|
continue;
|
||||||
|
py -= scr;
|
||||||
|
if (px >= x2 || px + p->cols <= x1 || py > y || py + p->rows <= y)
|
||||||
|
continue;
|
||||||
|
if (n >= cap) {
|
||||||
|
int ncap = cap ? cap * 2 : 8;
|
||||||
|
KittyPlacement **t = realloc(list, ncap * sizeof *t);
|
||||||
|
if (!t)
|
||||||
|
break;
|
||||||
|
list = t;
|
||||||
|
cap = ncap;
|
||||||
|
}
|
||||||
|
list[n++] = p;
|
||||||
|
}
|
||||||
|
if (n > 1)
|
||||||
|
qsort(list, n, sizeof *list, kitty_cmp);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
int px, py;
|
||||||
|
if (kitty_resolve_pos(list[i], &px, &py, 0))
|
||||||
|
kitty_blit_clipped(list[i], px, py, x1, x2, y);
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kitty_blit(KittyPlacement *p, int px, int py)
|
kitty_blit(KittyPlacement *p, int px, int py)
|
||||||
{
|
{
|
||||||
@ -2401,8 +2493,12 @@ kitty_draw_placeholders(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*
|
||||||
kitty_draw(void)
|
* Draw the visible placements whose z-index falls in [zlo, zhi].
|
||||||
|
* Negative z-index images are drawn under the text (see kitty_draw_under).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
kitty_draw_range(int zlo, int zhi)
|
||||||
{
|
{
|
||||||
KittyPlacement **list = NULL, *p;
|
KittyPlacement **list = NULL, *p;
|
||||||
int n = 0, cap = 0, i;
|
int n = 0, cap = 0, i;
|
||||||
@ -2416,6 +2512,8 @@ kitty_draw(void)
|
|||||||
int px, py;
|
int px, py;
|
||||||
if (p->virt)
|
if (p->virt)
|
||||||
continue;
|
continue;
|
||||||
|
if (p->z < zlo || p->z > zhi)
|
||||||
|
continue;
|
||||||
if (!kitty_resolve_pos(p, &px, &py, 0))
|
if (!kitty_resolve_pos(p, &px, &py, 0))
|
||||||
continue;
|
continue;
|
||||||
if (px >= term.col || py - scr >= term.row || py - scr + p->rows <= 0)
|
if (px >= term.col || py - scr >= term.row || py - scr + p->rows <= 0)
|
||||||
@ -2441,11 +2539,38 @@ kitty_draw(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(list);
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
kitty_draw(void)
|
||||||
|
{
|
||||||
|
kitty_draw_range(0, INT_MAX);
|
||||||
|
|
||||||
/* images displayed via Unicode placeholders */
|
/* images displayed via Unicode placeholders */
|
||||||
kitty_draw_placeholders();
|
kitty_draw_placeholders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* is the cell (x, y) covered by an image drawn under the text? */
|
||||||
|
int
|
||||||
|
kitty_cell_under(int x, int y)
|
||||||
|
{
|
||||||
|
KittyPlacement *p;
|
||||||
|
int s = IS_SET(MODE_ALTSCREEN) ? 1 : 0;
|
||||||
|
int scr = kitty_scr();
|
||||||
|
|
||||||
|
for (p = placements[s]; p; p = p->next) {
|
||||||
|
int px, py;
|
||||||
|
if (p->virt || p->z >= 0)
|
||||||
|
continue;
|
||||||
|
if (!kitty_resolve_pos(p, &px, &py, 0))
|
||||||
|
continue;
|
||||||
|
py -= scr;
|
||||||
|
if (x >= px && x < px + p->cols && y >= py && y < py + p->rows)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* terminal lifecycle hooks */
|
/* terminal lifecycle hooks */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|||||||
2
kitty.h
2
kitty.h
@ -76,6 +76,8 @@ typedef struct KittyPlacement {
|
|||||||
/* entry points used by st.c / x.c */
|
/* entry points used by st.c / x.c */
|
||||||
void kitty_apc(const char *buf, size_t len);
|
void kitty_apc(const char *buf, size_t len);
|
||||||
void kitty_draw(void);
|
void kitty_draw(void);
|
||||||
|
void kitty_draw_under_cells(int x1, int y, int x2);
|
||||||
|
int kitty_cell_under(int x, int y);
|
||||||
void kitty_scroll(int top, int bot, int n, int save);
|
void kitty_scroll(int top, int bot, int n, int save);
|
||||||
void kitty_deleteplacements(int alt);
|
void kitty_deleteplacements(int alt);
|
||||||
void kitty_clearregion(int x1, int y1, int x2, int y2);
|
void kitty_clearregion(int x1, int y1, int x2, int y2);
|
||||||
|
|||||||
5
x.c
5
x.c
@ -3065,6 +3065,11 @@ xdrawline(Line line, int x1, int y1, int x2)
|
|||||||
/* Draw line in 2 passes: background and foreground. This way wide glyphs
|
/* Draw line in 2 passes: background and foreground. This way wide glyphs
|
||||||
won't get truncated (#223) */
|
won't get truncated (#223) */
|
||||||
for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
|
for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
|
||||||
|
#if KITTY_GRAPHICS_PATCH
|
||||||
|
/* negative z-index images sit between the background and the text */
|
||||||
|
if (dmode == DRAW_FG)
|
||||||
|
kitty_draw_under_cells(x1, y1, x2);
|
||||||
|
#endif // KITTY_GRAPHICS_PATCH
|
||||||
specs = xw.specbuf;
|
specs = xw.specbuf;
|
||||||
numspecs = numspecs_cached;
|
numspecs = numspecs_cached;
|
||||||
i = ox = 0;
|
i = ox = 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user