This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository echart.

View the commit online.

commit 9ac0acc7753a4cf74eca8bc721368af8a9ec6d1e
Author: Vincent Torri <[email protected]>
AuthorDate: Wed May 27 07:36:23 2026 +0200

    several changes
    
     * change line API
     * add smooth line using cubic Bezier curve
     * fix EOL
---
 src/bin/echart_main.c |  39 ++-
 src/lib/echart_bar.c  | 888 +++++++++++++++++++++++++-------------------------
 src/lib/echart_bar.h  |  58 ++--
 src/lib/echart_line.c | 218 +++++++++++--
 src/lib/echart_line.h |  14 +-
 5 files changed, 710 insertions(+), 507 deletions(-)

diff --git a/src/bin/echart_main.c b/src/bin/echart_main.c
index 0931150..e42391c 100644
--- a/src/bin/echart_main.c
+++ b/src/bin/echart_main.c
@@ -15,7 +15,6 @@ elm_main(int argc, char **argv)
    Evas_Object *win;
    Evas_Object *o, *line;
    double *absciss;
-   double *d;
    unsigned int num;
    int w;
    int h;
@@ -75,7 +74,7 @@ elm_main(int argc, char **argv)
    absciss[4] = 7;
    absciss[5] = 8;
 
-   d = (double *)calloc(num, sizeof(double));
+   double d[6];
    d[0] = 1.5;
    d[1] = -1.5;
    d[2] = 2.3;
@@ -88,8 +87,32 @@ elm_main(int argc, char **argv)
    o = line = echart_line_add(evas_object_evas_get(win));
    evas_object_move(o, xo, yo);
    evas_object_resize(o, wo, ho);
-   echart_line_data_set(o, d, num);
-   echart_line_color_set(o, 255, 0, 0, 255);
+   echart_line_data_append(o, d, num);
+   d[0] = 5.5;
+   d[1] = 2.7;
+   d[2] = -2.3;
+   d[3] = 3.9;
+   d[4] = 6.2;
+   d[5] = -3.4;
+   echart_line_data_append(o, d, num);
+   echart_line_width_set(o, 3);
+   evas_object_show(o);
+
+   /* smooth line */
+   d[0] = 1.5;
+   d[1] = -1.5;
+   d[2] = 2.3;
+   d[3] = 7.9;
+   d[4] = -4.2;
+   d[5] = 8.4;
+   xo = wo;
+   yo = 0;
+
+   o = line = echart_line_add(evas_object_evas_get(win));
+   echart_line_bicubic_set(o, EINA_TRUE);
+   evas_object_move(o, xo, yo);
+   evas_object_resize(o, wo, ho);
+   echart_line_data_append(o, d, num);
    echart_line_width_set(o, 3);
    evas_object_show(o);
 
@@ -98,8 +121,8 @@ elm_main(int argc, char **argv)
    evas_object_move(o, xo, yo);
    evas_object_resize(o, wo, ho);
    echart_grid_set(o, 0, 1, 0.2);
-   echart_grid_color_set(o, 0, 0, 255, 255);
-   echart_grid_width_set(o, 3);
+   echart_grid_color_set(o, 0, 0, 0, 255);
+   echart_grid_width_set(o, 1);
    evas_object_show(o);
 
    /* grid ordinate */
@@ -107,8 +130,8 @@ elm_main(int argc, char **argv)
    evas_object_move(o, xo, yo);
    evas_object_resize(o, wo, ho);
    echart_grid_set(o, -4.1, 8.4, (8.4 + 4.1) / 5);
-   echart_grid_color_set(o, 0, 0, 255, 255);
-   echart_grid_width_set(o, 3);
+   echart_grid_color_set(o, 0, 0, 0, 255);
+   echart_grid_width_set(o, 1);
    evas_object_show(o);
 
    /* vbar */
