From 267910666579014438820f5eb6987b7a3a66412d Mon Sep 17 00:00:00 2001 From: ChunEon Park Date: Fri, 3 Apr 2015 16:31:20 +0200 Subject: [PATCH] evas: add evas_vg_simple example. Signed-off-by: Cedric BAIL --- evas/Makefile.am | 17 +- unsorted/evas/evas-vg-simple.c | 617 +++++++++++++++++++++++++++++++++ 2 files changed, 629 insertions(+), 5 deletions(-) create mode 100644 unsorted/evas/evas-vg-simple.c diff --git a/evas/Makefile.am b/evas/Makefile.am index ad1893c4..165d7898 100644 --- a/evas/Makefile.am +++ b/evas/Makefile.am @@ -7,12 +7,12 @@ AM_CPPFLAGS = \ -I$(top_builddir)/src/lib/efl/interfaces \ -I$(top_srcdir)/src/lib/eina \ -I$(top_srcdir)/src/lib/eo \ --I$(top_srcdir)/src/lib/evas \ -I$(top_srcdir)/src/lib/ector \ +-I$(top_srcdir)/src/lib/evas \ -I$(top_builddir)/src/lib/eina \ -I$(top_builddir)/src/lib/eo \ --I$(top_builddir)/src/lib/evas \ -I$(top_builddir)/src/lib/ector \ +-I$(top_builddir)/src/lib/evas \ @EVAS_CFLAGS@ EDCS = aspect.edc @@ -54,11 +54,11 @@ ECORE_EVAS_COMMON_LDADD = \ $(top_builddir)/src/lib/efl/libefl.la \ $(top_builddir)/src/lib/eina/libeina.la \ $(top_builddir)/src/lib/eo/libeo.la \ -$(top_builddir)/src/lib/ector/libector.la \ $(top_builddir)/src/lib/ecore/libecore.la \ $(top_builddir)/src/lib/ecore_file/libecore_file.la \ $(top_builddir)/src/lib/ecore_input/libecore_input.la \ $(top_builddir)/src/lib/ecore_evas/libecore_evas.la \ +$(top_builddir)/src/lib/ector/libector.la \ $(top_builddir)/src/lib/evas/libevas.la \ @EVAS_LDFLAGS@ -lm @@ -71,7 +71,9 @@ EDJE_COMMON_CPPFLAGS = \ -I$(top_builddir)/src/lib/eo \ -I$(top_srcdir)/src/lib/eet \ -I$(top_builddir)/src/lib/eet \ +-I$(top_srcdir)/src/lib/ector \ -I$(top_srcdir)/src/lib/evas \ +-I$(top_builddir)/src/lib/ector \ -I$(top_builddir)/src/lib/evas \ -I$(top_srcdir)/src/lib/ecore \ -I$(top_builddir)/src/lib/ecore \ @@ -96,7 +98,6 @@ EDJE_COMMON_LDADD = \ $(top_builddir)/src/lib/eina/libeina.la \ $(top_builddir)/src/lib/eo/libeo.la \ $(top_builddir)/src/lib/eet/libeet.la \ -$(top_builddir)/src/lib/ector/libector.la \ $(top_builddir)/src/lib/evas/libevas.la \ $(top_builddir)/src/lib/ecore/libecore.la \ $(top_builddir)/src/lib/ecore_evas/libecore_evas.la \ @@ -288,6 +289,11 @@ evas_gl_SOURCES = evas-gl.c evas_gl_LDADD = $(ECORE_EVAS_COMMON_LDADD) @EFL_PTHREAD_LIBS@ evas_gl_CPPFLAGS = $(ECORE_EVAS_COMMON_CPPFLAGS) +EXTRA_PROGRAMS += evas_vg_simple +evas_vg_simple_SOURCES = evas-vg-simple.c +evas_vg_simple_LDADD = $(ECORE_EVAS_COMMON_LDADD) +evas_vg_simple_CPPFLAGS = $(ECORE_EVAS_COMMON_CPPFLAGS) + .edc.edj: $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) $< $(builddir)/$(@F) @@ -330,7 +336,8 @@ evas-smart-object.c \ evas-stacking.c \ evas-table.c \ evas-multi-touch.c \ -evas-text.c +evas-text.c \ +evas-vg-simple.c DATA_FILES = \ resources/images/enlightenment.png \ diff --git a/unsorted/evas/evas-vg-simple.c b/unsorted/evas/evas-vg-simple.c new file mode 100644 index 00000000..d90932fa --- /dev/null +++ b/unsorted/evas/evas-vg-simple.c @@ -0,0 +1,617 @@ +/** + * Simple Evas example illustrating a custom Evas box object + * + * You'll need at least one engine built for it (excluding the buffer + * one). See stdout/stderr for output. + * + * @verbatim + * gcc -o evas-box evas-box.c `pkg-config --libs --cflags evas ecore ecore-evas eina ector eo efl` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define PACKAGE_EXAMPLES_DIR "." +#endif + +#define WIDTH 400 +#define HEIGHT 400 + +#ifndef EFL_BETA_API_SUPPORT +#define EFL_BETA_API_SUPPORT 1 +#endif + +#ifndef EFL_EO_API_SUPPORT +#define EFL_EO_API_SUPPORT 1 +#endif + +#include +#include +#include +#include +#include + + +#include +#include + +#define PATH_KAPPA 0.5522847498 +#define PI 3.1415926535 + +typedef struct _Bezier +{ +float x1, y1, x2, y2, x3, y3, x4, y4; +}Bezier; + +typedef struct _Point +{ + int x; + int y; +}Point; + +static +Bezier bezierFromPoints(Point p1, Point p2, + Point p3, Point p4) +{ + Bezier b; + b.x1 = p1.x; + b.y1 = p1.y; + b.x2 = p2.x; + b.y2 = p2.y; + b.x3 = p3.x; + b.y3 = p3.y; + b.x4 = p4.x; + b.y4 = p4.y; + return b; +} + +inline void +parameterSplitLeft(Bezier *b, float t, Bezier *left) +{ + left->x1 = b->x1; + left->y1 = b->y1; + + left->x2 = b->x1 + t * ( b->x2 - b->x1 ); + left->y2 = b->y1 + t * ( b->y2 - b->y1 ); + + left->x3 = b->x2 + t * ( b->x3 - b->x2 ); // temporary holding spot + left->y3 = b->y2 + t * ( b->y3 - b->y2 ); // temporary holding spot + + b->x3 = b->x3 + t * ( b->x4 - b->x3 ); + b->y3 = b->y3 + t * ( b->y4 - b->y3 ); + + b->x2 = left->x3 + t * ( b->x3 - left->x3); + b->y2 = left->y3 + t * ( b->y3 - left->y3); + + left->x3 = left->x2 + t * ( left->x3 - left->x2 ); + left->y3 = left->y2 + t * ( left->y3 - left->y2 ); + + left->x4 = b->x1 = left->x3 + t * (b->x2 - left->x3); + left->y4 = b->y1 = left->y3 + t * (b->y2 - left->y3); +} +static +Bezier bezierOnInterval(Bezier *b, float t0, float t1) +{ + if (t0 == 0 && t1 == 1) + return *b; + + Bezier result; + parameterSplitLeft(b, t0, &result); + float trueT = (t1-t0)/(1-t0); + parameterSplitLeft(b, trueT, &result); + + return result; +} + +inline void +_bezier_coefficients(float t, float *ap, float *bp, float *cp, float *dp) +{ + float a,b,c,d; + float m_t = 1. - t; + b = m_t * m_t; + c = t * t; + d = c * t; + a = b * m_t; + b *= 3. * t; + c *= 3. * m_t; + *ap = a; + *bp = b; + *cp = c; + *dp = d; +} + +static +float _t_for_arc_angle(float angle) +{ + if (angle < 0.00001) + return 0; + + if (angle == 90.0) + return 1; + + float radians = PI * angle / 180; + float cosAngle = cos(radians); + float sinAngle = sin(radians); + + // initial guess + float tc = angle / 90; + // do some iterations of newton's method to approximate cosAngle + // finds the zero of the function b.pointAt(tc).x() - cosAngle + tc -= ((((2-3*PATH_KAPPA) * tc + 3*(PATH_KAPPA-1)) * tc) * tc + 1 - cosAngle) // value + / (((6-9*PATH_KAPPA) * tc + 6*(PATH_KAPPA-1)) * tc); // derivative + tc -= ((((2-3*PATH_KAPPA) * tc + 3*(PATH_KAPPA-1)) * tc) * tc + 1 - cosAngle) // value + / (((6-9*PATH_KAPPA) * tc + 6*(PATH_KAPPA-1)) * tc); // derivative + + // initial guess + float ts = tc; + // do some iterations of newton's method to approximate sinAngle + // finds the zero of the function b.pointAt(tc).y() - sinAngle + ts -= ((((3*PATH_KAPPA-2) * ts - 6*PATH_KAPPA + 3) * ts + 3*PATH_KAPPA) * ts - sinAngle) + / (((9*PATH_KAPPA-6) * ts + 12*PATH_KAPPA - 6) * ts + 3*PATH_KAPPA); + ts -= ((((3*PATH_KAPPA-2) * ts - 6*PATH_KAPPA + 3) * ts + 3*PATH_KAPPA) * ts - sinAngle) + / (((9*PATH_KAPPA-6) * ts + 12*PATH_KAPPA - 6) * ts + 3*PATH_KAPPA); + + // use the average of the t that best approximates cosAngle + // and the t that best approximates sinAngle + float t = 0.5 * (tc + ts); + return t; +} + +static void +_find_ellipse_coords(int x, int y, int w, int h, float angle, float length, + Point* startPoint, Point *endPoint) +{ + if (!w || !h ) { + if (startPoint) + startPoint->x = 0 , startPoint->y = 0; + if (endPoint) + endPoint->x = 0 , endPoint->y = 0; + return; + } + + int w2 = w / 2; + int h2 = h / 2; + + float angles[2] = { angle, angle + length }; + Point *points[2] = { startPoint, endPoint }; + int i =0; + for (i = 0; i < 2; ++i) { + if (!points[i]) + continue; + + float theta = angles[i] - 360 * floor(angles[i] / 360); + float t = theta / 90; + // truncate + int quadrant = (int)t; + t -= quadrant; + + t = _t_for_arc_angle(90 * t); + + // swap x and y? + if (quadrant & 1) + t = 1 - t; + + float a, b, c, d; + _bezier_coefficients(t, &a, &b, &c, &d); + float px = a + b + c*PATH_KAPPA; + float py = d + c + b*PATH_KAPPA; + + // left quadrants + if (quadrant == 1 || quadrant == 2) + px = -px; + + // top quadrants + if (quadrant == 0 || quadrant == 1) + py = -py; + int cx = x+w/2; + int cy = y+h/2; + points[i]->x = cx + w2 * px; + points[i]->y = cy + h2 * py; + } +} + + +//// The return value is the starting point of the arc +static +Point _curves_for_arc(int x, int y, int w, int h, + float startAngle, float sweepLength, + Point *curves, int *point_count) +{ + *point_count = 0; + int w2 = w / 2; + int w2k = w2 * PATH_KAPPA; + + int h2 = h / 2; + int h2k = h2 * PATH_KAPPA; + + Point points[16] = + { + // start point + x + w, y + h2, + + // 0 -> 270 degrees + x + w, y + h2 + h2k, + x + w2 + w2k, y + h, + x + w2, y + h, + + // 270 -> 180 degrees + x + w2 - w2k, y + h, + x, y + h2 + h2k, + x, y + h2, + + // 180 -> 90 degrees + x, y + h2 - h2k, + x + w2 - w2k, y, + x + w2, y, + + // 90 -> 0 degrees + x + w2 + w2k, y, + x + w, y + h2 - h2k, + x + w, y + h2 + }; + + if (sweepLength > 360) sweepLength = 360; + else if (sweepLength < -360) sweepLength = -360; + + // Special case fast paths + if (startAngle == 0) { + if (sweepLength == 360) { + int i; + for (i = 11; i >= 0; --i) + curves[(*point_count)++] = points[i]; + return points[12]; + } else if (sweepLength == -360) { + int i ; + for (i = 1; i <= 12; ++i) + curves[(*point_count)++] = points[i]; + return points[0]; + } + } + + int startSegment = (int)(floor(startAngle / 90)); + int endSegment = (int)(floor((startAngle + sweepLength) / 90)); + + float startT = (startAngle - startSegment * 90) / 90; + float endT = (startAngle + sweepLength - endSegment * 90) / 90; + + int delta = sweepLength > 0 ? 1 : -1; + if (delta < 0) { + startT = 1 - startT; + endT = 1 - endT; + } + + // avoid empty start segment + if (startT == 1.0) { + startT = 0; + startSegment += delta; + } + + // avoid empty end segment + if (endT == 0) { + endT = 1; + endSegment -= delta; + } + + startT = _t_for_arc_angle(startT * 90); + endT = _t_for_arc_angle(endT * 90); + + Eina_Bool splitAtStart = !(fabs(startT) <= 0.00001f); + Eina_Bool splitAtEnd = !(fabs(endT - 1.0) <= 0.00001f); + + const int end = endSegment + delta; + + // empty arc? + if (startSegment == end) { + const int quadrant = 3 - ((startSegment % 4) + 4) % 4; + const int j = 3 * quadrant; + return delta > 0 ? points[j + 3] : points[j]; + } + + + Point startPoint, endPoint; + _find_ellipse_coords(x, y, w, h, startAngle, sweepLength, &startPoint, &endPoint); + int i; + for (i = startSegment; i != end; i += delta) { + const int quadrant = 3 - ((i % 4) + 4) % 4; + const int j = 3 * quadrant; + + Bezier b; + if (delta > 0) + b = bezierFromPoints(points[j + 3], points[j + 2], points[j + 1], points[j]); + else + b = bezierFromPoints(points[j], points[j + 1], points[j + 2], points[j + 3]); + + // empty arc? + if (startSegment == endSegment && (startT == endT)) + return startPoint; + + if (i == startSegment) { + if (i == endSegment && splitAtEnd) + b = bezierOnInterval(&b, startT, endT); + else if (splitAtStart) + b = bezierOnInterval(&b, startT, 1); + } else if (i == endSegment && splitAtEnd) { + b = bezierOnInterval(&b, 0, endT); + } + + // push control points + curves[(*point_count)].x = b.x2; + curves[(*point_count)++].y = b.y2; + curves[(*point_count)].x = b.x3; + curves[(*point_count)++].y = b.y3; + curves[(*point_count)].x = b.x4; + curves[(*point_count)++].y = b.y4; + } + + curves[*(point_count)-1] = endPoint; + + return startPoint; +} + +void _arcto(Efl_Graphics_Path_Command **path_cmd, double **points,int x, int y, int width, int height, int startAngle, int sweepLength) +{ + int point_count; + + Point pts[15]; + Point curve_start = _curves_for_arc(x,y,width,height, startAngle, sweepLength, pts, &point_count); + int cx = x + (width)/2; + int cy = y + (height)/2; + + efl_gfx_path_append_move_to(path_cmd, points, cx, cy); + + efl_gfx_path_append_line_to(path_cmd, points, curve_start.x, curve_start.y); + int i; + for (i=0; i