Add backdrop and text drawing

This commit is contained in:
Midgard 2022-09-07 16:28:43 +02:00
parent 103dcf9e69
commit bbb8c41f01
Signed by: midgard
GPG key ID: 511C112F1331BBB4
3 changed files with 106 additions and 21 deletions

View file

@ -1,4 +1,4 @@
# Generated by YCM Generator at 2022-09-07 00:00:45.256036
# Generated by YCM Generator at 2022-09-07 15:55:49.892367
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
@ -36,6 +36,18 @@ import ycm_core
flags = [
'-x',
'c',
'-I/usr/include/blkid',
'-I/usr/include/cairo',
'-I/usr/include/freetype2',
'-I/usr/include/fribidi',
'-I/usr/include/glib-2.0',
'-I/usr/include/harfbuzz',
'-I/usr/include/libmount',
'-I/usr/include/libpng16',
'-I/usr/include/pango-1.0',
'-I/usr/include/pixman-1',
'-I/usr/lib64/glib-2.0/include',
'-I/usr/lib64/libffi/include',
'-Wall',
]

View file

@ -1,7 +1,20 @@
BUILD = build
CFLAGS += -Wall
LDLIBS = -lwayland-client -lrt -lcairo
# Pango and dependencies
CFLAGS += $(shell pkg-config --cflags pangocairo)
LDLIBS += $(shell pkg-config --libs pangocairo)
#CFLAGS += $(shell pkg-config --cflags glib-2.0)
#LDLIBS += $(shell pkg-config --libs glib-2.0)
#CFLAGS += $(shell pkg-config --cflags harfbuzz)
#LDLIBS += $(shell pkg-config --libs harfbuzz)
LDLIBS += -lwayland-client
LDLIBS += -lrt
LDLIBS += -lcairo
$(shell mkdir -p $(BUILD))
@ -25,4 +38,4 @@ build/wlr-layer-shell-protocol.c: wlr-layer-shell-unstable-v1.xml
C_FILES = wl-overlay.c build/xdg-shell-protocol.c build/wlr-layer-shell-protocol.c
build/wl-overlay: $(C_FILES) xdg-shell-client-protocol.h wlr-layer-shell-protocol.h
$(CC) $(CFLAGS) $(LDLIBS) -o "$@" $(C_FILES)
$(CC) $(CFLAGS) $(INC) $(LDFLAGS) $(LDLIBS) -o "$@" $(C_FILES)

View file