diff --git a/src/lib/echart_bar.c b/src/lib/echart_bar.c
index a048d07..7f00d7f 100644
--- a/src/lib/echart_bar.c
+++ b/src/lib/echart_bar.c
@@ -1,439 +1,449 @@
-/*
- * SPDX-FileCopyrightText: Vincent Torri <[email protected]>
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <config.h>
-
-#include "Echart.h"
-#include "echart_color.h"
-#include "echart_private.h"
-
-/*============================================================================*
- *                                  Local                                     *
- *============================================================================*/
-
-#define X_VG(x) (w) * ((x) - sd->ymin) / (sd->ymax - sd->ymin)
-#define Y_VG(y) (h) * (sd->ymax - (y)) / (sd->ymax - sd->ymin)
-
-typedef struct Data Data;
-typedef struct Chart_Bar Chart_Bar;
-
-struct Data
-{
-   Evas_Vg_Shape *bars;
-   double *values;
-   unsigned char r, g, b;
-};
-
-struct Chart_Bar
-{
-   Evas_Object_Smart_Clipped_Data __clipped_data;
-
-   Evas_Object *o_bg;
-   Evas_Object *o_vg;
-
-   /* evas_vg */
-   Evas_Vg_Container *container;
-
-   /* data */
-   Data *data;
-   int nbr_series;
-   int nbr_values;
-   double group_width; /* % between 0 and 100 */
-   double ymin;
-   double ymax;
-   unsigned int is_horizontal : 1;
-};
-
-static Evas_Smart *_bar_smart = NULL;
-static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
-
-/* Evas_Object smart callbacks */
-
-static void
-_bar_smart_add(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = calloc(1, sizeof(Chart_Bar));
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   sd->o_bg = evas_object_rectangle_add(evas_object_evas_get(obj));
-   evas_object_move(sd->o_bg, 0, 0);
-   sd->o_vg = evas_object_vg_add(evas_object_evas_get(obj));
-
-   /* evas_vg */
-   sd->container = evas_vg_container_add(sd->o_vg);
-   evas_object_vg_root_node_set(sd->o_vg, sd->container);
-
-   /* data */
-   sd->group_width = 61.8;
-   sd->is_horizontal = 0;
-
-   evas_object_smart_data_set(obj, sd);
-
-   _parent_sc.add(obj);
-}
-
-static void
-_bar_smart_del(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   _parent_sc.del(obj);
-
-   free(sd->data);
-   evas_object_del(sd->o_bg);
-   evas_object_del(sd->o_vg);
-
-   evas_object_smart_data_set(obj, NULL);
-   memset(sd, 0, sizeof(*sd));
-   free(sd);
-}
-
-static void
-_bar_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
-{
-   Chart_Bar *sd;
-   Evas_Coord ox;
-   Evas_Coord oy;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
-   if ((x == ox) && (y == oy))
-      return;
-
-   evas_object_move(sd->o_bg, x, y);
-   evas_object_move(sd->o_vg, x, y);
-
-   evas_object_smart_changed(obj);
-}
-
-static void
-_bar_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
-{
-   Chart_Bar *sd;
-   Evas_Coord ow;
-   Evas_Coord oh;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
-   if ((w == ow) && (h == oh))
-      return;
-
-   evas_object_resize(sd->o_bg, w, h);
-   evas_object_resize(sd->o_vg, w, h);
-
-   evas_object_smart_changed(obj);
-}
-
-static void
-_bar_smart_show(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   evas_object_show(sd->o_bg);
-   evas_object_show(sd->o_vg);
-}
-
-static void
-_bar_smart_hide(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   INF(" * %s", __FUNCTION__);
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   evas_object_hide(sd->o_bg);
-   evas_object_hide(sd->o_vg);
-}
-
-static void
-_bar_smart_calculate(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-   double gw; /* width of 1 group of bars */
-   double sw; /* space between 2 group of bars */
-   double bw; /* width of 1 bar */
-   int w, h;
-
-   INF(" * %s", __FUNCTION__);
-   /*
-       #   #
-     # #   # #
-     ###   ###
-     ###   ###
-        <->
-         sw
-     <->
-      gw
-
-    */
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
-
-   gw = (w * sd->group_width) / (100.0 * sd->nbr_values);
-   sw = (w - sd->nbr_values * gw) / (sd->nbr_values - 1);
-   bw = (gw - sd->nbr_series + 1) / sd->nbr_series; /* bars separated by 1 px */
-
-   for (int j = 0; j < sd->nbr_series; j++)
-   {
-      Evas_Vg_Shape *bar;
-      double *d;
-      double y = j * (bw + 1);
-
-      d = sd->data[j].values;
-      bar = sd->data[j].bars;
-
-      for (int i = 0; i < sd->nbr_values; i++)
-      {
-         double x = i * (gw + sw) + y;
-
-         if (sd->is_horizontal)
-         {
-            evas_vg_shape_append_move_to(bar, X_VG(0), x);
-            evas_vg_shape_append_line_to(bar, X_VG(0), (x + bw));
-            evas_vg_shape_append_line_to(bar, X_VG(d[i]), (x + bw));
-            evas_vg_shape_append_line_to(bar, X_VG(d[i]), x);
-         }
-         else
-         {
-            evas_vg_shape_append_move_to(bar, x, Y_VG(0));
-            evas_vg_shape_append_line_to(bar, (x + bw), Y_VG(0));
-            evas_vg_shape_append_line_to(bar, (x + bw), Y_VG(d[i]));
-            evas_vg_shape_append_line_to(bar, x, Y_VG(d[i]));
-         }
-      }
-      evas_vg_node_color_set(bar,
-                             sd->data[j].r, sd->data[j].g, sd->data[j].b, 255);
-   }
-}
-
-static void
-_bar_smart_init(void)
-{
-   static Evas_Smart_Class sc;
-
-   INF(" * %s", __FUNCTION__);
-
-   evas_object_smart_clipped_smart_set(&_parent_sc);
-   sc           = _parent_sc;
-   sc.name      = "bar";
-   sc.version   = EVAS_SMART_CLASS_VERSION;
-   sc.add       = _bar_smart_add;
-   sc.del       = _bar_smart_del;
-   sc.move      = _bar_smart_move;
-   sc.resize    = _bar_smart_resize;
-   sc.show      = _bar_smart_show;
-   sc.hide      = _bar_smart_hide;
-   sc.calculate = _bar_smart_calculate;
-   _bar_smart = evas_smart_class_new(&sc);
-}
-
-/*============================================================================*
- *                                 Global                                     *
- *============================================================================*/
-
-/*============================================================================*
- *                                   API                                      *
- *============================================================================*/
-
-ECH_API Evas_Object *
-echart_bar_add(Evas *evas)
-{
-   Evas_Object *obj;
-
-   INF(" * %s", __FUNCTION__);
-
-   if (!_bar_smart) _bar_smart_init();
-   obj = evas_object_smart_add(evas, _bar_smart);
-
-   return obj;
-}
-
-ECH_API void
-echart_bar_data_append(Evas_Object *obj, double *values, int nbr_values)
-{
-   Chart_Bar *sd;
-   double ymin;
-   double ymax;
-   unsigned int c;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   if (!values || (nbr_values <= 0))
-      return;
-
-   if (sd->nbr_series == 0)
-   {
-      sd->nbr_values = nbr_values;
-   }
-   else
-   {
-      if (nbr_values != sd->nbr_values)
-      {
-         ERR("Append a serie with wrong values count.");
-         return;
-      }
-   }
-
-   sd->data = "" sizeof(Data) * (sd->nbr_series + 1));
-   if (!sd->data)
-   {
-      ERR("Can not allocate memory.");
-      return;
-   }
-
-   sd->data[sd->nbr_series].values = malloc(nbr_values * sizeof(double));
-   if (!sd->data[sd->nbr_series].values)
-   {
-      ERR("Can not allocate memory.");
-      return;
-   }
-
-   memcpy(sd->data[sd->nbr_series].values, values, nbr_values * sizeof(double));
-   c = echart_color_get(sd->nbr_series).line;
-   sd->data[sd->nbr_series].r = (unsigned char)((c >> 16) & 0xff);
-   sd->data[sd->nbr_series].g = (unsigned char)((c >> 8) & 0xff);
-   sd->data[sd->nbr_series].b = (unsigned char)((c >> 0) & 0xff);
-
-   sd->data[sd->nbr_series].bars = evas_vg_shape_add(sd->container);
-
-   sd->nbr_series++;
-
-   ymin = values[0];
-   ymax = values[0];
-   for (int i = 1; i < nbr_values; i++)
-   {
-      if (values[i] < ymin) ymin = values[i];
-      if (values[i] > ymax) ymax = values[i];
-   }
-
-   if (sd->nbr_values == 0)
-   {
-      sd->nbr_values = nbr_values;
-      sd->ymin = ymin;
-      sd->ymax = ymax;
-   }
-   else
-   {
-      if (ymin < sd->ymin) sd->ymin = ymin;
-      if (ymax > sd->ymax) sd->ymax = ymax;
-   }
-
-   evas_object_smart_changed(obj);
-}
-
-ECH_API void echart_bar_horizontal_set(Evas_Object *obj, int on)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   sd->is_horizontal = !!on;
-
-   evas_object_smart_changed(obj);
-}
-
-ECH_API int echart_bar_horizontal_get(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
-
-   return sd->is_horizontal;
-}
-
-ECH_API int
-echart_bar_nbr_series_get(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
-
-   return sd->nbr_series;
-}
-
-ECH_API int
-echart_bar_nbr_values_get(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
-
-   return sd->nbr_values;
-}
-
-ECH_API void
-echart_bar_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   sd->data[serie_num].r = r;
-   sd->data[serie_num].g = g;
-   sd->data[serie_num].b = b;
-
-   evas_object_smart_changed(obj);
-}
-
-ECH_API void
-echart_bar_group_width_set(Evas_Object *obj, double group_width)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN(sd);
-
-   if ((group_width <= 0.0) || (group_width > 100.0))
-      return;
-
-   sd->group_width = group_width;
-
-   evas_object_smart_changed(obj);
-}
-
-ECH_API double
-echart_bar_group_width_get(Evas_Object *obj)
-{
-   Chart_Bar *sd;
-
-   sd = evas_object_smart_data_get(obj);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0.0);
-
-   return sd->group_width;
-}
-
+/*
+ * SPDX-FileCopyrightText: Vincent Torri <[email protected]>
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <config.h>
+
+#include "Echart.h"
+#include "echart_color.h"
+#include "echart_private.h"
+
+/*============================================================================*
+ *                                  Local                                     *
+ *============================================================================*/
+
+#define X_VG(x) (w) * ((x) - sd->ymin) / (sd->ymax - sd->ymin)
+#define Y_VG(y) (h) * (sd->ymax - (y)) / (sd->ymax - sd->ymin)
+
+typedef struct Data Data;
+typedef struct Chart_Bar Chart_Bar;
+
+struct Data
+{
+   Evas_Vg_Shape *bars;
+   double *values;
+   unsigned char r, g, b;
+};
+
+struct Chart_Bar
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+
+   Evas_Object *o_bg;
+   Evas_Object *o_vg;
+
+   /* evas_vg */
+   Evas_Vg_Container *container;
+
+   /* data */
+   Data *data;
+   int nbr_series;
+   int nbr_values;
+   double group_width; /* % between 0 and 100 */
+   double ymin;
+   double ymax;
+   unsigned int is_horizontal : 1;
+};
+
+static Evas_Smart *_bar_smart = NULL;
+static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
+
+/* Evas_Object smart callbacks */
+
+static void
+_bar_smart_add(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = calloc(1, sizeof(Chart_Bar));
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   sd->o_bg = evas_object_rectangle_add(evas_object_evas_get(obj));
+   evas_object_move(sd->o_bg, 0, 0);
+   sd->o_vg = evas_object_vg_add(evas_object_evas_get(obj));
+
+   /* evas_vg */
+   sd->container = evas_vg_container_add(sd->o_vg);
+   evas_object_vg_root_node_set(sd->o_vg, sd->container);
+
+   /* data */
+   sd->group_width = 61.8;
+
+   evas_object_smart_data_set(obj, sd);
+
+   _parent_sc.add(obj);
+}
+
+static void
+_bar_smart_del(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   _parent_sc.del(obj);
+
+   free(sd->data);
+   evas_object_del(sd->o_bg);
+   evas_object_del(sd->o_vg);
+
+   evas_object_smart_data_set(obj, NULL);
+   memset(sd, 0, sizeof(*sd));
+   free(sd);
+}
+
+static void
+_bar_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Chart_Bar *sd;
+   Evas_Coord ox;
+   Evas_Coord oy;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
+   if ((x == ox) && (y == oy))
+      return;
+
+   evas_object_move(sd->o_bg, x, y);
+   evas_object_move(sd->o_vg, x, y);
+
+   evas_object_smart_changed(obj);
+}
+
+static void
+_bar_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   Chart_Bar *sd;
+   Evas_Coord ow;
+   Evas_Coord oh;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   if ((w == ow) && (h == oh))
+      return;
+
+   evas_object_resize(sd->o_bg, w, h);
+   evas_object_resize(sd->o_vg, w, h);
+
+   evas_object_smart_changed(obj);
+}
+
+static void
+_bar_smart_show(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   evas_object_show(sd->o_bg);
+   evas_object_show(sd->o_vg);
+}
+
+static void
+_bar_smart_hide(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   INF(" * %s", __FUNCTION__);
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   evas_object_hide(sd->o_bg);
+   evas_object_hide(sd->o_vg);
+}
+
+static void
+_bar_smart_calculate(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+   double gw; /* width of 1 group of bars */
+   double sw; /* space between 2 group of bars */
+   double bw; /* width of 1 bar */
+   int w, h;
+
+   INF(" * %s", __FUNCTION__);
+   /*
+       #   #
+     # #   # #
+     ###   ###
+     ###   ###
+        <->
+         sw
+     <->
+      gw
+
+    */
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+   gw = (w * sd->group_width) / (100.0 * sd->nbr_values);
+   sw = (w - sd->nbr_values * gw) / (sd->nbr_values - 1);
+   bw = (gw - sd->nbr_series + 1) / sd->nbr_series; /* bars separated by 1 px */
+
+   for (int j = 0; j < sd->nbr_series; j++)
+   {
+      Evas_Vg_Shape *bar;
+      double *d;
+      double y = j * (bw + 1);
+
+      d = sd->data[j].values;
+      bar = sd->data[j].bars;
+
+      for (int i = 0; i < sd->nbr_values; i++)
+      {
+         double x = i * (gw + sw) + y;
+
+         if (sd->is_horizontal)
+         {
+            evas_vg_shape_append_move_to(bar, X_VG(0), x);
+            evas_vg_shape_append_line_to(bar, X_VG(0), (x + bw));
+            evas_vg_shape_append_line_to(bar, X_VG(d[i]), (x + bw));
+            evas_vg_shape_append_line_to(bar, X_VG(d[i]), x);
+         }
+         else
+         {
+            evas_vg_shape_append_move_to(bar, x, Y_VG(0));
+            evas_vg_shape_append_line_to(bar, (x + bw), Y_VG(0));
+            evas_vg_shape_append_line_to(bar, (x + bw), Y_VG(d[i]));
+            evas_vg_shape_append_line_to(bar, x, Y_VG(d[i]));
+         }
+      }
+      evas_vg_node_color_set(bar,
+                             sd->data[j].r, sd->data[j].g, sd->data[j].b, 255);
+   }
+}
+
+static void
+_bar_smart_init(void)
+{
+   static Evas_Smart_Class sc;
+
+   INF(" * %s", __FUNCTION__);
+
+   evas_object_smart_clipped_smart_set(&_parent_sc);
+   sc           = _parent_sc;
+   sc.name      = "bar";
+   sc.version   = EVAS_SMART_CLASS_VERSION;
+   sc.add       = _bar_smart_add;
+   sc.del       = _bar_smart_del;
+   sc.move      = _bar_smart_move;
+   sc.resize    = _bar_smart_resize;
+   sc.show      = _bar_smart_show;
+   sc.hide      = _bar_smart_hide;
+   sc.calculate = _bar_smart_calculate;
+   _bar_smart = evas_smart_class_new(&sc);
+}
+
+/*============================================================================*
+ *                                 Global                                     *
+ *============================================================================*/
+
+/*============================================================================*
+ *                                   API                                      *
+ *============================================================================*/
+
+ECH_API Evas_Object *
+echart_bar_add(Evas *evas)
+{
+   Evas_Object *obj;
+
+   INF(" * %s", __FUNCTION__);
+
+   if (!_bar_smart) _bar_smart_init();
+   obj = evas_object_smart_add(evas, _bar_smart);
+
+   return obj;
+}
+
+ECH_API void
+echart_bar_data_append(Evas_Object *obj, double *values, int nbr_values)
+{
+   Chart_Bar *sd;
+   double ymin;
+   double ymax;
+   unsigned int c;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   if (!values || (nbr_values <= 0))
+      return;
+
+   if (sd->nbr_series == 0)
+   {
+      sd->nbr_values = nbr_values;
+   }
+   else
+   {
+      if (nbr_values != sd->nbr_values)
+      {
+         ERR("Append a serie with wrong values count.");
+         return;
+      }
+   }
+
+   sd->data = "" sizeof(Data) * (sd->nbr_series + 1));
+   if (!sd->data)
+   {
+      ERR("Can not allocate memory.");
+      return;
+   }
+
+   sd->data[sd->nbr_series].values = malloc(nbr_values * sizeof(double));
+   if (!sd->data[sd->nbr_series].values)
+   {
+      ERR("Can not allocate memory.");
+      return;
+   }
+
+   memcpy(sd->data[sd->nbr_series].values, values, nbr_values * sizeof(double));
+   c = echart_color_get(sd->nbr_series).line;
+   sd->data[sd->nbr_series].r = (unsigned char)((c >> 16) & 0xff);
+   sd->data[sd->nbr_series].g = (unsigned char)((c >> 8) & 0xff);
+   sd->data[sd->nbr_series].b = (unsigned char)((c >> 0) & 0xff);
+
+   sd->data[sd->nbr_series].bars = evas_vg_shape_add(sd->container);
+
+   sd->nbr_series++;
+
+   ymin = values[0];
+   ymax = values[0];
+   for (int i = 1; i < nbr_values; i++)
+   {
+      if (values[i] < ymin) ymin = values[i];
+      if (values[i] > ymax) ymax = values[i];
+   }
+
+   if (sd->nbr_values == 0)
+   {
+      sd->nbr_values = nbr_values;
+      sd->ymin = ymin;
+      sd->ymax = ymax;
+   }
+   else
+   {
+      if (ymin < sd->ymin) sd->ymin = ymin;
+      if (ymax > sd->ymax) sd->ymax = ymax;
+   }
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API void echart_bar_horizontal_set(Evas_Object *obj, int on)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   if (sd->is_horizontal == !!on)
+      return;
+
+   sd->is_horizontal = !!on;
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API int echart_bar_horizontal_get(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->is_horizontal;
+}
+
+ECH_API int
+echart_bar_nbr_series_get(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->nbr_series;
+}
+
+ECH_API int
+echart_bar_nbr_values_get(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->nbr_values;
+}
+
+ECH_API void
+echart_bar_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   if ((sd->data[serie_num].r == r) &&
+       (sd->data[serie_num].g == g) &&
+       (sd->data[serie_num].b == b))
+      return;
+
+   sd->data[serie_num].r = r;
+   sd->data[serie_num].g = g;
+   sd->data[serie_num].b = b;
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API void
+echart_bar_group_width_set(Evas_Object *obj, double group_width)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   if ((group_width <= 0.0) || (group_width > 100.0))
+      return;
+
+   if (EINA_FLT_EQ(sd->group_width, group_width))
+      return;
+
+   sd->group_width = group_width;
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API double
+echart_bar_group_width_get(Evas_Object *obj)
+{
+   Chart_Bar *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0.0);
+
+   return sd->group_width;
+}
+
diff --git a/src/lib/echart_bar.h b/src/lib/echart_bar.h
index fa8bfcc..d7246c0 100644
--- a/src/lib/echart_bar.h
+++ b/src/lib/echart_bar.h
@@ -1,29 +1,29 @@
-/*
- * SPDX-FileCopyrightText: Vincent Torri <[email protected]>
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#ifndef ECHART_BAR_H
-#define ECHART_BAR_H
-
-#include <Evas.h>
-
-ECH_API Evas_Object *echart_bar_add(Evas *evas);
-
-ECH_API void echart_bar_data_append(Evas_Object *obj, double *values, int nbr_vamues);
-
-ECH_API void echart_bar_horizontal_set(Evas_Object *obj, int on);
-
-ECH_API int echart_bar_horizontal_get(Evas_Object *obj);
-
-ECH_API int echart_bar_nbr_series_get(Evas_Object *obj);
-
-ECH_API int echart_bar_nbr_values_get(Evas_Object *obj);
-
-ECH_API void echart_bar_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a);
-
-ECH_API void echart_bar_group_width_set(Evas_Object *obj, double group_width);
-
-ECH_API double echart_bar_group_width_get(Evas_Object *obj);
-
-#endif /* ECHART_BAR_H */
+/*
+ * SPDX-FileCopyrightText: Vincent Torri <[email protected]>
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef ECHART_BAR_H
+#define ECHART_BAR_H
+
+#include <Evas.h>
+
+ECH_API Evas_Object *echart_bar_add(Evas *evas);
+
+ECH_API void echart_bar_data_append(Evas_Object *obj, double *values, int nbr_vamues);
+
+ECH_API void echart_bar_horizontal_set(Evas_Object *obj, int on);
+
+ECH_API int echart_bar_horizontal_get(Evas_Object *obj);
+
+ECH_API int echart_bar_nbr_series_get(Evas_Object *obj);
+
+ECH_API int echart_bar_nbr_values_get(Evas_Object *obj);
+
+ECH_API void echart_bar_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a);
+
+ECH_API void echart_bar_group_width_set(Evas_Object *obj, double group_width);
+
+ECH_API double echart_bar_group_width_get(Evas_Object *obj);
+
+#endif /* ECHART_BAR_H */
diff --git a/src/lib/echart_line.c b/src/lib/echart_line.c
index ee35b27..6579548 100644
--- a/src/lib/echart_line.c
+++ b/src/lib/echart_line.c
@@ -6,6 +6,7 @@
 #include <config.h>
 
 #include "Echart.h"
