summaryrefslogtreecommitdiffstats
path: root/friendfinder/render/line.c
diff options
context:
space:
mode:
Diffstat (limited to 'friendfinder/render/line.c')
-rw-r--r--friendfinder/render/line.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/friendfinder/render/line.c b/friendfinder/render/line.c
new file mode 100644
index 0000000..5af1ec7
--- /dev/null
+++ b/friendfinder/render/line.c
@@ -0,0 +1,394 @@
+#include <stdio.h>
+
+#include <Evas.h>
+
+#include <math.h>
+#include "render/line.h"
+
+static Evas_Smart *get_smart();
+
+static void _line_object_add(Evas_Object *o);
+static void _line_object_del(Evas_Object *o);
+static void _line_object_move(Evas_Object *o, Evas_Coord x, Evas_Coord y);
+static void _line_object_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h);
+static void _line_object_show(Evas_Object *o);
+static void _line_object_hide(Evas_Object *o);
+static void _line_object_color_set(Evas_Object *o, int r, int g, int b, int a);
+static void _line_object_clip_set(Evas_Object *o, Evas_Object *clip);
+static void _line_object_clip_unset(Evas_Object *o);
+
+#define SMART_LINE_NAME "e_smart_line"
+
+struct polyline *polyline_empty()
+{
+ struct polyline *pl;
+
+ pl = (struct polyline *)malloc(sizeof(struct polyline));
+ if (pl == NULL)
+ return NULL;
+
+ pl->w = 0;
+ pl->a = 255;
+ pl->r = 0;
+ pl->g = 0;
+ pl->b = 0;
+
+ pl->points = NULL;
+ pl->count = 0;
+ pl->mode = 0;
+
+ return pl;
+}
+
+void polyline_delete(struct polyline *pl)
+{
+ free(pl->points);
+ free(pl);
+}
+
+void polyline_set_color(struct polyline *pl, int r, int g, int b, int a)
+{
+ pl->a = a;
+ pl->r = r;
+ pl->g = g;
+ pl->b = b;
+}
+
+void polyline_set_width(struct polyline *pl, int w)
+{
+ pl->w = w;
+}
+
+void polyline_add_point(struct polyline *pl, struct point p)
+{
+ pl->points = realloc(pl->points, (pl->count + 1) * sizeof(struct point));
+ pl->points[pl->count] = p;
+ pl->count++;
+}
+
+struct smart_line
+{
+ Evas_Object *obj;
+ Evas_Coord x, y, w, h;
+
+ Evas_Object *clip;
+ Evas_Object *poly;
+ struct point *points;
+ struct polyline *pl;
+ int pcount;
+};
+
+Evas_Object *e_smart_line_add(Evas *e)
+{
+ Evas_Object *o;
+ struct smart_line *smart;
+
+ o = evas_object_smart_add(e, get_smart());
+ smart = evas_object_smart_data_get(o);
+ if(smart == NULL)
+ {
+ evas_object_del(o);
+ return NULL;
+ }
+ smart->points = NULL;
+ smart->pcount = 0;
+ smart->pl = NULL;
+ return o;
+}
+
+static inline int
+line_cut(struct line l0, struct line l1, struct point *p)
+{
+ Evas_Coord c1, c2, det, a1, a2, b1, b2;
+
+ b1 = l0.p0.x - l0.p1.x; // b1 = x1 - x2
+ a1 = l0.p1.y - l0.p0.y; // a1 = y2 - y1
+ c1 = l0.p1.x * l0.p0.y - l0.p0.x * l0.p1.y; // c = x2*y1 - x1*y2;
+
+ b2 = l1.p0.x - l1.p1.x; // b2 = x3 - x4
+ a2 = l1.p1.y - l1.p0.y; // a2 = y4 - y3
+ c2 = l1.p1.x * l1.p0.y - l1.p0.x * l1.p1.y;
+
+ det = a1 * b2 - a2 * b1;
+ if(det == 0)
+ return -1;
+
+ p->x = (b1*c2 - b2*c1)/det;
+ p->y = (a2*c1 - a1*c2)/det;
+
+ return 0;
+}
+
+static inline struct line
+new_line(struct point p0, struct point p1)
+{
+ struct line l;
+ l.p0 = p0;
+ l.p1 = p1;
+ return l;
+}
+
+static inline void
+wide_line(Evas_Coord w, struct line l, struct line *l0, struct line *l1)
+{
+ Evas_Coord dX, dY, dx, dy;
+ double scale, len, ddx, ddy;
+
+ dX = l.p1.x - l.p0.x;
+ dY = l.p1.y - l.p0.y;
+ len = sqrt(dX * dX + dY * dY);
+ scale = (double)(w) / (2 * len);
+
+ ddx = -scale * (double)dY;
+ ddy = scale * (double)dX;
+ ddx += (ddx > 0) ? 0.5 : -0.5;
+ ddy += (ddy > 0) ? 0.5 : -0.5;
+
+ dx = (Evas_Coord)ddx;
+ dy = (Evas_Coord)ddy;
+
+ l0->p0.x = l.p0.x + dx;
+ l0->p0.y = l.p0.y + dy;
+
+ l1->p0.x = l.p0.x - dx;
+ l1->p0.y = l.p0.y - dy;
+
+ l0->p1.x = l.p1.x + dx;
+ l0->p1.y = l.p1.y + dy;
+
+ l1->p1.x = l.p1.x - dx;
+ l1->p1.y = l.p1.y - dy;
+}
+
+static int _is_line_valid(struct line *l, int w)
+{
+ int dx = abs(l->p1.x - l->p0.x);
+ int dy = abs(l->p1.y - l->p0.y);
+ if(dx < w && dy < w)
+ return 0;
+ return 1;
+}
+
+static void _line_update(struct smart_line *smart, int dx, int dy)
+{
+ int i;
+
+ evas_object_polygon_points_clear(smart->poly);
+ for(i = 0; i < smart->pcount; i++)
+ {
+// printf("p[%i]: %i,%i\n", i, poly[i].x, poly[i].y);
+ evas_object_polygon_point_add(smart->poly, smart->points[i].x - dx, smart->points[i].y - dy);
+ }
+ evas_object_show(smart->poly);
+}
+
+struct polyline *e_smart_line_get(Evas_Object *o)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+ return smart->pl;
+}
+
+void e_smart_line_set(Evas_Object *o, struct polyline *pl)
+{
+ int i;
+ struct smart_line *smart;
+ struct line l0_0 = {{0}};
+ struct line l0_1 = {{0}};
+
+ struct point fwd[pl->count];
+ struct point bwd[pl->count];
+
+ int pcount = 0;
+ struct point last;
+
+ if(pl->count < 1)
+ return;
+ smart = evas_object_smart_data_get(o);
+ last = pl->points[0];
+
+ for(i = 1; i < pl->count; i++)
+ {
+ struct point tmp;
+ struct line l = new_line(last, pl->points[i]);
+ if(!_is_line_valid(&l, pl->w))
+ continue;
+
+ if(pcount == 0)
+ {
+ wide_line(pl->w, l, &l0_0, &l0_1);
+ fwd[pcount] = l0_0.p0;
+ bwd[pcount] = l0_1.p0;
+ last = pl->points[i];
+ pcount++;
+ continue;
+ }
+ if(i >= pl->count - 1)
+ {
+ fwd[pcount] = l0_0.p1;
+ bwd[pcount] = l0_1.p1;
+ pcount++;
+ break;
+ }
+
+ struct line l1_0, l1_1;
+
+ wide_line(pl->w, l, &l1_0, &l1_1);
+
+ if(line_cut(l0_0, l1_0, &tmp) < 0)
+ continue;
+ fwd[pcount] = tmp;
+
+ if(line_cut(l0_1, l1_1, &tmp) < 0)
+ continue;
+
+ bwd[pcount] = tmp;
+ last = pl->points[i];
+ l0_0 = l1_0;
+ l0_1 = l1_1;
+ pcount++;
+ }
+
+ if(smart->points != NULL)
+ free(smart->points);
+ smart->points = (struct point *)malloc(sizeof(struct point) * pcount * 2);
+ smart->pcount = pcount * 2;
+
+ for(i = 0; i < pcount; i++)
+ {
+ smart->points[i] = fwd[i];
+ smart->points[2 * pcount - i - 1] = bwd[i];
+ }
+ evas_object_color_set(smart->poly, pl->r, pl->g, pl->b, pl->a);
+ _line_update(smart, smart->x, smart->y);
+ smart->pl = pl;
+}
+
+static void _line_object_add(Evas_Object *o)
+{
+ struct smart_line *smart;
+
+ smart = calloc(1, sizeof(struct smart_line));
+ if (smart == NULL)
+ return;
+
+ smart->obj = o;
+ smart->x = 0;
+ smart->y = 0;
+ smart->w = 0;
+ smart->h = 0;
+
+ smart->clip = evas_object_rectangle_add(evas_object_evas_get(o));
+ evas_object_smart_member_add(smart->clip, o);
+ evas_object_color_set(smart->clip, 255, 255, 255, 255);
+ evas_object_move(smart->clip, smart->x, smart->y);
+ evas_object_resize(smart->clip, smart->w, smart->h);
+
+ smart->poly = evas_object_polygon_add(evas_object_evas_get(o));
+ evas_object_smart_member_add(smart->poly, o);
+ evas_object_color_set(smart->poly, 255, 255, 255, 255);
+ evas_object_move(smart->poly, smart->x, smart->y);
+ evas_object_resize(smart->poly, smart->w, smart->h);
+ evas_object_show(smart->poly);
+
+ evas_object_smart_data_set(o, smart);
+}
+
+static void _line_object_del(Evas_Object *o)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_del(smart->clip);
+ evas_object_del(smart->poly);
+
+ free(smart);
+}
+
+static void _line_object_move(Evas_Object *o, Evas_Coord x, Evas_Coord y)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ smart->x = x;
+ smart->y = y;
+
+ _line_update(smart, smart->x, smart->y);
+}
+
+static void _line_object_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ smart->w = w;
+ smart->h = h;
+ evas_object_resize(smart->clip, smart->w, smart->h);
+ evas_object_resize(smart->poly, smart->w, smart->h);
+}
+
+static void _line_object_show(Evas_Object *o)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_show(smart->clip);
+}
+
+static void _line_object_hide(Evas_Object *o)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_hide(smart->clip);
+}
+
+static void _line_object_color_set(Evas_Object *o, int r, int g, int b, int a)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_color_set(smart->poly, r, g, b, a);
+}
+
+static void _line_object_clip_set(Evas_Object *o, Evas_Object *clip)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_clip_set(smart->clip, clip);
+}
+
+static void _line_object_clip_unset(Evas_Object *o)
+{
+ struct smart_line *smart;
+ smart = evas_object_smart_data_get(o);
+
+ evas_object_clip_unset(smart->clip);
+}
+
+static Evas_Smart *get_smart()
+{
+ static Evas_Smart *e_smart_line = NULL;
+
+ if(e_smart_line != NULL)
+ return e_smart_line;
+
+ e_smart_line = evas_smart_new(SMART_LINE_NAME,
+ _line_object_add,
+ _line_object_del,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _line_object_move,
+ _line_object_resize,
+ _line_object_show,
+ _line_object_hide,
+ _line_object_color_set,
+ _line_object_clip_set,
+ _line_object_clip_unset,
+ NULL);
+ return e_smart_line;
+}