@ -10,8 +10,11 @@
#include <unistd.h>
#include <wayland-client.h>
#include <cairo/cairo.h>
#include <pango/pangocairo.h>
#include "wlr-layer-shell-protocol.h"
#define STR_EQUAL 0
/* Shared memory support code */
static void
randname(char *buf)
@ -60,8 +63,14 @@ allocate_shm_file(size_t size)
}
/* Wayland code */
struct user_request {
char *graphics_filename;
char *text;
bool backdrop;
};
struct client_state {
char *filename;
struct user_request user_request;
/* Globals */
struct wl_display *wl_display;
struct wl_registry *wl_registry;
@ -84,6 +93,17 @@ static const struct wl_buffer_listener wl_buffer_listener = {
.release = wl_buffer_release,
};
static void
draw_rounded_rectangle(cairo_t *cr, int x, int y, int width, int height, int radius)
{
cairo_new_sub_path(cr);
cairo_arc(cr, x + radius, y + radius, radius, M_PI, 3*M_PI/2);
cairo_arc(cr, x + width - radius, y + radius, radius, 3*M_PI/2, 0);
cairo_arc(cr, x + width - radius, y + height - radius, radius, 0, M_PI/2);
cairo_arc(cr, x + radius, y + height - radius, radius, M_PI/2, M_PI);
cairo_close_path(cr);
}
static struct wl_buffer *
draw_frame(struct client_state *state, const int width, const int height)
{
@ -108,20 +128,45 @@ draw_frame(struct client_state *state, const int width, const int height)
wl_shm_pool_destroy(pool);
close(fd);
/* Load PNG */
/* Draw background */
cairo_surface_t *cairo_target_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cairo = cairo_create(cairo_target_surface);
memset(cairo_image_surface_get_data(cairo_target_surface), 0, size);
cairo_surface_t *cairo_png_surface = cairo_image_surface_create_from_png(state->filename);
if (cairo_surface_status(cairo_png_surface) != CAIRO_STATUS_SUCCESS) {
fprintf(stderr, "Failed to open PNG image.\n");
exit(1);
if (state->user_request.backdrop) {
cairo_set_source_rgba(cairo, 0x11 / 255.0, 0x11 / 255.0, 0x11 / 255.0, 0.85);
draw_rounded_rectangle(cairo, 0, 0, width, height, 15);
/*cairo_rectangle(cairo, 0, 0, width, height);*/
cairo_fill(cairo);
}
cairo_set_source_surface(cairo, cairo_png_surface, 0.0, 0.0);
cairo_paint(cairo);
memcpy(data, cairo_image_surface_get_data(cairo_target_surface), size);
cairo_surface_destroy(cairo_png_surface);
/* Load and draw PNG */
if (strcmp("", state->user_request.graphics_filename) != STR_EQUAL) {
cairo_surface_t *cairo_png_surface = cairo_image_surface_create_from_png(state->user_request.graphics_filename);
if (cairo_surface_status(cairo_png_surface) != CAIRO_STATUS_SUCCESS) {
fprintf(stderr, "Failed to open PNG image.\n");
exit(1);
}
cairo_set_source_surface(cairo, cairo_png_surface, 0.0, 0.0);
cairo_paint(cairo);
cairo_surface_destroy(cairo_png_surface);
}
/* Draw text */
if (state->user_request.text) {
PangoLayout *layout = pango_cairo_create_layout(cairo);
pango_layout_set_text(layout, state->user_request.text, -1);
PangoFontDescription *desc = pango_font_description_from_string("Fira Sans 12");
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
int text_width, text_height;
pango_layout_get_size(layout, &text_width, &text_height);
cairo_move_to(cairo, (width - text_width/PANGO_SCALE)/2.0, 3*height/4.0);
pango_cairo_show_layout(cairo, layout);
g_object_unref(layout);
}
memcpy(data, cairo_image_surface_get_data(cairo_target_surface), size);
cairo_surface_destroy(cairo_target_surface);
cairo_destroy(cairo);
@ -152,15 +197,15 @@ registry_global(void *data, struct wl_registry *wl_registry,
uint32_t name, const char *interface, uint32_t version)
{
struct client_state *state = data;
if (strcmp(interface, wl_shm_interface.name) == 0) {
if (strcmp(interface, wl_shm_interface.name) == STR_EQUAL) {
state->wl_shm = wl_registry_bind(
wl_registry, name, &wl_shm_interface, 1);
} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
} else if (strcmp(interface, wl_compositor_interface.name) == STR_EQUAL) {
state->wl_compositor = wl_registry_bind(
wl_registry, name, &wl_compositor_interface, 4);
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == STR_EQUAL) {
state->layer_shell = wl_registry_bind(
wl_registry, name, &zwlr_layer_shell_v1_interface, 1);
}
@ -183,12 +228,24 @@ main(int argc, char *argv[])
{
struct client_state state = { 0 };
if (argc < 2 || strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0) {
fprintf(stderr, "Usage: wl-overlay <image.png>\n\nThe image must be a 256×256 PNG with ARGB.\n");
int i = 1;
if (argc < 2 || strcmp("-h", argv[i]) == STR_EQUAL || strcmp("--help", argv[i]) == STR_EQUAL) {
fprintf(stderr, "Usage: wl-overlay <image.png> [text]\n\nThe image must be a 256×256 PNG with ARGB.\n");
return 1;
}
state.filename = strdup(argv[1]);
if (argc > i && strcmp("--backdrop", argv[i]) == STR_EQUAL) {
state.user_request.backdrop = true;
i++;
} else {
state.user_request.backdrop = false;
}
state.user_request.graphics_filename = strdup(argv[i++]);
if (argc > i) {
state.user_request.text = strdup(argv[i++]);
} else {
state.user_request.text = NULL;
}
state.wl_display = wl_display_connect(NULL);
if (!state.wl_display) {
fprintf(stderr, "Could not connect to Wayland server\n");
@ -213,7 +270,10 @@ main(int argc, char *argv[])
/* This space deliberately left blank */
}
free(state.filename);
free(state.user_request.graphics_filename);
if (state.user_request.text != NULL) {
free(state.user_request.text);
}
return 0;
}