+#include "echart_color.h"
 #include "echart_private.h"
 
 /*============================================================================*
@@ -15,8 +16,16 @@
 #define X_VG(x) (w) * ((x) - xmin) / (xmax - xmin)
 #define Y_VG(y) (h) * (sd->ymax - (y)) / (sd->ymax - sd->ymin)
 
+typedef struct Data Data;
 typedef struct Chart_Line Chart_Line;
 
+struct Data
+{
+   Evas_Vg_Shape *line;
+   double *values;
+   unsigned char r, g, b;
+};
+
 struct Chart_Line
 {
    Evas_Object_Smart_Clipped_Data __clipped_data;
@@ -26,13 +35,16 @@ struct Chart_Line
    /* Evas_Vg_Node *vg_dot; /\* the dot which appears when mouse is over *\/ */
 
    /* evas_vg */
-   Evas_Vg_Shape *line;
+   Evas_Vg_Container *container;
 
    /* data */
-   double *data;
-   int num;
+   Data *data;
+   int nbr_series;
+   int nbr_values;
+   double width;
    double ymin;
    double ymax;
+   unsigned int is_cubic : 1;
 };
 
 static Evas_Smart *_line_smart = NULL;
@@ -55,11 +67,11 @@ _line_smart_add(Evas_Object *obj)
    sd->o_vg = evas_object_vg_add(evas_object_evas_get(obj));
 
    /* evas_vg */
