summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de>2020-09-24 18:50:50 +0200
committerLeon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de>2020-09-24 18:50:50 +0200
commit3a85053e4e72e7bd19790032e5851d2a6c785e9e (patch)
tree685cb56f66eb3d979e73e2611ff8c59b065dc6dd /src
parent76c39ec0b1b6e48f8aa527c481a03f9aa6bfe472 (diff)
downloadwlclock-3a85053e4e72e7bd19790032e5851d2a6c785e9e.tar.gz
wlclock-3a85053e4e72e7bd19790032e5851d2a6c785e9e.tar.bz2
Render background
Diffstat (limited to 'src')
-rw-r--r--src/colour.c82
-rw-r--r--src/colour.h17
-rw-r--r--src/render.c155
-rw-r--r--src/render.h8
-rw-r--r--src/surface.c3
-rw-r--r--src/surface.h3
-rw-r--r--src/wlclock.c19
-rw-r--r--src/wlclock.h6
8 files changed, 288 insertions, 5 deletions
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