optimize drawing routines

This commit is contained in:
kolunmi 2023-02-09 20:26:10 -07:00
parent 38fcc46115
commit 729304fb1f

206
dwlb.c
View File

@ -226,47 +226,48 @@ draw_text(char *text,
pixman_image_t *background, pixman_image_t *background,
pixman_color_t *fgcolor, pixman_color_t *fgcolor,
pixman_color_t *bgcolor, pixman_color_t *bgcolor,
uint32_t surface_width, uint32_t maxxpos,
uint32_t height, uint32_t bufheight,
uint32_t padding, uint32_t padding,
bool commands) bool commands)
{ {
uint32_t codepoint; if (!*text || !maxxpos)
uint32_t state = UTF8_ACCEPT; return xpos;
uint32_t ixpos = xpos; uint32_t ixpos = xpos;
uint32_t nxpos; uint32_t nxpos;
uint32_t lastcp = 0;
if (!*text || !surface_width || xpos >= surface_width) if ((nxpos = xpos + padding) + padding >= maxxpos)
return xpos;
if ((nxpos = xpos + padding) > surface_width)
return xpos; return xpos;
xpos = nxpos; xpos = nxpos;
pixman_color_t cur_fgcolor = *fgcolor;
pixman_color_t cur_bgcolor;
if (background && bgcolor) {
cur_bgcolor = *bgcolor;
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
&cur_bgcolor, 1, &(pixman_box32_t){
.x1 = ixpos,
.x2 = xpos,
.y1 = 0,
.y2 = height
});
}
pixman_image_t *fgfill = pixman_image_create_solid_fill(fgcolor);
bool drawfg = foreground && fgcolor;
bool drawbg = background && bgcolor;
pixman_image_t *fgfill;
pixman_color_t cur_fgcolor;
pixman_color_t cur_bgcolor;
if (drawfg) {
fgfill = pixman_image_create_solid_fill(fgcolor);
cur_fgcolor = *fgcolor;
}
if (drawbg)
cur_bgcolor = *bgcolor;
uint32_t codepoint;
uint32_t state = UTF8_ACCEPT;
uint32_t lastcp = 0;
for (char *p = text; *p; p++) { for (char *p = text; *p; p++) {
/* Check for inline ^ commands */ /* If commands are enabled, check for inline ^ commands */
if (commands && state == UTF8_ACCEPT && *p == '^') { if (commands && state == UTF8_ACCEPT && *p == '^') {
p++; p++;
if (*p != '^') { if (*p != '^') {
p = handle_cmd(p, &cur_fgcolor, &cur_bgcolor, fgcolor, bgcolor); p = handle_cmd(p, &cur_fgcolor, &cur_bgcolor, fgcolor, bgcolor);
pixman_image_unref(fgfill); if (drawfg) {
fgfill = pixman_image_create_solid_fill(&cur_fgcolor); pixman_image_unref(fgfill);
fgfill = pixman_image_create_solid_fill(&cur_fgcolor);
}
continue; continue;
} }
} }
@ -285,62 +286,70 @@ draw_text(char *text,
long x_kern = 0; long x_kern = 0;
if (lastcp) if (lastcp)
fcft_kerning(font, lastcp, codepoint, &x_kern, NULL); fcft_kerning(font, lastcp, codepoint, &x_kern, NULL);
if ((nxpos = xpos + x_kern + glyph->advance.x) > surface_width) if ((nxpos = xpos + x_kern + glyph->advance.x) + padding > maxxpos)
break; break;
xpos += x_kern;
lastcp = codepoint; lastcp = codepoint;
xpos += x_kern;
/* Detect and handle pre-rendered glyphs (e.g. emoji) */ if (drawfg) {
if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) { /* Detect and handle pre-rendered glyphs (e.g. emoji) */
/* Only the alpha channel of the mask is used, so we can if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) {
* use fgfill here to blend prerendered glyphs with the /* Only the alpha channel of the mask is used, so we can
* same opacity */ * use fgfill here to blend prerendered glyphs with the
pixman_image_composite32( * same opacity */
PIXMAN_OP_OVER, glyph->pix, fgfill, foreground, 0, 0, 0, 0, pixman_image_composite32(
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height); PIXMAN_OP_OVER, glyph->pix, fgfill, foreground, 0, 0, 0, 0,
} else { xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height);
/* Applying the foreground color here would mess up } else {
* component alphas for subpixel-rendered text, so we /* Applying the foreground color here would mess up
* apply it when blending. */ * component alphas for subpixel-rendered text, so we
pixman_image_composite32( * apply it when blending. */
PIXMAN_OP_OVER, fgfill, glyph->pix, foreground, 0, 0, 0, 0, pixman_image_composite32(
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height); PIXMAN_OP_OVER, fgfill, glyph->pix, foreground, 0, 0, 0, 0,
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height);
}
} }
if (background && bgcolor) if (drawbg)
pixman_image_fill_boxes(PIXMAN_OP_OVER, background, pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
&cur_bgcolor, 1, &(pixman_box32_t){ &cur_bgcolor, 1, &(pixman_box32_t){
.x1 = xpos, .x1 = xpos, .x2 = nxpos,
.x2 = nxpos, .y1 = 0, .y2 = bufheight
.y1 = 0,
.y2 = height
}); });
/* increment pen position */ /* increment pen position */
xpos = nxpos; xpos = nxpos;
ypos += glyph->advance.y; ypos += glyph->advance.y;
} }
if (drawfg)
pixman_image_unref(fgfill);
if (!lastcp)
return ixpos;
if (state != UTF8_ACCEPT) if (state != UTF8_ACCEPT)
fprintf(stderr, "malformed UTF-8 sequence\n"); fprintf(stderr, "malformed UTF-8 sequence\n");
nxpos = MIN(xpos + padding, surface_width); nxpos = xpos + padding;
if (drawbg) {
if (background && bgcolor) /* Fill padding background */
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
&cur_bgcolor, 1, &(pixman_box32_t){
.x1 = ixpos, .x2 = ixpos + padding,
.y1 = 0, .y2 = bufheight
});
pixman_image_fill_boxes(PIXMAN_OP_OVER, background, pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
bgcolor, 1, &(pixman_box32_t){ bgcolor, 1, &(pixman_box32_t){
.x1 = xpos, .x1 = xpos, .x2 = nxpos,
.x2 = nxpos, .y1 = 0, .y2 = bufheight
.y1 = 0,
.y2 = height
}); });
xpos = nxpos; }
pixman_image_unref(fgfill); return nxpos;
return xpos;
} }
#define TEXT_WIDTH(text, maxxpos, padding, commands) \
draw_text(text, 0, 0, NULL, NULL, NULL, NULL, maxxpos, 0, padding, commands)
static int static int
draw_frame(Bar *b) draw_frame(Bar *b)
{ {
@ -364,22 +373,14 @@ draw_frame(Bar *b)
/* Pixman image corresponding to main buffer */ /* Pixman image corresponding to main buffer */
pixman_image_t *bar = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, data, b->width * 4); pixman_image_t *bar = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, data, b->width * 4);
/* Fill bar with background color */
pixman_image_fill_boxes(PIXMAN_OP_SRC, bar, b->selmon ? &activecolor : &inactivecolor, 1,
&(pixman_box32_t) {.x1 = 0, .x2 = b->width, .y1 = 0, .y2 = b->height});
/* Text background and foreground layers */ /* Text background and foreground layers */
pixman_image_t *background_left = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4); pixman_image_t *foreground = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
pixman_image_t *foreground_left = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4); pixman_image_t *background = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
pixman_image_t *background_right = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
pixman_image_t *foreground_right = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
pixman_image_t *foreground_title = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
/* Draw on images */ /* Draw on images */
uint32_t xpos_left = 0; uint32_t xpos_left = 0;
uint32_t xpos_right;
uint32_t ypos = (b->height + font->ascent - font->descent) / 2; uint32_t ypos = (b->height + font->ascent - font->descent) / 2;
uint32_t boxs = font->height / 9; uint32_t boxs = font->height / 9;
uint32_t boxw = font->height / 6 + 2; uint32_t boxw = font->height / 6 + 2;
@ -392,43 +393,44 @@ draw_frame(Bar *b)
continue; continue;
if (!hide_vacant && occupied) if (!hide_vacant && occupied)
pixman_image_fill_boxes(PIXMAN_OP_SRC, foreground_left, pixman_image_fill_boxes(PIXMAN_OP_SRC, foreground,
&textcolor, 1, &(pixman_box32_t){ &textcolor, 1, &(pixman_box32_t){
.x1 = xpos_left + boxs, .x1 = xpos_left + boxs, .x2 = xpos_left + boxs + boxw,
.x2 = xpos_left + boxs + boxw, .y1 = boxs, .y2 = boxs + boxw
.y1 = boxs,
.y2 = boxs + boxw
}); });
if (urgent) if (urgent)
xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, xpos_left = draw_text(tags[i], xpos_left, ypos, foreground, background, &urgtextcolor,
&urgtextcolor, &urgbgcolor, b->width, b->height, b->textpadding, false); &urgbgcolor, b->width, b->height, b->textpadding, false);
else else
xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, xpos_left = draw_text(tags[i], xpos_left, ypos, foreground, background, &textcolor,
&textcolor, active ? &activecolor : &inactivecolor, b->width, b->height, b->textpadding, false); active ? &activecolor : &inactivecolor, b->width, b->height,
b->textpadding, false);
} }
xpos_left = draw_text(b->layout, xpos_left, ypos, foreground_left, background_left, xpos_left = draw_text(b->layout, xpos_left, ypos, foreground, background, &textcolor,
&textcolor, &inactivecolor, b->width, b->height, b->textpadding, false); &inactivecolor, b->width, b->height, b->textpadding, false);
xpos_right = draw_text(b->status, 0, ypos, foreground_right, background_right, uint32_t status_width = TEXT_WIDTH(b->status, b->width - xpos_left, b->textpadding, true);
&textcolor, &inactivecolor, b->width, b->height, b->textpadding, true); draw_text(b->status, b->width - status_width, ypos, foreground, background, &textcolor,
&inactivecolor, b->width, b->height, b->textpadding, true);
draw_text(b->title, 0, ypos, foreground_title, NULL,
&textcolor, NULL, b->width, b->height, b->textpadding, false); xpos_left = draw_text(b->title, xpos_left, ypos, foreground, background, &textcolor,
b->selmon ? &activecolor : &inactivecolor, b->width - status_width,
b->height, b->textpadding, false);
pixman_image_fill_boxes(PIXMAN_OP_SRC, bar, b->selmon ? &activecolor : &inactivecolor, 1,
&(pixman_box32_t){
.x1 = xpos_left, .x2 = b->width - status_width,
.y1 = 0, .y2 = b->height
});
/* Draw background and foreground on bar */ /* Draw background and foreground on bar */
pixman_image_composite32(PIXMAN_OP_OVER, foreground_title, NULL, bar, 0, 0, 0, 0, xpos_left, 0, b->width, b->height); pixman_image_composite32(PIXMAN_OP_OVER, background, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
pixman_image_composite32(PIXMAN_OP_OVER, background_right, NULL, bar, 0, 0, 0, 0, b->width - xpos_right, 0, b->width, b->height); pixman_image_composite32(PIXMAN_OP_OVER, foreground, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
pixman_image_composite32(PIXMAN_OP_OVER, foreground_right, NULL, bar, 0, 0, 0, 0, b->width - xpos_right, 0, b->width, b->height);
pixman_image_composite32(PIXMAN_OP_OVER, background_left, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
pixman_image_composite32(PIXMAN_OP_OVER, foreground_left, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
pixman_image_unref(foreground_left); pixman_image_unref(foreground);
pixman_image_unref(background_left); pixman_image_unref(background);
pixman_image_unref(foreground_right);
pixman_image_unref(background_right);
pixman_image_unref(foreground_title);
pixman_image_unref(bar); pixman_image_unref(bar);
munmap(data, b->bufsize); munmap(data, b->bufsize);
@ -517,10 +519,10 @@ output_description(void *data, struct zxdg_output_v1 *xdg_output,
static const struct zxdg_output_v1_listener output_listener = { static const struct zxdg_output_v1_listener output_listener = {
.name = output_name, .name = output_name,
.description = output_description,
.done = output_done,
.logical_position = output_logical_position, .logical_position = output_logical_position,
.logical_size = output_logical_size .logical_size = output_logical_size,
.done = output_done,
.description = output_description
}; };
static void static void