-   sd->line = evas_vg_shape_add(sd->o_vg);
-   evas_vg_shape_stroke_width_set(sd->line, 1);
-   evas_vg_shape_stroke_color_set(sd->line, 0, 0, 0, 255);
+   sd->container = evas_vg_container_add(sd->o_vg);
+   evas_object_vg_root_node_set(sd->o_vg, sd->container);
 
-   evas_object_vg_root_node_set(sd->o_vg, sd->line);
+   /* data */
+   sd->width = 1.0;
 
    evas_object_smart_data_set(obj, sd);
 
@@ -165,7 +177,7 @@ static void
 _line_smart_calculate(Evas_Object *obj)
 {
    Chart_Line *sd;
-   double *x; /* FIXME */
+   double *a; /* FIXME */
    double xmin;
    double xmax;
    int w, h;
@@ -178,19 +190,46 @@ _line_smart_calculate(Evas_Object *obj)
    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
 
    /* FIXME abscissa */
-   x = malloc(sd->num * sizeof(double));
-   if (!x)
+   a = malloc(sd->nbr_values * sizeof(double));
+   if (!a)
       return;
 
-   for ( int i = 0; i < sd->num; i++)
-      x[i] =  i;
+   for (int i = 0; i < sd->nbr_values; i++)
+      a[i] =  i;
    xmin = 0;
-   xmax = sd->num - 1;
+   xmax = sd->nbr_values - 1;
 
-   evas_vg_shape_append_move_to(sd->line, X_VG(x[0]), Y_VG(sd->data[0]));
-   for (int i = 1; i < sd->num; i++)
+   for (int j = 0; j < sd->nbr_series; j++)
    {
-      evas_vg_shape_append_line_to(sd->line, X_VG(x[i]), Y_VG(sd->data[i]));
+      Evas_Vg_Shape *line;
+      double *d;
+      double dx;
+
+      d = sd->data[j].values;
+      line = sd->data[j].line;
+      if (sd->is_cubic)
+         dx = w / (sd->nbr_values - 1);
+
+      evas_vg_shape_append_move_to(line, X_VG(a[0]), Y_VG(d[0]));
+      for (int i = 1; i < sd->nbr_values; i++)
+      {
+         if (sd->is_cubic)
+         {
+            double x = X_VG(a[i]);
+            double y = Y_VG(d[i]);
+            double px = X_VG(a[i - 1]);
+            double py = Y_VG(d[i - 1]);
+            double cx1 = px + dx * 0.4;
+            double cx2 = x - dx * 0.4;
+            evas_vg_shape_append_cubic_to(line, x, y, cx1, py, cx2, y);
+         }
+         else
+            evas_vg_shape_append_line_to(line, X_VG(a[i]), Y_VG(d[i]));
+      }
+
+      evas_vg_shape_stroke_width_set(line, sd->width);
+      evas_vg_shape_stroke_color_set(line,
+                                     sd->data[j].r, sd->data[j].g, sd->data[j].b, 255);
    }
 }
 
