changeset 193:4b48e6e9b3cb trunk

[svn] - rewrite line drawing algorithm for speed - use lines instead of dots by default in horizontal and vertical waveforms
author nenolod
date Fri, 03 Nov 2006 02:54:12 -0800
parents a7c823478180
children 5e8cf0611af3
files ChangeLog src/paranormal/drawing.c src/paranormal/wave.c
diffstat 3 files changed, 161 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Nov 02 22:19:05 2006 -0800
+++ b/ChangeLog	Fri Nov 03 02:54:12 2006 -0800
@@ -1,3 +1,13 @@
+2006-11-03 06:19:05 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [384]
+  - add fast linedrawing code
+  
+  trunk/src/paranormal/Makefile     |    1 
+  trunk/src/paranormal/drawing.c    |   74 ++++++++++++++++++++++++++++++++++++++
+  trunk/src/paranormal/paranormal.c |    2 -
+  3 files changed, 76 insertions(+), 1 deletion(-)
+
+
 2006-11-03 05:44:14 +0000  William Pitcock <nenolod@nenolod.net>
   revision [382]
   - fix warning (oops)
--- a/src/paranormal/drawing.c	Thu Nov 02 22:19:05 2006 -0800
+++ b/src/paranormal/drawing.c	Fri Nov 03 02:54:12 2006 -0800
@@ -1,3 +1,5 @@
+#include <math.h>
+
 #include "paranormal.h"
 #include "actuators.h"
 #include "pn_utils.h"
@@ -12,63 +14,23 @@
   gint x1 = _x1;
   gint y1 = _y1;
 
+  gint dx = x1 - x0;
   gint dy = y1 - y0;
-  gint dx = x1 - x0;
-  gint stepx, stepy;
-  gint fraction;
 
-  if (dy < 0)
-    {
-      dy = -dy;
-      stepy = -(screen->pitch >> 2);
-    }
-  else
-    {
-      stepy = screen->pitch>>2;
-    }
-  if (dx < 0)
-    {
-      dx = -dx;
-      stepx = -1;
-    }
-  else
-    {
-      stepx = 1;
-    }
-  dy <<= 1;
-  dx <<= 1;
-
-  y0 *= screen->pitch>>2;
-  y1 *= screen->pitch>>2;
   pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value;
-  if (dx > dy)
+
+  if (dx != 0)
     {
-      fraction = dy - (dx >> 1);
+      gfloat m = (gfloat) dy / (gfloat) dx;
+      gfloat b = y0 - m * x0;
+
+      dx = (x1 > x0) ? 1 : - 1;
       while (x0 != x1)
-	{
-	  if (fraction >= 0)
-	    {
-	      y0 += stepy;
-	      fraction -= dx;
-	    }
-	  x0 += stepx;
-	  fraction += dy;
-	  pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value;
-	}
-    }
-  else
-    {
-      fraction = dx - (dy >> 1);
-      while (y0 != y1)
-	{
-	  if (fraction >= 0)
-	    {
-	      x0 += stepx;
-	      fraction -= dy;
-	    }
-	  y0 += stepy;
-	  fraction += dx;
-	  pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value;
-	}
+        {
+          x0 += dx;
+          y0 = round(m * x0 + b);
+
+          pn_image_data->surface[0][PN_IMG_INDEX(x0, y0)] = value;
+        }
     }
 }
--- a/src/paranormal/wave.c	Thu Nov 02 22:19:05 2006 -0800
+++ b/src/paranormal/wave.c	Fri Nov 03 02:54:12 2006 -0800
@@ -12,11 +12,12 @@
   {"channels", "Which sound channels to use: negative = channel 1, \npositive = channel 2, "
    "zero = both (two wave-forms.)", OPT_TYPE_INT, {ival: -1} },
   {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} },
+  {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} },
   { NULL }
 };
 
 static void
-wave_horizontal_exec (const struct pn_actuator_option *opts,
+wave_horizontal_exec_dots (const struct pn_actuator_option *opts,
 		    gpointer data)
 {
   int i;
@@ -51,6 +52,71 @@
   }
 }
 
