refactor: move shape into union

This commit is contained in:
Jeremy Attali 2019-12-22 13:14:53 -05:00
parent be90fffa14
commit a855e3b370
3 changed files with 130 additions and 87 deletions

View File

@ -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;

View File

@ -2,6 +2,7 @@
#include <glib-2.0/glib.h>
#include <gtk-layer-shell/gtk-layer-shell.h>
#include <gtk/gtk.h>
#include <include/swappy.h>
#include <time.h>
#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,

View File

@ -1,7 +1,5 @@
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#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);