@@ -237,38 +276,144 @@ echart_line_add(Evas *evas)
 }
 
 ECH_API void
-echart_line_data_set(Evas_Object *obj, double *data, int num)
+echart_line_data_append(Evas_Object *obj, double *values, int nbr_values)
 {
    Chart_Line *sd;
+   double ymin;
+   double ymax;
+   unsigned int c;
 
    sd = evas_object_smart_data_get(obj);
    EINA_SAFETY_ON_NULL_RETURN(sd);
 
-   if (!data || (num <= 0))
+   if (!values || (nbr_values <= 0))
       return;
 
-   sd->data = ""
-   sd->num = num;
-   sd->ymin = sd->data[0];
-   sd->ymax = sd->data[0];
-   for (int i = 1; i < sd->num; i++)
+   if (sd->nbr_series == 0)
    {
-      if (sd->data[i] < sd->ymin) sd->ymin = sd->data[i];
-      if (sd->data[i] > sd->ymax) sd->ymax = sd->data[i];
+      sd->nbr_values = nbr_values;
+   }
+   else
+   {
+      if (nbr_values != sd->nbr_values)
+      {
+         ERR("Append a serie with wrong values count.");
+         return;
+      }
+   }
+
+   sd->data = "" sizeof(Data) * (sd->nbr_series + 1));
+   if (!sd->data)
+   {
+      ERR("Can not allocate memory.");
+      return;
+   }
+
+   sd->data[sd->nbr_series].values = malloc(nbr_values * sizeof(double));
+   if (!sd->data[sd->nbr_series].values)
+   {
+      ERR("Can not allocate memory.");
+      return;
+   }
+
+   memcpy(sd->data[sd->nbr_series].values, values, nbr_values * sizeof(double));
+   c = echart_color_get(sd->nbr_series).line;
+   sd->data[sd->nbr_series].r = (unsigned char)((c >> 16) & 0xff);
+   sd->data[sd->nbr_series].g = (unsigned char)((c >> 8) & 0xff);
+   sd->data[sd->nbr_series].b = (unsigned char)((c >> 0) & 0xff);
+
+   sd->data[sd->nbr_series].line = evas_vg_shape_add(sd->container);
+
+   sd->nbr_series++;
+
+   ymin = values[0];
+   ymax = values[0];
+   for (int i = 1; i < nbr_values; i++)
+   {
+      if (values[i] < ymin) ymin = values[i];
+      if (values[i] > ymax) ymax = values[i];
+   }
+
+   if (sd->nbr_values == 0)
+   {
+      sd->nbr_values = nbr_values;
+      sd->ymin = ymin;
+      sd->ymax = ymax;
+   }
+   else
+   {
+      if (ymin < sd->ymin) sd->ymin = ymin;
+      if (ymax > sd->ymax) sd->ymax = ymax;
    }
 
    evas_object_smart_changed(obj);
 }
 
