From f0413d2c8c1a32259cb234bb44a1d1d9d7e0f69f Mon Sep 17 00:00:00 2001 From: Jeremy Attali Date: Sat, 21 Dec 2019 14:43:17 -0500 Subject: [PATCH] draw: ability to draw circles --- meson.build | 2 ++ src/application.c | 49 +++++++++++++++++++++++++++++++---------------- src/draw.c | 41 +++++++++++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 20 deletions(-) diff --git a/meson.build b/meson.build index 567030a..3cac09d 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,7 @@ swappy_inc = include_directories('include') cc = meson.get_compiler('c') cairo = dependency('cairo') +math = cc.find_library('m') realtime = cc.find_library('rt') gtk = dependency('gtk+-wayland-3.0', version: '>=3.22.0') gtk_layer_shell = dependency('gtk-layer-shell-0', version: '>= 0.1.0') @@ -49,6 +50,7 @@ executable( gtk, gtk_layer_shell, libnotify, + math, realtime, wayland_client, wayland_cursor, diff --git a/src/application.c b/src/application.c index 7860fa9..d106467 100644 --- a/src/application.c +++ b/src/application.c @@ -260,6 +260,9 @@ static void paint_commit_temporary(struct swappy_state *state, double x, g_memdup(state->temp_shape, sizeof(struct swappy_shape)); state->shapes = g_slist_append(state->shapes, shape); + + g_free(state->temp_shape); + state->temp_shape = NULL; } static void draw_area_button_press_handler(GtkWidget *widget, @@ -271,9 +274,14 @@ static void draw_area_button_press_handler(GtkWidget *widget, } if (event->button == 1) { - if (state->mode == SWAPPY_PAINT_MODE_RECTANGLE) { - paint_add_temporary(state, event->x, event->y, - SWAPPY_PAINT_MODE_RECTANGLE); + switch (state->mode) { + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + paint_add_temporary(state, event->x, event->y, state->mode); + break; + default: + return; } } } @@ -291,8 +299,9 @@ static void draw_area_button_release_handler(GtkWidget *widget, brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_LAST); draw_state(state); break; - case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: paint_commit_temporary(state, event->x, event->y); draw_state(state); break; @@ -309,18 +318,26 @@ static void draw_area_motion_notify_handler(GtkWidget *widget, GdkCursor *crosshair = gdk_cursor_new_for_display(display, GDK_CROSSHAIR); gdk_window_set_cursor(window, crosshair); - if (state->mode == SWAPPY_PAINT_MODE_BRUSH) { - if (event->state & GDK_BUTTON1_MASK) { - brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_WITHIN); - draw_state(state); - } - } else if (state->mode == SWAPPY_PAINT_MODE_RECTANGLE) { - if (event->state & GDK_BUTTON1_MASK) { - paint_update_temporary(state, event->x, event->y); - draw_state(state); - } - } else { - gdk_window_set_cursor(window, NULL); + gboolean is_button1_pressed = event->state & GDK_BUTTON1_MASK; + + switch (state->mode) { + case SWAPPY_PAINT_MODE_BRUSH: + if (is_button1_pressed) { + brush_add_point(state, event->x, event->y, SWAPPY_BRUSH_POINT_WITHIN); + draw_state(state); + } + break; + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + if (is_button1_pressed) { + paint_update_temporary(state, event->x, event->y); + draw_state(state); + } + break; + default: + // gdk_window_set_cursor(window, NULL); + return; } } diff --git a/src/draw.c b/src/draw.c index 9f001c4..7c23ce8 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,9 +1,14 @@ + #include #include #include #include "swappy.h" +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + static cairo_format_t get_cairo_format(enum wl_shm_format wl_fmt) { switch (wl_fmt) { case WL_SHM_FORMAT_ARGB8888: @@ -27,8 +32,23 @@ static void apply_output_transform(enum wl_output_transform transform, *height = tmp; } } +static void draw_shape_ellipse(cairo_t *cr, struct swappy_shape *shape) { + double x = fabs(shape->from.x - shape->to.x); + double y = fabs(shape->from.y - shape->to.y); + double xc = shape->from.x + ((shape->to.x - shape->from.x) / 2); + double yc = shape->from.y + ((shape->to.y - shape->from.y) / 2); -static void draw_shape(cairo_t *cr, struct swappy_shape *shape) { + double r = sqrt(x * x + y * y) / 2; + + cairo_set_source_rgba(cr, 1, 0, 0, 1); + cairo_set_line_width(cr, 2); + + cairo_arc(cr, xc, yc, r, 0, 2 * M_PI); + cairo_stroke(cr); + cairo_close_path(cr); +} + +static void draw_shape_rectangle(cairo_t *cr, struct swappy_shape *shape) { double x = fmin(shape->from.x, shape->to.x); double y = fmin(shape->from.y, shape->to.y); double w = fabs(shape->from.x - shape->to.x); @@ -38,18 +58,31 @@ static void draw_shape(cairo_t *cr, struct swappy_shape *shape) { cairo_set_line_width(cr, 2); cairo_rectangle(cr, x, y, w, h); - cairo_stroke_preserve(cr); - // cairo_fill(cr); + cairo_close_path(cr); + cairo_stroke(cr); +} + +static void draw_shape(cairo_t *cr, struct swappy_shape *shape) { + switch (shape->type) { + case SWAPPY_PAINT_MODE_RECTANGLE: + draw_shape_rectangle(cr, shape); + break; + case SWAPPY_PAINT_MODE_ELLIPSE: + draw_shape_ellipse(cr, shape); + break; + default: + g_debug("unknown shape type: %d", shape->type); + } } static void draw_shapes(cairo_t *cr, struct swappy_state *state) { for (GSList *elem = state->shapes; elem; elem = elem->next) { struct swappy_shape *shape = elem->data; - draw_shape(cr, shape); } if (state->temp_shape) { + g_debug("drawing temporary shape"); draw_shape(cr, state->temp_shape); } }