]> git.sesse.net Git - nms/blobdiff - web/ext/graph.c
Merge from andun.
[nms] / web / ext / graph.c
diff --git a/web/ext/graph.c b/web/ext/graph.c
new file mode 100644 (file)
index 0000000..ddd726b
--- /dev/null
@@ -0,0 +1,246 @@
+#include "graph.h"
+
+
+void
+mygraph_fill_background(graph *mygraph);
+
+void
+mygraph_draw_graph (cairo_t *cr,
+                   int x,
+                   int y );
+
+graph *
+mygraph_new (int width, int height)
+{
+  graph *mygraph;
+  mygraph = malloc(sizeof(graph));
+  mygraph->width = width;
+  mygraph->height = height;
+
+
+  int stride = width * 4;
+  unsigned char *image;
+  image = (unsigned char *) malloc (sizeof(unsigned char) * stride * height);
+
+  mygraph->surface = cairo_image_surface_create_for_data (image, CAIRO_FORMAT_ARGB32,
+                                                      width, height, stride);
+  mygraph->cr = cairo_create (mygraph->surface);
+
+  cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0);
+  mygraph_fill_background (mygraph);
+
+  cairo_select_font_face (mygraph->cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
+                         CAIRO_FONT_WEIGHT_NORMAL);
+  cairo_set_font_size (mygraph->cr, 10);
+
+  cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_NONE);
+  cairo_set_line_width (mygraph->cr, 1.0);
+
+  return mygraph;
+}
+
+graph *
+mygraph_make_graph (graph *mygraph, float min_x, float max_x,
+                   float min_y, float max_y, int tickgran)
+{
+  int xoffset = 70;
+  cairo_text_extents_t extents;
+
+  mygraph->xoffset = xoffset;
+  mygraph->min_x = min_x;
+  mygraph->max_x = max_x;
+  mygraph->min_y = min_y;
+  mygraph->max_y = max_y;
+
+/*   cairo_t *cr; */
+/*   cairo_surface_t *surface; */
+
+  float xs = ((float)mygraph->width - (float)(xoffset+2)) /
+             (float)(max_x - min_x);
+
+  float ys = ((float)mygraph->height - 33.) / (float)(min_y - max_y);
+
+  mygraph->xs = xs;
+  mygraph->ys = ys;
+
+  float starthour = fmod((min_x + (float)tz_local_offset()) / 3600., 24.);
+  float diff, center, begin, end;
+
+  char string[20];
+  int i;
+  for (i = 0; i<24; i++)
+    { // Hour marks and text
+      if ((i % 2) == 0)
+       cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0);
+      else
+       cairo_set_source_rgb (mygraph->cr, 0.90, 0.90, 1.0);
+      
+      diff = fmod((float)i - starthour + 24., 24.);
+      begin = (diff * 3600.) * xs;
+      end = ((fmod(((float)i+1) - starthour + 24., 24.)) * 3600.) * xs;
+      center = (begin + end) / 2.;
+
+      if (begin > end)
+       begin = 0.;
+
+      //      printf("i: %d, starthour: %f, diff: %f, begin: %f, end: %f\n", i, starthour, diff, begin, end);
+
+      if (begin < 0.)
+       begin = 0.0;
+      if (begin > ((float)mygraph->width - ((float)xoffset)))
+       continue;
+      //      printf("drawing\n");
+
+      cairo_rectangle (mygraph->cr, xoffset+begin, 0,
+                      end - begin, mygraph->height);
+      
+      cairo_fill (mygraph->cr);
+
+      if (begin <= 0.0 || end >= mygraph->width - (xoffset))
+       continue;
+
+      cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0);
+
+      sprintf(string, "%d", i);
+      //      printf("showing string %s\n", string);
+
+      cairo_text_extents (mygraph->cr, string, &extents);
+      cairo_move_to (mygraph->cr, xoffset + center -
+                    (extents.width/2),
+                    (mygraph->height - extents.height - 2));
+
+      cairo_show_text (mygraph->cr, string);
+
+    }
+
+  cairo_set_source_rgb (mygraph->cr, 0.4, 0.4, 0.4);
+  int ytick;
+  do
+    {
+      ytick = ((int)max_y - (int)min_y) / 11;
+      ytick = ceil (ytick / tickgran) * tickgran;
+      tickgran *= 0.1;
+    } while (((int)max_y - (int)min_y) / ytick < 4);
+
+  int y, traf;
+  for (i = -11; i<12; i++)
+    {
+      y = (i * ytick - (int)max_y) * ys + 10;
+      if (y < 2 || y > mygraph->height - 18)
+       continue;
+
+/*       printf("draw line at %d\n", y); */
+
+      cairo_move_to (mygraph->cr, xoffset, y);
+      cairo_line_to (mygraph->cr, mygraph->width-1, y);
+
+      if (i == 0)
+       {
+
+         cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 1.0);
+         cairo_stroke (mygraph->cr);
+         cairo_set_source_rgb (mygraph->cr, 0.6, 0.6, 0.6);
+       }
+      else
+       cairo_stroke (mygraph->cr);
+
+      // draw text
+      traf = 8 * (i * ytick);
+/*       printf("traffic: %d\n", traf); */
+
+      if (traf >= 500000000)
+       sprintf (string, "%.1f Gbit", ((float)traf/1000000000));
+      else if (traf >= 500000)
+       sprintf (string, "%.1f Mbit", ((float)traf/1000000));
+      else
+       sprintf (string, "%.1f kbit", ((float)traf/1000));
+
+      cairo_text_extents (mygraph->cr, string, &extents);
+
+      if (y - (extents.height/2) < 2 ||
+         y + (extents.height/2) > mygraph->height - (extents.height + 2))
+       continue;
+
+      cairo_move_to (mygraph->cr,
+                    xoffset - 4 - extents.width,
+                    y + (extents.height/2));
+
+      cairo_show_text (mygraph->cr, string);
+    }
+
+  cairo_rectangle (mygraph->cr, xoffset, 0, mygraph->width-xoffset-1, mygraph->height-1);
+
+  cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0);
+  cairo_stroke (mygraph->cr);
+
+  return mygraph;
+}
+
+void
+mygraph_plot_series (graph *mygraph, int *xvals, int *yvals, int n_vals,
+                    float r, float g, float b)
+{
+  int x, y, i;
+  x = xvals[0];
+  y = yvals[0];
+
+  cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_DEFAULT);
+  cairo_set_source_rgb (mygraph->cr, r, g, b);
+
+  cairo_move_to (mygraph->cr,
+                (int)((float)(x - (int)mygraph->min_x) *
+                      mygraph->xs + (float)(mygraph->xoffset + 1)),
+                (int)((float)(y - (int)mygraph->max_y) * mygraph->ys + 10.));
+
+/*   printf("Plotting from:\n"); */
+/*   printf("(%d, %d) %d (%d, %d)<br/>\n", */
+/*      x, y, (int)((float)(x - (int)mygraph->min_x) * mygraph->xs + (float)(mygraph->xoffset + 1)) , */
+/*      (int)((float)(x - (int)mygraph->min_x) * mygraph->xs + (float)(mygraph->xoffset + 1)), */
+/*      (int)((float)(y - (int)mygraph->max_y) * mygraph->ys + 10.)); */
+
+  for (i = 1; i < n_vals; i++)
+    {
+
+      if (mygraph->xs * (xvals[i] - x) < 2 &&
+         mygraph->ys * (yvals[i] - y) > -2)
+       continue;
+      
+      x = xvals[i];
+      y = yvals[i];
+      
+      cairo_line_to (mygraph->cr,
+                    (int)((float)(x - (int)mygraph->min_x) *
+                          mygraph->xs + (float)(mygraph->xoffset + 1)),
+                    (int)((float)(y - (int)mygraph->max_y) * mygraph->ys + 10.));
+
+/*       printf("(%d, %d) = > (%d, %d)<br/>\n", */
+/*          x, y, */
+/*          (int)((x - (int)x-mygraph->min_x) * (int)mygraph->xs + (int)mygraph->xoffset + 1), */
+/*          (int)((y - (int)mygraph->max_y) * (int)mygraph->ys + 10)); */
+
+    }
+
+  cairo_stroke(mygraph->cr);
+}
+
+void
+mygraph_to_file (graph *mygraph, char *filename)
+{
+  cairo_surface_write_to_png (mygraph->surface, filename);
+}
+
+void
+mygraph_cleanup (graph *self)
+{
+  cairo_destroy (self->cr);
+  cairo_surface_destroy (self->surface);
+}
+
+void
+mygraph_fill_background (graph *mygraph)
+{
+  cairo_rectangle (mygraph->cr, 0, 0, mygraph->width, mygraph->height);
+  cairo_fill (mygraph->cr);
+}
+