-ECH_API void
-echart_line_color_set(Evas_Object *obj, int r, int g, int b, int a)
+ECH_API void echart_line_cubic_set(Evas_Object *obj, int on)
 {
    Chart_Line *sd;
 
    sd = evas_object_smart_data_get(obj);
    EINA_SAFETY_ON_NULL_RETURN(sd);
 
-   evas_vg_shape_stroke_color_set(sd->line, r, g, b, a);
+   if (sd->is_cubic == !!on)
+      return;
+
+   sd->is_cubic = !!on;
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API int echart_line_cubic_get(Evas_Object *obj)
+{
+   Chart_Line *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->is_cubic;
+}
+
+ECH_API int
+echart_line_nbr_series_get(Evas_Object *obj)
+{
+   Chart_Line *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->nbr_series;
+}
+
+ECH_API int
+echart_line_nbr_values_get(Evas_Object *obj)
+{
+   Chart_Line *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0);
+
+   return sd->nbr_values;
+}
+
+ECH_API void
+echart_line_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a)
+{
+   Chart_Line *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN(sd);
+
+   if ((sd->data[serie_num].r == r) &&
+       (sd->data[serie_num].g == g) &&
+       (sd->data[serie_num].b == b))
+      return;
+
+   sd->data[serie_num].r = r;
+   sd->data[serie_num].g = g;
+   sd->data[serie_num].b = b;
+
+   evas_object_smart_changed(obj);
 }
 
 ECH_API void
