diff options
author | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-24 18:50:50 +0200 |
---|---|---|
committer | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-24 18:50:50 +0200 |
commit | 3a85053e4e72e7bd19790032e5851d2a6c785e9e (patch) | |
tree | 685cb56f66eb3d979e73e2611ff8c59b065dc6dd | |
parent | 76c39ec0b1b6e48f8aa527c481a03f9aa6bfe472 (diff) | |
download | wlclock-3a85053e4e72e7bd19790032e5851d2a6c785e9e.tar.gz wlclock-3a85053e4e72e7bd19790032e5851d2a6c785e9e.tar.bz2 |
Render background
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | src/colour.c | 82 | ||||
-rw-r--r-- | src/colour.h | 17 | ||||
-rw-r--r-- | src/render.c | 155 | ||||
-rw-r--r-- | src/render.h | 8 | ||||
-rw-r--r-- | src/surface.c | 3 | ||||
-rw-r--r-- | src/surface.h | 3 | ||||
-rw-r--r-- | src/wlclock.c | 19 | ||||
-rw-r--r-- | src/wlclock.h | 6 |
9 files changed, 290 insertions, 5 deletions
diff --git a/meson.build b/meson.build index 31a32e1..bbaae41 100644 --- a/meson.build +++ b/meson.build @@ -45,8 +45,10 @@ executable( 'wlclock', files( 'src/buffer.c', + 'src/colour.c', 'src/misc.c', 'src/output.c', + 'src/render.c', 'src/surface.c', 'src/wlclock.c', ), diff --git a/src/colour.c b/src/colour.c new file mode 100644 index 0000000..8095d69 --- /dev/null +++ b/src/colour.c @@ -0,0 +1,82 @@ +#include<stdio.h> +#include<stdlib.h> +#include<stdint.h> +#include<stdbool.h> +#include<string.h> +#include<cairo/cairo.h> + +#include"misc.h" +#include"colour.h" + +static bool colour_from_hex_string (struct Wlclock_colour *colour, const char *hex) +{ + unsigned int r = 0, g = 0, b = 0, a = 255; + if ( 4 != sscanf(hex, "#%02x%02x%02x%02x", &r, &g, &b, &a) + && 3 != sscanf(hex, "#%02x%02x%02x", &r, &g, &b) + && 4 != sscanf(hex, "0x%02x%02x%02x%02x", &r, &g, &b, &a) + && 3 != sscanf(hex, "0x%02x%02x%02x", &r, &g, &b) ) + return false; + + colour->r = (float)r / 255.0f; + colour->g = (float)g / 255.0f; + colour->b = (float)b / 255.0f; + colour->a = (float)a / 255.0f; + + return true; +} + +static bool colour_from_rgb_string (struct Wlclock_colour *colour, const char *str) +{ + int32_t r = 0, g = 0, b = 0, a = 255; + if ( 4 != sscanf(str, "rgba(%d,%d,%d,%d)", &r, &g, &b, &a) + && 3 != sscanf(str, "rgb(%d,%d,%d)", &r, &g, &b) ) + return false; + + if ( r > 255 || g > 255 || b > 255 || a > 255 ) + return false; + if ( r < 0 || g < 0 || b < 0 || a < 0 ) + return false; + + colour->r = (float)r / 255.0f; + colour->g = (float)g / 255.0f; + colour->b = (float)b / 255.0f; + colour->a = (float)a / 255.0f; + + return true; +} + +bool colour_from_string (struct Wlclock_colour *colour, const char *str) +{ + if ( colour == NULL || str == NULL || *str == '\0' ) + goto error; + + if ( *str == '#' || strstr(str, "0x") == str ) + { + if (! colour_from_hex_string(colour, str)) + goto error; + } + else if ( strstr(str, "rgb") == str ) + { + if (! colour_from_rgb_string(colour, str)) + goto error; + } + else + goto error; + + return true; + +error: + clocklog(NULL, 0, "ERROR: \"%s\" is not a valid colour.\n"); + return false; +} + +void colour_set_cairo_source (cairo_t *cairo, struct Wlclock_colour *colour) +{ + cairo_set_source_rgba(cairo, colour->r, colour->g, colour->b, colour->a); +} + +bool colour_is_transparent (struct Wlclock_colour *colour) +{ + return colour->a == 0.0; +} + diff --git a/src/colour.h b/src/colour.h new file mode 100644 index 0000000..1159abd --- /dev/null +++ b/src/colour.h @@ -0,0 +1,17 @@ +#ifndef WLCLOCK_COLOUR_H +#define WLCLOCK_COLOUR_H + +#include<stdbool.h> +#include<cairo/cairo.h> + +struct Wlclock_colour +{ + double r, g, b, a; +}; + +bool colour_from_string (struct Wlclock_colour *colour, const char *hex); +void colour_set_cairo_source (cairo_t *cairo, struct Wlclock_colour *colour); +bool colour_is_transparent (struct Wlclock_colour *colour); + +#endif + diff --git a/src/render.c b/src/render.c new file mode 100644 index 0000000..bd3d91e --- /dev/null +++ b/src/render.c @@ -0,0 +1,155 @@ +#include<stdio.h> +#include<stdlib.h> +#include<stdbool.h> +#include<unistd.h> +#include<string.h> +#include<cairo/cairo.h> +#include<wayland-server.h> +#include<wayland-client.h> +#include<wayland-client-protocol.h> + +#include"wlclock.h" +#include"surface.h" +#include"output.h" +#include"misc.h" +#include"colour.h" +#include"render.h" + +static void rounded_rectangle (cairo_t *cairo, uint32_t x, uint32_t y, uint32_t w, uint32_t h, + double tl_r, double tr_r, double bl_r, double br_r) +{ + double degrees = 3.1415927 / 180.0; + cairo_new_sub_path(cairo); + cairo_arc(cairo, x + w - tr_r, y + tr_r, tr_r, -90 * degrees, 0 * degrees); + cairo_arc(cairo, x + w - br_r, y + h - br_r, br_r, 0 * degrees, 90 * degrees); + cairo_arc(cairo, x + bl_r, y + h - bl_r, bl_r, 90 * degrees, 180 * degrees); + cairo_arc(cairo, x + tl_r, y + tl_r, tl_r, 180 * degrees, 270 * degrees); + cairo_close_path(cairo); +} + +static void draw_background (cairo_t *cairo, + uint32_t x, uint32_t y, uint32_t w, uint32_t h, + uint32_t border_top, uint32_t border_right, + uint32_t border_bottom, uint32_t border_left, + uint32_t top_left_radius, uint32_t top_right_radius, + uint32_t bottom_left_radius, uint32_t bottom_right_radius, + uint32_t scale, + struct Wlclock_colour *background_colour, + struct Wlclock_colour *border_colour) +{ + if ( colour_is_transparent(background_colour) && colour_is_transparent(border_colour) ) + return; + + /* Scale. */ + x *= scale, y *= scale, w *= scale, h *= scale; + border_top *= scale, border_bottom *= scale; + border_left *= scale, border_right *= scale; + top_left_radius *= scale, top_right_radius *= scale; + bottom_left_radius *= scale, bottom_right_radius *= scale; + + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + + if ( top_left_radius == 0 && top_right_radius == 0 + && bottom_left_radius == 0 && bottom_right_radius == 0 ) + { + if ( border_top == 0 && border_bottom == 0 + && border_left == 0 && border_right == 0 ) + { + cairo_rectangle(cairo, x, y, w, h); + colour_set_cairo_source(cairo, background_colour); + cairo_fill(cairo); + } + else + { + fputs("here\n", stderr); + /* Calculate dimensions of center. */ + uint32_t cx = x + border_left, + cy = y + border_top, + cw = w - (border_left + border_right), + ch = h - (border_top + border_bottom); + + /* Borders. */ + cairo_rectangle(cairo, x, y, w, border_top); + cairo_rectangle(cairo, x + w - border_right, y + border_top, + border_right, h - border_top - border_bottom); + cairo_rectangle(cairo, x, y + h - border_bottom, w, border_bottom); + cairo_rectangle(cairo, x, y + border_top, border_left, + h - border_top - border_bottom); + colour_set_cairo_source(cairo, border_colour); + cairo_fill(cairo); + + /* Center. */ + cairo_rectangle(cairo, cx, cy, cw, ch); + colour_set_cairo_source(cairo, background_colour); + cairo_fill(cairo); + } + } + else + { + if ( border_top == 0 && border_bottom == 0 + && border_left == 0 && border_right == 0 ) + { + rounded_rectangle(cairo, x, y, w, h, + top_left_radius, top_right_radius, + bottom_left_radius, bottom_right_radius); + colour_set_cairo_source(cairo, background_colour); + cairo_fill(cairo); + } + else + { + rounded_rectangle(cairo, x, y, w, h, + top_left_radius, top_right_radius, + bottom_left_radius, bottom_right_radius); + colour_set_cairo_source(cairo, border_colour); + cairo_fill(cairo); + + rounded_rectangle(cairo, x + border_left, y + border_top, + w - (border_left + border_right), + h - (border_bottom + border_top), + top_left_radius, top_right_radius, + bottom_left_radius, bottom_right_radius); + colour_set_cairo_source(cairo, background_colour); + cairo_fill(cairo); + } + } + cairo_restore(cairo); +} + +static void clear_buffer (cairo_t *cairo) +{ + cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + cairo_restore(cairo); +} + +void render_surface_frame (struct Wlclock_surface *surface) +{ + struct Wlclock_output *output = surface->output; + struct Wlclock *clock = output->clock; + uint32_t scale = output->scale; + clocklog(clock, 2, "[render] Render frame: global_name=%d\n", output->global_name); + + /* Get new/next buffer. */ + if (! next_buffer(&surface->current_buffer, clock->shm, surface->buffers, + surface->size * scale, surface->size * scale)) + return; + + cairo_t *cairo = surface->current_buffer->cairo; + clear_buffer(cairo); + + draw_background(cairo, 0, 0, surface->size, surface->size, + clock->border_top, clock->border_right, + clock->border_bottom, clock->border_left, + clock->radius_top_left, clock->radius_top_right, + clock->radius_bottom_left, clock->radius_bottom_right, + scale, &clock->background_colour, &clock->border_colour); + + // TODO draw clock stuff + + wl_surface_set_buffer_scale(surface->surface, scale); + wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); + wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX); +} + diff --git a/src/render.h b/src/render.h new file mode 100644 index 0000000..ca4e54b --- /dev/null +++ b/src/render.h @@ -0,0 +1,8 @@ +#ifndef WLCLOCK_RENDER_H +#define WLCLOCK_RENDER_H + +struct Wlclock_surface; + +void render_surface_frame (struct Wlclock_surface *surface); + +#endif diff --git a/src/surface.c b/src/surface.c index 9e6c8e2..243a23d 100644 --- a/src/surface.c +++ b/src/surface.c @@ -18,6 +18,7 @@ #include"misc.h" #include"surface.h" #include"buffer.h" +#include"render.h" static uint32_t min (uint32_t a, uint32_t b) { @@ -149,7 +150,7 @@ void update_surface (struct Wlclock_surface *surface) if ( surface == NULL || ! surface->configured ) return; configure_layer_surface(surface); - // render_surface_frame(surface); // TODO + render_surface_frame(surface); wl_surface_commit(surface->surface); } diff --git a/src/surface.h b/src/surface.h index 8fd99bc..57dd239 100644 --- a/src/surface.h +++ b/src/surface.h @@ -18,7 +18,8 @@ struct Wlclock_surface struct zwlr_layer_surface_v1 *layer_surface; int32_t size; - struct Wlclock_buffer buffers[2]; + struct Wlclock_buffer buffers[2]; + struct Wlclock_buffer *current_buffer; bool configured; }; diff --git a/src/wlclock.c b/src/wlclock.c index 04f8a75..1fad08f 100644 --- a/src/wlclock.c +++ b/src/wlclock.c @@ -24,6 +24,7 @@ #include"misc.h" #include"output.h" #include"surface.h" +#include"colour.h" static void registry_handle_global (void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -220,16 +221,19 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[]) case 1100: // TODO anchor break; - case 1101: // TODO background colour + case 1101: /* Background colour */ + colour_from_string(&clock->background_colour, optarg); break; - case 1102: // TODO border colour + case 1102: /* Border colour */ + colour_from_string(&clock->border_colour, optarg); break; case 1103: // TODO border size break; - case 1104: // TODO clock colour + case 1104: /* Clock colour */ + colour_from_string(&clock->clock_colour, optarg); break; case 1105: // TODO exclusive zone @@ -336,6 +340,15 @@ int main (int argc, char *argv[]) clock.anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; set_string(&clock.namespace, "wlclock"); wl_list_init(&clock.outputs); + clock.border_bottom = clock.border_top + = clock.border_left = clock.border_right = 1; + clock.radius_bottom_left = clock.radius_bottom_right + = clock.radius_top_left = clock.radius_top_right = 5; + clock.margin_bottom = clock.margin_top + = clock.margin_left = clock.margin_right = 0; + colour_from_string(&clock.background_colour, "#000000"); + colour_from_string(&clock.border_colour, "#FFFFFF"); + colour_from_string(&clock.clock_colour, "#FFFFFF"); if (! handle_command_flags(&clock, argc, argv)) return clock.ret; diff --git a/src/wlclock.h b/src/wlclock.h index 684c4b3..78b5c41 100644 --- a/src/wlclock.h +++ b/src/wlclock.h @@ -8,6 +8,8 @@ #include"wlr-layer-shell-unstable-v1-protocol.h" +#include"colour.h" + struct Wlclock { struct wl_display *display; @@ -35,6 +37,10 @@ struct Wlclock uint32_t radius_top_left, radius_top_right, radius_bottom_left, radius_bottom_right; uint32_t anchor; bool input; + + struct Wlclock_colour background_colour; + struct Wlclock_colour border_colour; + struct Wlclock_colour clock_colour; }; #endif |