--- /dev/null
+#include "triangulator_simple.h"
+
+Triangulator_Simple *
+triangulator_simple_new(void)
+{
+ Triangulator_Simple *st = calloc(1, sizeof(Triangulator_Simple));
+ st->vertices = eina_inarray_new(sizeof(float), 0);
+ st->stops = eina_inarray_new(sizeof(int), 0);
+ return st;
+}
+
+void
+triangulator_simple_free(Triangulator_Simple *st)
+{
+ eina_inarray_free(st->vertices);
+ eina_inarray_free(st->stops);
+}
+
+static void
+_add_line(Triangulator_Simple *st, const float x, const float y)
+{
+ float *ptr;
+
+ ptr = eina_inarray_grow(st->vertices, 2);
+ ptr[0] = x;
+ ptr[1] = y;
+
+ if (x > st->maxx)
+ st->maxx = x;
+ else if (x < st->minx)
+ st->minx = x;
+ if (y > st->maxy)
+ st->maxy = y;
+ else if (y < st->miny)
+ st->miny = y;
+}
+
+static void
+_calculate_centroid(const Efl_Gfx_Path_Command *cmds, const double *pts, double *cx, double *cy)
+{
+ double sumx = 0, sumy = 0;
+ int count = 0;
+
+ sumx += pts[0];
+ sumy += pts[1];
+ for (cmds++, count++, pts+=2; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
+ {
+ switch (*cmds)
+ {
+ case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
+ sumx += pts[0];
+ sumy += pts[1];
+ pts +=2;
+ count++;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
+ sumx += pts[0];
+ sumy += pts[1];
+ sumx += pts[2];
+ sumy += pts[3];
+ sumx += pts[4];
+ sumy += pts[5];
+ pts +=6;
+ count +=3;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
+ case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
+ *cx = sumx/count;
+ *cy = sumy/count;
+ return;
+ default:
+ break;
+ }
+ }
+ //
+ *cx = sumx/count;
+ *cy = sumy/count;
+}
+
+void
+triangulator_simple_process(Triangulator_Simple *st, const Efl_Gfx_Path_Command *cmds, const double *pts, Eina_Bool convex)
+{
+ double bw, bh, cx, cy, x, y, t, one_over_threshold_minus_1;
+ float *ptr;
+ int *stop_ptr, threshold, i;
+ Eina_Bezier b;
+
+ eina_inarray_resize(st->vertices, 0);
+ eina_inarray_resize(st->stops, 0);
+ if (!convex)
+ {
+ _calculate_centroid(cmds, pts, &cx, &cy);
+ _add_line(st, cx, cy);
+ }
+
+ cx = pts[0];
+ cy = pts[1];
+ // The first element is always a moveTo
+ _add_line(st, cx, cy);
+ pts += 2;
+ cmds++;
+ for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
+ {
+ switch (*cmds)
+ {
+ case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
+
+ // add closing line for the previous contour
+ _add_line(st, cx, cy);
+
+ // update stop array
+ stop_ptr = eina_inarray_grow(st->stops, 1);
+ stop_ptr[0] = eina_inarray_count(st->vertices);
+
+ // add centroid if not convex
+ if (!convex)
+ {
+ _calculate_centroid(cmds, pts, &cx, &cy);
+ _add_line(st, cx, cy);
+ }
+ cx = pts[0];
+ cy = pts[1];
+ _add_line(st, cx, cy);
+ pts += 2;
+ break;
+
+ case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
+
+ _add_line(st, pts[0], pts[1]);
+ pts += 2;
+ break;
+
+ case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
+ ptr = eina_inarray_nth(st->vertices, eina_inarray_count(st->vertices) - 2);
+ eina_bezier_values_set(&b, ptr[0], ptr[1], pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
+ eina_bezier_bounds_get(&b, NULL, NULL , &bw, &bh);
+ threshold = fminf(64, fmaxf(bw, bh) * 3.14f / 6);
+ if (threshold < 3) threshold = 3;
+ one_over_threshold_minus_1 = 1.0 / (threshold - 1);
+ for (i=1; i<threshold; ++i)
+ {
+ t = i * one_over_threshold_minus_1;
+ eina_bezier_point_at(&b, t, &x, &y);
+ _add_line(st, x, y);
+ }
+ pts += 6;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
+ case EFL_GFX_PATH_COMMAND_TYPE_LAST:
+ case EFL_GFX_PATH_COMMAND_TYPE_END:
+ break;
+ }
+ }
+ // add closing line for the previous contour
+ _add_line(st, cx, cy);
+
+ // update stop array
+ stop_ptr = eina_inarray_grow(st->stops, 1);
+ stop_ptr[0] = eina_inarray_count(st->vertices);
+}
\ No newline at end of file
--- /dev/null
+
+#include "triangulator_stroker.h"
+#include <math.h>
+
+#define PI 3.1415
+#define CURVE_FLATNESS PI / 8
+
+Triangulator_Stroker *
+triangulator_stroker_new(void)
+{
+ Triangulator_Stroker *stroker = calloc(1, sizeof(Triangulator_Stroker));
+ stroker->vertices = eina_inarray_new(sizeof(float), 0);
+ stroker->arc_pts = eina_inarray_new(sizeof(float), 0);
+ stroker->miter_limit = 2;
+ return stroker;
+}
+
+void
+triangulator_stroker_free(Triangulator_Stroker *stroker)
+{
+ eina_inarray_free(stroker->vertices);
+ eina_inarray_free(stroker->arc_pts);
+}
+
+void triangulator_stroker_stroke_set(Triangulator_Stroker *stroker, float width,
+ Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style, Eina_Matrix3 *m)
+{
+ float scale_factor = 1.0;
+ if (m)
+ {
+ // get the minimum scale factor from matrix
+ scale_factor = m->xx < m->yy ? m->xx : m->yy;
+ }
+ //@TODO devide the witdth/2 after fixing tizen_vector.c
+ stroker->width = (width * scale_factor);
+ stroker->join_style = join_style;
+ stroker->cap_style = cap_style;
+}
+
+// calculate the normal vector
+static void
+normal_vector(float x1, float y1, float x2, float y2, float width,
+ float *nx, float *ny)
+{
+ float pw;
+ float dx = x2 - x1;
+ float dy = y2 - y1;
+
+ if (dx == 0)
+ pw = width / fabsf(dy);
+ else if (dy == 0)
+ pw = width / fabsf(dx);
+ else
+ pw = width / sqrtf(dx*dx + dy*dy);
+
+ *nx = -dy * pw;
+ *ny = dx * pw;
+}
+
+// add a line segment
+static void
+add_line_segment(Triangulator_Stroker *stroker, float x, float y, float vx, float vy)
+{
+ float *ptr;
+
+ ptr = eina_inarray_grow(stroker->vertices, 4);
+ ptr[0] = x + vx;
+ ptr[1] = y + vy;
+ ptr[2] = x - vx;
+ ptr[3] = y - vy;
+}
+
+static void
+add_arc_points(Triangulator_Stroker *stroker, float cx, float cy, float from_x, float from_y, float to_x, float to_y)
+{
+ float tmp_x, tmp_y, *ptr;
+ float dx1 = from_x - cx;
+ float dy1 = from_y - cy;
+ float dx2 = to_x - cx;
+ float dy2 = to_y - cy;
+ int size;
+
+ eina_inarray_resize(stroker->arc_pts, 0);
+
+#define ADD_NEW_POINT \
+ tmp_x = dx1 * stroker->cos_theta - dy1 * stroker->sin_theta; \
+ tmp_y = dx1 * stroker->sin_theta + dy1 * stroker->cos_theta; \
+ dx1 = tmp_x; \
+ dy1 = tmp_y; \
+ ptr = eina_inarray_grow(stroker->arc_pts, 2); \
+ ptr[0] = cx + dx1; \
+ ptr[1] = cy + dy1;
+
+ // while more than 180 degrees left:
+ while (dx1 * dy2 - dx2 * dy1 < 0)
+ {
+ ADD_NEW_POINT
+ }
+
+ // while more than 90 degrees left:
+ while (dx1 * dx2 + dy1 * dy2 < 0)
+ {
+ ADD_NEW_POINT
+ }
+
+ // while more than 0 degrees left:
+ while (dx1 * dy2 - dx2 * dy1 > 0)
+ {
+ ADD_NEW_POINT
+ }
+
+ // remove last point which was rotated beyond [to_x, to_y].
+ size = eina_inarray_count(stroker->arc_pts);
+ if (size)
+ eina_inarray_resize(stroker->arc_pts, size - 2);
+}
+
+static void
+move_to(Triangulator_Stroker *stroker, const double *pts)
+{
+ float x2,y2, sx, sy, *ptr=NULL, *ptr1=NULL;
+ int pts_count, arc_pts_count, front, end, i=0;
+ Eina_Bool jump;
+
+ stroker->cx = pts[0];
+ stroker->cy = pts[1];
+ x2 = pts[2];
+ y2 = pts[3];
+ normal_vector(stroker->cx, stroker->cy, x2, y2, stroker->width, &stroker->nvx, &stroker->nvy);
+
+ // To acheive jumps we insert zero-area tringles. This is done by
+ // adding two identical points in both the end of previous strip
+ // and beginning of next strip
+ jump = eina_inarray_count(stroker->vertices);
+
+ switch (stroker->cap_style)
+ {
+ case EFL_GFX_CAP_BUTT:
+ if (jump)
+ {
+ ptr = eina_inarray_grow(stroker->vertices, 2);
+ ptr[0] = stroker->cx + stroker->nvx;
+ ptr[1] = stroker->cy + stroker->nvy;
+ }
+ break;
+ case EFL_GFX_CAP_SQUARE:
+ {
+ sx = stroker->cx - stroker->nvy;
+ sy = stroker->cy + stroker->nvx;
+ if (jump)
+ {
+ ptr = eina_inarray_grow(stroker->vertices, 2);
+ ptr[0] = sx + stroker->nvx;
+ ptr[1] = sy + stroker->nvy;
+ }
+ add_line_segment(stroker, sx, sy, stroker->nvx, stroker->nvy);
+ break;
+ }
+ case EFL_GFX_CAP_ROUND:
+ {
+ add_arc_points(stroker, stroker->cx, stroker->cy,
+ stroker->cx + stroker->nvx, stroker->cy + stroker->nvy,
+ stroker->cx - stroker->nvx, stroker->cy - stroker->nvy);
+ arc_pts_count = eina_inarray_count(stroker->arc_pts);
+ front = 0;
+ end = arc_pts_count / 2;
+ if (arc_pts_count)
+ {
+ eina_inarray_grow(stroker->vertices, eina_inarray_count(stroker->arc_pts) + 2 * jump);
+ pts_count = eina_inarray_count(stroker->vertices);
+ ptr1 = eina_inarray_nth(stroker->arc_pts, 0);
+ ptr = eina_inarray_nth(stroker->vertices, 0);
+ i = pts_count;
+ }
+ while (front != end)
+ {
+ ptr[--i] = ptr1[2 * end - 1];
+ ptr[--i] = ptr1[2 * end - 2];
+ --end;
+ if (front == end)
+ break;
+ ptr[--i] = ptr1[2 * front + 1];
+ ptr[--i] = ptr1[2 * front + 0];
+ ++front;
+ }
+
+ if (jump)
+ {
+ ptr[i - 1] = ptr[i + 1];
+ ptr[i - 2] = ptr[i + 0];
+ }
+ break;
+ }
+ default: break;
+ }
+ add_line_segment(stroker, stroker->cx, stroker->cy, stroker->nvx, stroker->nvy);
+}
+
+static void
+line_to(Triangulator_Stroker *stroker, const double *pts)
+{
+ add_line_segment(stroker, pts[0], pts[1], stroker->nvx, stroker->nvy);
+ stroker->cx = pts[0];
+ stroker->cy = pts[1];
+}
+
+static void
+cubic_to(Triangulator_Stroker *stroker, const double *pts)
+{
+ Eina_Bezier b;
+ float rad, vx, vy, cx, cy, threshold_minus_1, t;
+ double bw, bh, x, y;
+ int i, threshold;
+
+ eina_bezier_values_set(&b, stroker->cx, stroker->cy, pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
+ eina_bezier_bounds_get(&b, NULL, NULL, &bw, &bh);
+
+ rad = fmaxf(bw, bh);
+ threshold = fminf(64, (rad + stroker->curvyness_add) * stroker->curvyness_mul);
+ if (threshold < 4)
+ threshold = 4;
+ threshold_minus_1 = threshold - 1;
+ cx = stroker->cx;
+ cy = stroker->cy;
+
+ for (i = 1; i < threshold; ++i)
+ {
+ t = i / threshold_minus_1;
+ eina_bezier_point_at(&b, t, &x, &y);
+ normal_vector(cx, cy, x, y, stroker->width, &vx, &vy);
+ add_line_segment(stroker, x, y, vx, vy);
+ cx = x;
+ cy = y;
+ }
+
+ stroker->cx = cx;
+ stroker->cy = cy;
+
+ stroker->nvx = vx;
+ stroker->nvy = vy;
+}
+
+static void
+add_join(Triangulator_Stroker *stroker, float x , float y)
+{
+ int arc_pts_count, pts_count, i;
+ float prev_nvx, prev_nvy, xprod, px, py, qx, qy, pu, qv, ix, iy, *ptr;
+
+ // Creates a join to the next segment (cx, cy) -> (x, y)
+ normal_vector(stroker->cx, stroker->cy, x, y, stroker->width, &stroker->nvx, &stroker->nvy);
+
+ switch (stroker->join_style)
+ {
+ case EFL_GFX_JOIN_BEVEL:
+ break;
+ case EFL_GFX_JOIN_MITER:
+ {
+ // Find out on which side the join should be.
+ pts_count = eina_inarray_count(stroker->vertices);
+ ptr = eina_inarray_nth(stroker->vertices, pts_count - 2);
+ prev_nvx = ptr[0] - stroker->cx;
+ prev_nvy = ptr[1] - stroker->cy;
+ xprod = prev_nvx * stroker->nvy - prev_nvy * stroker->nvx;
+
+ // If the segments are parallel, use bevel join.
+ if (xprod < 0.001)
+ break;
+
+ // Find the corners of the previous and next segment to join.
+ if (xprod < 0)
+ {
+ ptr = eina_inarray_nth(stroker->vertices, pts_count - 2);
+ px = ptr[0];
+ py = ptr[1];
+ qx = stroker->cx - stroker->nvx;
+ qy = stroker->cy - stroker->nvy;
+ }
+ else
+ {
+ ptr = eina_inarray_nth(stroker->vertices, pts_count - 4);
+ px = ptr[0];
+ py = ptr[1];
+ qx = stroker->cx + stroker->nvx;
+ qy = stroker->cy - stroker->nvy;
+ }
+
+ // Find intersection point.
+ pu = px * prev_nvx + py * prev_nvy;
+ qv = qx * stroker->nvx + qy * stroker->nvy;
+ ix = (stroker->nvx * pu - prev_nvy * qv) / xprod;
+ iy = (prev_nvx * qv - stroker->nvx * pu) / xprod;
+
+ // Check that the distance to the intersection point is less than the miter limit.
+ if ((ix - px) * (ix - px) + (iy - py) * (iy - py) <= stroker->miter_limit * stroker->miter_limit)
+ {
+ ptr = eina_inarray_grow(stroker->vertices, 4);
+ ptr[0] = ix;
+ ptr[1] = iy;
+ ptr[2] = ix;
+ ptr[3] = iy;
+ }
+ break;
+ }
+ case EFL_GFX_JOIN_ROUND:
+ {
+ pts_count = eina_inarray_count(stroker->vertices);
+ ptr = eina_inarray_nth(stroker->vertices, pts_count - 2);
+ prev_nvx = ptr[0] - stroker->cx;
+ prev_nvy = ptr[1] - stroker->cy;
+ if (stroker->nvx * prev_nvx - stroker->nvy * prev_nvy < 0)
+ {
+ add_arc_points(stroker, 0, 0, stroker->nvx, stroker->nvy, -prev_nvx, -prev_nvy);
+ arc_pts_count = eina_inarray_count(stroker->arc_pts);
+ if (arc_pts_count)
+ ptr = eina_inarray_nth(stroker->arc_pts, 0);
+ for (i = arc_pts_count / 2; i > 0; --i)
+ add_line_segment(stroker, stroker->cx, stroker->cy, ptr[2 * i - 2], ptr[2 * i - 1]);
+ }
+ else
+ {
+ add_arc_points(stroker, 0, 0, -prev_nvx, -prev_nvy, stroker->nvx, stroker->nvy);
+ arc_pts_count = eina_inarray_count(stroker->arc_pts) / 2;
+ if (arc_pts_count)
+ ptr = eina_inarray_nth(stroker->arc_pts, 0);
+ for (i = 0; i < arc_pts_count / 2; ++i)
+ add_line_segment(stroker, stroker->cx, stroker->cy, ptr[2 * i + 0], ptr[2 * i + 1]);
+ }
+ break;
+ }
+ default: break;
+ }
+ add_line_segment(stroker, stroker->cx, stroker->cy, stroker->nvx, stroker->nvy);
+}
+
+static void
+end_cap(Triangulator_Stroker *stroker)
+{
+ float *ptr, *ptr1;
+ int front, end, pts_count, arc_pts_count, i;
+
+ switch (stroker->cap_style)
+ {
+ case EFL_GFX_CAP_BUTT:
+ break;
+ case EFL_GFX_CAP_SQUARE:
+ add_line_segment(stroker, stroker->cx + stroker->nvy, stroker->cy - stroker->nvx, stroker->nvx, stroker->nvy);
+ break;
+ case EFL_GFX_CAP_ROUND:
+ {
+ pts_count = eina_inarray_count(stroker->vertices);
+ ptr = eina_inarray_nth(stroker->vertices, pts_count-4);
+ add_arc_points(stroker, stroker->cx, stroker->cy, ptr[2], ptr[3], ptr[0], ptr[1]);
+ arc_pts_count = eina_inarray_count(stroker->arc_pts);
+ if (arc_pts_count)
+ {
+ ptr = eina_inarray_grow(stroker->vertices, arc_pts_count);
+ ptr1 = eina_inarray_nth(stroker->arc_pts, 0);
+ }
+ front = 0;
+ end = arc_pts_count / 2;
+ i = 0;
+ while (front != end)
+ {
+ ptr[i++] = ptr1[2 * end - 2];
+ ptr[i++] = ptr1[2 * end - 1];
+ --end;
+ if (front == end)
+ break;
+ ptr[i++] = ptr1[2 * front + 0];
+ ptr[i++] = ptr1[2 * front + 1];
+ ++front;
+ }
+ break;
+ }
+ default: break;
+ }
+}
+
+static void
+_end_cap_or_join_closed(Triangulator_Stroker *stroker,
+ const double *start,
+ Eina_Bool implicit_close, Eina_Bool ends_at_start)
+{
+ int count;
+ float x, y, *ptr;
+
+ if (ends_at_start)
+ {
+ add_join(stroker, start[2], start[3]);
+ }
+ else if (implicit_close)
+ {
+ add_join(stroker, start[0], start[1]);
+ line_to(stroker, start);
+ add_join(stroker, start[2], start[3]);
+ }
+ else
+ {
+ end_cap(stroker);
+ }
+ // add the invisible triangle
+ count = eina_inarray_count(stroker->vertices);
+ ptr = eina_inarray_nth(stroker->vertices, 0);
+ x = ptr[count-2];
+ y = ptr[count-1];
+ ptr = eina_inarray_grow(stroker->vertices, 2);
+ ptr[0] = x;
+ ptr[1] = y;
+}
+
+static inline void
+_skip_duplicate_points(const double **pts, const double *end_pts)
+{
+ while ((*pts + 2) < end_pts && (*pts)[0] == (*pts)[2] &&
+ (*pts)[1] == (*pts)[3])
+ {
+ *pts += 2;
+ }
+}
+
+static void
+_path_info_get(const Efl_Gfx_Path_Command *cmds, const double *pts, Eina_Bool *implicit_close, Eina_Bool *ends_at_start)
+{
+ int i = 0;
+
+ *implicit_close = EINA_FALSE;
+ *ends_at_start = EINA_FALSE;
+ for (++cmds; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END ; ++cmds)
+ {
+ switch (*cmds)
+ {
+ case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
+ i += 2;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
+ i += 6;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
+ // this path has a implicit close
+ *implicit_close = EINA_TRUE;
+ // fall through
+ case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
+ if ((pts[0] == pts[i]) && (pts[1] == pts[i+1]))
+ *ends_at_start = EINA_TRUE;
+ return;
+ default:
+ break;
+ }
+ }
+ // this path is the last path with out implicit close.
+ *ends_at_start = pts[0] == pts[i] &&
+ pts[1] == pts[i+1];
+}
+
+void
+triangulator_stroker_process(Triangulator_Stroker *stroker,
+ const Efl_Gfx_Path_Command *cmds, const double *pts, int cmd_count, int pt_count)
+{
+ const double *end_pts = pts + pt_count;
+ const double *start_pts = 0;
+ Eina_Bool ends_at_start, implicit_close;
+ Efl_Gfx_Cap cap;
+ Efl_Gfx_Path_Command previous_type;
+
+ if (cmd_count < 2)
+ return;
+
+ eina_inarray_resize(stroker->vertices, 0);
+ stroker->curvyness_add = stroker->width;
+ stroker->curvyness_mul = CURVE_FLATNESS;
+ stroker->roundness = fmax(4, 2 * stroker->width * stroker->curvyness_mul);
+ // Over this level of segmentation, there doesn't seem to be any
+ // benefit, even for huge penWidth
+ if (stroker->roundness > 24)
+ stroker->roundness = 24;
+
+ stroker->sin_theta = sinf(PI / stroker->roundness);
+ stroker->cos_theta = cosf(PI / stroker->roundness);
+
+ cap = stroker->cap_style;
+ ends_at_start = EINA_FALSE;
+ implicit_close = EINA_FALSE;
+ previous_type = EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO;
+ for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
+ {
+ switch (*cmds)
+ {
+ case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
+ {
+ if (previous_type != EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
+ _end_cap_or_join_closed(stroker, start_pts, implicit_close, ends_at_start);
+
+ // get the sub path deatils like closed path or start at end info.
+ _path_info_get(cmds, pts, &implicit_close, &ends_at_start);
+
+ start_pts = pts;
+ _skip_duplicate_points(&start_pts, end_pts); // Skip duplicates to find correct normal.
+ if (start_pts + 2 >= end_pts)
+ return; // Nothing to see here...
+
+ if (ends_at_start || implicit_close)
+ stroker->cap_style = EFL_GFX_CAP_BUTT;
+
+ move_to(stroker, start_pts);
+ stroker->cap_style = cap;
+ previous_type = EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO;
+ pts+=2;
+ break;
+ }
+ case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
+ if (stroker->cx != (float)pts[0] || stroker->cy != (float)pts[1])
+ {
+ if (previous_type != EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
+ add_join(stroker, pts[0], pts[1]);
+ line_to(stroker, pts);
+ previous_type = EFL_GFX_PATH_COMMAND_TYPE_LINE_TO;
+ }
+ pts+=2;
+ break;
+ case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
+ if (stroker->cx != (float)pts[0] || stroker->cy != (float)pts[1] ||
+ (float)pts[0] != (float)pts[2] || (float)pts[1] != (float)pts[3] ||
+ (float)pts[2] != (float)pts[4] || (float)pts[3] != (float)pts[5])
+ {
+ if (stroker->cx != (float)pts[0] || stroker->cy != (float)pts[1])
+ {
+ if (previous_type != EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
+ add_join(stroker, pts[0], pts[1]);
+ }
+ cubic_to(stroker, pts);
+ previous_type = EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO;
+ }
+ pts+=6;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (previous_type != EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO)
+ _end_cap_or_join_closed(stroker, start_pts, implicit_close, ends_at_start);
+}