mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-13 04:27:47 -05:00
render: replace all usage of cairo with pixman
This commit is contained in:
parent
bed7b34c28
commit
81107753bf
5 changed files with 90 additions and 81 deletions
4
config.c
4
config.c
|
|
@ -224,7 +224,7 @@ parse_section_colors(const char *key, const char *value, struct config *conf,
|
|||
return false;
|
||||
}
|
||||
|
||||
conf->colors.alpha = alpha;
|
||||
conf->colors.alpha = alpha * 65535.;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -466,7 +466,7 @@ config_load(struct config *conf)
|
|||
default_bright[6],
|
||||
default_bright[7],
|
||||
},
|
||||
.alpha = 1.,
|
||||
.alpha = 0xffff,
|
||||
},
|
||||
|
||||
.cursor = {
|
||||
|
|
|
|||
2
config.h
2
config.h
|
|
@ -18,7 +18,7 @@ struct config {
|
|||
uint32_t bg;
|
||||
uint32_t regular[8];
|
||||
uint32_t bright[8];
|
||||
double alpha;
|
||||
uint16_t alpha;
|
||||
} colors;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
8
font.h
8
font.h
|
|
@ -41,13 +41,13 @@ struct font {
|
|||
double pixel_size_fixup; /* Scale factor - should only be used with ARGB32 glyphs */
|
||||
|
||||
struct {
|
||||
double position;
|
||||
double thickness;
|
||||
int position;
|
||||
int thickness;
|
||||
} underline;
|
||||
|
||||
struct {
|
||||
double position;
|
||||
double thickness;
|
||||
int position;
|
||||
int thickness;
|
||||
} strikeout;
|
||||
|
||||
bool is_fallback;
|
||||
|
|
|
|||
4
main.c
4
main.c
|
|
@ -555,8 +555,8 @@ main(int argc, char *const *argv)
|
|||
LOG_DBG("ft: x-scale: %f, height: %f, descent: %f",
|
||||
x_scale, height, descent);
|
||||
|
||||
f->underline.position = ft_face->underline_position * x_scale / 64.;
|
||||
f->underline.thickness = ft_face->underline_thickness * x_scale / 64.;
|
||||
f->underline.position = round(ft_face->underline_position * x_scale / 64.);
|
||||
f->underline.thickness = ceil(ft_face->underline_thickness * x_scale / 64.);
|
||||
|
||||
if (f->underline.position == 0.) {
|
||||
f->underline.position = descent / 2.;
|
||||
|
|
|
|||
153
render.c
153
render.c
|
|
@ -37,15 +37,23 @@ color_hex_to_rgb(uint32_t color)
|
|||
};
|
||||
}
|
||||
|
||||
static inline pixman_color_t
|
||||
color_hex_to_pixman_with_alpha(uint32_t color, uint16_t alpha)
|
||||
{
|
||||
int alpha_div = 0xffff / alpha;
|
||||
return (pixman_color_t){
|
||||
.red = ((color >> 16 & 0xff) | (color >> 8 & 0xff00)) / alpha_div,
|
||||
.green = ((color >> 8 & 0xff) | (color >> 0 & 0xff00)) / alpha_div,
|
||||
.blue = ((color >> 0 & 0xff) | (color << 8 & 0xff00)) / alpha_div,
|
||||
.alpha = alpha,
|
||||
};
|
||||
}
|
||||
|
||||
static inline pixman_color_t
|
||||
color_hex_to_pixman(uint32_t color)
|
||||
{
|
||||
return (pixman_color_t){
|
||||
.red = (((color >> 16) & 0xff) + 1) * 256 - 1,
|
||||
.green = (((color >> 8) & 0xff) + 1) * 256 - 1,
|
||||
.blue = (((color >> 0) & 0xff) + 1) * 256 - 1,
|
||||
.alpha = -1,
|
||||
};
|
||||
/* Count on the compiler optimizing this */
|
||||
return color_hex_to_pixman_with_alpha(color, 0xffff);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -65,47 +73,41 @@ pixman_color_dim(pixman_color_t *color)
|
|||
}
|
||||
|
||||
static void
|
||||
draw_underline(const struct terminal *term, cairo_t *cr, const struct font *font,
|
||||
struct rgb color, double x, double y, int cols)
|
||||
draw_bar(const struct terminal *term, pixman_image_t *pix,
|
||||
const pixman_color_t *color, int x, int y)
|
||||
{
|
||||
double baseline = y + term->fextents.height - term->fextents.descent;
|
||||
double width = font->underline.thickness;
|
||||
double y_under = baseline - font->underline.position - width / 2.;
|
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgb(cr, color.r, color.g, color.b);
|
||||
cairo_set_line_width(cr, width);
|
||||
cairo_move_to(cr, x, round(y_under) + 0.5);
|
||||
cairo_rel_line_to(cr, cols * term->cell_width, 0);
|
||||
cairo_stroke(cr);
|
||||
/* TODO: investigate if this is the best way */
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, pix, color,
|
||||
1, &(pixman_rectangle16_t){x, y, 1, term->cell_height});
|
||||
}
|
||||
|
||||
static void
|
||||
draw_bar(const struct terminal *term, cairo_t *cr, struct rgb color,
|
||||
double x, double y)
|
||||
draw_underline(const struct terminal *term, pixman_image_t *pix,
|
||||
const struct font *font,
|
||||
const pixman_color_t *color, int x, int y, int cols)
|
||||
{
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgb(cr, color.r, color.g, color.b);
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
cairo_move_to(cr, x + 0.5, y);
|
||||
cairo_rel_line_to(cr, 0, term->cell_height);
|
||||
cairo_stroke(cr);
|
||||
int baseline = y + term->fextents.height - term->fextents.descent;
|
||||
int width = font->underline.thickness;
|
||||
int y_under = baseline - font->underline.position - width / 2;
|
||||
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, pix, color,
|
||||
1, &(pixman_rectangle16_t){x, y_under, cols * term->cell_width, width});
|
||||
}
|
||||
|
||||
static void
|
||||
draw_strikeout(const struct terminal *term, cairo_t *cr, const struct font *font,
|
||||
struct rgb color, double x, double y, int cols)
|
||||
draw_strikeout(const struct terminal *term, pixman_image_t *pix,
|
||||
const struct font *font,
|
||||
const pixman_color_t *color, int x, int y, int cols)
|
||||
{
|
||||
double baseline = y + term->fextents.height - term->fextents.descent;
|
||||
double width = font->strikeout.thickness;
|
||||
double y_strike = baseline - font->strikeout.position - width / 2.;
|
||||
int baseline = y + term->fextents.height - term->fextents.descent;
|
||||
int width = font->strikeout.thickness;
|
||||
int y_strike = baseline - font->strikeout.position - width / 2;
|
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgb(cr, color.r, color.g, color.b);
|
||||
cairo_set_line_width(cr, width);
|
||||
cairo_move_to(cr, x, round(y_strike) + 0.5);
|
||||
cairo_rel_line_to(cr, cols * term->cell_width, 0);
|
||||
cairo_stroke(cr);
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, pix, color,
|
||||
1, &(pixman_rectangle16_t){x, y_strike, cols * term->cell_width, width});
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -155,7 +157,7 @@ arm_blink_timer(struct terminal *term)
|
|||
}
|
||||
|
||||
static int
|
||||
render_cell(struct terminal *term, cairo_t *cr, pixman_image_t *pix,
|
||||
render_cell(struct terminal *term, pixman_image_t *pix,
|
||||
struct cell *cell, int col, int row, bool has_cursor)
|
||||
{
|
||||
if (cell->attrs.clean)
|
||||
|
|
@ -163,10 +165,10 @@ render_cell(struct terminal *term, cairo_t *cr, pixman_image_t *pix,
|
|||
|
||||
cell->attrs.clean = 1;
|
||||
|
||||
double width = term->cell_width;
|
||||
double height = term->cell_height;
|
||||
double x = col * width;
|
||||
double y = row * height;
|
||||
int width = term->cell_width;
|
||||
int height = term->cell_height;
|
||||
int x = col * width;
|
||||
int y = row * height;
|
||||
|
||||
bool block_cursor = has_cursor && term->cursor_style == CURSOR_BLOCK;
|
||||
bool is_selected = coord_is_selected(term, col, row);
|
||||
|
|
@ -189,7 +191,8 @@ render_cell(struct terminal *term, cairo_t *cr, pixman_image_t *pix,
|
|||
_fg = _bg;
|
||||
|
||||
pixman_color_t fg = color_hex_to_pixman(_fg);
|
||||
pixman_color_t bg = color_hex_to_pixman(_bg);
|
||||
pixman_color_t bg = color_hex_to_pixman_with_alpha(
|
||||
_bg, block_cursor ? 0xffff : term->colors.alpha);
|
||||
|
||||
if (cell->attrs.dim)
|
||||
pixman_color_dim(&fg);
|
||||
|
|
@ -213,17 +216,16 @@ render_cell(struct terminal *term, cairo_t *cr, pixman_image_t *pix,
|
|||
|
||||
/* Non-block cursors */
|
||||
if (has_cursor) {
|
||||
#if 1
|
||||
struct rgb cursor_color = term->cursor_color.text >> 31
|
||||
? color_hex_to_rgb(term->cursor_color.cursor)
|
||||
: color_hex_to_rgb(_fg);
|
||||
#endif
|
||||
pixman_color_t cursor_color = term->cursor_color.text >> 31
|
||||
? color_hex_to_pixman(term->cursor_color.cursor)
|
||||
: color_hex_to_pixman(_fg);
|
||||
|
||||
if (term->cursor_style == CURSOR_BAR)
|
||||
draw_bar(term, cr, cursor_color, x, y);
|
||||
draw_bar(term, pix, &cursor_color, x, y);
|
||||
else if (term->cursor_style == CURSOR_UNDERLINE)
|
||||
draw_underline(
|
||||
term, cr, attrs_to_font(term, &cell->attrs), cursor_color, x, y, cell_cols);
|
||||
term, pix, attrs_to_font(term, &cell->attrs), &cursor_color,
|
||||
x, y, cell_cols);
|
||||
}
|
||||
|
||||
if (cell->attrs.blink && !term->blink.active) {
|
||||
|
|
@ -256,11 +258,17 @@ render_cell(struct terminal *term, cairo_t *cr, pixman_image_t *pix,
|
|||
}
|
||||
|
||||
/* Underline */
|
||||
if (cell->attrs.underline)
|
||||
draw_underline(term, cr, attrs_to_font(term, &cell->attrs), color_hex_to_rgb(_fg), x, y, cell_cols);
|
||||
if (cell->attrs.underline) {
|
||||
pixman_color_t color = color_hex_to_pixman(_fg);
|
||||
draw_underline(term, pix, attrs_to_font(term, &cell->attrs),
|
||||
&color, x, y, cell_cols);
|
||||
}
|
||||
|
||||
if (cell->attrs.strikethrough)
|
||||
draw_strikeout(term, cr, attrs_to_font(term, &cell->attrs), color_hex_to_rgb(_fg), x, y, cell_cols);
|
||||
if (cell->attrs.strikethrough) {
|
||||
pixman_color_t color = color_hex_to_pixman(_fg);
|
||||
draw_strikeout(term, pix, attrs_to_font(term, &cell->attrs),
|
||||
&color, x, y, cell_cols);
|
||||
}
|
||||
|
||||
return cell_cols;
|
||||
}
|
||||
|
|
@ -318,10 +326,10 @@ grid_render_scroll_reverse(struct terminal *term, struct buffer *buf,
|
|||
}
|
||||
|
||||
static void
|
||||
render_row(struct terminal *term, cairo_t *cr, pixman_image_t *pix, struct row *row, int row_no)
|
||||
render_row(struct terminal *term, pixman_image_t *pix, struct row *row, int row_no)
|
||||
{
|
||||
for (int col = term->cols - 1; col >= 0; col--)
|
||||
render_cell(term, cr, pix, &row->cells[col], col, row_no, false);
|
||||
render_cell(term, pix, &row->cells[col], col, row_no, false);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -359,7 +367,7 @@ render_worker_thread(void *_ctx)
|
|||
switch (row_no) {
|
||||
default:
|
||||
assert(buf != NULL);
|
||||
render_row(term, buf->cairo[my_id], buf->pix[my_id], grid_row_in_view(term->grid, row_no), row_no);
|
||||
render_row(term, buf->pix[my_id], grid_row_in_view(term->grid, row_no), row_no);
|
||||
break;
|
||||
|
||||
case -1:
|
||||
|
|
@ -397,8 +405,6 @@ grid_render(struct terminal *term)
|
|||
assert(term->height > 0);
|
||||
|
||||
struct buffer *buf = shm_get_buffer(term->wl.shm, term->width, term->height, 1 + term->render.workers.count);
|
||||
cairo_t *cr = buf->cairo[0];
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
pixman_image_t *pix = buf->pix[0];
|
||||
|
||||
bool all_clean = tll_length(term->grid->scroll_damage) == 0;
|
||||
|
|
@ -410,7 +416,7 @@ grid_render(struct terminal *term)
|
|||
|
||||
if (cell->attrs.clean) {
|
||||
cell->attrs.clean = 0;
|
||||
render_cell(term, cr, pix, cell, at.col, at.row, false);
|
||||
render_cell(term, pix, cell, at.col, at.row, false);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->wl.surface,
|
||||
|
|
@ -442,12 +448,15 @@ grid_render(struct terminal *term)
|
|||
int bmargin_height = term->height - bmargin;
|
||||
|
||||
uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg;
|
||||
struct rgb bg = color_hex_to_rgb(_bg);
|
||||
cairo_set_source_rgba(buf->cairo[0], bg.r, bg.g, bg.b, term->colors.alpha);
|
||||
|
||||
cairo_rectangle(buf->cairo[0], rmargin, 0, rmargin_width, term->height);
|
||||
cairo_rectangle(buf->cairo[0], 0, bmargin, term->width, bmargin_height);
|
||||
cairo_fill(buf->cairo[0]);
|
||||
pixman_color_t bg = color_hex_to_pixman_with_alpha(_bg, term->colors.alpha);
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, pix, &bg, 1,
|
||||
&(pixman_rectangle16_t){rmargin, 0, rmargin_width, term->height});
|
||||
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, pix, &bg, 1,
|
||||
&(pixman_rectangle16_t){0, bmargin, term->width, bmargin_height});
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->wl.surface, rmargin, 0, rmargin_width, term->height);
|
||||
|
|
@ -515,7 +524,7 @@ grid_render(struct terminal *term)
|
|||
if (!row->dirty)
|
||||
continue;
|
||||
|
||||
render_row(term, cr, pix, row, r);
|
||||
render_row(term, pix, row, r);
|
||||
|
||||
row->dirty = false;
|
||||
all_clean = false;
|
||||
|
|
@ -601,7 +610,7 @@ grid_render(struct terminal *term)
|
|||
cell->attrs.clean = 0;
|
||||
term->render.last_cursor.cell = cell;
|
||||
int cols_updated = render_cell(
|
||||
term, cr, pix, cell, term->cursor.col, view_aligned_row, true);
|
||||
term, pix, cell, term->cursor.col, view_aligned_row, true);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->wl.surface,
|
||||
|
|
@ -616,10 +625,11 @@ grid_render(struct terminal *term)
|
|||
}
|
||||
|
||||
if (term->flash.active) {
|
||||
cairo_set_source_rgba(buf->cairo[0], 1.0, 1.0, 0.0, 0.5);
|
||||
cairo_set_operator(buf->cairo[0], CAIRO_OPERATOR_OVER);
|
||||
cairo_rectangle(buf->cairo[0], 0, 0, term->width, term->height);
|
||||
cairo_fill(buf->cairo[0]);
|
||||
/* Note: alpha is pre-computed in each color component */
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_OVER, pix,
|
||||
&(pixman_color_t){.red=0x7fff, .green=0x7fff, .blue=0, .alpha=0x7fff},
|
||||
1, &(pixman_rectangle16_t){0, 0, term->width, term->height});
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->wl.surface, 0, 0, term->width, term->height);
|
||||
|
|
@ -628,7 +638,6 @@ grid_render(struct terminal *term)
|
|||
assert(term->grid->offset >= 0 && term->grid->offset < term->grid->num_rows);
|
||||
assert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows);
|
||||
|
||||
cairo_surface_flush(buf->cairo_surface[0]);
|
||||
wl_surface_attach(term->wl.surface, buf->wl_buf, 0, 0);
|
||||
|
||||
assert(term->render.frame_callback == NULL);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue