From a855e3b370bd05664b74f28a507cba1dc5670d27 Mon Sep 17 00:00:00 2001 From: Jeremy Attali Date: Sun, 22 Dec 2019 13:14:53 -0500 Subject: [PATCH] refactor: move shape into union --- include/swappy.h | 23 +++++++---- src/application.c | 98 +++++++++++++++++++++++++++++------------------ src/draw.c | 96 +++++++++++++++++++++++++--------------------- 3 files changed, 130 insertions(+), 87 deletions(-) diff --git a/include/swappy.h b/include/swappy.h index 9da1cbd..7af4aa9 100644 --- a/include/swappy.h +++ b/include/swappy.h @@ -21,7 +21,7 @@ enum swappy_brush_point_kind { SWAPPY_BRUSH_POINT_LAST, /* A point at the end of brush batch */ }; -enum swappy_paint_mode_type { +enum swappy_paint_type { SWAPPY_PAINT_MODE_BRUSH = 0, /* Brush mode to draw arbitrary shapes */ SWAPPY_PAINT_MODE_TEXT, /* Mode to draw texts */ SWAPPY_PAINT_MODE_RECTANGLE, /* Rectangle shapes */ @@ -34,7 +34,7 @@ struct swappy_point { gdouble y; }; -struct swappy_shape { +struct swappy_paint_shape { double r; double g; double b; @@ -42,10 +42,10 @@ struct swappy_shape { double w; struct swappy_point from; struct swappy_point to; - enum swappy_paint_mode_type type; + enum swappy_paint_type type; }; -struct swappy_brush_point { +struct swappy_paint_brush { double x; double y; double r; @@ -56,6 +56,14 @@ struct swappy_brush_point { enum swappy_brush_point_kind kind; }; +struct swappy_paint { + enum swappy_paint_type type; + union { + struct swappy_paint_brush brush; + struct swappy_paint_shape shape; + } content; +}; + struct swappy_box { int32_t x; int32_t y; @@ -100,7 +108,7 @@ struct swappy_state { char *storage_path; - enum swappy_paint_mode_type mode; + enum swappy_paint_type mode; int width; int height; @@ -112,8 +120,9 @@ struct swappy_state { struct swappy_box *geometry; GSList *brushes; - GSList *shapes; - struct swappy_shape *temp_shape; // Temporary shape + GSList *paints; + struct swappy_paint_shape *temp_shape; // Temporary shape + struct swappy_paint *temp_paint; // Temporary pain int argc; char **argv; diff --git a/src/application.c b/src/application.c index f8493f1..2268540 100644 --- a/src/application.c +++ b/src/application.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "clipboard.h" @@ -17,14 +18,14 @@ static void swappy_overlay_clear(struct swappy_state *state) { state->brushes = NULL; } - if (state->shapes) { - g_slist_free_full(state->shapes, g_free); - state->shapes = NULL; + if (state->paints) { + g_slist_free_full(state->paints, g_free); + state->paints = NULL; } - if (state->temp_shape) { - g_free(state->temp_shape); - state->temp_shape = NULL; + if (state->temp_paint) { + g_free(state->temp_paint); + state->temp_paint = NULL; } } @@ -205,7 +206,7 @@ static void keypress_handler(GtkWidget *widget, GdkEventKey *event, static void brush_add_point(struct swappy_state *state, double x, double y, enum swappy_brush_point_kind kind) { - struct swappy_brush_point *point = g_new(struct swappy_brush_point, 1); + struct swappy_paint_brush *point = g_new(struct swappy_paint_brush, 1); point->x = x; point->y = y; point->r = 1; @@ -219,56 +220,79 @@ static void brush_add_point(struct swappy_state *state, double x, double y, } static void paint_add_temporary(struct swappy_state *state, double x, double y, - enum swappy_paint_mode_type type) { - struct swappy_shape *temp = g_new(struct swappy_shape, 1); + enum swappy_paint_type type) { + struct swappy_paint *paint = g_new(struct swappy_paint, 1); + paint->type = type; - temp->from.x = x; - temp->from.y = y; - temp->r = 1; - temp->g = 0; - temp->b = 0; - temp->a = 1; - temp->w = 2; - temp->type = type; - - if (state->temp_shape) { - g_free(state->temp_shape); - state->temp_shape = NULL; + switch (type) { + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + paint->content.shape.from.x = x; + paint->content.shape.from.y = y; + paint->content.shape.r = 1; + paint->content.shape.g = 0; + paint->content.shape.b = 0; + paint->content.shape.a = 1; + paint->content.shape.w = 2; + paint->content.shape.type = type; + break; + default: + g_info("unable to add temporary paint: %d", type); + break; } - state->temp_shape = temp; + if (state->temp_paint) { + g_free(state->temp_paint); + } + + state->temp_paint = paint; } static void paint_update_temporary(struct swappy_state *state, double x, double y) { - if (!state->temp_shape) { + if (!state->temp_paint) { return; } - state->temp_shape->to.x = x; - state->temp_shape->to.y = y; + switch (state->temp_paint->type) { + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + state->temp_paint->content.shape.to.x = x; + state->temp_paint->content.shape.to.y = y; + break; + default: + g_info("unable to update temporary paint: %d", state->temp_paint->type); + break; + } } static void paint_commit_temporary(struct swappy_state *state, double x, double y) { - if (!state->temp_shape) { + if (!state->temp_paint) { return; } - state->temp_shape->to.x = x; - state->temp_shape->to.y = y; + switch (state->temp_paint->type) { + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + state->temp_paint->content.shape.to.x = x; + state->temp_paint->content.shape.to.y = y; - g_debug("commit temp paint: from: %lf,%lf to: %lf,%lf", - state->temp_shape->from.x, state->temp_shape->from.y, - state->temp_shape->to.x, state->temp_shape->to.y); + struct swappy_paint *paint = + g_memdup(state->temp_paint, sizeof(struct swappy_paint)); - struct swappy_shape *shape = - g_memdup(state->temp_shape, sizeof(struct swappy_shape)); + state->paints = g_slist_append(state->paints, paint); + break; + default: + g_info("unable to commit temporary paint: %d", state->temp_paint->type); + break; + } - state->shapes = g_slist_append(state->shapes, shape); - - g_free(state->temp_shape); - state->temp_shape = NULL; + g_free(state->temp_paint); + state->temp_paint = NULL; } static void draw_area_button_press_handler(GtkWidget *widget, diff --git a/src/draw.c b/src/draw.c index 99f56ba..18282b7 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,7 +1,5 @@ - #include #include -#include #include "swappy.h" @@ -33,12 +31,12 @@ static void apply_output_transform(enum wl_output_transform transform, } } -static void draw_shape_arrow(cairo_t *cr, struct swappy_shape *shape) { - cairo_set_source_rgba(cr, shape->r, shape->g, shape->b, shape->a); - cairo_set_line_width(cr, shape->w); +static void draw_shape_arrow(cairo_t *cr, struct swappy_paint_shape shape) { + cairo_set_source_rgba(cr, shape.r, shape.g, shape.b, shape.a); + cairo_set_line_width(cr, shape.w); - cairo_move_to(cr, shape->from.x, shape->from.y); - cairo_line_to(cr, shape->to.x, shape->to.y); + cairo_move_to(cr, shape.from.x, shape.from.y); + cairo_line_to(cr, shape.to.x, shape.to.y); cairo_stroke(cr); cairo_fill(cr); @@ -51,8 +49,8 @@ static void draw_shape_arrow(cairo_t *cr, struct swappy_shape *shape) { double xb = r * cos(tb); double yb = r * sin(tb); - double ftx = shape->to.x - shape->from.x; - double fty = shape->to.y - shape->from.y; + double ftx = shape.to.x - shape.from.x; + double fty = shape.to.y - shape.from.y; double ftz = sqrt(ftx * ftx + fty * fty); if (ftz == 0) { @@ -64,7 +62,7 @@ static void draw_shape_arrow(cairo_t *cr, struct swappy_shape *shape) { theta = M_PI + theta; } - cairo_translate(cr, shape->to.x, shape->to.y); + cairo_translate(cr, shape.to.x, shape.to.y); cairo_rotate(cr, theta); cairo_move_to(cr, 0, 0); cairo_line_to(cr, xa, ya); @@ -73,17 +71,17 @@ static void draw_shape_arrow(cairo_t *cr, struct swappy_shape *shape) { cairo_fill(cr); } -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_ellipse(cairo_t *cr, struct swappy_paint_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); double n = sqrt(x * x + y * y); double r = n / 2; - cairo_set_source_rgba(cr, shape->r, shape->g, shape->b, shape->a); - cairo_set_line_width(cr, shape->w); + cairo_set_source_rgba(cr, shape.r, shape.g, shape.b, shape.a); + cairo_set_line_width(cr, shape.w); cairo_matrix_t save_matrix; cairo_get_matrix(cr, &save_matrix); @@ -95,23 +93,23 @@ static void draw_shape_ellipse(cairo_t *cr, struct swappy_shape *shape) { 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); - double h = fabs(shape->from.y - shape->to.y); +static void draw_shape_rectangle(cairo_t *cr, struct swappy_paint_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); + double h = fabs(shape.from.y - shape.to.y); - cairo_set_source_rgba(cr, shape->r, shape->g, shape->b, shape->a); - cairo_set_line_width(cr, shape->w); + cairo_set_source_rgba(cr, shape.r, shape.g, shape.b, shape.a); + cairo_set_line_width(cr, shape.w); cairo_rectangle(cr, x, y, w, h); cairo_close_path(cr); cairo_stroke(cr); } -static void draw_shape(cairo_t *cr, struct swappy_shape *shape) { +static void draw_shape(cairo_t *cr, struct swappy_paint_shape shape) { cairo_save(cr); - switch (shape->type) { + switch (shape.type) { case SWAPPY_PAINT_MODE_RECTANGLE: draw_shape_rectangle(cr, shape); break; @@ -122,23 +120,11 @@ static void draw_shape(cairo_t *cr, struct swappy_shape *shape) { draw_shape_arrow(cr, shape); break; default: - g_debug("unknown shape type: %d", shape->type); + g_debug("unknown shape type: %d", shape.type); } cairo_restore(cr); } -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); - } -} - static void draw_buffer(cairo_t *cr, struct swappy_state *state) { // FIXME This is wrong, the geometry here is not quite valid // It must be based on output, but will work fine on single screen @@ -202,10 +188,10 @@ static void draw_buffer(cairo_t *cr, struct swappy_state *state) { static void draw_brushes(cairo_t *cr, struct swappy_state *state) { for (GSList *brush = state->brushes; brush; brush = brush->next) { GSList *brush_next = brush->next; - struct swappy_brush_point *point = brush->data; + struct swappy_paint_brush *point = brush->data; if (brush_next && point->kind == SWAPPY_BRUSH_POINT_WITHIN) { - struct swappy_brush_point *next = brush_next->data; + struct swappy_paint_brush *next = brush_next->data; cairo_set_source_rgba(cr, point->r, point->g, point->b, point->a); cairo_set_line_width(cr, point->w); cairo_move_to(cr, point->x, point->y); @@ -221,6 +207,30 @@ static void draw_brushes(cairo_t *cr, struct swappy_state *state) { } } +static void draw_paint(cairo_t *cr, struct swappy_paint *paint) { + switch (paint->type) { + case SWAPPY_PAINT_MODE_RECTANGLE: + case SWAPPY_PAINT_MODE_ELLIPSE: + case SWAPPY_PAINT_MODE_ARROW: + draw_shape(cr, paint->content.shape); + break; + default: + g_info("unable to draw paint with type: %d", paint->type); + break; + } +} + +static void draw_paints(cairo_t *cr, struct swappy_state *state) { + for (GSList *elem = state->paints; elem; elem = elem->next) { + struct swappy_paint *paint = elem->data; + draw_paint(cr, paint); + } + + if (state->temp_paint) { + draw_paint(cr, state->temp_paint); + } +} + void draw_state(struct swappy_state *state) { cairo_t *cr = cairo_create(state->cairo_surface); @@ -228,9 +238,9 @@ void draw_state(struct swappy_state *state) { draw_buffer(cr, state); draw_brushes(cr, state); - draw_shapes(cr, state); + draw_paints(cr, state); - // Drawing is finised, notify the GtkDrawingArea it needs to be redrawn. + // Drawing is finished, notify the GtkDrawingArea it needs to be redrawn. gtk_widget_queue_draw(state->area); cairo_destroy(cr);