From 2c721ef054577287e941c79f1c27f5c42629b3f2 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 24 Jun 2024 07:39:00 +0300 Subject: [PATCH] Switch back to Cairo for drawing selection --- meson.build | 2 ++ src/config.c | 7 +++---- src/dulcepan.h | 10 ++++------ src/main.c | 18 ------------------ src/output.c | 45 +++++++++++++++++++++++++-------------------- src/save.c | 1 + 6 files changed, 35 insertions(+), 48 deletions(-) diff --git a/meson.build b/meson.build index 7f4a539..1f49cfe 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ add_project_arguments(cc.get_supported_arguments([ wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols') +cairo = dependency('cairo') pixman = dependency('pixman-1') spng = dependency('spng', fallback: 'libspng') xkbcommon = dependency( @@ -75,6 +76,7 @@ executable( dependencies: [ client_protos, wayland_client, + cairo, pixman, spng, xkbcommon, diff --git a/src/config.c b/src/config.c index 4f99146..2e2000e 100644 --- a/src/config.c +++ b/src/config.c @@ -10,10 +10,9 @@ #define CONFIG_SUBPATH "dulcepan.cfg" -static void bytes_to_color(uint8_t bytes[static 4], float out[static 4]) { - out[3] = (float)bytes[3] / UINT8_MAX; - for (size_t i = 0; i < 3; i++) { - out[i] = (float)bytes[i] * out[3] / UINT8_MAX; +static inline void bytes_to_color(uint8_t bytes[static 4], float out[static 4]) { + for (size_t i = 0; i < 4; i++) { + out[i] = (float)bytes[i] / UINT8_MAX; } } diff --git a/src/dulcepan.h b/src/dulcepan.h index 85f0950..24fa65e 100644 --- a/src/dulcepan.h +++ b/src/dulcepan.h @@ -1,7 +1,7 @@ #ifndef DULCEPAN_H #define DULCEPAN_H -#include +#include #include #include #include @@ -18,7 +18,8 @@ enum dp_status { struct dp_buffer { struct wl_buffer *wl_buffer; - pixman_image_t *image; + cairo_t *cairo; + cairo_surface_t *cairo_surface; void *data; size_t size; bool used; @@ -123,6 +124,7 @@ enum dp_file_format { }; struct dp_config { + // RGBA, not premultiplied float unselected_color[4]; float selected_color[4]; float border_color[4]; @@ -161,10 +163,6 @@ struct dp_state { enum dp_file_format output_format; bool show_cursors; - - pixman_image_t *unselected_fill_image; - pixman_image_t *selected_fill_image; - pixman_image_t *border_fill_image; }; void dp_config_load(struct dp_config *config, const char *user_path); diff --git a/src/main.c b/src/main.c index dbe326e..8bac0a4 100644 --- a/src/main.c +++ b/src/main.c @@ -166,16 +166,6 @@ static void help(const char *prog) { prog); } -static pixman_image_t *make_image(float color[static 4]) { - pixman_color_t pixman_color = { - .red = (uint16_t)(color[0] * UINT16_MAX), - .green = (uint16_t)(color[1] * UINT16_MAX), - .blue = (uint16_t)(color[2] * UINT16_MAX), - .alpha = (uint16_t)(color[3] * UINT16_MAX), - }; - return pixman_image_create_solid_fill(&pixman_color); -} - int main(int argc, char **argv) { struct dp_state state = {0}; @@ -233,16 +223,8 @@ int main(int argc, char **argv) { dp_log_fatal("Failed to connect to a Wayland compositor"); } - state.unselected_fill_image = make_image(state.config.unselected_color); - state.selected_fill_image = make_image(state.config.selected_color); - state.border_fill_image = make_image(state.config.border_color); - run(&state); - pixman_image_unref(state.unselected_fill_image); - pixman_image_unref(state.selected_fill_image); - pixman_image_unref(state.border_fill_image); - xkb_context_unref(state.xkb_context); wl_display_disconnect(state.display); diff --git a/src/output.c b/src/output.c index 625382b..a68bf5d 100644 --- a/src/output.c +++ b/src/output.c @@ -208,8 +208,9 @@ static void output_handle_done(void *data, struct wl_output *wl_output) { buffer->wl_buffer = dp_buffer_create(state, output->transformed_width, output->transformed_height, stride, WL_SHM_FORMAT_ARGB8888, &buffer->data, &buffer->size); - buffer->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, output->transformed_width, - output->transformed_height, buffer->data, stride); + buffer->cairo_surface = cairo_image_surface_create_for_data(buffer->data, + CAIRO_FORMAT_ARGB32, output->transformed_width, output->transformed_height, stride); + buffer->cairo = cairo_create(buffer->cairo_surface); wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer); } @@ -242,6 +243,10 @@ static const struct wl_callback_listener redraw_callback_listener = { .done = redraw_callback_handle_done, }; +static inline void set_cairo_color(cairo_t *cairo, float color[static 4]) { + cairo_set_source_rgba(cairo, color[0], color[1], color[2], color[3]); +} + static void redraw(struct dp_output *output) { assert(output->redraw_callback == NULL); @@ -260,30 +265,29 @@ static void redraw(struct dp_output *output) { buffer->used = true; struct dp_state *state = output->state; + struct dp_config *config = &state->config; - pixman_image_composite32(PIXMAN_OP_SRC, state->unselected_fill_image, NULL, buffer->image, 0, 0, - 0, 0, 0, 0, output->transformed_width, output->transformed_height); + cairo_set_operator(buffer->cairo, CAIRO_OPERATOR_SOURCE); + + set_cairo_color(buffer->cairo, config->unselected_color); + cairo_paint(buffer->cairo); struct dp_selection *selection = &state->selection; if (output == selection->output) { - int border_size = state->config.border_size; + int border_size = config->border_size; if (border_size != 0) { - pixman_image_composite32(PIXMAN_OP_SRC, state->border_fill_image, NULL, buffer->image, - 0, 0, 0, 0, selection->x - border_size, selection->y - border_size, - selection->width + border_size * 2, border_size); - pixman_image_composite32(PIXMAN_OP_SRC, state->border_fill_image, NULL, buffer->image, - 0, 0, 0, 0, selection->x - border_size, selection->y + selection->height, - selection->width + border_size * 2, border_size); - pixman_image_composite32(PIXMAN_OP_SRC, state->border_fill_image, NULL, buffer->image, - 0, 0, 0, 0, selection->x - border_size, selection->y, border_size, - selection->height); - pixman_image_composite32(PIXMAN_OP_SRC, state->border_fill_image, NULL, buffer->image, - 0, 0, 0, 0, selection->x + selection->width, selection->y, border_size, - selection->height); + cairo_set_line_width(buffer->cairo, border_size); + double off = border_size / 2.0; + cairo_rectangle(buffer->cairo, selection->x - off, selection->y - off, + selection->width + border_size, selection->height + border_size); + set_cairo_color(buffer->cairo, config->border_color); + cairo_stroke(buffer->cairo); } - pixman_image_composite32(PIXMAN_OP_SRC, state->selected_fill_image, NULL, buffer->image, 0, - 0, 0, 0, selection->x, selection->y, selection->width, selection->height); + cairo_rectangle( + buffer->cairo, selection->x, selection->y, selection->width, selection->height); + set_cairo_color(buffer->cairo, config->selected_color); + cairo_fill(buffer->cairo); } wl_surface_attach(output->select_surface, buffer->wl_buffer, 0, 0); @@ -335,7 +339,8 @@ void dp_output_destroy(struct dp_output *output) { for (size_t i = 0; i < DP_SWAPCHAIN_LEN; i++) { struct dp_buffer *buffer = &output->swapchain[i]; wl_buffer_destroy(buffer->wl_buffer); - pixman_image_unref(buffer->image); + cairo_destroy(buffer->cairo); + cairo_surface_destroy(buffer->cairo_surface); munmap(buffer->data, buffer->size); } diff --git a/src/save.c b/src/save.c index 81fb7ec..08102cd 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,5 @@ #include +#include #include #include #include