@@ -279,5 +424,20 @@ echart_line_width_set(Evas_Object *obj, double width)
    sd = evas_object_smart_data_get(obj);
    EINA_SAFETY_ON_NULL_RETURN(sd);
 
-   evas_vg_shape_stroke_width_set(sd->line, width);
+   if (EINA_FLT_EQ(sd->width, width))
+      return;
+
+   sd->width = width;
+
+   evas_object_smart_changed(obj);
+}
+
+ECH_API double echart_line_width_get(Evas_Object *obj)
+{
+   Chart_Line *sd;
+
+   sd = evas_object_smart_data_get(obj);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0.0);
+
+   return sd->width;
 }
diff --git a/src/lib/echart_line.h b/src/lib/echart_line.h
index 55e123f..df3e078 100644
--- a/src/lib/echart_line.h
+++ b/src/lib/echart_line.h
@@ -10,10 +10,20 @@
 
 ECH_API Evas_Object *echart_line_add(Evas *evas);
 
-ECH_API void echart_line_data_set(Evas_Object *obj, double *data, int num);
+ECH_API void echart_line_data_append(Evas_Object *obj, double *values, int nbr_values);
 
-ECH_API void echart_line_color_set(Evas_Object *obj, int r, int g, int b, int a);
+ECH_API void echart_line_cubic_set(Evas_Object *obj, int on);
+
+ECH_API int echart_line_cubic_get(Evas_Object *obj);
+
+ECH_API int echart_line_nbr_series_get(Evas_Object *obj);
+
+ECH_API int echart_line_nbr_values_get(Evas_Object *obj);
+
+ECH_API void echart_line_color_set(Evas_Object *obj, int serie_num, int r, int g, int b, int a);
 
 ECH_API void echart_line_width_set(Evas_Object *obj, double width);
 
+ECH_API double echart_line_width_get(Evas_Object *obj);
+
 #endif /* ECHART_LINE_H */

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to