+void
+wave_horizontal_exec_lines (const struct pn_actuator_option *opts,
+		    gpointer data)
+{
+  int channel = ( opts[0].val.ival < 0 ) ? 0 : 1;
+  guchar value = (opts[1].val.ival < 0 || opts[1].val.ival > 255) ? 255 : opts[1].val.ival;
+  int *x_pos, *y_pos;	/* dynamic tables which store the positions for the line */
+  int *x2_pos, *y2_pos;	/* dynamic tables which store the positions for the line */
+  int i;
+
+  x_pos = g_new0(int, pn_image_data->width + 1);
+  y_pos = g_new0(int, pn_image_data->width + 1);
+  x2_pos = g_new0(int, pn_image_data->width + 1);
+  y2_pos = g_new0(int, pn_image_data->width + 1);
+
+  /* calculate the line. */
+  for (i = 0; i < pn_image_data->width; i++)
+    {
+      if (opts[0].val.ival != 0)
+        {
+           x_pos[i] = i;
+           y_pos[i] = (pn_image_data->height>>1) - 
+			CAP (pn_sound_data->pcm_data[channel][i*512/pn_image_data->width]>>8, 
+			(pn_image_data->height>>1)-1);
+        }
+      else
+        {
+           x_pos[i] = i;
+           y_pos[i] = (pn_image_data->height>>2) - 
+			CAP (pn_sound_data->pcm_data[0][i*512/pn_image_data->width]>>9,
+			(pn_image_data->height>>2)-1);
+
+           x2_pos[i] = i;
+           y2_pos[i] = 3*(pn_image_data->height>>2) - 
+			CAP (pn_sound_data->pcm_data[1][i*512/pn_image_data->width]>>9,
+			(pn_image_data->height>>2)-1);
+
+        }
+    }
+
+  /* draw the line. */
+  for (i = 1; i < pn_image_data->width; i++)
+    {
+       pn_draw_line(x_pos[i - 1], y_pos[i - 1], x_pos[i], y_pos[i], value);
+
+       if ( opts[0].val.ival == 0 )
+         pn_draw_line(x2_pos[i - 1], y2_pos[i - 1], x2_pos[i], y2_pos[i], value);
+    }
+
+  g_free(x_pos);
+  g_free(y_pos);
+  g_free(x2_pos);
+  g_free(y2_pos);
+}
+
+static void
+wave_horizontal_exec (const struct pn_actuator_option *opts,
+		    gpointer data)
+{
+  if (opts[2].val.bval == TRUE)
+    wave_horizontal_exec_lines(opts, data);
+  else
+    wave_horizontal_exec_dots(opts, data);
+}
+
 struct pn_actuator_desc builtin_wave_horizontal =
 {
   "wave_horizontal", "Horizontal Waveform",
@@ -66,11 +132,12 @@
   {"channels", "Which sound channels to use: negative = channel 1, \npositive = channel 2, "
    "zero = both (two wave-forms.)", OPT_TYPE_INT, {ival: -1} },
   {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} },
+  {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} },
   { NULL }
 };
 
 static void
-wave_vertical_exec (const struct pn_actuator_option *opts,
+wave_vertical_exec_dots (const struct pn_actuator_option *opts,
 		    gpointer data)
 {
   int i;
@@ -101,6 +168,72 @@
   }
 }
 
+static void
+wave_vertical_exec_lines (const struct pn_actuator_option *opts,
+		    gpointer data)
+{
+  int channel = ( opts[0].val.ival < 0 ) ? 0 : 1;
+  guchar value = (opts[1].val.ival < 0 || opts[1].val.ival > 255) ? 255 : opts[1].val.ival;
+  int *x_pos, *y_pos;	/* dynamic tables which store the positions for the line */
+  int *x2_pos, *y2_pos;	/* dynamic tables which store the positions for the line */
+  int i;
+
+  x_pos = g_new0(int, pn_image_data->height + 1);
+  y_pos = g_new0(int, pn_image_data->height + 1);
+  x2_pos = g_new0(int, pn_image_data->height + 1);
+  y2_pos = g_new0(int, pn_image_data->height + 1);
+
+  /* calculate the line. */
+  for (i = 0; i < pn_image_data->height; i++)
+    {
+      if (opts[0].val.ival != 0)
+        {
+           x_pos[i] = (pn_image_data->width>>1) - 
+			CAP (pn_sound_data->pcm_data[channel]
+			[i*512/pn_image_data->height]>>8,
+			(pn_image_data->width>>1)-1);
+	   y_pos[i] = i;
+        }
+      else
+        {
+           x_pos[i] = (pn_image_data->width>>2) 
+		      - CAP (pn_sound_data->pcm_data[0]
+		     [i*512/pn_image_data->height]>>9,
+		     (pn_image_data->width>>2)-1);
+           y_pos[i] = i;
+
+           x2_pos[i] = 3*(pn_image_data->width>>2) 
+		      - CAP (pn_sound_data->pcm_data[1]
+		     [i*512/pn_image_data->height]>>9,
+		     (pn_image_data->width>>2)-1);
+           y2_pos[i] = i;
+        }
+    }
+
+  /* draw the line. */
+  for (i = 1; i < pn_image_data->width; i++)
+    {
+       pn_draw_line(x_pos[i - 1], y_pos[i - 1], x_pos[i], y_pos[i], value);
+
+       if ( opts[0].val.ival == 0 )
+         pn_draw_line(x2_pos[i - 1], y2_pos[i - 1], x2_pos[i], y2_pos[i], value);
+    }
+
+  g_free(x_pos);
+  g_free(y_pos);
+  g_free(x2_pos);
+  g_free(y2_pos);
+}
+
+static void
+wave_vertical_exec (const struct pn_actuator_option *opts,
+		    gpointer data)
+{
+  if (opts[2].val.bval == TRUE)
+    wave_vertical_exec_lines(opts, data);
+  else
+    wave_vertical_exec_dots(opts, data);
+}
 
 struct pn_actuator_desc builtin_wave_vertical =
 {
@@ -221,6 +354,7 @@
   { "base_radius", " ", 
     OPT_TYPE_FLOAT, { fval: 0 } },
   {"value", "The colour value to use.", OPT_TYPE_INT, {ival: 255} },
+/*  {"lines", "Use lines instead of dots.", OPT_TYPE_BOOLEAN, {bval: TRUE} }, */
   { NULL }
 };